📄 nua_dialog.c
字号:
} return NULL;}/** @internal Remove dialog usage. */void nua_dialog_usage_remove(nua_owner_t *own, nua_dialog_state_t *ds, nua_dialog_usage_t *du, nua_client_request_t *cr, nua_server_request_t *sr){ nua_dialog_usage_t **at; assert(own); assert(ds); assert(du); for (at = &ds->ds_usage; *at; at = &(*at)->du_next) if (du == *at) break; assert(*at); nua_dialog_usage_remove_at(own, ds, at, cr, sr);}/** @internal Remove dialog usage. * * Zap dialog state (leg, tag and route) if no usages remain. */static void nua_dialog_usage_remove_at(nua_owner_t *own, nua_dialog_state_t *ds, nua_dialog_usage_t **at, nua_client_request_t *cr0, nua_server_request_t *sr0){ if (*at) { nua_dialog_usage_t *du = *at; sip_event_t const *o = NULL; nua_client_request_t *cr, *cr_next; nua_server_request_t *sr, *sr_next; *at = du->du_next; o = du->du_event; SU_DEBUG_5(("nua(%p): removing %s usage%s%s\n", (void *)own, nua_dialog_usage_name(du), o ? " with event " : "", o ? o->o_type :"")); du->du_class->usage_remove(own, ds, du, cr0, sr0); /* Destroy saved client request */ if (cr0 != du->du_cr && nua_client_is_bound(du->du_cr)) { nua_client_bind(cr = du->du_cr, NULL); if (nua_client_is_queued(cr)) nua_client_request_complete(cr); else if (nua_client_is_reporting(cr)) ; else nua_client_request_destroy(cr); } /* Clean references from queued client requests */ for (cr = ds->ds_cr; cr; cr = cr_next) { cr_next = cr->cr_next; if (cr->cr_usage == du) cr->cr_usage = NULL; } for (sr = ds->ds_sr; sr; sr = sr_next) { sr_next = sr->sr_next; if (sr->sr_usage == du) { if (sr != sr0) nua_server_request_destroy(sr); sr->sr_usage = NULL; } } su_home_unref(own); su_free(own, du); } /* Zap dialog if there are no more usages */ if (ds->ds_terminating) ; else if (ds->ds_usage == NULL) { nua_dialog_remove(own, ds, NULL); ds->ds_has_events = 0; return; } else { nua_dialog_log_usage(own, ds); }}staticvoid nua_dialog_log_usage(nua_owner_t *own, nua_dialog_state_t *ds){ nua_dialog_usage_t *du; if (SU_LOG->log_level >= 3) { char buffer[160]; size_t l = 0, N = sizeof buffer; ssize_t n; buffer[0] = '\0'; for (du = ds->ds_usage; du; du = du->du_next) { msg_header_t const *h = (void *)du->du_event; if (!h) continue; n = sip_event_e(buffer + l, N - l, h, 0); if (n == -1) break; l += (size_t)n; if (du->du_next && l + 2 < sizeof(buffer)) { strcpy(buffer + l, ", "); l += 2; } } SU_DEBUG_3(("nua(%p): handle with %s%s%s\n", (void *)own, ds->ds_has_session ? "session and " : "", ds->ds_has_events ? "events " : "", buffer)); }}/** Deinitialize dialog and its usage. @internal */void nua_dialog_deinit(nua_owner_t *own, nua_dialog_state_t *ds){ ds->ds_terminating = 1; while (ds->ds_usage) { nua_dialog_usage_remove_at(own, ds, &ds->ds_usage, NULL, NULL); } nua_dialog_remove(own, ds, NULL); ds->ds_has_events = 0; ds->ds_terminating = 0;}void nua_dialog_update_params(nua_dialog_state_t *ds, nua_handle_preferences_t const *changed, nua_handle_preferences_t const *params, nua_handle_preferences_t const *defaults){ nua_dialog_usage_t *usage; for (usage = ds->ds_usage; usage; usage = usage->du_next) { usage->du_class->usage_update_params(usage, changed, params, defaults); }}void nua_base_usage_update_params(nua_dialog_usage_t const *du, nua_handle_preferences_t const *changed, nua_handle_preferences_t const *params, nua_handle_preferences_t const *defaults){ (void)du, (void)changed, (void)params, (void)defaults;}/**@internal * Set refresh value suitably. * * The refresh time is set either around half of the @a delta interval or, * if @a delta is less than 5 minutes but longer than 90 seconds, 30..60 * seconds before end of interval. * * If @a delta is 0, the dialog usage is never refreshed. */void nua_dialog_usage_set_refresh(nua_dialog_usage_t *du, unsigned delta){ if (delta == 0) nua_dialog_usage_reset_refresh(du); else if (delta > 90 && delta < 5 * 60) /* refresh 30..60 seconds before deadline */ nua_dialog_usage_set_refresh_range(du, delta - 60, delta - 30); else { /* By default, refresh around half time before deadline */ unsigned min = (delta + 2) / 4; unsigned max = (delta + 2) / 4 + (delta + 1) / 2; if (min == 0) min = 1; nua_dialog_usage_set_refresh_range(du, min, max); }}/**@internal Set refresh in range min..max seconds in the future. */void nua_dialog_usage_set_refresh_range(nua_dialog_usage_t *du, unsigned min, unsigned max){ sip_time_t now = sip_now(), target; unsigned delta; if (max < min) max = min; if (min != max) delta = su_randint(min, max); else delta = min; if (now + delta >= now) target = now + delta; else target = SIP_TIME_MAX; SU_DEBUG_7(("nua(): refresh %s after %lu seconds (in [%u..%u])\n", nua_dialog_usage_name(du), target - now, min, max)); du->du_refquested = now; nua_dialog_usage_set_refresh_at(du, target);}/** Set absolute refresh time */void nua_dialog_usage_set_refresh_at(nua_dialog_usage_t *du, sip_time_t target){ SU_DEBUG_7(("nua(): refresh %s after %lu seconds\n", nua_dialog_usage_name(du), target - sip_now())); du->du_refresh = target;} /**@internal Do not refresh. */void nua_dialog_usage_reset_refresh(nua_dialog_usage_t *du){ if (du) { du->du_refquested = sip_now(); du->du_refresh = 0; }}/** @internal Refresh usage. */void nua_dialog_usage_refresh(nua_owner_t *owner, nua_dialog_state_t *ds, nua_dialog_usage_t *du, sip_time_t now){ assert(du && du->du_class->usage_refresh); du->du_class->usage_refresh(owner, ds, du, now);}/** Terminate all dialog usages gracefully. */int nua_dialog_shutdown(nua_owner_t *owner, nua_dialog_state_t *ds){ nua_dialog_usage_t *du; ds->ds_terminating = 1; do { for (du = ds->ds_usage; du; du = du->du_next) { if (!du->du_shutdown) { nua_dialog_usage_shutdown(owner, ds, du); break; } } } while (du); return 1;}/** Shutdown (gracefully terminate) usage. * * @retval >0 shutdown done * @retval 0 shutdown in progress * @retval <0 try again later */int nua_dialog_usage_shutdown(nua_owner_t *owner, nua_dialog_state_t *ds, nua_dialog_usage_t *du){ if (du) { nua_dialog_usage_reset_refresh(du); du->du_shutdown = 1; assert(du->du_class->usage_shutdown); return du->du_class->usage_shutdown(owner, ds, du); } else return 200;}/** Repeat shutdown of all usages. * * @note Caller must have a reference to nh */int nua_dialog_repeat_shutdown(nua_owner_t *owner, nua_dialog_state_t *ds){ nua_dialog_usage_t *du; nua_server_request_t *sr, *sr_next; for (sr = ds->ds_sr; sr; sr = sr_next) { sr_next = sr->sr_next; if (nua_server_request_is_pending(sr)) { SR_STATUS1(sr, SIP_410_GONE); /* 410 terminates dialog */ nua_server_respond(sr, NULL); nua_server_report(sr); } } for (du = ds->ds_usage; du ;) { nua_dialog_usage_t *du_next = du->du_next; nua_dialog_usage_shutdown(owner, ds, du); if (du_next == NULL) break; for (du = ds->ds_usage; du; du = du->du_next) { if (du == du_next) break; else if (!du->du_shutdown) break; } } return ds->ds_usage != NULL;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -