📄 nua_session.c
字号:
} nua_dialog_usage_remove(nh, ds, du, NULL, NULL); return 200;}/**@fn void nua_prack(nua_handle_t *nh, tag_type_t tag, tag_value_t value, ...); * Send a PRACK request. * * PRACK is used to acknowledge receipt of 100rel responses. See @RFC3262. * * @param nh Pointer to operation handle * @param tag, value, ... List of tagged parameters * * @return * nothing * * @par Related Tags: * Tags in <sofia-sip/soa_tag.h>, <sofia-sip/sip_tag.h>. * * @par Events: * #nua_r_prack *//** @NUA_EVENT nua_r_prack * * Response to an outgoing @b PRACK request. PRACK request is used to * acknowledge reliable preliminary responses and it is usually sent * automatically by the nua stack. * * @param status response status code * (if the request is retried, @a status is 100, the @a * sip->sip_status->st_status contain the real status code * from the response message, e.g., 302, 401, or 407) * @param phrase a short textual description of @a status code * @param nh operation handle associated with the call * @param hmagic application context associated with the call * @param sip response to @b PRACK or NULL upon an error * (status code is in @a status and * descriptive message in @a phrase parameters) * @param tags empty * * @sa nua_prack(), #nua_i_prack, @RFC3262 * * @END_NUA_EVENT */static int nua_prack_client_init(nua_client_request_t *cr, msg_t *msg, sip_t *sip, tagi_t const *tags);static int nua_prack_client_request(nua_client_request_t *cr, msg_t *msg, sip_t *sip, tagi_t const *tags);static int nua_prack_client_response(nua_client_request_t *cr, int status, char const *phrase, sip_t const *sip);static int nua_prack_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_client_methods_t const nua_prack_client_methods = { SIP_METHOD_PRACK, /* crm_method, crm_method_name */ 0, /* crm_extra */ { /* crm_flags */ /* create_dialog */ 0, /* in_dialog */ 1, /* target refresh */ 0 }, NULL, /* crm_template */ nua_prack_client_init, /* crm_init */ nua_prack_client_request, /* crm_send */ NULL, /* crm_check_restart */ nua_prack_client_response, /* crm_recv */ NULL, /* crm_preliminary */ nua_prack_client_report, /* crm_report */ NULL, /* crm_complete */};int nua_stack_prack(nua_t *nua, nua_handle_t *nh, nua_event_t e, tagi_t const *tags){ return nua_client_create(nh, e, &nua_prack_client_methods, tags);}static int nua_prack_client_init(nua_client_request_t *cr, msg_t *msg, sip_t *sip, tagi_t const *tags){ nua_handle_t *nh = cr->cr_owner; nua_dialog_usage_t *du = nua_dialog_usage_for_session(nh->nh_ds); cr->cr_usage = du; return 0;}static int nua_prack_client_request(nua_client_request_t *cr, msg_t *msg, sip_t *sip, tagi_t const *tags){ nua_handle_t *nh = cr->cr_owner; nua_dialog_usage_t *du = cr->cr_usage; nua_session_usage_t *ss; nua_client_request_t *cri; int offer_sent = 0, answer_sent = 0, retval; int status = 0; char const *phrase = "PRACK Sent"; uint32_t rseq = 0; if (du == NULL) /* Call terminated */ return nua_client_return(cr, SIP_481_NO_TRANSACTION, msg); ss = NUA_DIALOG_USAGE_PRIVATE(du); if (ss->ss_state >= nua_callstate_terminating) return nua_client_return(cr, 900, "Session is terminating", msg); cri = du->du_cr; if (sip->sip_rack) rseq = sip->sip_rack->ra_response; if (cri->cr_offer_recv && !cri->cr_answer_sent) { if (nh->nh_soa == NULL) /* It is up to application to handle SDP */ answer_sent = session_get_description(sip, NULL, NULL); else if (sip->sip_payload) /* XXX - we should just do MIME in session_include_description() */; else if (soa_generate_answer(nh->nh_soa, NULL) < 0 || session_include_description(nh->nh_soa, 1, msg, sip) < 0) { status = soa_error_as_sip_response(nh->nh_soa, &phrase); SU_DEBUG_3(("nua(%p): local response to PRACK: %d %s\n", (void *)nh, status, phrase)); nua_stack_event(nh->nh_nua, nh, NULL, nua_i_media_error, status, phrase, NULL); return nua_client_return(cr, status, phrase, msg); } else { answer_sent = 1; soa_activate(nh->nh_soa, NULL); } } else if (nh->nh_soa == NULL) { offer_sent = session_get_description(sip, NULL, NULL); } /* When 100rel response status was 183 do support for preconditions */ else if (cri->cr_status == 183 && ss->ss_precondition) { if (soa_generate_offer(nh->nh_soa, 0, NULL) < 0 || session_include_description(nh->nh_soa, 1, msg, sip) < 0) { status = soa_error_as_sip_response(nh->nh_soa, &phrase); SU_DEBUG_3(("nua(%p): PRACK offer: %d %s\n", (void *)nh, status, phrase)); nua_stack_event(nh->nh_nua, nh, NULL, nua_i_media_error, status, phrase, NULL); return nua_client_return(cr, status, phrase, msg); } else { offer_sent = 1; } } retval = nua_base_client_request(cr, msg, sip, NULL); if (retval == 0) { cr->cr_offer_sent = offer_sent; cr->cr_answer_sent = answer_sent; if (offer_sent) ss->ss_oa_sent = Offer; else if (answer_sent) ss->ss_oa_sent = Answer; if (cr->cr_restarting) /* Restart logic calls nua_prack_client_report */; else if (!cr->cr_auto && (!offer_sent || !answer_sent)) /* Suppose application know it called nua_prack() */; else signal_call_state_change(nh, ss, status, phrase, ss->ss_state); } return retval;}static int nua_prack_client_response(nua_client_request_t *cr, int status, char const *phrase, sip_t const *sip){ /* XXX - fatal error cases? */ return nua_session_client_response(cr, status, phrase, sip);}static int nua_prack_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_usage_t *du = cr->cr_usage; nua_session_usage_t *ss = nua_dialog_usage_private(du); nua_stack_event(nh->nh_nua, nh, nta_outgoing_getresponse(orq), cr->cr_event, status, phrase, tags); if (!ss || cr->cr_terminated || cr->cr_graceful || cr->cr_waiting) return 1; if (cr->cr_offer_sent || cr->cr_answer_sent) { unsigned next_state = ss->ss_state; if (status < 200) ; else if (du->du_cr && du->du_cr->cr_orq && du->du_cr->cr_status >= 200) { /* There is an un-ACK-ed INVITE there */ assert(du->du_cr->cr_method == sip_method_invite); 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))) { /* No UPDATE with offer/answer if PRACK with offer/answer was ongoing! */ if (nua_invite_client_ack(du->du_cr, NULL) > 0) next_state = nua_callstate_ready; else next_state = nua_callstate_terminating; } } signal_call_state_change(nh, ss, status, phrase, next_state); } if (ss->ss_update_needed && 200 <= status && status < 300 && !SIP_IS_ALLOWED(NH_PGET(nh, appl_method), sip_method_update)) nua_client_create(nh, nua_r_update, &nua_update_client_methods, NULL); return 1;}/* ---------------------------------------------------------------------- *//* UAS side of INVITE *//** @NUA_EVENT nua_i_invite * * Indication of incoming call or re-INVITE request. * * @param status statuscode of response sent automatically by stack * @param phrase a short textual description of @a status code * @param nh operation handle associated with this call * (maybe created for this call) * @param hmagic application context associated with this call * (maybe NULL if call handle was created for this call) * @param sip incoming INVITE request * @param tags SOATAG_ACTIVE_AUDIO(), SOATAG_ACTIVE_VIDEO() * * @par * @par Responding to INVITE with nua_respond() * * If @a status in #nua_i_invite event is below 200, the application should * accept or reject the call with nua_respond(). See the @ref nua_call_model * for the detailed explanation of various options in call processing at * server end. * * The @b INVITE request takes care of session setup using SDP Offer-Answer * negotiation as specified in @RFC3264 (updated in @RFC3262 section 5, * @RFC3311, and @RFC3312). The Offer-Answer can be taken care by * application (if NUTAG_MEDIA_ENABLE(0) parameter has been set) or by the * built-in SDP Offer/Answer engine @soa (by default and when * NUTAG_MEDIA_ENABLE(1) parameter has been set). When @soa is enabled, it * will take care of parsing the SDP, negotiating the media and codecs, and * including the SDP in the SIP message bodies as required by the * Offer-Answer model. * * When @soa is enabled, the SDP in the incoming INVITE is parsed and feed * to a #soa_session_t object. The #nua_i_state event sent to the * application immediately after #nua_i_invite will contain the parsing * results in SOATAG_REMOTE_SDP() and SOATAG_REMOTE_SDP_STR() tags. * * Note that currently the parser within @nua does not handle MIME * multipart. The SDP Offer/Answer engine can get confused if the SDP offer * is included in a MIME multipart, therefore such an @b INVITE is rejected * with <i>415 Unsupported Media Type</i> error response: the client is * expected to retry the INVITE without MIME multipart content. * * If the call is to be accepted, the application should include the SDP in * the 2XX response. If @soa is not disabled with NUTAG_MEDIA_ENABLE(0), the * SDP should be included in the SOATAG_USER_SDP() or SOATAG_USER_SDP_STR() * parameter given to nua_respond(). If it is disabled, the SDP should be * included in the response message using SIPTAG_PAYLOAD() or * SIPTAG_PAYLOAD_STR(). Also, the @ContentType should be set using * SIPTAG_CONTENT_TYPE() or SIPTAG_CONTENT_TYPE_STR(). * * @par Preliminary Responses and 100rel * * Call progress can be signaled with preliminary responses (with status * code in the range 101..199). It is possible to conclude the SDP * Offer-Answer negotiation using preliminary responses, too. If * NUTAG_EARLY_ANSWER(1), SOATAG_USER_SDP() or SOATAG_USER_SDP_STR() * parameter is included with in a preliminary nua_response(), the SDP * answer is generated and sent with the preliminary responses, too. * * The preliminary responses are sent reliably if feature tag "100rel" is * included in the @Require header of the response or if * NUTAG_EARLY_MEDIA(1) parameter has been given. The reliably delivery of * preliminary responses mean that a sequence number is included in the * @RSeq header in the response message and the response message is resent * until the client responds with a @b PRACK request with matching sequence * number in @RAck header. * * Note that only the "183" response is sent reliably if the * NUTAG_ONLY183_100REL(1) parameter has been given. The reliable * preliminary responses are acknowledged with @b PRACK request sent by the * client. * * Note if the SDP offer-answer is completed with the reliable preliminary * responses, the is no need to include SDP in 200 OK response (or other 2XX * response). However, it the tag NUTAG_INCLUDE_EXTRA_SDP(1) is included * with nua_respond(), a copy of the SDP answer generated earlier by @soa is * included as the message body. * * @sa nua_respond(), @ref nua_uas_call_model, #nua_i_state, * NUTAG_MEDIA_ENABLE(), SOATAG_USER_SDP(), SOATAG_USER_SDP_STR(), * @RFC3262, NUTAG_EARLY_ANSWER(), NUTAG_EARLY_MEDIA(), * NUTAG_ONLY183_100REL(), * NUTAG_INCLUDE_EXTRA_SDP(), * #nua_i_prack, #nua_i_update, nua_update(), * nua_invite(), #nua_r_invite * * @par * @par Third Party Call Control * * When so called 2rd party call control is used, the initial @b INVITE may * not contain SDP offer. In that case, the offer is sent by the recipient * of the @b INVITE request (User-Agent Server, UAS). The SDP sent in 2XX * response (or in a preliminary reliable response) is considered as an * offer, and the answer will be included in the @b ACK request sent by the * UAC (or @b PRACK in case of preliminary reliable response). * * @sa @ref nua_3pcc_call_model * * @END_NUA_EVENT */static int nua_invite_server_init(nua_server_request_t *sr);static int nua_session_server_init(nua_server_request_t *sr);static int nua_invite_server_preprocess(nua_server_request_t *sr);static int nua_invite_server_respond(nua_server_request_t *sr, tagi_t const *);static int nua_invite_server_is_100rel(nua_server_request_t *, tagi_t const *);static int nua_invite_server_report(nua_server_request_t *sr, tagi_t const *);static int process_ack_or_cancel(nua_server_request_t *, nta_incoming_t *, sip_t const *), process_ack(nua_server_request_t *, nta_incoming_t *, sip_t const *), process_cancel(nua_server_request_t *, nta_incoming_t *, sip_t const *), process_timeout(nua_server_request_t *, nta_incoming_t *), process_prack(nua_server_request_t *, nta_reliable_t *rel, nta_incoming_t *irq, sip_t const *sip);nua_server_methods_t const nua_invite_server_methods = { SIP_METHOD_INVITE, nua_i_invite, /* Event */ { 1, /* Create dialog */ 0, /* Initial request */ 1, /* Target refresh request */ 1, /* Add Contact */ }, nua_invite_server_init, nua_invite_server_preprocess, nua_base_server_params, nua_invite_server_respond, nua_invite_server_report, };/** @internal Preprocess incoming invite - sure we have a valid request. * * @return 0 if request is valid, or error statuscode otherwise */static intnua_invite_server_init(nua_server_request_t *sr){ nua_handle_t *nh = sr->sr_owner; nua_t *nua
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -