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

📄 nta.c

📁 this is simple sip stack.
💻 C
📖 第 1 页 / 共 5 页
字号:
staticsip_via_t const *agent_tport_via(tport_t *tport){  sip_via_t *v = tport_magic(tport);  while (v && v->v_next)    v = v->v_next;  return v;}/** Insert Via to a request message */staticint outgoing_insert_via(nta_outgoing_t *orq, 			sip_via_t const *via){  nta_agent_t *self = orq->orq_agent;  msg_t *msg = orq->orq_request;  sip_t *sip = sip_object(msg);  char const *branch = orq->orq_via_branch;  int user_via = orq->orq_user_via;  sip_via_t *v;  int clear = 0;  assert(sip); assert(via);  if (user_via && sip->sip_via) {    /* Use existing Via provided by application */    v = sip->sip_via;  }  else if (msg && via && sip->sip_request &&	   (v = sip_via_copy(msg_home(msg), via))) {    msg_header_insert(msg, (msg_pub_t *)sip, (msg_header_t *)v);  }  else    return -1;  if (!v->v_rport &&       ((self->sa_rport && v->v_protocol == sip_transport_udp) ||       (self->sa_tcp_rport && v->v_protocol == sip_transport_tcp)))    msg_header_add_param(msg_home(msg), v->v_common, "rport");  if (!orq->orq_tpn->tpn_comp)    msg_header_remove_param(v->v_common, "comp");  if (branch && branch != v->v_branch) {    char const *bvalue = branch + strcspn(branch, "=");    if (*bvalue) bvalue++;    if (!v->v_branch || strcasecmp(bvalue, v->v_branch))      msg_header_replace_param(msg_home(msg), v->v_common, branch);  }  if (via->v_protocol != v->v_protocol &&      strcasecmp(via->v_protocol, v->v_protocol))    clear = 1, v->v_protocol = via->v_protocol;  /* XXX - should we do this? */  if (via->v_host != v->v_host &&      str0cmp(via->v_host, v->v_host))    clear = 1, v->v_host = via->v_host;  if (via->v_port != v->v_port &&      str0cmp(via->v_port, v->v_port))    clear = 1, v->v_port = via->v_port;  if (clear)    msg_fragment_clear(v->v_common);  return 0;}/** Get destination name from Via.  * * If @a using_rport is non-null, try rport. * If *using_rport is non-zero, try rport even if <protocol> is not UDP. * If <protocol> is UDP, set *using_rport to zero. */staticint nta_tpn_by_via(tp_name_t *tpn, sip_via_t const *v, int *using_rport){  if (!v)    return -1;  tpn->tpn_proto = sip_via_transport(v);  tpn->tpn_canon = v->v_host;  if (v->v_maddr)    tpn->tpn_host = v->v_maddr;  else if (v->v_received)    tpn->tpn_host = v->v_received;  else    tpn->tpn_host = v->v_host;  tpn->tpn_port = sip_via_port(v, using_rport);  tpn->tpn_comp = v->v_comp;  tpn->tpn_ident = NULL;  return 0;}/** Get transport name from URL. */int nta_tpn_by_url(su_home_t *home,		   tp_name_t *tpn,		   char const **scheme,		   char const **port,		   url_string_t const *us){  url_t url[1];  int n;  char *b;  n = url_xtra(us->us_url);  b = su_alloc(home, n);  if (b == NULL || url_dup(b, n, url, us->us_url) < 0) {    su_free(home, b);    return -1;  }  if (url->url_type != url_sip &&       url->url_type != url_sips &&      url->url_type != url_im &&      url->url_type != url_pres) {    su_free(home, b);    return -1;  }  SU_DEBUG_7(("nta: selecting scheme %s\n", url->url_scheme));  *scheme = url->url_scheme;  if (strcasecmp(url->url_scheme, "sips") == 0)    tpn->tpn_proto = "tls";  else    tpn->tpn_proto = "*";  tpn->tpn_canon = url->url_host;  tpn->tpn_host = url->url_host;  if (url->url_params) {    for (b = (char *)url->url_params; b[0]; b += n) {      n = strcspn(b, ";");      if (n > 10 && strncasecmp(b, "transport=", 10) == 0)	tpn->tpn_proto = b + 10;      else if (n > 5 && strncasecmp(b, "comp=", 5) == 0)	tpn->tpn_comp = b + 5;      else if (n > 6 && strncasecmp(b, "maddr=", 6) == 0)	tpn->tpn_host = b + 6;      if (b[n])	b[n++] = '\0';    }  }  if ((*port = url->url_port))    tpn->tpn_port = url->url_port;  tpn->tpn_ident = NULL;  return 0;}/** Handle transport errors. */staticvoid agent_tp_error(nta_agent_t *agent,		    tport_t *tport,		    int errcode,		    char const *remote){  su_llog(nta_log, 1,	  "nta_agent: tport: %s%s%s\n",	  remote ? remote : "", remote ? ": " : "",	  su_strerror(errcode));}/** Handle updated transport addresses */static void agent_update_tport(nta_agent_t *self, tport_t *tport){  /* Initialize local Vias first */  agent_init_via(self, tport_primaries(self->sa_tports), 0);  if (self->sa_update_tport) {    self->sa_update_tport(self->sa_update_magic, self);  }  else {    /* XXX - we should do something else? */    SU_DEBUG_3(("nta(%p): transport address updated\n", self));  }}/* ====================================================================== *//* 3) Message dispatch */static void agent_recv_request(nta_agent_t *agent,			       msg_t *msg,			       sip_t *sip,			       tport_t *tport);static int agent_check_request_via(nta_agent_t *agent,				   msg_t *msg,				   sip_t *sip,				   sip_via_t *v,				   tport_t *tport);static int agent_aliases(nta_agent_t const *, url_t [], tport_t *);static void agent_recv_response(nta_agent_t*, msg_t *, sip_t *,				sip_via_t *, tport_t*);static void agent_recv_garbage(nta_agent_t*, msg_t*, tport_t*);/** Handle incoming message. */staticvoid agent_recv_message(nta_agent_t *agent,			tport_t *tport,			msg_t *msg,			sip_via_t *tport_via,			su_time_t now){  sip_t *sip = sip_object(msg);  agent->sa_millisec = su_time_ms(agent->sa_now = now);  if (sip && sip->sip_request) {    agent_recv_request(agent, msg, sip, tport);  }  else if (sip && sip->sip_status) {    agent_recv_response(agent, msg, sip, tport_via, tport);  }  else {    agent_recv_garbage(agent, msg, tport);  }  agent->sa_millisec = 0;}/** @internal Handle incoming requests. */staticvoid agent_recv_request(nta_agent_t *agent,			msg_t *msg,			sip_t *sip,			tport_t *tport){  nta_leg_t *leg;  nta_incoming_t *irq, *merge = NULL, *ack = NULL;  sip_method_t method = sip->sip_request->rq_method;  char const *method_name = sip->sip_request->rq_method_name;  url_t url[1];  unsigned cseq = sip->sip_cseq ? sip->sip_cseq->cs_seq : 0;  int insane, errors, stream;  agent->sa_stats->as_recv_msg++;  agent->sa_stats->as_recv_request++;  SU_DEBUG_5(("nta: received %s " URL_PRINT_FORMAT " %s (CSeq %u)\n",	      method_name,	      URL_PRINT_ARGS(sip->sip_request->rq_url),	      sip->sip_request->rq_version, cseq));  stream = tport_is_stream(tport);  /* Try to use compression on reverse direction if Via has comp=sigcomp  */  if (stream &&       sip->sip_via->v_comp &&      tport_can_send_sigcomp(tport) &&      tport_name(tport)->tpn_comp == NULL &&       tport_has_compression(tport_parent(tport), sip->sip_via->v_comp)) {    tport_set_compression(tport, sip->sip_via->v_comp);  }  if (sip->sip_flags & MSG_FLG_TOOLARGE) {    SU_DEBUG_5(("nta: %s (%u) is %s\n", 		method_name, cseq, sip_413_Request_too_large));    agent->sa_stats->as_bad_request++;    nta_msg_treply(agent, msg, SIP_413_REQUEST_TOO_LARGE,		   NTATAG_TPORT(tport),		   NTATAG_INCOMPLETE(1),		   		   TPTAG_SDWN_AFTER(stream),		   TAG_END());    return;  }  insane = 0;  if (agent->sa_bad_req_mask)    errors = msg_extract_errors(msg) & agent->sa_bad_req_mask;  else    errors = sip->sip_error != NULL;  if (errors ||      (sip->sip_flags & MSG_FLG_ERROR) /* Fatal error */ ||       (insane = (sip_sanity_check(sip) < 0))) {    sip_header_t const *h;    char const *badname = NULL, *phrase;        agent->sa_stats->as_bad_message++;    agent->sa_stats->as_bad_request++;    if (insane)      SU_DEBUG_5(("nta: %s (%u) %s\n", method_name, cseq,		  "failed sanity check"));    for (h = (sip_header_t const *)sip->sip_error; h; h = h->sh_next) {      char const *bad;      if (h->sh_class == sip_error_class)	bad = h->sh_error->er_name;      else 	bad = h->sh_class->hc_name;      if (bad)	SU_DEBUG_5(("nta: %s has bad %s header\n", method_name, bad));            if (!badname)	badname = bad;    }    if (sip->sip_via && method != sip_method_ack) {      msg_t *reply = nta_msg_create(agent, 0);            if (reply) {	agent_check_request_via(agent, msg, sip, sip->sip_via, tport);	if (badname)	  phrase = su_sprintf(msg_home(reply), "Bad %s Header", badname);	else	  phrase = sip_400_Bad_request;	SU_DEBUG_5(("nta: %s (%u) is %s\n", method_name, cseq, phrase));		nta_msg_mreply(agent, reply, sip_object(reply),		       400, phrase,		       msg,		       NTATAG_TPORT(tport), 		       NTATAG_INCOMPLETE(1), 		       TPTAG_SDWN_AFTER(stream),		       TAG_END());      }    } else {      msg_destroy(msg);      if (stream)		/* Send FIN */	tport_shutdown(tport, 1);    }    return;  }  if (str0casecmp(sip->sip_request->rq_version, sip_version_2_0) != 0) {    agent->sa_stats->as_bad_request++;    agent->sa_stats->as_bad_message++;    SU_DEBUG_5(("nta: bad version %s for %s (%u)\n",		sip->sip_request->rq_version, method_name, cseq));    nta_msg_treply(agent, msg, SIP_505_VERSION_NOT_SUPPORTED,		   NTATAG_TPORT(tport), 		   TPTAG_SDWN_AFTER(stream),		   TAG_END());    return;  }  if (agent_check_request_via(agent, msg, sip, sip->sip_via, tport) < 0) {    agent->sa_stats->as_bad_message++;    agent->sa_stats->as_bad_request++;    SU_DEBUG_5(("nta: %s (%u) %s\n", method_name, cseq, "has invalid Via"));    msg_destroy(msg);    return;  }  /* First, try existing incoming requests */  irq = incoming_find(agent, sip, sip->sip_via, &merge, &ack);  if (irq) {    /* Match - this is a retransmission */    SU_DEBUG_5(("nta: %s (%u) going to existing %s transaction\n",		method_name, cseq, irq->irq_rq->rq_method_name));    if (incoming_recv(irq, msg, sip, tport) >= 0)      return;  }  else if (ack) {    /* Match - this is an ACK or CANCEL or PRACK */    SU_DEBUG_5(("nta: %s (%u) is going to %s (%u)\n",		method_name, cseq,		ack->irq_rq->rq_method_name, ack->irq_cseq->cs_seq));    if (method == sip_method_ack) {      if (incoming_ack(ack, msg, sip, tport) >= 0)	return;    }    else if (method == sip_method_cancel) {      if (incoming_cancel(ack, msg, sip, tport) >= 0)	return;    }    else if (method == sip_method_prack) {      if (reliable_recv(ack, msg, sip, tport) >= 0)	return;    }    else {      assert(!method);    }  }  else if (merge) {    SU_DEBUG_5(("nta: %s (%u) %s\n",		method_name, cseq, "is a merged request"));    if (incoming_merge(merge, msg, sip, tport) >= 0)      return;  }  *url = *sip->sip_request->rq_url;  url->url_params = NULL;  agent_aliases(agent, url, tport); /* canonize urls */  if ((leg = leg_find(agent, 		      method_name, url, 		      sip->sip_call_id,		      sip->sip_from->a_tag, sip->sip_from->a_url, 		      sip->sip_to->a_tag, sip->sip_to->a_url))) {    /* Try existing dialog */    SU_DEBUG_5(("nta: %s (%u) %s\n",		method_name, cseq, "going to existing leg"));    leg_recv(leg, msg, sip, tport);    return;  }  else if (!agent->sa_is_stateless &&	   (leg = dst_find(agent, url, method_name))) {    /* Dialogless legs - let application process transactions statefully */    SU_DEBUG_5(("nta: %s (%u) %s\n",		method_name, cseq, "going to a dialogless leg"));    leg_recv(leg, msg, sip, tport);  }  else if (!agent->sa_is_stateless && (leg = agent->sa_default_leg)) {    SU_DEBUG_5(("nta: %s (%u) %s\n",		method_name, cseq, "going to a default leg"));    leg_recv(leg, msg, sip, tport);  }  else if (agent->sa_callback) {    /* Stateless processing for request */    agent->sa_stats->as_trless_request++;    SU_DEBUG_5(("nta: %s (%u) %s\n", 		method_name, cseq, "to message callback"));    (void)agent->sa_callback(agent->sa_magic, agent, msg, sip);  }  else {    agent->sa_stats->as_trless_request++;    SU_DEBUG_5(("nta: %s (%u) no place to go: %d %s\n",		method_name, cseq, SIP_501_NOT_IMPLEMENTED));    if (method != sip

⌨️ 快捷键说明

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