/** @internal Create a handle for processing incoming request */ nua_handle_t *nua_stack_incoming_handle(nua_t *nua, nta_incoming_t *irq, sip_t const *sip, int create_dialog) { nua_handle_t *nh; url_t const *url; sip_to_t to[1]; sip_from_t from[1]; assert(sip && sip->sip_from && sip->sip_to); if (sip->sip_contact) url = sip->sip_contact->m_url; else url = sip->sip_from->a_url; /* Strip away parameters */ sip_from_init(from)->a_display = sip->sip_to->a_display; *from->a_url = *sip->sip_to->a_url; sip_to_init(to)->a_display = sip->sip_from->a_display; *to->a_url = *sip->sip_from->a_url; nh = nh_create(nua, NUTAG_URL((url_string_t *)url), /* Remote target */ SIPTAG_TO(to), /* Local AoR */ SIPTAG_FROM(from), /* Remote AoR */ TAG_END()); if (nh && nua_stack_init_handle(nua, nh, NULL) < 0) nh_destroy(nua, nh), nh = NULL; if (nh && create_dialog) { struct nua_dialog_state *ds = nh->nh_ds; nua_dialog_store_peer_info(nh, ds, sip); ds->ds_leg = nta_leg_tcreate(nua->nua_nta, nua_stack_process_request, nh, SIPTAG_CALL_ID(sip->sip_call_id), SIPTAG_FROM(sip->sip_to), SIPTAG_TO(sip->sip_from), NTATAG_REMOTE_CSEQ(sip->sip_cseq->cs_seq), TAG_END()); if (!ds->ds_leg || !nta_leg_tag(ds->ds_leg, nta_incoming_tag(irq, NULL))) nh_destroy(nua, nh), nh = NULL; } if (nh) nua_dialog_uas_route(nh, nh->nh_ds, sip, 1); return nh; }
/** Remove dialog information. */ int nua_dialog_zap(nua_owner_t *own, nua_dialog_state_t *ds) { /* zap peer info */ nua_dialog_store_peer_info(own, ds, NULL); /* Local Contact */ msg_header_free(own, (msg_header_t *)ds->ds_ltarget), ds->ds_ltarget = NULL; /* Leg */ nta_leg_destroy(ds->ds_leg), ds->ds_leg = NULL; /* Remote tag */ su_free(own, (void *)ds->ds_remote_tag), ds->ds_remote_tag = NULL; /* Ready to set route/remote target */ ds->ds_route = 0; return 0; }
/** Process response to the client request. * * The response can be generated by the stack (@a sip is NULL) or * returned by the remote server. * * @retval 0 if response event was preliminary * @retval 1 if response event was final * @retval 2 if response event destroyed the handle, too. */ int nua_client_response(nua_client_request_t *cr, int status, char const *phrase, sip_t const *sip) { nua_handle_t *nh = cr->cr_owner; nua_dialog_usage_t *du = cr->cr_usage; int retval = 0; if (cr->cr_restarting) return 0; nua_client_request_ref(cr); cr->cr_status = status; cr->cr_phrase = phrase; if (status < 200) { /* Xyzzy */ } else if (sip && nua_client_check_restart(cr, status, phrase, sip)) { nua_client_request_unref(cr); return 0; } else if (status < 300) { if (cr->cr_terminating) { cr->cr_terminated = 1; } else { if (sip) { if (cr->cr_contactize) nua_dialog_uac_route(nh, nh->nh_ds, sip, 1, cr->cr_initial); nua_dialog_store_peer_info(nh, nh->nh_ds, sip); } if (du && du->du_cr == cr) du->du_ready = 1; } } else { sip_method_t method = cr->cr_method; int terminated, graceful = 1; if (status < 700) terminated = sip_response_terminates_dialog(status, method, &graceful); else /* XXX - terminate usage by all internal error responses */ terminated = 0, graceful = 1; if (terminated < 0) cr->cr_terminated = terminated; else if (cr->cr_terminating || terminated) cr->cr_terminated = 1; else if (graceful) cr->cr_graceful = 1; } if (status < 200) { if (cr->cr_methods->crm_preliminary) cr->cr_methods->crm_preliminary(cr, status, phrase, sip); else nua_base_client_response(cr, status, phrase, sip, NULL); cr->cr_phrase = NULL; } else { if (cr->cr_methods->crm_recv) retval = cr->cr_methods->crm_recv(cr, status, phrase, sip); else retval = nua_base_client_response(cr, status, phrase, sip, NULL); } nua_client_request_unref(cr); return retval; }