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

📄 tport.c

📁 this is simple sip stack.
💻 C
📖 第 1 页 / 共 5 页
字号:
  return 0;}/** Check if we can bind to IPv6 separately from IPv4 bind */staticint bind6only_check(tport_master_t *mr){  int retval = 0;#if SU_HAVE_IN6  su_sockaddr_t su[1], su4[1];  socklen_t sulen, su4len;  int s6, s4;  if (mr->mr_boundserver)    return 0;  s4 = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);  s6 = socket(AF_INET6, SOCK_DGRAM, IPPROTO_UDP);    memset(su, 0, sizeof *su);  su->su_len = sulen = (sizeof su->su_sin6);  su->su_family = AF_INET6;    memset(su4, 0, sizeof *su4);  su4->su_len = su4len = (sizeof su->su_sin);  su4->su_family = AF_INET;    if (bind(s6, &su->su_sa, sulen) < 0)    ;  else if (getsockname(s6, &su->su_sa, &sulen) < 0)    ;  else if ((su4->su_port = su->su_port) != 0 && 	   bind(s4, &su4->su_sa, su4len) == 0)    retval = 1;  su_close(s6), su_close(s4);  mr->mr_bindv6only = retval;  mr->mr_boundserver = 1;#endif  return retval;}/* Number of supported transports */#define TPORT_N (8)/** Return list of addrinfo structures matching to  * canon/host/service/protocol */staticint tport_server_addrinfo(tport_master_t *mr,			  char const *canon,			  int family,			  char const *host, 			  char const *service,			  char const *protocol,			  char const * const transports[],			  su_addrinfo_t **return_addrinfo){  int i, N;  su_addrinfo_t hints[TPORT_N + 1];  *return_addrinfo = NULL;  /*    * Resolve all the transports requested by the protocol   */  for (i = 0, N = 0; transports[i] && N < TPORT_N; i++) {    su_addrinfo_t *ai = &hints[N];    if (strcasecmp(transports[i], protocol) != 0 && 	strcmp(protocol, tpn_any) != 0)      continue;    /* Resolve protocol, skip unknown transport protocols. */    if (getprotohints(ai, transports[i], AI_PASSIVE) < 0)      continue;    ai->ai_family = family;    ai->ai_next = &hints[++N];  }  if (N == 0)    return su_seterrno(EPROTONOSUPPORT);  if (transports[i] /* Too many protocols */)     return su_seterrno(ENOMEM);  hints[N - 1].ai_next = NULL;  if (host) {    int error = tport_getaddrinfo(host, service, hints, return_addrinfo);    if (error || !*return_addrinfo) {      SU_DEBUG_3(("%s(%p): su_getaddrinfo(%s, %s) for %s: %s\n", 		  __func__, mr, host ? host : "\"\"", service, protocol,		  su_gai_strerror(error)));      return su_seterrno(error != EAI_MEMORY ? ENOENT : ENOMEM);    }    return 0;  }  return tport_get_local_addrinfo(mr, service, hints, return_addrinfo);}/** Convert localinfo into addrinfo */staticinttport_get_local_addrinfo(tport_master_t *mr, 			 char const *port,			 su_addrinfo_t const *hints,			 su_addrinfo_t **return_ai){  int error, family;  su_localinfo_t lihints[1] = {{ 0 }};  su_localinfo_t *li, *li_result;  su_addrinfo_t const *h;  su_addrinfo_t *ai, **prev;  su_sockaddr_t *su;  unsigned long lport = 0;  char *rest;  prev = return_ai, *prev = NULL;  if (port) {    lport = strtoul(port, &rest, 10);    if (lport >= 65536) {      su_seterrno(EINVAL);      return -1;    }  }  family = hints->ai_family;  for (h = hints->ai_next; h && family; h = h->ai_next)    if (h->ai_family != family)      family = 0;  lihints->li_flags = 0;  lihints->li_family = family;  lihints->li_scope = LI_SCOPE_GLOBAL | LI_SCOPE_SITE | LI_SCOPE_HOST;  error = su_getlocalinfo(lihints, &li_result);  if (error) {#if SU_HAVE_IN6    SU_DEBUG_3(("%s(%p): su_getlocalinfo() for %s address: %s\n", 		__func__, mr, 		family == AF_INET6 ? "ip6" 		: family == AF_INET ? "ip4" : "ip",		su_gli_strerror(error)));#else    SU_DEBUG_3(("%s(%p): su_getlocalinfo() for %s address: %s\n", 		__func__, mr, 		family == AF_INET ? "ip4" : "ip",		su_gli_strerror(error)));#endif    su_seterrno(ENOENT);    return -1;  }  for (li = li_result; li; li = li->li_next) {    for (h = hints; h; h = h->ai_next) {      if (h->ai_family && h->ai_family != li->li_family)	continue;      ai = calloc(1, sizeof *ai + li->li_addrlen);      if (ai == NULL)	break;          *prev = ai, prev = &ai->ai_next;      ai->ai_flags = AI_PASSIVE | TP_AI_ANY;      ai->ai_family = li->li_family;      ai->ai_socktype = h->ai_socktype;      ai->ai_protocol = h->ai_protocol;      ai->ai_canonname = h->ai_canonname;      ai->ai_addr = memcpy(ai + 1, li->li_addr, 			   ai->ai_addrlen = li->li_addrlen);      su = (void *)ai->ai_addr;      su->su_port = htons(lport);    }  }  su_freelocalinfo(li_result);  if (li) {    tport_freeaddrinfo(*return_ai);    su_seterrno(ENOMEM);    return -1;  }  if (*return_ai == NULL) {    su_seterrno(ENOENT);    return -1;  }  return 0;}static inline su_addrinfo_t *get_next_addrinfo(su_addrinfo_t **all);/** Translate address and service. * * This is a getaddrinfo() supporting multiple hints in a list. */int tport_getaddrinfo(char const *node, char const *service,		      su_addrinfo_t const *hints,		      su_addrinfo_t **res){  su_addrinfo_t const *h0;  su_addrinfo_t *tbf, **prev;  int error = EAI_SOCKTYPE;  int i, N;  su_addrinfo_t *all[TPORT_N + 1]; /* Lists for all supported transports */  su_addrinfo_t *results[TPORT_N + 1];   void *addr;  int addrlen;  *res = NULL;  for (N = 0, h0 = hints; h0; h0 = h0->ai_next) {    su_addrinfo_t h[1];    *h = *h0, h->ai_next = NULL, h->ai_canonname = NULL;    error = su_getaddrinfo(node, service, h, &all[N]);    results[N] = all[N];    if (error == EAI_SOCKTYPE) {      SU_DEBUG_7(("%s(): su_getaddrinfo(%s, %s) for %s: %s\n", 		  __func__, node ? node : "\"\"", service,		  h0->ai_canonname, su_gai_strerror(error)));      continue;    }    if (error || !all[N])      break;    N++;  }  if (h0)    for (i = 0; i < N; i++)      su_freeaddrinfo(all[i]);  if (error)    return error;  /* Combine all the valid addrinfo structures to a single list */  prev = &tbf, tbf = NULL;  for (;;) {    su_addrinfo_t *ai = NULL, *ai0;    for (i = 0, h0 = hints; i < N; i++, h0 = h0->ai_next) {      if ((ai = get_next_addrinfo(&results[i])))	break;    }    if (i == N)      break;    assert(ai);    addr = SU_ADDR((su_sockaddr_t *)ai->ai_addr);    addrlen = SU_ADDRLEN((su_sockaddr_t *)ai->ai_addr);    /* Copy all the addrinfo structures with same address to the list */    for (; i < N; i++, h0 = h0->ai_next) {      while ((ai0 = get_next_addrinfo(&results[i]))) {	void *a = SU_ADDR((su_sockaddr_t *)ai0->ai_addr);	if (memcmp(addr, a, addrlen)) /* Different address */	  break;		results[i] = ai0->ai_next;	ai = calloc(1, sizeof *ai + ai0->ai_addrlen);	if (ai == NULL) 	  goto error;	*prev = memcpy(ai, ai0, sizeof *ai); prev = &ai->ai_next; *prev = NULL;	ai->ai_addr = memcpy(ai + 1, ai0->ai_addr, ai0->ai_addrlen);	ai->ai_canonname = h0->ai_canonname;      }    }  }      for (i = 0; i < N; i++)    su_freeaddrinfo(all[i]);    *res = tbf;  return 0; error:  for (i = 0; i < N; i++)    su_freeaddrinfo(all[i]);  tport_freeaddrinfo(tbf);  return EAI_MEMORY;}static inlinesu_addrinfo_t *get_next_addrinfo(su_addrinfo_t **all){  su_addrinfo_t *ai;  while ((ai = *all)) {    if (ai->ai_family == AF_INET)      return ai;#if SU_HAVE_IN6    if (ai->ai_family == AF_INET6)      return ai;#endif    *all = ai->ai_next;  }  return ai;}staticvoid tport_freeaddrinfo(su_addrinfo_t *ai){  su_addrinfo_t *ai_next;  while (ai) {    ai_next = ai->ai_next;    free(ai);    ai = ai_next;  }}staticint tport_addrinfo_copy(su_addrinfo_t *dst, void *addr, socklen_t addrlen,			su_addrinfo_t const *src){  if (addrlen < src->ai_addrlen)    return -1;  memcpy(dst, src, sizeof *dst);  if (src->ai_addrlen < addrlen)    memset(addr, 0, addrlen);  dst->ai_addr = memcpy(addr, src->ai_addr, src->ai_addrlen);  dst->ai_next = NULL;  return 0;}/** Close a transport.  *  * The function tport_close() closes a socket associated with a transport * object. */void tport_close(tport_t *self){  int i;  SU_DEBUG_5(("%s(%p): " TPN_FORMAT "\n", "tport_close", self,	      TPN_ARGS(self->tp_name)));  self->tp_closed = 1;  self->tp_send_close = 3;  self->tp_recv_close = 3;  if (self->tp_params->tpp_sdwn_error && self->tp_pused)    tport_error_report(self, -1, NULL);  if (self->tp_pri->pri_vtable->vtp_shutdown)    self->tp_pri->pri_vtable->vtp_shutdown(self, 2);  else if (self->tp_socket != -1)    shutdown(self->tp_socket, 2);  if (self->tp_index)    su_root_deregister(self->tp_master->mr_root, self->tp_index);  self->tp_index = 0;#if SU_HAVE_BSDSOCK  if (self->tp_socket != -1)    su_close(self->tp_socket);  self->tp_socket = -1;#endif  /* Zap the queued messages */  if (self->tp_queue) {    int N = self->tp_params->tpp_qsize;    for (i = 0; i < N; i++) {      if (self->tp_queue[i])	msg_ref_destroy(self->tp_queue[i]), self->tp_queue[i] = NULL;    }  }  self->tp_index = 0;  self->tp_events = 0;}/** Shutdown a transport. * * The tport_shutdown() shuts down a full-duplex transport connection * partially or completely. If @a how is 0, the further incoming data is * shut down. If @a how is 1, further outgoing data is shut down. If @a how * is 2, both incoming and outgoing traffic is shut down. * */int tport_shutdown(tport_t *self, int how){  if (!tport_is_secondary(self))    return -1;  SU_DEBUG_7(("%s(%p, %d)\n", "tport_shutdown", self, how));  if (!tport_is_tcp(self) ||      how < 0 ||       (how == 0 && self->tp_send_close) ||      (how == 1 && self->tp_recv_close > 1) ||       how >= 2) {    tport_close(self);    return 1;  }  if (self->tp_pri->pri_vtable->vtp_shutdown)    self->tp_pri->pri_vtable->vtp_shutdown(self, how);  else    shutdown(self->tp_socket, how);  if (how == 0) {    self->tp_recv_close = 2;    tport_set_events(self, 0, SU_WAIT_IN);    if (self->tp_params->tpp_sdwn_error && self->tp_pused)      tport_error_report(self, -1, NULL);  }  else if (how == 1) {    self->tp_send_close = 2;    tport_set_events(self, 0, SU_WAIT_OUT);    if (self->tp_queue && self->tp_queue[self->tp_qhead]) {      int i, N = self->tp_params->tpp_qsize;      for (i = 0; i < N; i++) {	if (self->tp_queue[i]) {	  tport_pending_errmsg(self, self->tp_queue[i], EPIPE);	  msg_ref_destroy(self->tp_queue[i]), self->tp_queue[i] = NULL;	}      }    }  }  return 0;}static inlineunsigned long tport_now(void){  return su_now().tv_sec;}/** Transport timer function. */staticvoid tport_tick(su_root_magic_t *magic, su_timer_t *t, tport_master_t *mr){  tport_primary_t *dad;  tport_t *tp, *tp_next;  su_time_t now = su_now();  int ts = su_time_ms(now);  /* Go through all primary transports */  for (dad = mr->mr_primaries; dad; dad = dad->pri_next) {    if (dad->pri_primary->tp_addrinfo->ai_protocol == IPPROTO_SCTP) {      /* Go through all SCTP connections */      tp = dad->pri_secondary;      for (tp = tprb_first(tp); tp; tp = tp_next) {	tp_next = tprb_succ(tp);	if (tp->tp_queue && tp->tp_queue[tp->tp_qhead]) {	  SU_DEBUG_9(("tport_tick(%p) - trying to send to %s/%s:%s\n", 		      tp, tp->tp_protoname, tp->tp_host, tp->tp_port));	  tport_send_queue(tp);	}      }          }    /* Go through all secondary transports with incomplete messages */    for (tp = tprb_first(dad->pri_secondary); tp; tp = tp_next) {      msg_t *msg = tp->tp_msg;      int closed;      if (msg &&	  tp->tp_params->tpp_timeout != UINT_MAX && 	  tp->tp_params->tpp_timeout < ts - (int)tp->tp_time &&	  !msg_is_streaming(msg)) {	SU_DEBUG_5(("tport_tick(%p): incomplete message idle for %d ms\n",		    tp, ts - (int)tp->tp_time));	msg_set_streaming(msg, 0);	msg_set_flags(msg, MSG_FLG_ERROR | MSG_FLG_TRUNC | MSG_FLG_TIMEOUT);	tport_deliver(tp, msg, NULL, NULL, now);	tp->tp_msg = NULL;      }      tp_next = tprb_succ(tp);      if (tp->tp_refs)	continue;      closed = tport_is_closed(tp);      if (!closed &&	  !(tp->tp_params->tpp_idle > 0 	    && tp->tp_params->tpp_idle < ts - (int)tp->tp_time)) {	continue;      }      if (closed) {	SU_DEBUG_5(("tport_tick(%p): closed, zapping\n", tp));      } else {	SU_DEBUG_5(("tport_tick(%p): unused for %d ms, closing and zapping\n",		    tp, ts - (int)tp->tp_time));	if (!tport_is_closed(tp))	  tport_close(tp);      }      tport_zap_secondary(tp);    }  }

⌨️ 快捷键说明

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