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

📄 nua_register.c

📁 this is simple sip stack.
💻 C
📖 第 1 页 / 共 3 页
字号:
				  NH_PGET(nh, instance));    if (!ob)      goto error;  }  if (ob) {    outbound_set_options(ob,			 NH_PGET(nh, outbound),			 NH_PGET(nh, keepalive),			 NH_PISSET(nh, keepalive_stream)			 ? NH_PGET(nh, keepalive_stream)			 : NH_PGET(nh, keepalive));    nua_stack_outbound_features(nh, ob);    outbound_stop_keepalive(ob);    if (outbound_set_contact(ob, sip->sip_contact, nr->nr_contact, terminating) < 0)      goto error;  }  /* This calls nta_outgoing_mcreate() but adds a few tags */  cr->cr_orq =    outbound_register_request(ob, terminating,			      nr->nr_by_stack ? nr->nr_contact : NULL,			      nua->nua_nta,			      process_response_to_register, nh, NULL,			      msg,			      SIPTAG_END(), 			      TAG_IF(terminating, NTATAG_SIGCOMP_CLOSE(1)),			      TAG_IF(!terminating, NTATAG_COMP("sigcomp")),			      TAG_NEXT(tags));  if (!cr->cr_orq)    goto error;  cr->cr_usage = du;  return cr->cr_event = e; error:  msg_destroy(msg);  msg_destroy(cr->cr_msg), cr->cr_msg = NULL;  nua_dialog_usage_remove(nh, nh->nh_ds, du);      return UA_EVENT1(e, NUA_INTERNAL_ERROR);}static voidrestart_register(nua_handle_t *nh, tagi_t *tags){  struct nua_client_request *cr = nh->nh_cr;  msg_t *msg;  nua_dialog_usage_t *du = cr->cr_usage;  nua_registration_t *nr = nua_dialog_usage_private(du);  int terminating = du && du->du_terminating;  cr->cr_restart = NULL;  if (!cr->cr_msg)    return;  msg = nua_creq_msg(nh->nh_nua, nh, cr, 1,		     SIP_METHOD_UNKNOWN,		     TAG_NEXT(tags));  if (!msg)    return;			/* XXX - Uh-oh */  if (terminating)    unregister_expires_contacts(msg, sip_object(msg));  /* This calls nta_outgoing_mcreate() but adds a few tags */  cr->cr_orq =    outbound_register_request(nr->nr_ob, terminating,			      nr->nr_by_stack ? nr->nr_contact : NULL,			      nh->nh_nua->nua_nta,			      process_response_to_register, nh, NULL,			      msg,			      SIPTAG_END(), 			      TAG_IF(terminating, NTATAG_SIGCOMP_CLOSE(1)),			      TAG_IF(!terminating, NTATAG_COMP("sigcomp")),			      TAG_NEXT(tags));  if (!cr->cr_orq)    msg_destroy(msg);}voidrefresh_register(nua_handle_t *nh, nua_dialog_usage_t *du, sip_time_t now){  nua_t *nua = nh->nh_nua;  nua_client_request_t *cr = nh->nh_cr;  nua_registration_t *nr = nua_dialog_usage_private(du);  nua_event_t e;  msg_t *msg;  sip_t *sip;  int terminating;  if (cr->cr_msg) {    /* Delay of 5 .. 15 seconds */    nua_dialog_usage_set_refresh(du, 5 + (unsigned)random() % 11U);    du->du_pending = refresh_register;    return;  }  if (now > 0)    e = nua_r_register;  else    e = nua_r_destroy, du->du_terminating = 1;  terminating = du->du_terminating;  outbound_stop_keepalive(nr->nr_ob);  cr->cr_msg = msg_copy(du->du_msg);  msg = nua_creq_msg(nua, nh, cr, 1,		     SIP_METHOD_REGISTER,		     NUTAG_USE_DIALOG(1),		     TAG_END());  sip = sip_object(msg);  if (!msg || !sip)    goto error;  if (terminating)    unregister_expires_contacts(msg, sip);  cr->cr_orq =    outbound_register_request(nr->nr_ob, terminating,			      nr->nr_by_stack ? nr->nr_contact : NULL,			      nh->nh_nua->nua_nta,			      process_response_to_register, nh, NULL,			      msg,			      SIPTAG_END(), 			      TAG_IF(terminating, NTATAG_SIGCOMP_CLOSE(1)),			      TAG_IF(!terminating, NTATAG_COMP("sigcomp")),			      TAG_END());  if (!cr->cr_orq)    goto error;  cr->cr_usage = du;  cr->cr_event = e;  return; error:  if (terminating)    nua_dialog_usage_remove(nh, nh->nh_ds, du);  msg_destroy(msg);  msg_destroy(cr->cr_msg);  UA_EVENT2(e, NUA_INTERNAL_ERROR, TAG_END());  return;}staticint process_response_to_register(nua_handle_t *nh,				 nta_outgoing_t *orq,				 sip_t const *sip){  struct nua_client_request *cr = nh->nh_cr;  nua_dialog_usage_t *du = cr->cr_usage;  nua_registration_t *nr = nua_dialog_usage_private(du);  int status, ready, reregister, terminating;  char const *phrase;  msg_t *_reqmsg = nta_outgoing_getrequest(orq);  sip_t *req = sip_object(_reqmsg); msg_destroy(_reqmsg);  assert(sip);  assert(du && du->du_class == nua_register_usage);  status = sip->sip_status->st_status;  phrase = sip->sip_status->st_phrase;  if (status < 200 || !du)    return nua_stack_process_response(nh, cr, orq, sip, TAG_END());  terminating = du->du_terminating;  if (!terminating)    nua_dialog_store_peer_info(nh, nh->nh_ds, sip);  reregister = outbound_register_response(nr->nr_ob, terminating, req, sip);  if (reregister < 0)    SET_STATUS1(NUA_INTERNAL_ERROR);  else if (reregister >= ob_reregister) {    /* Save msg otherwise nua_creq_check_restart() will zap it */    msg_t *msg = msg_ref_create(cr->cr_msg);    if (nua_creq_check_restart(nh, cr, orq, sip, restart_register)) {      msg_destroy(msg);      return 0;    }    assert(cr->cr_msg == NULL);    cr->cr_msg = msg;    if (reregister >= ob_reregister_now) {      /* We can try to reregister immediately */      nua_creq_restart_with(nh, cr, orq, 100, "Updated Contact",			    restart_register,			    TAG_END());    }    else {      /* Outbound will invoke refresh_register() later */      nua_creq_save_restart(nh, cr, orq, 100, "Updated Contact",			    restart_register);    }    return 0;  }  if (status >= 300)    if (nua_creq_check_restart(nh, cr, orq, sip, restart_register))      return 0;  ready = !terminating && status < 300;  du->du_ready = ready;  if (status < 300) {    sip_time_t mindelta = 0;    if (!du->du_terminating) {      sip_time_t now = sip_now(), delta, reqdelta;      sip_contact_t const *m, *sent;      /** 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) == 0) {            sip_time_t mdelta = reqdelta;            if (sent->m_expires)              mdelta = strtoul(sent->m_expires, NULL, 10);            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);    if (mindelta)      du->du_pending = refresh_register;  }#if HAVE_SIGCOMP  if (ready) {    struct sigcomp_compartment *cc;    cc = nta_outgoing_compartment(orq);    sigcomp_compartment_unref(nr->nr_compartment);    nr->nr_compartment = cc;  }#endif  /*  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.  */  if (ready) {    su_free(nh->nh_home, nr->nr_route);    nr->nr_route = sip_route_dup(nh->nh_home, sip->sip_service_route);  }  else {    su_free(nh->nh_home, nr->nr_route);    nr->nr_route = NULL;  }  if (ready) {    /* 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 (ready)    if (sip->sip_to->a_url->url_type == url_sips)      nr->nr_secure = 1;  if (nr->nr_ob) {    if (ready) {      outbound_gruuize(nr->nr_ob, sip);      outbound_start_keepalive(nr->nr_ob, orq);    }    else      outbound_stop_keepalive(nr->nr_ob);  }  nua_registration_set_ready(nr, ready);  return nua_stack_process_response(nh, cr, orq, sip, TAG_END());}/* ---------------------------------------------------------------------- *//* 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);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;}intnua_stack_init_registrations(nua_t *nua){  /* Create initial identities: peer-to-peer, public, sips */  nua_registration_t **list = &nua->nua_registrations;  su_home_t *home = nua->nua_dhandle->nh_home;  sip_via_t const *v;  v = nta_agent_public_via(nua->nua_nta);  if (v) {    nua_registration_from_via(list, home, v, 1);  }  v = nta_agent_via(nua->nua_nta);  if (v) {    nua_registration_from_via(list, home, v, 0);  }  else {    sip_via_t v[2];    sip_via_init(v)->v_next = v + 1;    v[0].v_protocol = sip_transport_udp;    v[0].v_host = "addr.is.invalid.";    sip_via_init(v + 1);    v[1].v_protocol = sip_transport_tcp;    v[1].v_host = "addr.is.invalid.";    nua_registration_from_via(list, home, v, 0);  }  nta_agent_bind_tport_update(nua->nua_nta, nua, nua_stack_tport_update);  return 0;}int nua_registration_from_via(nua_registration_t **list,			      su_home_t *home,			      sip_via_t const *via,			      int public){  sip_via_t *v, *pair, /* v2[2], */ *vias, **vv, **prev;  nua_registration_t *nr = NULL, **next;  su_home_t autohome[SU_HOME_AUTO_SIZE(1024)];  int nr_items = 0;  vias = sip_via_copy(su_home_auto(autohome, sizeof autohome), via);  for (; *list; list = &(*list)->nr_next)    ++nr_items;  next = list;  for (vv = &vias; (v = *vv);) {    char const *protocol;    sip_contact_t *contact;    *vv = v->v_next, v->v_next = NULL, pair = NULL;    if (v->v_protocol == sip_transport_tcp)      protocol = sip_transport_udp;    else if (v->v_protocol == sip_transport_udp)      protocol = sip_transport_tcp;    else      protocol = NULL;    if (protocol) {      /* Try to pair vias if we have both udp and tcp */      for (prev = vv; *prev; prev = &(*prev)->v_next) {        if (strcasecmp(protocol, (*prev)->v_protocol))          continue;        if (strcasecmp(v->v_host, (*prev)->v_host))          continue;        if (str0cmp(v->v_port, (*prev)->v_port))          continue;        break;      }      if (*prev) {        pair = *prev; *prev = pair->v_next; pair->v_next = NULL;      }    }    /* if more than one candidate, ignore local entries */    if (v && (*vv || nr_items > 0) && 	host_is_local(v->v_host)) {      SU_DEBUG_9(("nua_register: ignoring contact candidate %s:%s.\n", 		  v->v_host, v->v_port ? v->v_port : ""));      continue;    }         nr = su_zalloc(home, sizeof *nr);    if (!nr)      break;    /* v2[0] = *v; */

⌨️ 快捷键说明

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