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

📄 nta.c

📁 Internet Phone, Chat, Conferencing
💻 C
📖 第 1 页 / 共 5 页
字号:
		   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));}/* ====================================================================== *//* 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);#if HAVE_SIGCOMP  if (stream &&       tport_can_send_sigcomp(tport) &&      tport_name(tport)->tpn_comp == NULL &&       sip->sip_via->v_comp &&      tport_has_compression(tport_parent(tport), sip->sip_via->v_comp)) {    tport_set_compression(tport, sip->sip_via->v_comp);  }#endif  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_method_ack)      nta_msg_treply(agent, msg, SIP_501_NOT_IMPLEMENTED,		     NTATAG_TPORT(tport),		     TAG_END());    else      msg_destroy(msg);  }}/** Check Via header. * */staticint agent_check_request_via(nta_agent_t *agent,			    msg_t *msg,			    sip_t *sip,			    sip_via_t *v,			    tport_t *tport){  enum { receivedlen = sizeof("received=") - 1 };  char received[receivedlen + TPORT_HOSTPORTSIZE];  char *hostport = received + receivedlen;  char const *rport;  su_sockaddr_t *from;  sip_via_t *tpv = tport_magic(tport);  assert(tport); assert(msg); assert(sip);  assert(sip->sip_request); assert(tpv);  from = (su_sockaddr_t *)msg_addr(msg);  if (v == NULL) {    /* Make up a via line */    v = sip_via_format(msg_home(msg), "SIP/2.0/%s %s",		       tport_name(tport)->tpn_proto,		       tport_hostport(hostport, TPORT_HOSTPORTSIZE, from, 1));    msg_header_insert(msg, (msg_pub_t *)sip, (msg_header_t *)v);    return v ? 0 : -1;  }  if (str0casecmp(v->v_protocol, tpv->v_protocol)) {    tport_hostport(hostport, TPORT_HOSTPORTSIZE, from, 1);    SU_DEBUG_1(("nta: Via check: invalid transport \"%s\" from %s\n",		v->v_protocol, hostport));    return -1;  }  if (v->v_received) {    /* Nasty, nasty */    tport_hostport(hostport, TPORT_HOSTPORTSIZE, from, 1);    SU_DEBUG_1(("nta: Via check: extra received=%s from %s\n",		v->v_received, hostport));    msg_header_remove_param(v->v_common, "received");  }  if (!tport_hostport(hostport, TPORT_HOSTPORTSIZE, from, 0))    return -1;  if (strcasecmp(hostport, v->v_host)) {    int rlen;    /* Add the "received" field */    memcpy(received, "received=", receivedlen);    if (hostport[0] == '[') {      rlen = strlen(hostport + 1) - 1;      memmove(hostport, hostport + 1, rlen);      hostport[rlen] = '\0';    }    msg_header_replace_param(msg_home(msg), v->v_common, 			     su_strdup(msg_home(msg), received));    SU_DEBUG_5(("nta: Via check: %s\n", received));  }  if (!agent->sa_server_rport) {    /*Xyzzy*/;  }  else if (v->v_rport) {    rport = su_sprintf(msg_home(msg), "rport=%u", ntohs(from->su_port));    msg_header_replace_param(msg_home(msg), v->v_common, rport);  }   else if (tport_is_tcp(tport)) {    rport = su_sprintf(msg_home(msg), "rport=%u", ntohs(from->su_port));    msg_header_replace_param(msg_home(msg), v->v_common, rport);  }  return 0;}/** @internal Handle aliases of local node.  * * Return true if @a url is modified. */staticint agent_aliases(nta_agent_t const *agent, url_t url[], tport_t *tport){  sip_contact_t *m;  sip_via_t *lv;  char const *tport_port = "";  if (!url->url_host)    return 0;  if (tport)    tport_port = tport_name(tport)->tpn_port;  assert(tport_port);  for (m = agent->sa_aliases ? agent->sa_aliases : agent->sa_contact;       m;       m = m->m_next) {    if (url->url_type != m->m_url->url_type)      continue;    if (strcasecmp(url->url_host, m->m_url->url_host))      continue;    if (u

⌨️ 快捷键说明

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