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

📄 nua_notifier.c

📁 Sofia SIP is an open-source SIP User-Agent library, compliant with the IETF RFC3261 specification.
💻 C
📖 第 1 页 / 共 3 页
字号:
      expires = nu->nu_expires > now ? "noresource" : "timeout";    ss = sip_subscription_state_format(home, "%s;%s", 				       nua_substate_name(nu->nu_substate),				       expires);    msg_header_insert(msg, (void *)sip, (void *)ss);  }  else if (nu->nu_substate != nua_substate_terminated) {    msg_header_replace_param(home, ss->ss_common, expires);  }#if SU_HAVE_EXPERIMENTAL  if (nu->nu_tag && !sip->sip_etag)    msg_header_add_make(msg, (void *)sip, sip_etag_class, nu->nu_tag);  if (nu->nu_no_body) {    nu->nu_no_body = 0;    msg_header_remove(msg, (void *)sip, (void *)sip->sip_payload);    msg_header_remove(msg, (void *)sip, (void *)sip->sip_content_length);  }#endif  if (nu->nu_substate == nua_substate_terminated)    cr->cr_terminating = 1;  if (cr->cr_terminating) {    nua_server_request_t *sr;    for (sr = du->du_dialog->ds_sr; sr; sr = sr->sr_next) {      if (sr->sr_usage == du) {	/* If subscribe has not been responded, don't terminate usage by NOTIFY */	sr->sr_terminating = 1;	cr->cr_terminating = 0;	break;      }    }  }  if (du->du_event && !sip->sip_event)    sip_add_dup(cr->cr_msg, sip, (sip_header_t *)du->du_event);  return nua_base_client_request(cr, msg, sip, tags);}/** @NUA_EVENT nua_r_notify * * Response to an outgoing @b NOTIFY request. * * The @b NOTIFY may be sent explicitly by nua_notify() or implicitly by NUA * state machine. Implicit @b NOTIFY is sent when an established dialog is * refreshed by client or it is terminated (either by client or because of a * timeout). * * The current subscription state is included in NUTAG_SUBSTATE() tag. The * nua_substate_terminated indicates that the subscription is terminated, * the notifier usage has been removed and when there was no other usages of * the dialog the dialog state is also removed. * * @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 subscription * @param hmagic application context associated with the handle * @param sip    response to @b NOTIFY request or NULL upon an error  *               (status code is in @a status and  *               descriptive message in @a phrase parameters) * @param tags   NUTAG_SUBSTATE() indicating subscription state *               SIPTAG_EVENT() indicating subscription event * * @sa nua_notify(), @RFC3265, #nua_i_subscribe, #nua_i_refer, NUTAG_SUBSTATE() * * @END_NUA_EVENT */static int nua_notify_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;  struct notifier_usage *nu = nua_dialog_usage_private(du);  enum nua_substate substate = nua_substate_terminated;  if (nu && !cr->cr_terminated)    substate = nu->nu_substate;  nua_stack_tevent(nh->nh_nua, nh, 		   nta_outgoing_getresponse(orq),		   cr->cr_event,		   status, phrase,		   NUTAG_SUBSTATE(substate),		   SIPTAG_EVENT(du ? du->du_event : NULL),		   TAG_NEXT(tags));  if (du && du->du_cr == cr && !cr->cr_terminated) {    if (nu->nu_requested) {      /* Re-SUBSCRIBEd while NOTIFY was in progress, resend NOTIFY */      nua_client_resend_request(cr, 0);    }    else if (nu->nu_expires) {      nua_dialog_usage_set_refresh_at(du, nu->nu_expires);    }  }  return 0;}static void nua_notify_usage_refresh(nua_handle_t *nh,				     nua_dialog_state_t *ds,				     nua_dialog_usage_t *du,				     sip_time_t now){  struct notifier_usage *nu = nua_dialog_usage_private(du);  nua_client_request_t *cr = du->du_cr;  nua_event_t e = nua_r_notify;  if (cr) {    int terminating = 0;    if (nu->nu_expires && nu->nu_expires <= now)      terminating = 1;    else if (nu->nu_requested && nu->nu_requested <= now)      terminating = 1;    if (nua_client_resend_request(cr, terminating) >= 0)      return;  }  else {    if (nua_client_create(nh, e, &nua_notify_client_methods, NULL) >= 0)      return;  }  nua_stack_tevent(nh->nh_nua, nh, NULL, e, NUA_ERROR_AT(__FILE__, __LINE__),		   NUTAG_SUBSTATE(nua_substate_terminated),		   TAG_END());  nua_dialog_usage_remove(nh, ds, du, NULL, NULL);}/** @interal Shut down NOTIFY usage.  * * @retval >0  shutdown done * @retval 0   shutdown in progress * @retval <0  try again later */static int nua_notify_usage_shutdown(nua_handle_t *nh,				     nua_dialog_state_t *ds,				     nua_dialog_usage_t *du){  struct notifier_usage *nu = nua_dialog_usage_private(du);  nua_client_request_t *cr = du->du_cr;  nu->nu_substate = nua_substate_terminated;  if (cr) {    if (nua_client_resend_request(cr, 1) >= 0)      return 0;  }  else {    if (nua_client_tcreate(nh, nua_r_notify, 			   &nua_notify_client_methods, 			   SIPTAG_EVENT(du->du_event),			   NUTAG_SUBSTATE(nua_substate_terminated),			   TAG_END()) >= 0)      return 0;  }  nua_dialog_usage_remove(nh, ds, du, NULL, NULL);  return 200;}/* ======================================================================== *//* REFER *//* RFC 3515 */static int nua_refer_server_init(nua_server_request_t *sr);static int nua_refer_server_preprocess(nua_server_request_t *sr);static int nua_refer_server_respond(nua_server_request_t*, tagi_t const *);static int nua_refer_server_report(nua_server_request_t*, tagi_t const *);nua_server_methods_t const nua_refer_server_methods =   {    SIP_METHOD_REFER,    nua_i_refer,		/* Event */    {       1,			/* Create dialog */      0,			/* Initial request */      1,			/* Target refresh request  */      1,			/* Add Contact */    },    nua_refer_server_init,    nua_refer_server_preprocess,    nua_base_server_params,    nua_refer_server_respond,    nua_refer_server_report,  };static int nua_refer_server_init(nua_server_request_t *sr){  return 0;}static int nua_refer_server_preprocess(nua_server_request_t *sr){  nua_handle_t *nh = sr->sr_owner;  sip_t const *sip = sr->sr_request.sip;  struct notifier_usage *nu;  sip_event_t *o;  if (nh->nh_ds->ds_got_referrals || NH_PGET(nh, refer_with_id))    o = sip_event_format(nh->nh_home, "refer;id=%u", sip->sip_cseq->cs_seq);  else    o = sip_event_make(nh->nh_home, "refer");  if (o) {    sr->sr_usage = nua_dialog_usage_add(nh, nh->nh_ds, nua_notify_usage, o);    msg_header_free(nh->nh_home, (msg_header_t *)o);  }  if (!sr->sr_usage)    return SR_STATUS1(sr, SIP_500_INTERNAL_SERVER_ERROR);  nu = nua_dialog_usage_private(sr->sr_usage);  nu->nu_requested = sip_now() + NH_PGET(nh, refer_expires);  return 0;}staticint nua_refer_server_respond(nua_server_request_t *sr, tagi_t const *tags){  nua_handle_t *nh = sr->sr_owner;  struct notifier_usage *nu = nua_dialog_usage_private(sr->sr_usage);  sip_refer_sub_t const *rs = sip_refer_sub(sr->sr_response.sip);  if (sr->sr_status < 200 || nu == NULL) {  }  else if (sr->sr_status < 300 && 	   /* Application included Refer-Sub: false in response */	   (rs == NULL || str0casecmp("false", rs->rs_value))) {    sr->sr_usage->du_ready = 1;    nu->nu_expires = sip_now() + NH_PGET(nh, refer_expires);    if (sr->sr_application)	/* Application responded to REFER */      nu->nu_substate = nua_substate_active;  }  else {    /* Destroy the implicit subscription usage */    sr->sr_terminating = 1;  }  return nua_base_server_respond(sr, tags);}/** @NUA_EVENT nua_i_refer * * Incoming @b REFER request used to transfer calls. The tag list will * contain tag NUTAG_REFER_EVENT() with the @Event header constructed from * the REFER request. It will also contain the SIPTAG_REFERRED_BY() tag with * the @ReferredBy header containing the identity of the party sending the * REFER. The @ReferredBy structure contained in the tag is constructed from * the @From header if the @ReferredBy header was not present in the REFER * request. *  * The application can let the nua to send NOTIFYs from the call it * initiates with nua_invite() if it includes in the nua_invite() arguments * both the NUTAG_NOTIFY_REFER() with the handle with which nua_i_refer was * received and the NUTAG_REFER_EVENT() from #nua_i_refer event tags. * * @param status status code of response sent automatically by stack * @param phrase a short textual description of @a status code * @param nh     operation handle associated with the incoming request * @param hmagic application context associated with the handle *               (NULL if outside of an already established session) * @param sip    incoming REFER request * @param tags   NUTAG_REFER_EVENT() \n *               SIPTAG_REFERRED_BY() *   * @sa nua_refer(), #nua_r_refer, @ReferTo, NUTAG_REFER_EVENT(),  * SIPTAG_REFERRED_BY(), @ReferredBy, NUTAG_NOTIFY_REFER(), * NUTAG_REFER_WITH_ID(), @RFC3515. * * @END_NUA_EVENT */staticint nua_refer_server_report(nua_server_request_t *sr, tagi_t const *tags){  nua_handle_t *nh = sr->sr_owner;  struct notifier_usage *nu = nua_dialog_usage_private(sr->sr_usage);  sip_t const *sip = sr->sr_request.sip;  sip_referred_by_t *by = sip->sip_referred_by, default_by[1];  sip_event_t const *o = sr->sr_usage->du_event;  enum nua_substate substate = nua_substate_terminated;  int initial = sr->sr_initial, retval;  if (nu) {    if (!sr->sr_terminating)      substate = nu->nu_substate;  }  if (by == NULL) {     by = sip_referred_by_init(default_by);    by->b_display = sip->sip_from->a_display;    *by->b_url = *sip->sip_from->a_url;  }  retval = nua_base_server_treport(sr,				   NUTAG_SUBSTATE(substate),				   NUTAG_REFER_EVENT(o),				   TAG_IF(by, SIPTAG_REFERRED_BY(by)),				   TAG_END());  if (retval >= 2 || nu == NULL)    return retval;  if (initial)    nua_stack_post_signal(nh,			  nua_r_notify,			  SIPTAG_EVENT(o),			  SIPTAG_CONTENT_TYPE_STR("message/sipfrag"),			  SIPTAG_PAYLOAD_STR("SIP/2.0 100 Trying\r\n"),			  TAG_END());  return retval;}

⌨️ 快捷键说明

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