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

📄 outbound.c

📁 Sofia SIP is an open-source SIP User-Agent library, compliant with the IETF RFC3261 specification.
💻 C
📖 第 1 页 / 共 3 页
字号:
  }  if (status < 200)    return 0;  if (sip == NULL) {    SU_DEBUG_3(("outbound(%p): keepalive %u %s\n", (void *)ob->ob_owner,		status, phrase));    ob->ob_oo->oo_keepalive_error(ob->ob_owner, ob, status, phrase, TAG_END());    return 0;  }  if (status == 401 || status == 407) {    if (sip->sip_www_authenticate)      challenged += auc_challenge(ob->ob_keepalive.auc,				  ob->ob_home,				  sip->sip_www_authenticate,				  sip_authorization_class) > 0;    if (sip->sip_proxy_authenticate)      challenged += auc_challenge(ob->ob_keepalive.auc,				  ob->ob_home,				  sip->sip_proxy_authenticate,				  sip_proxy_authorization_class) > 0;    if (ob->ob_oo->oo_credentials)      credentials = ob->ob_oo->oo_credentials(ob->ob_owner,					      ob->ob_keepalive.auc);  }  binding_check = outbound_nat_detect(ob, request, sip);  if (orq == ob->ob_keepalive.orq)    ob->ob_keepalive.orq = NULL;  nta_outgoing_destroy(orq);  if (binding_check > 1) {    /* Bindings have changed */    if (outbound_contacts_from_via(ob, sip->sip_via) == 0) {      /* XXX - Destroy old keepalive template message */      /* re-REGISTER */      ob->ob_oo->oo_refresh(ob->ob_owner, ob);      return 0;    }  }  if (binding_check <= 1 && ob->ob_registered && ob->ob_keepalive.validating) {    int failed = 0;    unsigned loglevel = 3;    if (challenged > 0 && credentials > 0) {      keepalive_options_with_registration_probe(ob);      return 0;    }    if (status < 300 && ob->ob_keepalive.validated) {      loglevel = 5;      if (ob->ob_validated) 	loglevel = 99;		/* only once */      ob->ob_validated = ob->ob_once_validated = 1;    }    else if (status == 401 || status == 407 || status == 403)       loglevel = 5, failed = 1;    else      loglevel = 3, failed = 1;          if (loglevel >= SU_LOG->log_level) {      sip_contact_t const *m = ob->ob_rcontact;      if  (m)	su_llog(SU_LOG, loglevel,       		"outbound(%p): %s <" URL_PRINT_FORMAT ">\n",		(void *)ob->ob_owner,		failed ? "FAILED to validate" : "validated",		URL_PRINT_ARGS(m->m_url));      else	su_llog(SU_LOG, loglevel,       		"outbound(%p): %s registration\n",		(void *)ob->ob_owner,		failed ? "FAILED to validate" : "validated");      if (failed)	su_llog(SU_LOG, loglevel, "outbound(%p): FAILED with %u %s\n", 		(void *)ob->ob_owner, status, phrase);    }    if (failed)       ob->ob_oo->oo_probe_error(ob->ob_owner, ob, status, phrase, TAG_END());  }  else if (status == 408) {    SU_DEBUG_3(("outbound(%p): keepalive timeout\n", (void *)ob->ob_owner));    ob->ob_oo->oo_keepalive_error(ob->ob_owner, ob, status, phrase, TAG_END());    return 0;  }  ob->ob_keepalive.validating = 0;  if (ob->ob_keepalive.timer)    su_timer_set(ob->ob_keepalive.timer, keepalive_timer, ob);  return 0;}static void keepalive_timer(su_root_magic_t *root_magic,			    su_timer_t *t,			    su_timer_arg_t *ob_casted_as_timer_arg){  outbound_t *ob = (outbound_t *)ob_casted_as_timer_arg;  (void)root_magic;  if (keepalive_options(ob) < 0)    su_timer_set(t, keepalive_timer, ob_casted_as_timer_arg);	/* XXX */}/** @internal Send a keepalive OPTIONS that probes the registration */static int keepalive_options_with_registration_probe(outbound_t *ob){  msg_t *req;  sip_t *sip;  void *request_uri;  if (ob->ob_keepalive.orq)    return 0;  req = msg_copy(ob->ob_keepalive.msg);  if (!req)    return -1;  sip = sip_object(req); assert(sip);  request_uri = sip->sip_to->a_url;  if (nta_msg_request_complete(req, nta_default_leg(ob->ob_nta),       			SIP_METHOD_OPTIONS, request_uri) < 0)    return msg_destroy(req), -1;  if (ob->ob_keepalive.auc[0])    auc_authorization(ob->ob_keepalive.auc, req, (void *)sip,		      "OPTIONS", request_uri, sip->sip_payload);  ob->ob_keepalive.orq =    nta_outgoing_mcreate(ob->ob_nta,			 response_to_keepalive_options,			 ob,			 NULL,			 req,			 TAG_IF(ob->ob_proxy_override,				NTATAG_DEFAULT_PROXY(ob->ob_proxy)),			 SIPTAG_SUBJECT_STR("REGISTRATION PROBE"),			 /* NONE is used to remove			    Max-Forwards: 0 found in ordinary keepalives */			 SIPTAG_MAX_FORWARDS(SIP_NONE),			 TAG_END());  if (!ob->ob_keepalive.orq)    return msg_destroy(req), -1;  ob->ob_keepalive.validating = 1;  ob->ob_keepalive.validated = 0;  return 0;}/** Check if request should be processed by outbound */int outbound_targeted_request(sip_t const *sip){  return     sip && sip->sip_request &&    sip->sip_request->rq_method == sip_method_options &&    sip->sip_accept &&    sip->sip_accept->ac_type &&    strcasecmp(sip->sip_accept->ac_type, outbound_content_type) == 0;}/** Answer to the connectivity probe OPTIONS */int outbound_process_request(outbound_t *ob, 			     nta_incoming_t *irq,			     sip_t const *sip){  /* XXX - We assume that Call-ID is not modified. */  if (strcmp(sip->sip_call_id->i_id, ob->ob_cookie))    return 0;  if (ob->ob_keepalive.validating) {    SU_DEBUG_5(("outbound(%p): registration check OPTIONS received\n", 		(void *)ob->ob_owner));    ob->ob_keepalive.validated = 1;  }  nta_incoming_treply(irq, SIP_200_OK,		      SIPTAG_CONTENT_TYPE_STR(outbound_content_type),		      SIPTAG_PAYLOAD_STR(ob->ob_cookie),		      TAG_END());  return 200;}/* ---------------------------------------------------------------------- *//**@internal * Create contacts for outbound. * * There are two contacts:  * one suitable for registrations (ob_rcontact) and another that can be used * in dialogs (ob_dcontact). */int outbound_contacts_from_via(outbound_t *ob, sip_via_t const *via){  su_home_t *home = ob->ob_home;  sip_contact_t *rcontact, *dcontact;  int reg_id = 0;  char reg_id_param[20] = "";  sip_contact_t *previous_previous, *previous_rcontact, *previous_dcontact;  sip_via_t *v, v0[1], *previous_via;  int contact_uri_changed;  if (!via)    return -1;  v = v0; *v0 = *via; v0->v_next = NULL;  dcontact = ob->ob_oo->oo_contact(ob->ob_owner, home, 1, 				   v, v->v_protocol, NULL);  if (ob->ob_instance && ob->ob_reg_id != 0)    snprintf(reg_id_param, sizeof reg_id_param, ";reg-id=%u", ob->ob_reg_id);  rcontact = ob->ob_oo->oo_contact(ob->ob_owner, home, 0,				   v, v->v_protocol, 				   ob->ob_instance, reg_id_param, NULL);      v = sip_via_dup(home, v);  if (!rcontact || !dcontact || !v) {    msg_header_free(home, (void *)dcontact);    if (rcontact != dcontact)      msg_header_free(home, (void *)rcontact);    msg_header_free(home, (void *)v);    return -1;  }  contact_uri_changed = !ob->ob_rcontact ||    url_cmp_all(ob->ob_rcontact->m_url, rcontact->m_url);  if (contact_uri_changed) {    previous_previous = ob->ob_previous;    previous_dcontact = ob->ob_dcontact;    previous_via = ob->ob_via;    if (ob->ob_registering &&        (reg_id == 0 || ob->ob_info.outbound < outbound_feature_supported))      previous_rcontact = NULL, ob->ob_previous = ob->ob_rcontact;    else      previous_rcontact = ob->ob_rcontact, ob->ob_previous = NULL;    if (ob->ob_previous)      msg_header_replace_param(home, (void*)ob->ob_previous, "expires=0");  }  else {    previous_previous = ob->ob_rcontact;    previous_rcontact = NULL;    previous_dcontact = ob->ob_dcontact;    previous_via = ob->ob_via;  }  ob->ob_contacts = 1;  ob->ob_rcontact = rcontact;  ob->ob_dcontact = dcontact;  ob->ob_via = v;  if (contact_uri_changed) {    ob->ob_registering = 0;    ob->ob_registered = 0;    ob->ob_validated = 0;  }  msg_header_free(home, (void *)previous_rcontact);  msg_header_free(home, (void *)previous_previous);  if (previous_dcontact != ob->ob_previous &&      previous_dcontact != previous_rcontact &&      previous_dcontact != previous_previous)    msg_header_free(home, (void *)previous_dcontact);  msg_header_free(home, (void *)previous_via);  return 0;}/**Set new contact. * * @retval 0 when successful * @retval -1 error setting contact */int outbound_set_contact(outbound_t *ob,			 sip_contact_t const *application_contact,			 sip_via_t const *v,			 int terminating){  su_home_t *home = ob->ob_home;  sip_contact_t *rcontact = NULL, *dcontact = NULL, *previous = NULL;  sip_contact_t *m1, *m2, *m3;  int contact_uri_changed = 0;  m1 = ob->ob_rcontact;  m2 = ob->ob_dcontact;  m3 = ob->ob_previous;  if (terminating) {    if (ob->ob_by_stack && application_contact == NULL)      return 0;        if (ob->ob_contacts)      previous = ob->ob_rcontact;  }  else if (application_contact) {    rcontact = sip_contact_dup(home, application_contact);    if (!ob->ob_rcontact || 	url_cmp_all(ob->ob_rcontact->m_url, application_contact->m_url)) {      contact_uri_changed = 1;      previous = ob->ob_contacts ? ob->ob_rcontact : NULL;    }  }  else if (ob->ob_by_stack) {    return 0;    /* Xyzzy - nothing happens */  }  else if (v) {    char const *tport = !v->v_next ? v->v_protocol : NULL;     char reg_id_param[20];    dcontact = ob->ob_oo->oo_contact(ob->ob_owner, home, 1, 				     v, tport, NULL);    if (!dcontact)      return -1;    if (ob->ob_instance && ob->ob_reg_id != 0)      snprintf(reg_id_param, sizeof reg_id_param, ";reg-id=%u", ob->ob_reg_id);    rcontact = ob->ob_oo->oo_contact(ob->ob_owner, home, 0,				     v, v->v_protocol, 				     ob->ob_instance, reg_id_param, NULL);    if (!rcontact)      return -1;    if (!ob->ob_rcontact || 	url_cmp_all(ob->ob_rcontact->m_url, rcontact->m_url)) {      contact_uri_changed = 1;      previous = ob->ob_contacts ? ob->ob_rcontact : NULL;    }  }      ob->ob_by_stack = application_contact == NULL;  ob->ob_contacts = rcontact != NULL;  ob->ob_rcontact = rcontact;  ob->ob_dcontact = dcontact;  ob->ob_previous = previous;  if (contact_uri_changed) {    ob->ob_registering = 0;    ob->ob_registered = 0;    ob->ob_validated = 0;    ob->ob_once_validated = 0;  }  if (m1 != previous)    msg_header_free(home, (void *)m1);  if (m2 != m1 && m2 != m3)    msg_header_free(home, (void *)m2);  msg_header_free(home, (void *)m3);  return 0;}sip_contact_t const *outbound_dialog_contact(outbound_t const *ob){  if (ob == NULL)    return NULL;  else if (ob->ob_gruu)    return ob->ob_gruu;  else    return ob->ob_dcontact;}sip_contact_t const *outbound_dialog_gruu(outbound_t const *ob){  return ob ? ob->ob_gruu : NULL;}/* ---------------------------------------------------------------------- */static enum outbound_featurefeature_level(sip_t const *sip, char const *tag, int level){  if (sip_has_feature(sip->sip_require, tag))    return outbound_feature_required;  else if (sip_has_feature(sip->sip_supported, tag))    return outbound_feature_supported;  else if (sip_has_feature(sip->sip_unsupported, tag))    return outbound_feature_unsupported;  else    return level;}void outbound_peer_info(outbound_t *ob, sip_t const *sip){  if (sip == NULL) {    ob->ob_info.outbound = outbound_feature_unsure;    ob->ob_info.gruu = outbound_feature_unsure;    ob->ob_info.pref = outbound_feature_unsure;    return;  }  ob->ob_info.outbound = feature_level(sip, "outbound", ob->ob_info.outbound);  ob->ob_info.gruu = feature_level(sip, "gruu", ob->ob_info.gruu);  ob->ob_info.pref = feature_level(sip, "pref", ob->ob_info.pref);}

⌨️ 快捷键说明

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