⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 nua_session.c

📁 Sofia SIP is an open-source SIP User-Agent library, compliant with the IETF RFC3261 specification.
💻 C
📖 第 1 页 / 共 5 页
字号:
  }    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 + -