/** Start OPTIONS keepalive or contact validation process */ void outbound_start_keepalive(outbound_t *ob, nta_outgoing_t *register_transaction) { unsigned interval = 0; int need_to_validate, udp; if (!ob) return; udp = ob->ob_via && ob->ob_via->v_protocol == sip_transport_udp; if (/* ob->ob_prefs.natify && */ /* On UDP, use OPTIONS keepalive by default */ (udp ? ob->ob_prefs.okeepalive != 0 /* Otherwise, only if requested */ : ob->ob_prefs.okeepalive > 0)) interval = ob->ob_prefs.interval; need_to_validate = ob->ob_prefs.validate && !ob->ob_validated; if (!register_transaction || !(need_to_validate || interval != 0)) { outbound_stop_keepalive(ob); return; } if (ob->ob_keepalive.timer) su_timer_destroy(ob->ob_keepalive.timer), ob->ob_keepalive.timer = NULL; if (interval) { su_duration_t max_defer; max_defer = su_root_get_max_defer(ob->ob_root); if ((su_duration_t)interval >= max_defer) { interval -= max_defer - 100; } ob->ob_keepalive.timer = su_timer_create(su_root_task(ob->ob_root), interval); su_timer_deferrable(ob->ob_keepalive.timer, 1); } ob->ob_keepalive.interval = interval; if (!ob->ob_validated && ob->ob_keepalive.sipstun && 0 /* Stun is disabled for now */) { nta_tport_keepalive(register_transaction); } else { if (register_transaction) { msg_t *msg = nta_outgoing_getrequest(register_transaction); sip_t const *register_request = sip_object(msg); create_keepalive_message(ob, register_request); msg_destroy(msg); } keepalive_options(ob); } }
/** Initialize server timer. */ su_inline int server_timer_init(server_t *srv) { if (0) { srv->srv_timer = su_timer_create(su_root_task(srv->srv_root), SERVER_TICK); return su_timer_set(srv->srv_timer, server_timer, srv); } return 0; }
/**Create a resolver. * * The function sres_resolver_create() is used to allocate and initialize * the resolver object using the Sofia asynchronous reactor #su_root_t. */ sres_resolver_t * sres_resolver_create(su_root_t *root, char const *conf_file_path, tag_type_t tag, tag_value_t value, ...) { sres_resolver_t *res; sres_sofia_t *srs; sres_cache_t *cache = NULL; ta_list ta; if (root == NULL) return su_seterrno(EFAULT), (void *)NULL; ta_start(ta, tag, value); tl_gets(ta_args(ta), SRESTAG_RESOLV_CONF_REF(conf_file_path), SRESTAG_CACHE_REF(cache), TAG_END()); ta_end(ta); res = sres_resolver_new_with_cache(conf_file_path, cache, NULL); srs = res ? su_zalloc(0, sizeof *srs) : NULL; if (res && srs) { su_timer_t *t; srs->srs_resolver = res; srs->srs_root = root; srs->srs_socket = INVALID_SOCKET; sres_resolver_set_async(res, sres_sofia_update, srs, 0); t = su_timer_create(su_root_task(root), SRES_RETRANSMIT_INTERVAL); srs->srs_timer = t; if (!srs->srs_timer) SU_DEBUG_3(("sres: cannot create timer\n")); #if nomore else if (su_timer_set_for_ever(t, sres_sofia_timer, srs) < 0) SU_DEBUG_3(("sres: cannot set timer\n")); #else else if (sres_resolver_set_timer_cb(res, sres_sofia_set_timer, srs) < 0) SU_DEBUG_3(("sres: cannot set timer cb\n")); #endif else return res; /* Success! */ sres_resolver_destroy(res), res = NULL; } return res; }
void SipDialog::setSessionTimer( unsigned long nSecs, SessionRefresher_t whoIsResponsible ) { assert( NULL == m_timerSessionRefresh ) ; m_refresher = whoIsResponsible ; su_duration_t nMilliseconds = nSecs * 1000 ; m_nSessionExpiresSecs = nSecs ; DR_LOG(log_debug) << "Session expires has been set to " << nSecs << " seconds and refresher is " << (areWeRefresher() ? "us" : "them") ; /* if we are the refresher, then we want the timer to go off halfway through the interval */ if( areWeRefresher() ) nMilliseconds /= 2 ; m_timerSessionRefresh = su_timer_create( su_root_task(theOneAndOnlyController->getRoot()), nMilliseconds ) ; m_ppSelf = new boost::weak_ptr<SipDialog>( shared_from_this() ) ; su_timer_set(m_timerSessionRefresh, session_timer_handler, (su_timer_arg_t *) m_ppSelf ); }
static void nua_dialog_usage_set_refresh_timer(nua_dialog_usage_t *du, su_duration_t timeout, int deferrable) { du->du_refquested = sip_now(); if (!du->du_refresh_timer) { nua_handle_t const *nh = (nua_handle_t *)du->du_dialog->ds_owner; nua_t const *nua = nh->nh_nua; du->du_refresh_timer = su_timer_create(su_root_task(nua->nua_root), 0); } su_timer_deferrable(du->du_refresh_timer, deferrable); su_timer_set_interval(du->du_refresh_timer, nua_dialog_refresh_timer, du, timeout); }
/** @internal Shut down stack. */ void nua_stack_shutdown(nua_t *nua) { nua_handle_t *nh, *nh_next; int busy = 0; sip_time_t now = sip_now(); int status; char const *phrase; enter; if (!nua->nua_shutdown) nua->nua_shutdown = now; for (nh = nua->nua_handles; nh; nh = nh_next) { nua_dialog_state_t *ds = nh->nh_ds; nh_next = nh->nh_next; busy += nua_dialog_repeat_shutdown(nh, ds); if (nh->nh_ds->ds_soa) soa_destroy(nh->nh_ds->ds_soa), nh->nh_ds->ds_soa = NULL; if (nua_client_request_pending(ds->ds_cr)) busy++; if (nh_notifier_shutdown(nh, NULL, NEATAG_REASON("noresource"), TAG_END())) busy++; } if (!busy) SET_STATUS(200, "Shutdown successful"); else if (now == nua->nua_shutdown) SET_STATUS(100, "Shutdown started"); else if (now - nua->nua_shutdown < 30) SET_STATUS(101, "Shutdown in progress"); else SET_STATUS(500, "Shutdown timeout"); if (status >= 200) { for (nh = nua->nua_handles; nh; nh = nh_next) { nh_next = nh->nh_next; while (nh->nh_ds && nh->nh_ds->ds_usage) { nua_dialog_usage_remove(nh, nh->nh_ds, nh->nh_ds->ds_usage, NULL, NULL); } } if (nua->nua_shutdown_timer) { su_timer_destroy(nua->nua_shutdown_timer); nua->nua_shutdown_timer = NULL; } nta_agent_destroy(nua->nua_nta), nua->nua_nta = NULL; } else { if (!nua->nua_shutdown_timer) nua->nua_shutdown_timer = su_timer_create(su_root_task(nua->nua_root), NUA_SHUTDOWN_TIMER_INTERVAL); if (nua->nua_shutdown_timer) su_timer_set(nua->nua_shutdown_timer, nua_stack_shutdown_timer, NULL); else SET_STATUS(500, "Shutdown timer creation failed"); } nua_stack_event(nua, NULL, NULL, nua_r_shutdown, status, phrase, NULL); }
int nua_base_client_check_restart(nua_client_request_t *cr, int status, char const *phrase, sip_t const *sip) { nua_handle_t *nh = cr->cr_owner; nta_outgoing_t *orq; #if 0 if (status == 302 || status == 305) { sip_route_t r[1]; if (!can_redirect(sip->sip_contact, cr->cr_method)) return 0; switch (status) { case 302: if (nua_dialog_zap(nh, nh->nh_ds) == 0 && nua_client_set_target(cr, sip->sip_contact->m_url) >= 0) return nua_client_restart(cr, 100, "Redirected"); break; case 305: sip_route_init(r); *r->r_url = *sip->sip_contact->m_url; if (nua_dialog_zap(nh, nh->nh_ds) == 0 && sip_add_dup(cr->cr_msg, cr->cr_sip, (sip_header_t *)r) >= 0) return nua_client_restart(cr, 100, "Redirected via a proxy"); break; default: break; } } #endif if (status == 423) { unsigned my_expires = 0; if (cr->cr_sip->sip_expires) my_expires = cr->cr_sip->sip_expires->ex_delta; if (sip->sip_min_expires && sip->sip_min_expires->me_delta > my_expires) { sip_expires_t ex[1]; sip_expires_init(ex); ex->ex_delta = sip->sip_min_expires->me_delta; if (sip_add_dup(cr->cr_msg, NULL, (sip_header_t *)ex) < 0) return 0; return nua_client_restart(cr, 100, "Re-Negotiating Expiration"); } } if ((status == 401 && sip->sip_www_authenticate) || (status == 407 && sip->sip_proxy_authenticate)) { int server = 0, proxy = 0; if (sip->sip_www_authenticate) server = auc_challenge(&nh->nh_auth, nh->nh_home, sip->sip_www_authenticate, sip_authorization_class); if (sip->sip_proxy_authenticate) proxy = auc_challenge(&nh->nh_auth, nh->nh_home, sip->sip_proxy_authenticate, sip_proxy_authorization_class); if (server >= 0 && proxy >= 0) { int invalid = cr->cr_challenged && server + proxy == 0; cr->cr_challenged = 1; if (invalid) { /* Bad username/password */ SU_DEBUG_7(("nua(%p): bad credentials, clearing them\n", (void *)nh)); auc_clear_credentials(&nh->nh_auth, NULL, NULL); } else if (auc_has_authorization(&nh->nh_auth)) return nua_client_restart(cr, 100, "Request Authorized by Cache"); orq = cr->cr_orq, cr->cr_orq = NULL; cr->cr_waiting = cr->cr_wait_for_cred = 1; nua_client_report(cr, status, phrase, NULL, orq, NULL); nta_outgoing_destroy(orq); cr->cr_status = 0, cr->cr_phrase = NULL; nua_client_request_unref(cr); return 1; } } if (0 && 500 <= status && status < 600 && sip->sip_retry_after && sip->sip_retry_after->af_delta < 32) { su_timer_t *timer; char phrase[18]; /* Retry After XXXX\0 */ timer = su_timer_create(su_root_task(nh->nh_nua->nua_root), 0); if (su_timer_set_interval(timer, nua_client_restart_after, cr, sip->sip_retry_after->af_delta * 1000) < 0) { su_timer_destroy(timer); return 0; /* Too bad */ } cr->cr_timer = timer; /* This takes over cr reference from orq */ snprintf(phrase, sizeof phrase, "Retry After %u", (unsigned)sip->sip_retry_after->af_delta); orq = cr->cr_orq, cr->cr_orq = NULL; cr->cr_waiting = 1; nua_client_report(cr, 100, phrase, NULL, orq, NULL); nta_outgoing_destroy(orq); cr->cr_status = 0, cr->cr_phrase = NULL; return 1; } return 0; /* This was a final response that cannot be restarted. */ }
/* * test su_timer functionality: * * Create a timer, executing print_stamp() in every 20 ms */ int main(int argc, char *argv[]) { su_root_t *root; su_timer_t *t, *t1, *t_end; su_timer_t **timers; su_duration_t interval = 60; char *argv0 = argv[0]; char *s; int use_t1 = 0; su_time_t now, started; intptr_t i, N = 500; GSource *source; struct timing timing[1] = {{ 0 }}; struct tester tester[1] = {{ 0 }}; while (argv[1] && argv[1][0] == '-') { char *o = argv[1] + 1; while (*o) { if (*o == '1') o++, use_t1 = 1; else if (*o == 'r') o++, timing->t_run = 1; else if (*o == 'N') { if (o[1]) N = strtoul(o + 1, &o, 0); else if (argv[2]) N = strtoul(argv++[2], &o, 0); break; } else break; } if (*o) usage(argv0); argv++; } if (argv[1]) { interval = strtoul(argv[1], &s, 10); if (interval == 0 || s == argv[1]) usage(argv0); } su_init(); atexit(su_deinit); tester->root = root = su_glib_root_create(tester); source = su_root_gsource(tester->root); g_source_attach(source, NULL /*g_main_context_default ()*/); su_msg_create(intr_msg, su_root_task(root), su_root_task(root), test_break, 0); signal(SIGINT, intr_handler); #if HAVE_SIGPIPE signal(SIGPIPE, intr_handler); signal(SIGQUIT, intr_handler); signal(SIGHUP, intr_handler); #endif t = su_timer_create(su_root_task(root), interval); t1 = su_timer_create(su_root_task(root), 1); t_end = su_timer_create(su_root_task(root), 20 * interval); if (t == NULL || t1 == NULL || t_end == NULL) su_perror("su_timer_create"), exit(1); tester->t = t, tester->t1 = t1; timing->t_prev = su_now(); if (timing->t_run) su_timer_run(t, print_stamp, timing); else su_timer_set(t, print_stamp, timing); if (use_t1) su_timer_set(t1, print_X, NULL); su_timer_set(t_end, end_test, NULL); su_root_run(root); su_msg_destroy(intr_msg); su_timer_destroy(t); su_timer_destroy(t1); if (timing->t_times != 10) { fprintf(stderr, "%s: t expired %d times (expecting 10)\n", argv0, timing->t_times); return 1; } /* Insert timers in order */ timers = calloc(N, sizeof *timers); if (!timers) { perror("calloc"); exit(1); } now = started = su_now(); for (i = 0; i < N; i++) { t = su_timer_create(su_root_task(root), 1000); if (!t) { perror("su_timer_create"); exit(1); } if (++now.tv_usec == 0) ++now.tv_sec; su_timer_set_at(t, increment, (void *)i, now); timers[i] = t; } tester->sentinel = (void*)(i - 1); su_root_run(root); printf("Processing %u timers took %f millisec (%f expected)\n", (unsigned)i, su_time_diff(su_now(), started) * 1000, (double)i / 1000); for (i = 0; i < N; i++) { su_timer_destroy(timers[i]); } su_root_destroy(root); su_deinit(); return 0; }
/** Initialize engine timer. */ static int he_timer_init(nth_engine_t * he) { he->he_timer = su_timer_create(su_root_task(he->he_root), HE_TIMER); return su_timer_set(he->he_timer, he_timer, he); }
void DrachtioController::run() { if( m_bDaemonize ) { daemonize() ; } /* now we can initialize logging */ m_logger.reset( this->createLogger() ); this->logConfig() ; DR_LOG(log_debug) << "Main thread id: " << boost::this_thread::get_id() << endl ; /* open stats connection */ string adminAddress ; unsigned int adminPort = m_Config->getAdminPort( adminAddress ) ; if( 0 != adminPort ) { m_pClientController.reset( new ClientController( this, adminAddress, adminPort )) ; } string url ; m_Config->getSipUrl( url ) ; DR_LOG(log_notice) << "starting sip stack on " << url << endl ; int rv = su_init() ; if( rv < 0 ) { DR_LOG(log_error) << "Error calling su_init: " << rv << endl ; return ; } ::atexit(su_deinit); m_root = su_root_create( NULL ) ; if( NULL == m_root ) { DR_LOG(log_error) << "Error calling su_root_create: " << endl ; return ; } m_home = su_home_create() ; if( NULL == m_home ) { DR_LOG(log_error) << "Error calling su_home_create" << endl ; } su_log_redirect(NULL, __sofiasip_logger_func, NULL); /* for now set logging to full debug */ su_log_set_level(NULL, m_Config->getSofiaLogLevel() ) ; setenv("TPORT_LOG", "1", 1) ; /* this causes su_clone_start to start a new thread */ su_root_threading( m_root, 0 ) ; rv = su_clone_start( m_root, m_clone, this, clone_init, clone_destroy ) ; if( rv < 0 ) { DR_LOG(log_error) << "Error calling su_clone_start" << endl ; return ; } /* enable extended headers */ if (sip_update_default_mclass(sip_extend_mclass(NULL)) < 0) { DR_LOG(log_error) << "Error calling sip_update_default_mclass" << endl ; return ; } /* create our agent */ char str[URL_MAXLEN] ; memset(str, 0, URL_MAXLEN) ; strncpy( str, url.c_str(), url.length() ) ; m_nta = nta_agent_create( m_root, URL_STRING_MAKE(str), /* our contact address */ NULL, /* no callback function */ NULL, /* therefore no context */ TAG_NULL(), TAG_END() ) ; if( NULL == m_nta ) { DR_LOG(log_error) << "Error calling nta_agent_create" << endl ; return ; } m_defaultLeg = nta_leg_tcreate(m_nta, defaultLegCallback, this, NTATAG_NO_DIALOG(1), TAG_END()); if( NULL == m_defaultLeg ) { DR_LOG(log_error) << "Error creating default leg" << endl ; return ; } /* save my contact url, via, etc */ m_my_contact = nta_agent_contact( m_nta ) ; ostringstream s ; s << "SIP/2.0/UDP " << m_my_contact->m_url[0].url_host ; if( m_my_contact->m_url[0].url_port ) s << ":" << m_my_contact->m_url[0].url_port ; m_my_via.assign( s.str().c_str(), s.str().length() ) ; DR_LOG(log_debug) << "My via header: " << m_my_via << endl ; m_pDialogController = boost::make_shared<SipDialogController>( this, &m_clone ) ; /* sofia event loop */ DR_LOG(log_notice) << "Starting sofia event loop in main thread: " << boost::this_thread::get_id() << endl ; /* start a timer */ m_timer = su_timer_create( su_root_task(m_root), 30000) ; su_timer_set_for_ever(m_timer, watchdogTimerHandler, this) ; su_root_run( m_root ) ; DR_LOG(log_notice) << "Sofia event loop ended" << endl ; su_root_destroy( m_root ) ; m_root = NULL ; su_home_unref( m_home ) ; su_deinit() ; m_Config.reset(); this->deinitializeLogging() ; }
int nua_stack_init(su_root_t *root, nua_t *nua) { su_home_t *home; nua_handle_t *dnh; static int initialized_logs = 0; enter; if (!initialized_logs) { extern su_log_t tport_log[]; extern su_log_t nta_log[]; extern su_log_t nea_log[]; extern su_log_t iptsec_log[]; su_log_init(tport_log); su_log_init(nta_log); su_log_init(nea_log); su_log_init(iptsec_log); initialized_logs = 1; } nua->nua_root = root; nua->nua_timer = su_timer_create(su_root_task(root), NUA_STACK_TIMER_INTERVAL); if (!nua->nua_timer) return -1; home = nua->nua_home; nua->nua_handles_tail = &nua->nua_handles; sip_from_init(nua->nua_from); dnh = su_home_clone(nua->nua_home, sizeof (*dnh) + sizeof(*dnh->nh_prefs)); if (!dnh) return -1; dnh->nh_prefs = (void *)(dnh + 1); dnh->nh_valid = nua_valid_handle_cookie; dnh->nh_nua = nua; nua_handle_ref(dnh); dnh->nh_ref_by_stack = 1; nua_handle_ref(dnh); dnh->nh_ref_by_user = 1; nh_append(nua, dnh); dnh->nh_identity = dnh; dnh->nh_ds->ds_local = nua->nua_from; dnh->nh_ds->ds_remote = nua->nua_from; if (nua_stack_set_defaults(dnh, dnh->nh_prefs) < 0) return -1; if (nua_stack_set_params(nua, dnh, nua_i_none, nua->nua_args) < 0) return -1; nua->nua_invite_accept = sip_accept_make(home, SDP_MIME_TYPE); nua->nua_nta = nta_agent_create(root, NONE, NULL, NULL, NTATAG_MERGE_482(1), NTATAG_CLIENT_RPORT(1), NTATAG_UA(1), #if HAVE_SOFIA_SMIME NTATAG_SMIME(nua->sm), #endif TPTAG_STUN_SERVER(1), TAG_NEXT(nua->nua_args)); dnh->nh_ds->ds_leg = nta_leg_tcreate(nua->nua_nta, nua_stack_process_request, dnh, NTATAG_NO_DIALOG(1), TAG_END()); if (nua->nua_nta == NULL || dnh->nh_ds->ds_leg == NULL || nta_agent_set_params(nua->nua_nta, NTATAG_UA(1), TAG_END()) < 0 || nua_stack_init_transport(nua, nua->nua_args) < 0) { SU_DEBUG_1(("nua: initializing SIP stack failed\n")); return -1; } if (nua_stack_set_from(nua, 1, nua->nua_args) < 0) return -1; if (nua->nua_prefs->ngp_detect_network_updates) nua_stack_launch_network_change_detector(nua); nua_stack_timer(nua, nua->nua_timer, NULL); return 0; }
TimerQueue::TimerQueue(su_root_t* root, const char* szName) : m_root(root), m_head(NULL), m_tail(NULL), m_length(0), m_in_timer(0) { m_name.assign( szName ? szName : "timer") ; m_timer = su_timer_create(su_root_task(m_root), NTA_SIP_T1 / 8 ) ; }