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

📄 nua_notifier.c

📁 Sofia SIP is an open-source SIP User-Agent library, compliant with the IETF RFC3261 specification.
💻 C
📖 第 1 页 / 共 3 页
字号:
staticint nua_subscribe_server_report(nua_server_request_t *sr, tagi_t const *tags){  nua_handle_t *nh = sr->sr_owner;  nua_dialog_state_t *ds = nh->nh_ds;  nua_dialog_usage_t *du = sr->sr_usage;  struct notifier_usage *nu = nua_dialog_usage_private(du);  enum nua_substate substate = nua_substate_terminated;  int notify = 0;  int retval;  if (nu && !sr->sr_terminating) {    substate = nu->nu_substate;  }  /* nu_requested is set by SUBSCRIBE and cleared when NOTIFY is sent */  if (nu && nu->nu_requested && substate != nua_substate_embryonic) {#if SU_HAVE_EXPERIMENTAL    sip_t const *sip = sr->sr_request.sip;    sip_suppress_notify_if_match_t *snim = sip_suppress_notify_if_match(sip);    sip_suppress_body_if_match_t *sbim = sip_suppress_body_if_match(sip);        if (!nu->nu_tag)      notify = 1;    else if (snim && !strcasecmp(snim->snim_tag, nu->nu_tag))      notify = 0;    else if (sbim && !strcasecmp(snim->snim_tag, nu->nu_tag))      notify = 1, nu->nu_no_body = 1;    else #endif      notify = 1;    notify = notify && du->du_cr != NULL;  }  retval = nua_base_server_treport(sr, NUTAG_SUBSTATE(substate), TAG_END());  if (retval >= 2 || du == NULL)    return retval;    if (notify) {    /* Send NOTIFY (and terminate subscription, when needed) */    nua_dialog_usage_refresh(nh, ds, du, sip_now());  }    return retval;}/* ======================================================================== *//* NOTIFY client *//**@fn void nua_notify(nua_handle_t *nh, tag_type_t tag, tag_value_t value, ...); * * Send a SIP NOTIFY request message. * * This function is used when the application implements itself the * notifier. The application must provide valid @SubscriptionState and * @Event headers using SIP tags. The subscription state can be modified * with NUTAG_SUBSTATE(), however, its effect is overriden by * @SubscriptionState header included in the nua_notify() tags. * * @bug If the @Event is not given by application, stack uses the @Event * header from the first subscription usage on handle. *  * If there is no active <i>notifier dialog usage</i> or no notifier dialog * usage matches the @Event header given by the application the nua_notify() * request is rejected locally by the stack with status code 481. The local * rejection can be bypassed if NUTAG_NEWSUB(1) is included in tags. * * Please note that including NUTAG_NEWSUB(1) in nua_notify() tags if there * is a valid subscription may lead to an extra NOTIFY sent to subscriber if * the subscription had been terminated by the subscriber or by a timeout * before the nua_notify() is processed. * * @param nh              Pointer to operation handle * @param tag, value, ... List of tagged parameters * * @return  *    nothing * * @par Related Tags: *    NUTAG_SUBSTATE() \n *    NUTAG_NEWSUB() \n *    Tags of nua_set_hparams() \n *    Header tags defined in <sofia-sip/sip_tag.h> * * @par Events: *    #nua_r_notify * * @sa @RFC3265, #nua_i_subscribe, #nua_i_refer, NUTAG_ALLOW_EVENTS() */static int nua_notify_client_init(nua_client_request_t *cr, 				  msg_t *, sip_t *,				  tagi_t const *tags);static int nua_notify_client_init_etag(nua_client_request_t *cr,				       msg_t *msg, sip_t *sip,				       tagi_t const *tags);static int nua_notify_client_request(nua_client_request_t *cr,				     msg_t *, sip_t *,				     tagi_t const *tags);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);static nua_client_methods_t const nua_notify_client_methods = {  SIP_METHOD_NOTIFY,		/* crm_method, crm_method_name */  0,				/* crm_extra */  {				/* crm_flags */    /* create_dialog */ 1,    /* in_dialog */ 1,    /* target refresh */ 1  },  NULL,				/* crm_template */  nua_notify_client_init,	/* crm_init */  nua_notify_client_request,	/* crm_send */  NULL,				/* crm_check_restart */  NULL,				/* crm_recv */  NULL,				/* crm_preliminary */  nua_notify_client_report,	/* crm_report */  NULL,				/* crm_complete */};/**@internal Send NOTIFY. */int nua_stack_notify(nua_t *nua,		     nua_handle_t *nh,		     nua_event_t e,		     tagi_t const *tags){  return nua_client_create(nh, e, &nua_notify_client_methods, tags);}static int nua_notify_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;  struct notifier_usage *nu;  sip_event_t const *o = sip->sip_event;  sip_subscription_state_t *ss = sip->sip_subscription_state;  sip_time_t now = sip_now();      if (o == NULL && nh->nh_ds->ds_has_notifys == 1)    o = NONE;  du = nua_dialog_usage_get(nh->nh_ds, nua_notify_usage, o);  if (!du) {    tagi_t const *newsub = tl_find_last(tags, nutag_newsub);    if (!newsub || !newsub->t_value)      return 0; /* Rejected eventually by nua_notify_client_request() */    /* Create new notifier */    du = nua_dialog_usage_add(nh, nh->nh_ds, nua_notify_usage, o);    if (du == NULL)      return -1;    nu = nua_dialog_usage_private(du);    nu->nu_expires = now;  }  else    nu = nua_dialog_usage_private(du);  if (nu->nu_substate == nua_substate_terminated) {    /*Xyzzy*/;  }  else if (ss != NULL) {    /* SIPTAG_SUBSCRIPTION_STATE() overrides NUTAG_SUBSTATE() */    nu->nu_substate = nua_substate_make(ss->ss_substate);    if (ss->ss_expires) {      unsigned long expires = strtoul(ss->ss_expires, NULL, 10);      if (now + expires < now)	expires = SIP_TIME_MAX - now - 1;      /* We can change the lifetime of unsolicited subscription at will */      if (nu->nu_requested == 0)	nu->nu_expires = nu->nu_requested = now + expires;      /* Notifier can only shorten the subscribed time */       else if (nu->nu_requested >= now + expires)	nu->nu_expires = nu->nu_requested = now + expires;    }    else {      if (nu->nu_requested >= nu->nu_expires)	nu->nu_expires = nu->nu_requested;    }  }  else {    enum nua_substate substate = nu->nu_substate;    if (nu->nu_requested >= nu->nu_expires)      nu->nu_expires = nu->nu_requested;    if (nu->nu_expires > now) {      tagi_t const *t = tl_find_last(tags, nutag_substate);      if (t)        substate = (enum nua_substate)t->t_value;    }    else      substate = nua_substate_terminated;    switch (substate) {    case nua_substate_embryonic:      /*FALLTHROUGH*/    case nua_substate_pending:      nu->nu_substate = nua_substate_pending;      break;    case nua_substate_active:    default:      nu->nu_substate = nua_substate_active;      break;    case nua_substate_terminated:      nu->nu_substate = nua_substate_terminated;      break;    }  }  cr->cr_usage = du;  return nua_notify_client_init_etag(cr, msg, sip, tags);}static int nua_notify_client_init_etag(nua_client_request_t *cr,				       msg_t *msg, sip_t *sip,				       tagi_t const *tags){#if SU_HAVE_EXPERIMENTAL  nua_handle_t *nh = cr->cr_owner;  struct notifier_usage *nu = nua_dialog_usage_private(cr->cr_usage);  nua_server_request_t *sr;  if (nu->nu_tag)    su_free(nh->nh_home, nu->nu_tag), nu->nu_tag = NULL;    nu->nu_no_body = 0;  if (sip->sip_etag) {    nu->nu_appl_etags = 1;    nu->nu_tag = su_strdup(nh->nh_home, sip->sip_etag->g_string);  }  else if (!nu->nu_appl_etags && nu->nu_etags) {    su_md5_t md5[1];    unsigned char digest[SU_MD5_DIGEST_SIZE];    sip_payload_t pl[1] = { SIP_PAYLOAD_INIT() };    char token[2 * 16];    su_md5_init(md5);    if (sip->sip_payload) *pl = *sip->sip_payload;    if (pl->pl_len)      su_md5_update(md5, pl->pl_data, pl->pl_len);    su_md5_update(md5, &pl->pl_len, sizeof(pl->pl_len));    if (sip->sip_content_type)      su_md5_striupdate(md5, sip->sip_content_type->c_type);    su_md5_digest(md5, digest);    token64_e(token, sizeof token, digest, sizeof digest);    token[(sizeof token) - 1] = '\0';    nu->nu_tag = su_strdup(nh->nh_home, token);  }  if (!nu->nu_requested || !nu->nu_tag)    return 0;  /* Check if SUBSCRIBE had matching suppression */  for (sr = nh->nh_ds->ds_sr; sr; sr = sr->sr_next)    if (sr->sr_usage == cr->cr_usage && sr->sr_method == sip_method_subscribe)      break;  if (sr) {    sip_t const *sip = sr->sr_request.sip;    sip_suppress_body_if_match_t *sbim;    sip_suppress_notify_if_match_t *snim;        if (cr->cr_usage->du_ready) {      snim = sip_suppress_notify_if_match(sip);      if (snim && !strcasecmp(snim->snim_tag, nu->nu_tag)) {	if (nu->nu_requested > nu->nu_expires)	  nu->nu_expires = nu->nu_requested;	nu->nu_requested = 0;	return nua_client_return(cr, 202, "NOTIFY Suppressed", msg);      }    }    sbim = sip_suppress_body_if_match(sip);    if (sbim && !strcasecmp(sbim->sbim_tag, nu->nu_tag))      nu->nu_no_body = 1;  }#endif  return 0;}staticint nua_notify_client_request(nua_client_request_t *cr,			      msg_t *msg, sip_t *sip,			      tagi_t const *tags){  nua_dialog_usage_t *du = cr->cr_usage;   struct notifier_usage *nu = nua_dialog_usage_private(du);  su_home_t *home = msg_home(msg);  sip_time_t now = sip_now();  sip_subscription_state_t *ss = sip->sip_subscription_state;  char const *expires;  if (du == NULL)		/* Subscription has been terminated */    return nua_client_return(cr, SIP_481_NO_TRANSACTION, msg);  assert(du && nu);  if (du && nua_client_bind(cr, du) < 0)    return -1;  if (nu->nu_requested)    nu->nu_expires = nu->nu_requested;  nu->nu_requested = 0;  if (nu->nu_expires <= now || du->du_shutdown) {    nu->nu_substate = nua_substate_terminated;    expires = "expires=0";  }  else {    expires = su_sprintf(home, "expires=%lu", nu->nu_expires - now);  }  if (ss == NULL || nua_substate_make(ss->ss_substate) != nu->nu_substate) {    if (nu->nu_substate == nua_substate_terminated)

⌨️ 快捷键说明

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