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

📄 nua_register.c

📁 Sofia SIP is an open-source SIP User-Agent library, compliant with the IETF RFC3261 specification.
💻 C
📖 第 1 页 / 共 5 页
字号:
 * fields of dialog-establishing messages, such as INVITE or SUBSCRIBE.  * Also, if the registrar has included a Service-Route header in the * response, and the service route feature has not been disabled using * NUTAG_SERVICE_ROUTE_ENABLE(), the route URIs from the Service-Route * header will be used for initial non-REGISTER requests. * * The #nua_r_register message will include the contact header and route * used in with the registration. * * @par Registration Keep-Alive * * After the registration has successfully completed the nua_register() will * validate the registration and initiate the keepalive mechanism, too. The * user-agent validates the registration by sending a OPTIONS requests to * itself. If there is an error, nua_register() will indicate that to the * application using #nua_i_outbound event, and start unregistration * procedure (unless that has been explicitly disabled). * * You can disable validation by inserting "no-validate" into * NUTAG_OUTBOUND() string. * * The keepalive mechanism depends on the network features detected earlier.  * If @a outbound extension is used, the STUN keepalives will be used.  * Otherwise, NUA stack will repeatedly send OPTIONS requests to itself. In * order to save bandwidth, it will include Max-Forwards: 0 in the * keep-alive requests, however. The keepalive interval is determined by * NUTAG_KEEPALIVE() parameter. If the interval is 0, no keepalive messages * is sent. * * You can disable keepalive OPTIONS by inserting "no-options-keepalive" * into NUTAG_OUTBOUND() string. Currently there are no other keepalive * mechanisms available. * * The value of NUTAG_KEEPALIVE_STREAM(), if specified, is used to indicate * the desired transport-layer keepalive interval for stream-based * transports like TLS and TCP. * * As alternative to OPTIONS/STUN keepalives, the client can propose * a more frequent registration refresh interval with * NUTAG_M_FEATURES() (e.g. NUTAG_M_FEATURES("expires=120") given as  * parameter to nua_register()). *  * @sa #nua_r_register, nua_unregister(), #nua_r_unregister,  * #nua_i_register, * @RFC3261 section 10, * @Expires, @Contact, @CallID, @CSeq, * @Path, @RFC3327, @ServiceRoute, @RFC3608, @RFC3680, *     NUTAG_REGISTRAR(), NUTAG_INSTANCE(), NUTAG_OUTBOUND(), *     NUTAG_KEEPALIVE(), NUTAG_KEEPALIVE_STREAM(),  *     SIPTAG_CONTACT(), SIPTAG_CONTACT_STR(), NUTAG_M_USERNAME(), *     NUTAG_M_DISPLAY(), NUTAG_M_PARAMS(), NUTAG_M_FEATURES(),  *//** @NUA_EVENT nua_r_register * * Response to an outgoing REGISTER. * * The REGISTER may be sent explicitly by nua_register() or implicitly by * NUA state machines.  *  * When REGISTER request has been restarted the @a status may be 100 even * while the real response status returned is different. * * @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 registration * @param hmagic application context associated with the registration * @param sip    response message to REGISTER request or NULL upon an error *               (status code is in @a status and  *                descriptive message in @a phrase parameters) * @param tags   empty * * @sa nua_register(), nua_unregister(), #nua_r_unregister, * @Contact, @CallID, @CSeq, @RFC3261 section 10, * @Path, @RFC3327, @ServiceRoute, @RFC3608, @RFC3680 *  * @END_NUA_EVENT *//**@fn void nua_unregister(nua_handle_t *nh, tag_type_t tag, tag_value_t value, ...); * Unregister.  * * Send a REGISTER request with expiration time 0. This removes the  * registration from the registrar. If the handle was earlier used  * with nua_register() the periodic updates will be terminated.  * * If a SIPTAG_CONTACT_STR() with argument "*" is used, all the * registrations will be removed from the registrar otherwise only the * contact address belonging to the NUA stack is removed. * * @param nh              Pointer to operation handle * @param tag, value, ... List of tagged parameters * * @return *     nothing * * @par Related tags: *     NUTAG_REGISTRAR() \n *     Header tags defined in <sofia-sip/sip_tag.h> except SIPTAG_EXPIRES() or SIPTAG_EXPIRES_STR() * * @par Events: *     #nua_r_unregister * * @sa nua_register(), #nua_r_register, nua_handle_destroy(), nua_shutdown(), * #nua_i_register, * @Expires, @Contact, @CallID, @CSeq, @RFC3261 section 10, * @Path, @RFC3327, @ServiceRoute, @RFC3608, @RFC3680, *     NUTAG_REGISTRAR(), NUTAG_INSTANCE(), NUTAG_OUTBOUND(), *     NUTAG_KEEPALIVE(), NUTAG_KEEPALIVE_STREAM(),  *     SIPTAG_CONTACT(), SIPTAG_CONTACT_STR(), NUTAG_M_USERNAME(), *     NUTAG_M_DISPLAY(), NUTAG_M_PARAMS(), NUTAG_M_FEATURES(),  *//** @NUA_EVENT nua_r_unregister * * Answer to outgoing un-REGISTER. * * @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 registration * @param hmagic application context associated with the registration * @param sip    response message to REGISTER request or NULL upon an error *               (status code is in @a status and  *                descriptive message in @a phrase parameters) * @param tags   empty * * @sa nua_unregister(), nua_register(), #nua_r_register, * @Contact, @CallID, @CSeq, @RFC3261 section 10, * @Path, @RFC3327, @ServiceRoute, @RFC3608, @RFC3680 *  * @END_NUA_EVENT */static int nua_register_client_template(nua_client_request_t *cr,					msg_t **return_msg,					tagi_t const *tags);static int nua_register_client_init(nua_client_request_t *cr,				    msg_t *, sip_t *,				    tagi_t const *tags);static int nua_register_client_request(nua_client_request_t *cr,				       msg_t *, sip_t *,				       tagi_t const *tags);static int nua_register_client_check_restart(nua_client_request_t *cr,					     int status, char const *phrase,					     sip_t const *sip);static int nua_register_client_response(nua_client_request_t *cr,					int status, char const *phrase,					sip_t const *sip);static nua_client_methods_t const nua_register_client_methods = {  SIP_METHOD_REGISTER,		/* crm_method, crm_method_name */  0,				/* crm_extra */  {				/* crm_flags */    /* create_dialog */ 1,    /* in_dialog */ 0,    /* target refresh */ 0  },  nua_register_client_template,	/* crm_template */  nua_register_client_init,	/* crm_init */  nua_register_client_request,	/* crm_send */  nua_register_client_check_restart, /* crm_check_restart */  nua_register_client_response,	/* crm_recv */  NULL,				/* crm_preliminary */  NULL,				/* crm_report */  NULL,				/* crm_complete */};/**@internal Send REGISTER. */int nua_stack_register(nua_t *nua,		       nua_handle_t *nh,		       nua_event_t e,		       tagi_t const *tags){  return nua_client_create(nh, e, &nua_register_client_methods, tags);}static int nua_register_client_template(nua_client_request_t *cr,					msg_t **return_msg,					tagi_t const *tags){  nua_dialog_usage_t *du;  if (cr->cr_event == nua_r_register)    return 0;  /* Use a copy of REGISTER message as the template for un-REGISTER */  du = nua_dialog_usage_get(cr->cr_owner->nh_ds, nua_register_usage, NULL);  if (du && du->du_cr) {    if (nua_client_set_target(cr, du->du_cr->cr_target) < 0)      return -1;    *return_msg = msg_copy(du->du_cr->cr_msg);    return 1;  }  return 0;}static int nua_register_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_registration_t *nr;  sip_to_t const *aor = sip->sip_to;  int unreg;  /* Explicit empty (NULL) contact - used for CPL store/remove? */  if (!sip->sip_contact && cr->cr_has_contact)    /* Do not create any usage */    return 0;  unreg = cr->cr_event != nua_r_register ||    (sip->sip_expires && sip->sip_expires->ex_delta == 0);  if (unreg)    nua_client_terminating(cr);  du = nua_dialog_usage_add(nh, nh->nh_ds, nua_register_usage, NULL);  if (du == NULL)    return -1;  nr = nua_dialog_usage_private(du);  if (nua_client_bind(cr, du) < 0)    return -1;  if (!nr->nr_list) {    nua_registration_add(&nh->nh_nua->nua_registrations, nr);    if (aor == NULL)      aor = sip->sip_from;    if (aor == NULL)      aor = nh->nh_nua->nua_from;    if (nua_registration_set_aor(nh->nh_home, nr, aor) < 0)      return -1;  }  if (nua_registration_set_contact(nh, nr, sip->sip_contact, unreg) < 0)    return -1;  if (!nr->nr_ob && (NH_PGET(nh, outbound) || NH_PGET(nh, instance))) {    nr->nr_ob = outbound_new(nh, &nua_stack_outbound_callbacks,			     nh->nh_nua->nua_root,			     nh->nh_nua->nua_nta,			     NH_PGET(nh, instance));    if (!nr->nr_ob)      return nua_client_return(cr, 900, "Cannot create outbound", msg);    nua_register_usage_update_params(du,				     NULL,				     nh->nh_prefs,				     nh->nh_dprefs);  }  if (nr->nr_ob) {    outbound_t *ob = nr->nr_ob;    sip_contact_t *m;    if (!unreg && sip->sip_contact) {      for (m = sip->sip_contact; m; m = m->m_next)	if (!m->m_expires || strtoul(m->m_expires, NULL, 10) != 0)	  break;            if (m == NULL)	unreg = 1;	/* All contacts have expires=0 */    }    if (outbound_set_contact(ob, sip->sip_contact, nr->nr_via, unreg) < 0)      return nua_client_return(cr, 900, "Cannot set outbound contact", msg);  }  return 0;}staticint nua_register_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_registration_t *nr;  sip_contact_t *m, *contacts = sip->sip_contact;  char const *min_expires = NULL;  int unreg;  tport_t *tport = NULL;  (void)nh;  /* Explicit empty (NULL) contact - used for CPL store/remove? */  if (!contacts && cr->cr_has_contact)    return nua_base_client_request(cr, msg, sip, tags);  if ((du && du->du_shutdown) ||      (sip->sip_expires && sip->sip_expires->ex_delta == 0))    nua_client_terminating(cr);  if (contacts) {    if (!cr->cr_terminating) {      for (m = contacts; m; m = m->m_next)	if (!m->m_expires || strtoul(m->m_expires, NULL, 10) != 0)	  break;      /* All contacts have expires=0 */      if (m == NULL)	nua_client_terminating(cr);    }  }  unreg = cr->cr_terminating;  nr = nua_dialog_usage_private(du);  if (nr) {    if (nr->nr_ob) {      outbound_stop_keepalive(nr->nr_ob);      outbound_start_registering(nr->nr_ob);    }    if (nr->nr_by_stack) {      sip_contact_t *m = nr->nr_contact, *previous = NULL;      outbound_get_contacts(nr->nr_ob, &m, &previous);      sip_add_dup(msg, sip, (sip_header_t *)m);      /* previous is an outdated contact generated by stack        * and it is now unregistered */      if (previous)	sip_add_dup(msg, sip, (sip_header_t *)previous);    }    tport = nr->nr_tport;  }  for (m = sip->sip_contact; m; m = m->m_next) {    if (m->m_url->url_type == url_any) {      /* If there is a '*' in contact list, remove everything else */      while (m != sip->sip_contact)	sip_header_remove(msg, sip, (sip_header_t *)sip->sip_contact);      while (m->m_next)	sip_header_remove(msg, sip, (sip_header_t *)m->m_next);      contacts = m;      break;    }    if (!m->m_expires)      continue;    if (unreg) {      /* Remove the expire parameters from contacts */      msg_header_remove_param(m->m_common, "expires");    }    else if (nr && nr->nr_min_expires && 	     strtoul(m->m_expires, 0, 10) < nr->nr_min_expires) {      if (min_expires == NULL) 	min_expires = su_sprintf(msg_home(msg), "expires=%lu", 				 nr->nr_min_expires);      msg_header_replace_param(msg_home(msg), m->m_common, min_expires);    }  }  return nua_base_client_trequest(cr, msg, sip,				  TAG_IF(unreg, SIPTAG_EXPIRES_STR("0")),#if 0				  TAG_IF(unreg, NTATAG_SIGCOMP_CLOSE(1)),				  TAG_IF(!unreg, NTATAG_COMP("sigcomp")),#endif				  NTATAG_TPORT(tport),				  TAG_NEXT(tags));}static int nua_register_client_check_restart(nua_client_request_t *cr,					     int status, char const *phrase,					     sip_t const *sip){  nua_registration_t *nr = nua_dialog_usage_private(cr->cr_usage);  unsigned short retry_count = cr->cr_retry_count;  int restart = 0, retry;  if (nr && nr->nr_ob) {    msg_t *_reqmsg = nta_outgoing_getrequest(cr->cr_orq);    sip_t *req = sip_object(_reqmsg); msg_destroy(_reqmsg);    retry = outbound_register_response(nr->nr_ob, cr->cr_terminating,				       req, sip);    restart = retry >= ob_reregister_now;        if (retry == ob_reregister)      /* outbound restarts REGISTER later */;    if (retry < 0)      /* XXX - report an error? */;  }  if (nr && status == 423) {    if (sip->sip_min_expires)      nr->nr_min_expires = sip->sip_min_expires->me_delta;  }  /* Check for status-specific reasons to retry */  if (nua_base_client_check_restart(cr, status, phrase, sip))    return 1;  /* Restart only if nua_base_client_check_restart() did not try to restart */  if (restart && retry_count == cr->cr_retry_count)    return nua_client_restart(cr, 100, "Outbound NAT Detected");    return 0;}static int nua_register_client_response(nua_client_request_t *cr,					int status, char const *phrase,					sip_t const *sip){  nua_handle_t *nh = cr->cr_owner;  nua_dialog_usage_t *du = cr->cr_usage;  nua_registration_t *nr = nua_dialog_usage_private(du);  int ready;

⌨️ 快捷键说明

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