📄 nua_session.c
字号:
ss->ss_update_needed = ss->ss_100rel = 1; if (nh->nh_soa) { soa_init_offer_answer(nh->nh_soa); if (sip->sip_payload) offer_sent = 0; /* XXX - kludge */ else if (soa_generate_offer(nh->nh_soa, 0, NULL) < 0) return -1; else offer_sent = 1; if (offer_sent > 0 && session_include_description(nh->nh_soa, 1, msg, sip) < 0) return nua_client_return(cr, 900, "Internal media error", msg); if (NH_PGET(nh, media_features) && !nua_dialog_is_established(nh->nh_ds) && !sip->sip_accept_contact && !sip->sip_reject_contact) { sip_accept_contact_t ac[1]; sip_accept_contact_init(ac); ac->cp_params = (msg_param_t *) soa_media_features(nh->nh_soa, 1, msg_home(msg)); if (ac->cp_params) { msg_header_replace_param(msg_home(msg), ac->cp_common, "explicit"); sip_add_dup(msg, sip, (sip_header_t *)ac); } } } else { offer_sent = session_get_description(sip, NULL, NULL); } retval = nua_base_client_trequest(cr, msg, sip, NTATAG_REL100(ss->ss_100rel), TAG_NEXT(tags)); if (retval == 0) { if ((cr->cr_offer_sent = offer_sent)) ss->ss_oa_sent = Offer; if (!cr->cr_restarting) /* Restart logic calls nua_invite_client_report */ signal_call_state_change(nh, ss, 0, "INVITE sent", nua_callstate_calling); } return retval;}static int nua_invite_client_response(nua_client_request_t *cr, int status, char const *phrase, sip_t const *sip){ nua_dialog_usage_t *du = cr->cr_usage; nua_session_usage_t *ss = nua_dialog_usage_private(du); if (ss == NULL || sip == NULL) { /* Xyzzy */ } else if (status < 300) { du->du_ready = 1; if (session_timer_is_supported(ss->ss_timer)) session_timer_store(ss->ss_timer, sip); session_timer_set(ss); } return nua_session_client_response(cr, status, phrase, sip);}static int nua_invite_client_preliminary(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; nua_session_usage_t *ss = nua_dialog_usage_private(du); assert(sip); if (ss && sip && sip->sip_rseq) { /* Handle 100rel responses */ sip_rseq_t *rseq = sip->sip_rseq; /* Establish early dialog - we should fork here */ if (!nua_dialog_is_established(nh->nh_ds)) { nta_outgoing_t *tagged; nua_dialog_uac_route(nh, nh->nh_ds, sip, 1); nua_dialog_store_peer_info(nh, nh->nh_ds, sip); /* Tag the INVITE request */ tagged = nta_outgoing_tagged(cr->cr_orq, nua_client_orq_response, cr, sip->sip_to->a_tag, sip->sip_rseq); if (tagged) { nta_outgoing_destroy(cr->cr_orq), cr->cr_orq = tagged; } else { cr->cr_graceful = 1; ss->ss_reason = "SIP;cause=500;text=\"Cannot Create Early Dialog\""; } } if (!rseq) { SU_DEBUG_5(("nua(%p): 100rel missing RSeq\n", (void *)nh)); } else if (nta_outgoing_rseq(cr->cr_orq) > rseq->rs_response) { SU_DEBUG_5(("nua(%p): 100rel bad RSeq %u (got %u)\n", (void *)nh, (unsigned)rseq->rs_response, nta_outgoing_rseq(cr->cr_orq))); return 1; /* Do not send event */ } else if (nta_outgoing_setrseq(cr->cr_orq, rseq->rs_response) < 0) { SU_DEBUG_1(("nua(%p): cannot set RSeq %u\n", (void *)nh, (unsigned)rseq->rs_response)); cr->cr_graceful = 1; ss->ss_reason = "SIP;cause=400;text=\"Bad RSeq\""; } } return nua_session_client_response(cr, status, phrase, sip);}/** Process response to a session request (INVITE, PRACK, UPDATE) */static int nua_session_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; nua_session_usage_t *ss = nua_dialog_usage_private(du); char const *sdp = NULL; size_t len; char const *received = NULL;#define LOG3(m) \ SU_DEBUG_3(("nua(%p): %s: %s %s in %u %s\n", \ (void *)nh, cr->cr_method_name, (m), \ received ? received : "SDP", status, phrase))#define LOG5(m) \ SU_DEBUG_5(("nua(%p): %s: %s %s in %u %s\n", \ (void *)nh, cr->cr_method_name, (m), received, status, phrase)) if (!ss || !sip || 300 <= status) /* Xyzzy */; else if (!session_get_description(sip, &sdp, &len)) /* No SDP */; else if (cr->cr_answer_recv) { /* Ignore spurious answers after completing O/A */ LOG3("ignoring duplicate"); sdp = NULL; } else if (cr->cr_offer_sent) { /* case 1: answer to our offer */ cr->cr_answer_recv = status; received = Answer; if (nh->nh_soa == NULL) LOG5("got SDP"); else if (soa_set_remote_sdp(nh->nh_soa, NULL, sdp, len) < 0) { LOG3("error parsing SDP"); sdp = NULL; cr->cr_graceful = 1; ss->ss_reason = "SIP;cause=400;text=\"Malformed Session Description\""; } else if (soa_process_answer(nh->nh_soa, NULL) < 0) { LOG5("error processing SDP"); /* XXX */ sdp = NULL; } else if (soa_activate(nh->nh_soa, NULL) < 0) /* XXX - what about errors? */ LOG3("error activating media after"); else LOG5("processed SDP"); } else if (cr->cr_method != sip_method_invite) { /* If non-invite request did not have offer, ignore SDP in response */ LOG3("ignoring extra"); sdp = NULL; } else { /* case 2: new offer */ cr->cr_offer_recv = 1, cr->cr_answer_sent = 0; received = Offer; if (nh->nh_soa && soa_set_remote_sdp(nh->nh_soa, NULL, sdp, len) < 0) { LOG3("error parsing SDP"); sdp = NULL; cr->cr_graceful = 1; ss->ss_reason = "SIP;cause=400;text=\"Malformed Session Description\""; } else LOG5("got SDP"); } if (ss && received) ss->ss_oa_recv = received; if (sdp && nh->nh_soa) return nua_base_client_tresponse(cr, status, phrase, sip, NH_REMOTE_MEDIA_TAGS(1, nh->nh_soa), TAG_END()); else return nua_base_client_response(cr, status, phrase, sip, NULL);}static int nua_invite_client_report(nua_client_request_t *cr, int status, char const *phrase, sip_t const *sip, nta_outgoing_t *orq, tagi_t const *tags){ nua_handle_t *nh = cr->cr_owner; nua_dialog_state_t *ds = nh->nh_ds; nua_dialog_usage_t *du = cr->cr_usage; nua_session_usage_t *ss = nua_dialog_usage_private(du); unsigned next_state; int error; nh_referral_respond(nh, status, phrase); /* XXX - restarting after 401/407 */ nua_stack_event(nh->nh_nua, nh, nta_outgoing_getresponse(orq), cr->cr_event, status, phrase, tags); if (cr->cr_waiting) /* Do not report call state change if waiting for restart */ return 1; if (ss == NULL) { signal_call_state_change(nh, ss, status, phrase, nua_callstate_terminated); return 1; } ss->ss_reporting = 1; if (cr->cr_neutral) { signal_call_state_change(nh, ss, status, phrase, ss->ss_state); ss->ss_reporting = 0; return 1; } if (orq != cr->cr_orq && cr->cr_orq) { /* Being restarted */ next_state = nua_callstate_calling; } else if (status == 100) { next_state = nua_callstate_calling; } else if (status < 300 && cr->cr_graceful) { next_state = nua_callstate_terminating; if (200 <= status) { nua_invite_client_ack(cr, NULL); } } else if (status < 200) { next_state = nua_callstate_proceeding; if (sip && sip->sip_rseq && !SIP_IS_ALLOWED(NH_PGET(nh, appl_method), sip_method_prack)) { sip_rack_t rack[1]; sip_rack_init(rack); rack->ra_response = sip->sip_rseq->rs_response; rack->ra_cseq = sip->sip_cseq->cs_seq; rack->ra_method = sip->sip_cseq->cs_method; rack->ra_method_name = sip->sip_cseq->cs_method_name; error = nua_client_tcreate(nh, nua_r_prack, &nua_prack_client_methods, SIPTAG_RACK(rack), TAG_END()); if (error < 0) { cr->cr_graceful = 1; next_state = nua_callstate_terminating; } } } else if (status < 300) { next_state = nua_callstate_completing; } else if (cr->cr_terminated) { next_state = nua_callstate_terminated; } else if (cr->cr_graceful && ss->ss_state >= nua_callstate_completing) { next_state = nua_callstate_terminating; } else { next_state = nua_callstate_init; } if (next_state == nua_callstate_calling) { if (sip && sip->sip_status && sip->sip_status->st_status == 100) { ss->ss_reporting = 0; return 1; } } if (next_state == nua_callstate_completing) { if (NH_PGET(nh, auto_ack) || /* Auto-ACK response to re-INVITE unless auto_ack is set to 0 */ (ss->ss_state == nua_callstate_ready && !NH_PISSET(nh, auto_ack))) { nua_client_request_t *cru; for (cru = ds->ds_cr; cru; cru = cru->cr_next) { if (cr != cru && cru->cr_offer_sent && !cru->cr_answer_recv) break; } if (cru) /* A final response to UPDATE or PRACK with answer on its way? */; else if (nua_invite_client_ack(cr, NULL) > 0) next_state = nua_callstate_ready; else next_state = nua_callstate_terminating; } } if (next_state == nua_callstate_terminating) { /* Send BYE or CANCEL */ /* XXX - Forking - send BYE to early dialog?? */ if (ss->ss_state > nua_callstate_proceeding || status >= 200) error = nua_client_create(nh, nua_r_bye, &nua_bye_client_methods, NULL); else error = nua_client_create(nh, nua_r_cancel, &nua_cancel_client_methods, tags); if (error) { next_state = nua_callstate_terminated; cr->cr_terminated = 1; } cr->cr_graceful = 0; } ss->ss_reporting = 0; signal_call_state_change(nh, ss, status, phrase, next_state); return 1;}/**@fn void nua_ack(nua_handle_t *nh, tag_type_t tag, tag_value_t value, ...); * * Acknowledge a succesful response to INVITE request. * * Acknowledge a successful response (200..299) to INVITE request with the * SIP ACK request message. This function is needed only if NUTAG_AUTOACK() * parameter has been cleared. * * @param nh Pointer to operation handle * @param tag, value, ... List of tagged parameters * * @return * nothing * * @par Related Tags: * Header tags defined in <sofia-sip/sip_tag.h> * * @par Events: * #nua_i_media_error \n * #nua_i_state (#nua_i_active, #nua_i_terminated) * * @sa NUTAG_AUTOACK(), @ref nua_call_model, #nua_i_state */int nua_stack_ack(nua_t *nua, nua_handle_t *nh, nua_event_t e, tagi_t const *tags){ nua_dialog_usage_t *du = nua_dialog_usage_for_session(nh->nh_ds); nua_session_usage_t *ss = nua_dialog_usage_private(du); nua_client_request_t *cr = du ? du->du_cr : NULL; int error; if (!cr || cr->cr_orq == NULL || cr->cr_status < 200) { UA_EVENT2(nua_i_error, 900, "No response to ACK"); return 1; } if (tags) { nua_stack_set_params(nua, nh, nua_i_error, tags); if (nh->nh_soa) soa_set_params(nh->nh_soa, TAG_NEXT(tags)); } error = nua_invite_client_ack(cr, tags); if (error < 0) { if (ss->ss_reason == NULL) ss->ss_reason = "SIP;cause=500;text=\"Internal Error\"";
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -