void nh_destroy(nua_t *nua, nua_handle_t *nh) { assert(nh); assert(nh != nua->nua_dhandle); if (nh->nh_notifier) nea_server_destroy(nh->nh_notifier), nh->nh_notifier = NULL; while (nh->nh_ds->ds_cr) nua_client_request_complete(nh->nh_ds->ds_cr); while (nh->nh_ds->ds_sr) nua_server_request_destroy(nh->nh_ds->ds_sr); nua_dialog_deinit(nh, nh->nh_ds); if (nh_is_inserted(nh)) nh_remove(nua, nh); nua_handle_unref(nh); /* Remove stack reference */ }
/**@internal * Relay response event to the application. * * @todo * If handle has already been marked as destroyed by nua_handle_destroy(), * release the handle with nh_destroy(). * * @retval 0 if event was preliminary * @retval 1 if event was final * @retval 2 if event destroyed the handle, too. */ int nua_base_client_response(nua_client_request_t *cr, int status, char const *phrase, sip_t const *sip, tagi_t const *tags) { nua_handle_t *nh = cr->cr_owner; sip_method_t method = cr->cr_method; nua_dialog_usage_t *du; cr->cr_reporting = 1, nh->nh_ds->ds_reporting = 1; if (nh->nh_auth && sip && (sip->sip_authentication_info || sip->sip_proxy_authentication_info)) { /* Collect nextnonce */ if (sip->sip_authentication_info) auc_info(&nh->nh_auth, sip->sip_authentication_info, sip_authorization_class); if (sip->sip_proxy_authentication_info) auc_info(&nh->nh_auth, sip->sip_proxy_authentication_info, sip_proxy_authorization_class); } if ((method != sip_method_invite && status >= 200) || status >= 300) nua_client_request_remove(cr); nua_client_report(cr, status, phrase, sip, cr->cr_orq, tags); if (status < 200 || /* Un-ACKed 2XX response to INVITE */ (method == sip_method_invite && status < 300 && !cr->cr_acked)) { cr->cr_reporting = 0, nh->nh_ds->ds_reporting = 0; return 1; } nua_client_request_clean(cr); du = cr->cr_usage; if (cr->cr_terminated < 0) { /* XXX - dialog has been terminated */; nua_dialog_deinit(nh, nh->nh_ds), cr->cr_usage = NULL; } else if (du) { if (cr->cr_terminated || (!du->du_ready && status >= 300 && nua_client_is_bound(cr))) { /* Usage has been destroyed */ nua_dialog_usage_remove(nh, nh->nh_ds, du, cr, NULL), cr->cr_usage = NULL; } else if (cr->cr_graceful) { /* Terminate usage gracefully */ if (nua_dialog_usage_shutdown(nh, nh->nh_ds, du) > 0) cr->cr_usage = NULL; } } else if (cr->cr_terminated) { if (nh->nh_ds->ds_usage == NULL) nua_dialog_remove(nh, nh->nh_ds, NULL), cr->cr_usage = NULL; } cr->cr_phrase = NULL; cr->cr_reporting = 0, nh->nh_ds->ds_reporting = 0; if (method == sip_method_cancel) return 1; return nua_client_next_request(nh->nh_ds->ds_cr, method == sip_method_invite); }