/** 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); } }
static su_duration_t nua_dialog_usage_get_max_defer(nua_dialog_usage_t *du) { nua_handle_t const *nh = (nua_handle_t *)du->du_dialog->ds_owner; nua_t const *nua = nh->nh_nua; if (nua->nua_prefs->ngp_deferrable_timers) return su_root_get_max_defer(nua->nua_root); else return 0; }
/** Main function for clone thread. * * @internal */ static void *su_pthread_port_clone_main(void *varg) { struct clone_args *arg = (struct clone_args *)varg; su_task_r task; int zap = 1; #if SU_HAVE_WINSOCK su_init(); #endif task->sut_port = arg->create(); if (task->sut_port) { task->sut_root = su_salloc(su_port_home(task->sut_port), sizeof *task->sut_root); if (task->sut_root) { task->sut_root->sur_threading = 1; /* By default */ SU_TASK_COPY(task->sut_root->sur_parent, su_root_task(arg->parent), su_pthread_port_clone_main); SU_TASK_COPY(task->sut_root->sur_task, task, su_pthread_port_clone_main); if (su_msg_create(arg->clone, task, su_root_task(arg->parent), su_pthread_port_clone_break, 0) == 0) { task->sut_root->sur_magic = arg->magic; task->sut_root->sur_deinit = arg->deinit; su_root_set_max_defer(task->sut_root, su_root_get_max_defer(arg->parent)); if (arg->init(task->sut_root, arg->magic) == 0) { su_pthread_port_return_to_parent(arg, 0), arg = NULL; su_root_run(task->sut_root); /* Do the work */ /* Cleanup */ if (task->sut_port->sup_waiting_parent) { struct su_pthread_port_waiting_parent *mom; mom = task->sut_port->sup_waiting_parent; pthread_mutex_lock(mom->mutex); mom->waiting = 0; pthread_cond_signal(mom->cv); pthread_mutex_unlock(mom->mutex); pthread_mutex_lock(mom->deinit); su_port_getmsgs(task->sut_port); pthread_mutex_unlock(mom->deinit); } else zap = 0; } else su_msg_destroy(arg->clone); su_root_destroy(task->sut_root); } } task->sut_port->sup_base->sup_vtable-> su_port_decref(task->sut_port, zap, "su_pthread_port_clone_main"); } #if SU_HAVE_WINSOCK su_deinit(); #endif if (arg) su_pthread_port_return_to_parent(arg, -1); return NULL; /* Exit from thread */ }