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

📄 nua_session.c

📁 Sofia SIP is an open-source SIP User-Agent library, compliant with the IETF RFC3261 specification.
💻 C
📖 第 1 页 / 共 5 页
字号:
			     sip_content_disposition_t **return_cd,			     sip_content_type_t **return_ct,			     sip_payload_t **return_pl);staticint nua_server_retry_after(nua_server_request_t *sr,			   int status, char const *phrase,			   int min, int max);/**@fn void nua_invite(nua_handle_t *nh, tag_type_t tag, tag_value_t value, ...); * * Place a call using SIP @b INVITE method.  * * The INVITE method is used to initiate a call between two parties. The * call is also known as <i>SIP session</i>. *  * At SIP level the session is represented as @e Dialog, which is a * peer-to-peer association between two SIP User-Agents. The dialog is * established by a successful 2XX response to the INVITE. The dialog is * terminated by BYE transaction, which application can initiate with * nua_bye() call. * * An @e early @e dialog is established by an preliminary response * (101..199), such as <i>180 Ringing</i>. An early dialog is terminated * with an error response with response code in range 300...699. * * The media session belonging to the SIP session is usually represented by * SDP, Session Description Protocol. The media session it is usually * established during the call set-up with procedure known as SDP * Offer/Answer exchange, defined by @RFC3264. See <b>Media Session * Handling</b> below for details. * * @param nh              Pointer to operation handle * @param tag, value, ... List of tagged parameters * * @return  *    nothing * * @par Events: *    #nua_r_invite \n *    #nua_i_state (#nua_i_active, #nua_i_terminated) \n *    #nua_i_media_error \n *    #nua_i_fork \n * * @par Tags: *   NUTAG_AUTH_CACHE() \n *   NUTAG_AUTOACK() \n *   NUTAG_AUTOANSWER() \n *   NUTAG_EARLY_MEDIA() \n *   NUTAG_ENABLEINVITE() \n *   NUTAG_INITIAL_ROUTE(), NUTAG_INITIAL_ROUTE_STR() \n *   NUTAG_INVITE_TIMER() \n *   NUTAG_MEDIA_ENABLE() \n *   NUTAG_MEDIA_FEATURES() \n *   NUTAG_MIN_SE() \n *   NUTAG_RETRY_COUNT() \n *   NUTAG_SERVICE_ROUTE_ENABLE() \n *   NUTAG_SESSION_REFRESHER() \n *   NUTAG_SESSION_TIMER() \n *   NUTAG_SOA_NAME() \n *   NUTAG_UPDATE_REFRESH() \n * * @par Populating SIP Request Message with Tagged Arguments * The tagged arguments can be used to pass values for any SIP headers to * the stack. When the INVITE message (or any other SIP message) is created, * the tagged values saved with nua_handle() are used first, next the tagged * values given with the operation (nua_invite()) are added. * * @par * When multiple tags for the same header are specified, the behaviour * depends on the header type. If only a single header field can be included * in a SIP message, the latest non-NULL value is used, e.g., @Subject.  * However, if the SIP header can consist of multiple lines or header fields * separated by comma, e.g., @Accept, all the tagged * values are concatenated. *  * @par * However, if a tag value is #SIP_NONE (-1 casted as a void pointer), the * values from previous tags are ignored. * * @par * Next, values previously set with nua_set_params() or nua_set_hparams() * are used: @Allow, @Supported, @Organization, and @UserAgent headers are * added to the request if they are not already set. * * @par * Now, the target URI for the request needs to be determined. * * @par * For initial INVITE requests, values from tags are used. If NUTAG_URL() is * given, it is used as target URI. Otherwise, if SIPTAG_TO() is given, it * is used as target URI. If neither is given, the complete request line * already specified using SIPTAG_REQUEST() or SIPTAG_REQUEST_STR() is used.  * If none of the tags above are given, an internal error is returned to the * application. At this point, the target URI is stored in the request line, * together with method name ("INVITE") and protocol version ("SIP/2.0").  * The initial dialog information is also created: @CallID, @CSeq headers * are generated, if they do not exist, and an unique tag is added to @From * header. * * @par * For the initial INVITE requests, the @Route headers specified by * SIPTAG_ROUTE()/SIPTAG_ROUTER_STR() tags in nua_handle() and nua_invite() * calls are inserted to the request. Next the initial route set specified * by NUTAG_INITIAL_ROUTE()/NUTAG_INITIAL_ROUTE_STR() tags is prepended to * the route. Finally (unless NUTAG_SERVICE_ROUTE_ENABLE(0) is used) the * @ServiceRoute set received from the registrar is also appended to the * route set of the initial request message. * * @par * Next, the stack generates a @Contact header for the request (Unless the * application already gave a @Contact header or it does not want to use * @Contact and indicates that by including SIPTAG_CONTACT(NULL) or * SIPTAG_CONTACT(SIP_NONE) in the tagged parameters.) If the application * has a registration active, the @Contact header used with registration is * used. Otherwise, the @Contact header is generated from the local IP * address and port number, taking also the values from NUTAG_M_DISPLAY(), * NUTAG_M_FEATURES(), NUTAG_M_PARAMS(), and NUTAG_M_USERNAME(). * * @par * For in-dialog INVITE (re-INVITE), the request URI is taken from the * @Contact header received from the remote party during the dialog * establishment. Also, the @CallID and @CSeq headers and @From and @To tags * are generated based on the dialog information and added to the request.  * If the dialog has a route (set by @RecordRoute headers), it is added to * the request, too. * * @par * @MaxForwards header (with default value set by NTATAG_MAX_FORWARDS()) is * also added now, if it does not exist. *  * @par * The INVITE request message created by nua_invite() operation is saved as * a template for automatic re-INVITE requests sent by the session timer * ("timer") feature (see NUTAG_SESSION_TIMER() for more details). Please * note that the template message is not used when ACK, PRACK, UPDATE or * INFO requests are created (however, these requests will include * dialog-specific headers like @To, @From, and @CallID as well as * preference headers @Allow, @Supported, @UserAgent, @Organization). * * @par Tags Related to SIP Headers and Request-URI *    NUTAG_URL(), SIPTAG_REQUEST(), SIPTAG_REQUEST_STR() \n *    NUTAG_INITIAL_ROUTE(), NUTAG_INITIAL_ROUTE_STR(),  *    SIPTAG_ROUTE(), SIPTAG_ROUTE_STR(),  *    NUTAG_SERVICE_ROUTE_ENABLE() \n *    SIPTAG_MAX_FORWARDS(), SIPTAG_MAX_FORWARDS_STR() \n *    SIPTAG_PROXY_REQUIRE(), SIPTAG_PROXY_REQUIRE_STR() \n *    SIPTAG_FROM(), SIPTAG_FROM_STR() \n *    SIPTAG_TO(), SIPTAG_TO_STR() \n *    SIPTAG_CALL_ID(), SIPTAG_CALL_ID_STR() \n *    SIPTAG_CSEQ(), SIPTAG_CSEQ_STR() *    (note that @CSeq value is incremented if request gets retried)\n *    SIPTAG_CONTACT(), SIPTAG_CONTACT_STR() \n *    SIPTAG_REQUEST_DISPOSITION(), SIPTAG_REQUEST_DISPOSITION_STR() \n *    SIPTAG_ACCEPT_CONTACT(), SIPTAG_ACCEPT_CONTACT_STR() \n *    SIPTAG_REJECT_CONTACT(), SIPTAG_REJECT_CONTACT_STR() \n *    SIPTAG_EXPIRES(), SIPTAG_EXPIRES_STR() \n *    SIPTAG_DATE(), SIPTAG_DATE_STR() \n *    SIPTAG_TIMESTAMP(), SIPTAG_TIMESTAMP_STR() \n *    SIPTAG_SUBJECT(), SIPTAG_SUBJECT_STR() \n *    SIPTAG_PRIORITY(), SIPTAG_PRIORITY_STR() \n *    SIPTAG_CALL_INFO(), SIPTAG_CALL_INFO_STR() \n *    SIPTAG_ORGANIZATION(), SIPTAG_ORGANIZATION_STR() \n *    NUTAG_USER_AGENT(), SIPTAG_USER_AGENT() and SIPTAG_USER_AGENT_STR() \n *    SIPTAG_IN_REPLY_TO(), SIPTAG_IN_REPLY_TO_STR() \n *    SIPTAG_ACCEPT(), SIPTAG_ACCEPT_STR() \n *    SIPTAG_ACCEPT_ENCODING(), SIPTAG_ACCEPT_ENCODING_STR() \n *    SIPTAG_ACCEPT_LANGUAGE(), SIPTAG_ACCEPT_LANGUAGE_STR() \n *    NUTAG_ALLOW(), SIPTAG_ALLOW(), and SIPTAG_ALLOW_STR() \n *    NUTAG_EARLY_MEDIA(), SIPTAG_REQUIRE(), and SIPTAG_REQUIRE_STR() \n *    NUTAG_SUPPORTED(), SIPTAG_SUPPORTED(), and SIPTAG_SUPPORTED_STR() \n *    SIPTAG_ALLOW_EVENTS(), SIPTAG_ALLOW_EVENTS_STR() \n *    SIPTAG_PROXY_AUTHORIZATION(), SIPTAG_PROXY_AUTHORIZATION_STR() \n *    SIPTAG_AUTHORIZATION(), SIPTAG_AUTHORIZATION_STR() \n *    SIPTAG_REFERRED_BY(), SIPTAG_REFERRED_BY_STR() \n *    SIPTAG_REPLACES(), SIPTAG_REPLACES_STR() \n *    NUTAG_SESSION_TIMER(), NUTAG_SESSION_REFRESHER(),  *    SIPTAG_SESSION_EXPIRES(), SIPTAG_SESSION_EXPIRES_STR() \n *    NUTAG_MIN_SE(), SIPTAG_MIN_SE(), SIPTAG_MIN_SE_STR() \n *    SIPTAG_SECURITY_CLIENT(), SIPTAG_SECURITY_CLIENT_STR() \n *    SIPTAG_SECURITY_VERIFY(), SIPTAG_SECURITY_VERIFY_STR() \n *    SIPTAG_PRIVACY(), SIPTAG_PRIVACY_STR() \n *    SIPTAG_MIME_VERSION(), SIPTAG_MIME_VERSION_STR() \n *    SIPTAG_CONTENT_TYPE(), SIPTAG_CONTENT_TYPE_STR() \n *    SIPTAG_CONTENT_ENCODING(), SIPTAG_CONTENT_ENCODING_STR() \n *    SIPTAG_CONTENT_LANGUAGE(), SIPTAG_CONTENT_LANGUAGE_STR() \n *    SIPTAG_CONTENT_DISPOSITION(), SIPTAG_CONTENT_DISPOSITION_STR() \n *    SIPTAG_HEADER(), SIPTAG_HEADER_STR() \n *    SIPTAG_PAYLOAD(), SIPTAG_PAYLOAD_STR() \n * * @par SDP Handling * By default the nua_invite() uses an @ref soa_session_t "SOA media * session" object to take care of the Offer/Answer exchange. The SOA can * be disabled with tag NUTAG_MEDIA_ENABLE(0). * * @par * The SDP description of the * @ref soa_session_t "soa media session" is included in the INVITE request * as a message body.  * The SDP in the message body of the 1XX or 2XX response message is * interpreted as an answer, given to the @ref soa_session_t "soa media * session" object for processing. * * @bug If the INVITE request already contains a message body, SDP is not * added.  Also, if the response contains a multipart body, it is not parsed. * * @par Tags Related to SDP Management and Offer/Answer Model: *    NUTAG_MEDIA_ENABLE(), \n *    NUTAG_INCLUDE_EXTRA_SDP(), \n *    SOATAG_HOLD(), SOATAG_AF(), SOATAG_ADDRESS(), *    SOATAG_ORDERED_USER(), SOATAG_REUSE_REJECTED(),  *    SOATAG_RTP_SELECT(), SOATAG_RTP_SORT(), SOATAG_RTP_MISMATCH(),  *    SOATAG_AUDIO_AUX(), \n *    SOATAG_USER_SDP() or SOATAG_USER_SDP_STR() \n * * @par Alternative Call Models * In addition to the basic SIP call model described in @RFC3261 and * @RFC3264, the early media model described in @RFC3262 is available. The * use of 100rel and early media can be use can be forced with * NUTAG_EARLY_MEDIA(1). * * Also, the "precondition" call model described in @RFC3312 is supported at * SIP level, that is, the SIP PRACK and UPDATE requests are sent if * "precondition" is added to the @Require header in the INVITE request. * * Optionally  * - uses early media if NUTAG_EARLY_MEDIA() tag is used with non zero-value * - media parameters can be set by SOA tags * - nua_invite() can be used to change status of an existing call:  *   - #SOATAG_HOLD tag can be used to list the media that will be put on hold, *     the value "*" sets all the media beloginging to the session on hold * * @par Authentication * The INVITE request may need authentication. Each proxy or server * requiring authentication can respond with 401 or 407 response. The * nua_authenticate() operation stores authentication information (username * and password) to the handle, and stack tries to authenticate all the rest * of the requests (e.g., PRACK, ACK, UPDATE, re-INVITE, BYE) using the * stored username and password. * * @sa @ref nua_call_model, #nua_r_invite, #nua_i_state, \n *     nua_handle_has_active_call() \n *     nua_handle_has_call_on_hold()\n *     nua_handle_has_invite() \n *     nua_authenticate() \n *     nua_prack() \n *     nua_update() \n *     nua_info() \n  *     nua_cancel() \n *     nua_bye() \n *     #nua_i_invite, nua_respond() *//* Tags not implemented *    NUTAG_REFER_PAUSE() \n */static int nua_invite_client_init(nua_client_request_t *cr, 				  msg_t *msg, sip_t *sip,				  tagi_t const *tags);static int nua_invite_client_request(nua_client_request_t *cr,				     msg_t *msg, sip_t *sip,				     tagi_t const *tags);static int nua_invite_client_preliminary(nua_client_request_t *cr,					 int status, char const *phrase,					 sip_t const *sip);static int nua_invite_client_response(nua_client_request_t *cr,				      int status, char const *phrase,				      sip_t const *sip);static int nua_session_client_response(nua_client_request_t *cr,				       int status, char const *phrase,				       sip_t const *sip);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_client_methods_t const nua_invite_client_methods = {  SIP_METHOD_INVITE,		/* crm_method, crm_method_name */  0,				/* crm_extra */  {				/* crm_flags */    /* create_dialog */ 1,    /* in_dialog */ 1,    /* target refresh */ 1  },  NULL,				/* crm_template */  nua_invite_client_init,	/* crm_init */  nua_invite_client_request,	/* crm_send */  session_timer_check_restart,	/* crm_check_restart */  nua_invite_client_response,	/* crm_recv */  nua_invite_client_preliminary, /* crm_preliminary */  nua_invite_client_report,	/* crm_report */  nua_invite_client_complete,	/* crm_complete */};extern nua_client_methods_t const nua_bye_client_methods;extern nua_client_methods_t const nua_cancel_client_methods;extern nua_client_methods_t const nua_info_client_methods;extern nua_client_methods_t const nua_update_client_methods;extern nua_client_methods_t const nua_prack_client_methods;int nua_stack_invite(nua_t *nua, nua_handle_t *nh, nua_event_t e,		     tagi_t const *tags){  return nua_client_create(nh, e, &nua_invite_client_methods, tags);}static int nua_invite_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_session_usage_t *ss;  cr->cr_usage = du = nua_dialog_usage_for_session(nh->nh_ds);  /* Errors returned by nua_invite_client_init()      do not change the session state */  cr->cr_neutral = 1;	    if (nh_is_special(nh) ||       nua_stack_set_handle_special(nh, nh_has_invite, nua_i_error))    return nua_client_return(cr, 900, "Invalid handle for INVITE", msg);  else if (nh_referral_check(nh, tags) < 0)    return nua_client_return(cr, 900, "Invalid referral", msg);  if (du) {    nua_server_request_t *sr;    for (sr = nh->nh_ds->ds_sr; sr; sr = sr->sr_next)      /* INVITE in progress? */      if (sr->sr_usage == du && sr->sr_method == sip_method_invite &&	  nua_server_request_is_pending(sr))	return nua_client_return(cr, SIP_491_REQUEST_PENDING, msg);  }  else    du = nua_dialog_usage_add(nh, nh->nh_ds, nua_session_usage, NULL);  if (!du)    return -1;  ss = nua_dialog_usage_private(du);  if (ss->ss_state >= nua_callstate_terminating)    return nua_client_return(cr, 900, "Session is terminating", msg);  if (nua_client_bind(cr, du) < 0)    return nua_client_return(cr, 900, "INVITE already in progress", msg);  cr->cr_neutral = 0;  session_timer_preferences(ss->ss_timer,			    sip,			    NH_PGET(nh, supported),		     			    NH_PGET(nh, session_timer),			    NUA_PISSET(nh->nh_nua, nh, session_timer),			    NH_PGET(nh, refresher),			    NH_PGET(nh, min_se));  return 0;}static int nua_invite_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;  int offer_sent = 0, retval;  sip_time_t invite_timeout;  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);  invite_timeout = NH_PGET(nh, invite_timeout);  if (invite_timeout == 0)    invite_timeout = UINT_MAX;  /* Send CANCEL if we don't get response within timeout*/  /* nua_dialog_usage_set_expires(du, invite_timeout); Xyzzy */  nua_dialog_usage_reset_refresh(du);  /* Add session timer headers */  if (session_timer_is_supported(ss->ss_timer))    session_timer_add_headers(ss->ss_timer, ss->ss_state == nua_callstate_init,			      msg, sip);  ss->ss_100rel = NH_PGET(nh, early_media);  ss->ss_precondition = sip_has_feature(sip->sip_require, "precondition");  if (ss->ss_precondition)

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -