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

📄 tport.c

📁 this is simple sip stack.
💻 C
📖 第 1 页 / 共 5 页
字号:
tport_primary_t *tport_alloc_primary(tport_master_t *mr,				     tport_vtable_t const *vtable,				     tp_name_t tpn[1],				     su_addrinfo_t *ai,				     tagi_t const *tags,				     char const **return_culprit){  tport_primary_t *pri, **next;  tport_t *tp;  int save_errno;  for (next = &mr->mr_primaries; *next; next = &(*next)->pri_next)    ;    assert(vtable->vtp_pri_size >= sizeof *pri);  if ((pri = su_home_clone(mr->mr_home, vtable->vtp_pri_size))) {    tport_t *tp = pri->pri_primary;    pri->pri_vtable = vtable;    pri->pri_public = vtable->vtp_public;    tp->tp_master = mr;    tp->tp_pri = pri;    tp->tp_socket = SOCKET_ERROR;    tp->tp_magic = mr->mr_master->tp_magic;    tp->tp_params = pri->pri_params;    memcpy(tp->tp_params, mr->mr_params, sizeof (*tp->tp_params));    tp->tp_reusable = mr->mr_master->tp_reusable;    if (!pri->pri_public)      tp->tp_addrinfo->ai_addr = &tp->tp_addr->su_sa;    SU_DEBUG_5(("%s(%p): new primary tport %p\n", __func__, mr, pri));  }  *next = pri;   tp = pri->pri_primary;    if (!tp)    *return_culprit = "alloc";  else if (tport_set_params(tp, TAG_NEXT(tags)) < 0)    *return_culprit = "tport_set_params";  else if (vtable->vtp_init_primary &&	   vtable->vtp_init_primary(pri, tpn, ai, tags, return_culprit) < 0)    ;  else if (tport_setname(tp, vtable->vtp_name, ai, tpn->tpn_canon) == -1)     *return_culprit = "tport_setname";  else if (tpn->tpn_ident && 	   !(tp->tp_name->tpn_ident = su_strdup(tp->tp_home, tpn->tpn_ident)))    *return_culprit = "alloc ident";  else    return pri;			/* Success */  save_errno = su_errno();  tport_zap_primary(pri);  su_seterrno(save_errno);  return NULL;}/** Destroy a primary transport and its secondary transports. @internal */static void tport_zap_primary(tport_primary_t *pri){  tport_primary_t **prip;  if (pri == NULL)    return;  assert(tport_is_primary(pri->pri_primary));  if (pri->pri_vtable->vtp_deinit_primary)    pri->pri_vtable->vtp_deinit_primary(pri);  while (pri->pri_secondary)    tport_zap_secondary(pri->pri_secondary);  /* We have just a single-linked list for primary transports */  for (prip = &pri->pri_master->mr_primaries;       *prip != pri;       prip = &(*prip)->pri_next)    assert(*prip);  *prip = pri->pri_next;  tport_zap_secondary(pri->pri_primary);}/**Create a primary transport object with socket. * * Creates a primary transport object with a server socket, and then * registers the socket with suitable events to the root. * * @param dad   parent (master or primary) transport object * @param ai    pointer to addrinfo structure * @param canon canonical name of node * @param protoname name of the protocol */statictport_primary_t *tport_listen(tport_master_t *mr,			      tport_vtable_t const *vtable,			      tp_name_t tpn[1],			      su_addrinfo_t *ai, 			      tagi_t *tags){  tport_primary_t *pri = NULL;  int err;  int errlevel = 3;  char buf[TPORT_HOSTPORTSIZE];  char const *protoname = vtable->vtp_name;  char const *culprit = "unknown";  su_sockaddr_t *su = (void *)ai->ai_addr;  /* Log an error, return error */#define TPORT_LISTEN_ERROR(errno, what)				     \  ((void)(err = errno,						     \	  ((err == EADDRINUSE || err == EAFNOSUPPORT ||		     \	    err == ESOCKTNOSUPPORT || err == EPROTONOSUPPORT ||	     \	    err == ENOPROTOOPT ? 7 : 3) < SU_LOG_LEVEL ?	     \	     su_llog(tport_log, errlevel,			     \		     "%s(%p): %s(pf=%d %s/%s): %s\n",		     \		     __func__, pri ? pri : mr, what, ai->ai_family,  \		     protoname,					     \		     tport_hostport(buf, sizeof(buf), su, 2),	     \		     su_strerror(err)) : (void)0),		     \	    tport_zap_primary(pri),		                     \	    su_seterrno(err)),					     \     (void *)NULL)  /* Create a primary transport object for another transport. */  pri = tport_alloc_primary(mr, vtable, tpn, ai, tags, &culprit);  if (pri == NULL)    return TPORT_LISTEN_ERROR(errno, culprit);  if (pri->pri_primary->tp_socket != SOCKET_ERROR) {    int index = 0;    tport_t *tp = pri->pri_primary;    su_wait_t wait[1] = { SU_WAIT_INIT };    if (su_wait_create(wait, tp->tp_socket, tp->tp_events) == -1)      return TPORT_LISTEN_ERROR(su_errno(), "su_wait_create");    /* Register receiving or accepting function with events specified above */    index = su_root_register(mr->mr_root, wait, tport_wakeup_pri, tp, 0);     if (index == -1) {      su_wait_destroy(wait);      return TPORT_LISTEN_ERROR(su_errno(), "su_root_register");    }    tp->tp_index = index;  }  pri->pri_primary->tp_connected = 0;  SU_DEBUG_5(("%s(%p): %s " TPN_FORMAT "\n", 	      __func__, pri, "listening at",	      TPN_ARGS(pri->pri_primary->tp_name)));  return pri;}int tport_bind_socket(int socket,		      su_addrinfo_t *ai,		      char const **return_culprit){  su_sockaddr_t *su = (su_sockaddr_t *)ai->ai_addr;  socklen_t sulen = ai->ai_addrlen;  if (bind(socket, ai->ai_addr, ai->ai_addrlen) == -1) {    return *return_culprit = "bind", -1;  }  if (getsockname(socket, &su->su_sa, &sulen) == SOCKET_ERROR) {    return *return_culprit = "getsockname", -1;  }  ai->ai_addrlen = sulen;#if defined (__linux__) && defined (SU_HAVE_IN6)  if (ai->ai_family == AF_INET6) {    if (!SU_SOCKADDR_INADDR_ANY(su) &&	(IN6_IS_ADDR_V4MAPPED(&su->su_sin6.sin6_addr) ||	 IN6_IS_ADDR_V4COMPAT(&su->su_sin6.sin6_addr))) {      su_sockaddr_t su0[1];            memcpy(su0, su, sizeof su0);            memset(su, 0, ai->ai_addrlen = sizeof su->su_sin);      su->su_family = ai->ai_family = AF_INET;      su->su_port = su0->su_port;      #ifndef IN6_V4MAPPED_TO_INADDR#define IN6_V4MAPPED_TO_INADDR(in6, in4) \      memcpy((in4), 12 + (uint8_t *)(in6), sizeof(struct in_addr))#endif      IN6_V4MAPPED_TO_INADDR(&su0->su_sin6.sin6_addr, &su->su_sin.sin_addr);    }  }#endif  return 0;}/** Indicate stack that a transport has been updated */void tport_has_been_updated(tport_t *self){  self->tp_pri->pri_updating = 0;  if (self->tp_master->mr_tpac->tpac_address)    self->tp_master->mr_tpac->tpac_address(self->tp_master->mr_stack, self);}staticint tport_set_events(tport_t *self, int set, int clear){  int events;  if (self == NULL)    return -1;  events = (self->tp_events | set) & ~clear;  self->tp_events = events;  if (self->tp_pri->pri_vtable->vtp_set_events)    return self->tp_pri->pri_vtable->vtp_set_events(self);  SU_DEBUG_7(("tport_set_events(%p): events%s%s%s\n", self,	      (events & SU_WAIT_IN) ? " IN" : "",	      (events & SU_WAIT_OUT) ? " OUT" : "",	      SU_WAIT_CONNECT != SU_WAIT_OUT &&	      (events & SU_WAIT_CONNECT) ? " CONNECT" : ""));    return     su_root_eventmask(self->tp_master->mr_root, 		      self->tp_index, 		      self->tp_socket, 		      self->tp_events = events);}/**Allocate a secondary transport. @internal * * The function tport_alloc_secondary() creates a secondary transport * object. The new transport initally shares parameters structure with the * original transport. * * @param pri    primary transport * @param socket socket for transport * @parma accepted true if the socket was accepted from server socket * * @return * Pointer to the newly created transport, or NULL upon an error. * * @note The socket is always closed upon error. */tport_t *tport_alloc_secondary(tport_primary_t *pri, 			       int socket,			       int accepted,			       char const **return_reason){  tport_master_t *mr = pri->pri_master;  tport_t *self;  self = su_home_clone(mr->mr_home, pri->pri_vtable->vtp_secondary_size);  if (self) {    SU_DEBUG_7(("%s(%p): new secondary tport %p\n", __func__, pri, self));    self->tp_refs = -1;			/* Freshly allocated  */    self->tp_master = mr;    self->tp_pri = pri;    self->tp_params = pri->pri_params;    self->tp_accepted = accepted != 0;    self->tp_reusable = pri->pri_primary->tp_reusable;    self->tp_magic = pri->pri_primary->tp_magic;    self->tp_addrinfo->ai_addr = (void *)self->tp_addr;    self->tp_socket = socket;        if (pri->pri_vtable->vtp_init_secondary &&	pri->pri_vtable->vtp_init_secondary(self, socket, accepted,					    return_reason) < 0) {      if (pri->pri_vtable->vtp_deinit_secondary)	pri->pri_vtable->vtp_deinit_secondary(self);      su_home_zap(self->tp_home);      return NULL;    }  }  else {    su_close(socket);    *return_reason = "malloc";  }  return self;}/** Create a connected transport object with socket. * * The function tport_connect() creates a secondary transport with a * connected socket. It registers the socket with suitable events to the * root. * * @param pri   primary transport object * @param ai    pointer to addrinfo structure * @param tpn   canonical name of node */statictport_t *tport_connect(tport_primary_t *pri, 		       su_addrinfo_t *ai,		       tp_name_t const *tpn){  if (ai == NULL || ai->ai_addrlen > sizeof (pri->pri_primary->tp_addr))    return NULL;  if (pri->pri_vtable->vtp_connect)    return pri->pri_vtable->vtp_connect(pri, ai, tpn);  else    return tport_base_connect(pri, ai, ai, tpn);}/**Create a connected transport object with socket. * * The function tport_connect() creates a secondary transport with a * connected socket. It registers the socket with suitable events to the * root. * * @param pri   primary transport object * @param ai    pointer to addrinfo structure describing socket * @param real_ai  pointer to addrinfo structure describing real target * @param tpn   canonical name of node */tport_t *tport_base_connect(tport_primary_t *pri,			    su_addrinfo_t *ai,			    su_addrinfo_t *real_ai,			    tp_name_t const *tpn){  tport_master_t *mr = pri->pri_master;  tport_t *self = NULL;  su_socket_t s, server_socket;  su_wait_t wait[1] = { SU_WAIT_INIT };  su_wakeup_f wakeup = tport_wakeup;  int index = 0;  int events = SU_WAIT_IN | SU_WAIT_ERR;  int err, errlevel = 3;  char buf[TPORT_HOSTPORTSIZE];  char const *what;  /* Log an error, return error */#define TPORT_CONNECT_ERROR(errno, what)			     \  return							     \    ((void)(err = errno,					     \	    su_wait_destroy(wait),				     \	    (SU_LOG_LEVEL >= errlevel ?				     \	     su_llog(tport_log, errlevel,			     \		     "%s(%p): %s(pf=%d %s/%s): %s\n",		     \		     __func__, pri, #what, ai->ai_family,	     \		     tpn->tpn_proto,				     \		     tport_hostport(buf, sizeof(buf),		     \				    (void *)ai->ai_addr, 2),	     \		     su_strerror(err)) : (void)0),		     \	    tport_zap_secondary(self),				     \	    su_seterrno(err)),					     \     (void *)NULL)  s = su_socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol);  if (s == SOCKET_ERROR)    TPORT_CONNECT_ERROR(su_errno(), "socket");  what = "tport_alloc_secondary";  if ((self = tport_alloc_secondary(pri, s, 0, &what)) == NULL)    TPORT_CONNECT_ERROR(errno, what);  self->tp_conn_orient = 1;  if ((server_socket = pri->pri_primary->tp_socket) != SOCKET_ERROR) {    su_sockaddr_t susa;    socklen_t susalen = sizeof(susa);    /* Bind this socket to same IP address as the primary server socket */    if (getsockname(server_socket, &susa.su_sa, &susalen) < 0) {      SU_DEBUG_3(("tport_connect: getsockname(): %s\n", 		  su_strerror(su_errno())));    }    else {      susa.su_port = 0;      if (bind(s, &susa.su_sa, susalen) < 0) {	SU_DEBUG_3(("tport_connect: bind(local-ip): %s\n", 		    su_strerror(su_errno())));      }    }  }  /* Set sockname for the tport */  if (tport_setname(self, tpn->tpn_proto, real_ai, tpn->tpn_canon) == -1)     TPORT_CONNECT_ERROR(su_errno(), tport_setname);  if (connect(s, ai->ai_addr, ai->ai_addrlen) == SOCKET_ERROR) {    err = su_errno();    if (err != EINPROGRESS && err != EAGAIN && err != EWOULDBLOCK)      TPORT_CONNECT_ERROR(err, connect);    events = SU_WAIT_CONNECT | SU_WAIT_ERR;    wakeup = tport_connected;    what = "connecting";  }  else {    what = "connected";  }  if (su_wait_create(wait, s, self->tp_events = events) == -1)    TPORT_CONNECT_ERROR(su_errno(), su_wait_create);  /* Register receiving function with events specified above */  if ((index = su_root_register(mr->mr_root, wait, wakeup, self, 0)) == -1)    TPORT_CONNECT_ERROR(su_errno(), su_root_register);  self->tp_index = index;  if (ai == real_ai) {    SU_DEBUG_5(("%s(%p): %s to " TPN_FORMAT "\n", 		__func__, self, what, TPN_ARGS(self->tp_name)));  }  else {    SU_DEBUG_5(("%s(%p): %s via %s to " TPN_FORMAT "\n",		__func__, self, what,		tport_hostport(buf, sizeof(buf), (void *)ai->ai_addr, 2),		TPN_ARGS(self->tp_name)));  }    tprb_append(&pri->pri_secondary, self);  return self;}/** Destroy a secondary transport. @internal */void tport_zap_secondary(tport_t *self){  tport_master_t *mr;  if (self == NULL)    return;  /* Remove from rbtree */  tprb_remove(&self->tp_pri->pri_secondary, self);  /* Do not deinit primary as secondary! */  if (tport_is_secondary(self) &&      self->tp_pri->pri_vtable->vtp_deinit_secondary)    self->tp_pri->pri_vtable->vtp_deinit_secondary(self);  if (self->tp_msg) {    msg_destroy(self->tp_msg), self->tp_msg = NULL;    SU_DEBUG_3(("%s(%p): zapped partially received message\n", 		__func__, self));  }  if (self->tp_queue && self->tp_queue[self->tp_qhead]) {    size_t n = 0, i, N = self->tp_params->tpp_qsize;    for (i = self->tp_qhead; self->tp_queue[i]; i = (i + 1) % N) {      msg_destroy(self->tp_queue[i]), self->tp_queue[i] = NULL;      n++;    }    SU_DEBUG_3(("%s(%p): zapped %lu queued messages\n", 		__func__, self, (LU)n));  }  if (self->tp_pused) {    SU_DEBUG_3(("%s(%p): zapped with pending requests\n", __func__, self));  }  mr = self->tp_master;  tport_stun_server_remove_socket(self);  if (self->tp_index)    su_root_deregister(mr->mr_root, self->tp_index);  self->tp_index = 0;  if (self->tp_socket != -1)    su_close(self->tp_socket);  self->tp_socket = -1;  su_home_zap(self->tp_home);}/** Create a new reference to a transport object. */tport_t *tport_ref(tport_t *tp){  if (tp) {    if (tp->tp_refs >= 0)      tp->tp_refs++;    else if (tp->tp_refs == -1)      tp->tp_refs = 1;  }  return tp;}/** Destroy reference to a transport object. */void tport_unref(tport_t *tp){  if (tp && tp->tp_refs > 0)    if (--tp->tp_refs == 0 && tp->tp_params->tpp_idle == 0)      if (!tport_is_closed(tp))	tport_close(tp);}

⌨️ 快捷键说明

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