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

📄 nua_register.c

📁 Sofia SIP is an open-source SIP User-Agent library, compliant with the IETF RFC3261 specification.
💻 C
📖 第 1 页 / 共 5 页
字号:
  ready = du && !cr->cr_terminated && status < 300;  if (ready) {    sip_time_t mindelta = 0;    sip_time_t now = sip_now(), delta, reqdelta, mdelta;    sip_contact_t const *m, *sent;    msg_t *_reqmsg = nta_outgoing_getrequest(cr->cr_orq);    sip_t *req = sip_object(_reqmsg);    tport_t *tport;    msg_destroy(_reqmsg);    assert(nr); assert(sip); assert(req);#if HAVE_SIGCOMP    {      struct sigcomp_compartment *cc;      cc = nta_outgoing_compartment(cr->cr_orq);      sigcomp_compartment_unref(nr->nr_compartment);      nr->nr_compartment = cc;    }#endif    /* XXX - if store/remove, remove        Content-Disposition       Content-Type       body    */    /** Search for lowest delta of SIP contacts we tried to register */    mindelta = SIP_TIME_MAX;    reqdelta = req->sip_expires ? req->sip_expires->ex_delta : 0;    for (m = sip->sip_contact; m; m = m->m_next) {      if (m->m_url->url_type != url_sip && 	  m->m_url->url_type != url_sips)	continue;      for (sent = req->sip_contact; sent; sent = sent->m_next) {	if (url_cmp(m->m_url, sent->m_url))	  continue;	if (sent->m_expires)	  mdelta = strtoul(sent->m_expires, NULL, 10);	else	  mdelta = reqdelta;	if (mdelta == 0)	  mdelta = 3600;	  	delta = sip_contact_expires(m, sip->sip_expires, sip->sip_date,				    mdelta, now);	if (delta > 0 && delta < mindelta)	  mindelta = delta;	if (url_cmp_all(m->m_url, sent->m_url) == 0)	  break;      }    }    if (mindelta == SIP_TIME_MAX)      mindelta = 3600;    nua_dialog_usage_set_refresh(du, mindelta);  /*  RFC 3608 Section 6.1 Procedures at the UA   The UA performs a registration as usual.  The REGISTER response may   contain a Service-Route header field.  If so, the UA MAY store the   value of the Service-Route header field in an association with the   address-of-record for which the REGISTER transaction had registered a   contact.  If the UA supports multiple addresses-of-record, it may be   able to store multiple service routes, one per address-of-record.  If   the UA refreshes the registration, the stored value of the Service-   Route is updated according to the Service-Route header field of the   latest 200 class response.  If there is no Service-Route header field   in the response, the UA clears any service route for that address-   of-record previously stored by the UA.  If the re-registration   request is refused or if an existing registration expires and the UA   chooses not to re-register, the UA SHOULD discard any stored service   route for that address-of-record.  */    su_free(nh->nh_home, nr->nr_route);    nr->nr_route = sip_route_dup(nh->nh_home, sip->sip_service_route);    {      /* RFC 3327 */      /* Store last URI in Path header */      sip_path_t *path = sip->sip_path;      while (path && path->r_next)	path = path->r_next;      if (!nr->nr_path || !path ||	  url_cmp_all(nr->nr_path->r_url, path->r_url)) {	su_free(nh->nh_home, nr->nr_path);	nr->nr_path = sip_path_dup(nh->nh_home, path);      }    }    if (sip->sip_to->a_url->url_type == url_sips)      nr->nr_secure = 1;    if (nr->nr_ob) {      outbound_gruuize(nr->nr_ob, sip);      outbound_start_keepalive(nr->nr_ob, cr->cr_orq);    }    tport = nta_outgoing_transport (cr->cr_orq);    /* cache persistant connection for registration */    if (tport && tport != nr->nr_tport) {      if (nr->nr_error_report_id) {	if (tport_release(nr->nr_tport, nr->nr_error_report_id, NULL, NULL, nr, 0) < 0)	  SU_DEBUG_1(("nua_register: tport_release() failed\n"));	nr->nr_error_report_id = 0;      }      tport_unref(nr->nr_tport);      nr->nr_tport = tport;      if (tport_is_secondary(tport)) {	tport_set_params(tport, TPTAG_SDWN_ERROR(1), TAG_END());	nr->nr_error_report_id = 	  tport_pend(tport, NULL, nua_register_connection_closed, nr);      }    }    else      tport_unref(tport);    /* note: nta_outgoing_transport() makes a ref */    nua_registration_set_ready(nr, 1);  }  else if (du) {    nua_dialog_usage_reset_refresh(du);    su_free(nh->nh_home, nr->nr_route);    nr->nr_route = NULL;    outbound_stop_keepalive(nr->nr_ob);    /* release the persistant transport for registration */    if (nr->nr_tport) {      if (nr->nr_error_report_id) {	if (tport_release(nr->nr_tport, nr->nr_error_report_id, NULL, NULL, nr, 0) < 0)	  SU_DEBUG_1(("nua_register: tport_release() failed\n"));	nr->nr_error_report_id = 0;      }      tport_unref(nr->nr_tport), nr->nr_tport = NULL;    }    nua_registration_set_ready(nr, 0);  }  return nua_base_client_response(cr, status, phrase, sip, NULL);}staticvoid nua_register_connection_closed(tp_stack_t *sip_stack,				    nua_registration_t *nr,				    tport_t *tport,				    msg_t *msg,				    int error){  nua_dialog_usage_t *du;  tp_name_t const *tpn;  int pending;  assert(nr && tport == nr->nr_tport);  if (nr == NULL || tport != nr->nr_tport)    return;  du = NUA_DIALOG_USAGE_PUBLIC(nr);  pending = nr->nr_error_report_id;  if (tport_release(tport, pending, NULL, NULL, nr, 0) < 0)    SU_DEBUG_1(("nua_register: tport_release() failed\n"));  nr->nr_error_report_id = 0;  tpn = tport_name(nr->nr_tport);  SU_DEBUG_5(("nua_register(%p): tport to %s/%s:%s%s%s closed %s\n", 	      du->du_dialog->ds_owner,	      tpn->tpn_proto, tpn->tpn_host, tpn->tpn_port,	      tpn->tpn_comp ? ";comp=" : "",	      tpn->tpn_comp ? tpn->tpn_comp : "",	      error != 0 ? su_strerror(error) : ""));  tport_unref(nr->nr_tport), nr->nr_tport = NULL;  /* Schedule re-REGISTER immediately */  nua_dialog_usage_set_refresh_range(du, 0, 0);}static voidnua_register_usage_update_params(nua_dialog_usage_t const *du,				 nua_handle_preferences_t const *changed,				 nua_handle_preferences_t const *nhp,				 nua_handle_preferences_t const *dnhp){  nua_registration_t *nr = nua_dialog_usage_private(du);  outbound_t *ob = nr->nr_ob;  if (!ob)    return;  if (!changed ||      NHP_ISSET(changed, outbound) ||      NHP_ISSET(changed, keepalive) ||      NHP_ISSET(changed, keepalive_stream)) {    char const *outbound =      NHP_ISSET(nhp, outbound) ? nhp->nhp_outbound      : dnhp->nhp_outbound;    unsigned keepalive =      NHP_ISSET(nhp, keepalive) ? nhp->nhp_keepalive      : dnhp->nhp_keepalive;    unsigned keepalive_stream =      NHP_ISSET(nhp, keepalive_stream) ? nhp->nhp_keepalive_stream      : NHP_ISSET(dnhp, keepalive_stream) ? nhp->nhp_keepalive_stream      : keepalive;    outbound_set_options(ob, outbound, keepalive, keepalive_stream);  }  if (!changed || NHP_ISSET(changed, proxy)) {    if (NHP_ISSET(nhp, proxy))      outbound_set_proxy(ob, nhp->nhp_proxy);  }}static void nua_register_usage_refresh(nua_handle_t *nh,				       nua_dialog_state_t *ds,				       nua_dialog_usage_t *du,				       sip_time_t now){  nua_t *nua = nh->nh_nua;  nua_client_request_t *cr = du->du_cr;  if (cr) {    if (nua_client_resend_request(cr, 0) >= 0)      return;  }  /* Report that we have de-registered */  nua_stack_event(nua, nh, NULL, nua_r_register, NUA_ERROR_AT(__FILE__, __LINE__), NULL);  nua_dialog_usage_remove(nh, ds, du, NULL, NULL);}/** @interal Shut down REGISTER usage. * * @retval >0  shutdown done * @retval 0   shutdown in progress * @retval <0  try again later */static int nua_register_usage_shutdown(nua_handle_t *nh,				       nua_dialog_state_t *ds,				       nua_dialog_usage_t *du){  nua_client_request_t *cr = du->du_cr;  nua_registration_t *nr = NUA_DIALOG_USAGE_PRIVATE(du);  if (cr) {    if (nua_client_is_queued(cr)) /* Already registering. */      return -1;    cr->cr_event = nua_r_unregister;    if (nua_client_resend_request(cr, 1) >= 0)      return 0;  }  /* release the persistant transport for registration */  if (nr->nr_tport)    tport_decref(&nr->nr_tport), nr->nr_tport = NULL;  nua_dialog_usage_remove(nh, ds, du, NULL, NULL);  return 200;}/* ---------------------------------------------------------------------- *//* nua_registration_t interface */#if HAVE_SOFIA_STUN#include <sofia-sip/stun.h>#endifstatic void nua_stack_tport_update(nua_t *nua, nta_agent_t *nta);static int nua_registration_add_contact_and_route(nua_handle_t *nh,						  nua_registration_t *nr,						  msg_t *msg,						  sip_t *sip,						  int add_contact,						  int add_service_route);intnua_stack_init_transport(nua_t *nua, tagi_t const *tags){  url_string_t const *contact1 = NULL, *contact2 = NULL;  char const *name1 = "sip", *name2 = "sip";  char const *certificate_dir = NULL;  tl_gets(tags,          NUTAG_URL_REF(contact1),          NUTAG_SIPS_URL_REF(contact2),          NUTAG_CERTIFICATE_DIR_REF(certificate_dir),          TAG_END());  if (!contact1 && contact2)    contact1 = contact2, contact2 = NULL;  if (contact1 &&      (url_is_string(contact1)        ? strncasecmp(contact1->us_str, "sips:", 5) == 0       : contact1->us_url->url_type == url_sips))    name1 = "sips";  if (contact2 &&       (url_is_string(contact2)        ? strncasecmp(contact2->us_str, "sips:", 5) == 0       : contact2->us_url->url_type == url_sips))    name2 = "sips";  if (!contact1 /* && !contact2 */) {    if (nta_agent_add_tport(nua->nua_nta, NULL,			    TPTAG_IDENT("sip"),			    TPTAG_CERTIFICATE(certificate_dir),			    TAG_NEXT(nua->nua_args)) < 0 &&        nta_agent_add_tport(nua->nua_nta, URL_STRING_MAKE("sip:*:*"),			    TPTAG_IDENT("sip"),			    TPTAG_CERTIFICATE(certificate_dir),			    TAG_NEXT(nua->nua_args)) < 0)      return -1;#if HAVE_SOFIA_STUN    if (stun_is_requested(TAG_NEXT(nua->nua_args)) &&	nta_agent_add_tport(nua->nua_nta, URL_STRING_MAKE("sip:0.0.0.0:*"),			    TPTAG_IDENT("stun"),			    TPTAG_PUBLIC(tport_type_stun), /* use stun */			    TPTAG_CERTIFICATE(certificate_dir),			    TAG_NEXT(nua->nua_args)) < 0) {      SU_DEBUG_0(("nua: error initializing STUN transport\n"));    }#endif  }  else {    if (nta_agent_add_tport(nua->nua_nta, contact1,			    TPTAG_IDENT(name1),			    TPTAG_CERTIFICATE(certificate_dir),			    TAG_NEXT(nua->nua_args)) < 0)      return -1;    if (contact2 &&	nta_agent_add_tport(nua->nua_nta, contact2,			    TPTAG_IDENT(name2),			    TPTAG_CERTIFICATE(certificate_dir),			    TAG_NEXT(nua->nua_args)) < 0)       return -1;  }  if (nua_stack_init_registrations(nua) < 0)    return -1;  return 0;}#if 0  /* Store network detector param value */  if (agent->sa_nw_updates == 0)    agent->sa_nw_updates = nw_updates; 	      NTATAG_DETECT_NETWORK_UPDATES_REF(nw_updates),  unsigned nw_updates = 0;  unsigned nw_updates = 0;  su_network_changed_t *sa_nw_changed;#endifstaticvoid nua_network_changed_cb(nua_t *nua, su_root_t *root){  uint32_t nw_updates = NUA_NW_DETECT_TRY_FULL;  switch (nw_updates) {  case NUA_NW_DETECT_ONLY_INFO:    nua_stack_event(nua, NULL, NULL, nua_i_network_changed, SIP_200_OK, NULL);    break;      case NUA_NW_DETECT_TRY_FULL:    /* 1) Shutdown all tports */    nta_agent_close_tports(nua->nua_nta);    /* 2) Create new tports */    if (nua_stack_init_transport(nua, nua->nua_args) < 0)      /* We are hosed */      nua_stack_event(nua, NULL, NULL, nua_i_network_changed,		      900, "Internal Error", NULL);    else      nua_stack_event(nua, NULL, NULL, nua_i_network_changed,		      SIP_200_OK, NULL);    break;      default:    break;  }  return;}int nua_stack_launch_network_change_detector(nua_t *nua){  su_network_changed_t *snc = NULL;  snc = su_root_add_network_changed(nua->nua_home,				    nua->nua_api_root,				    nua_network_changed_cb,				    nua);    if (!snc)    return -1;

⌨️ 快捷键说明

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