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

📄 tport.c

📁 Sofia SIP is an open-source SIP User-Agent library, compliant with the IETF RFC3261 specification.
💻 C
📖 第 1 页 / 共 5 页
字号:
/* * This file is part of the Sofia-SIP package * * Copyright (C) 2005 Nokia Corporation. * * Contact: Pekka Pessi <pekka.pessi@nokia.com> * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public License * as published by the Free Software Foundation; either version 2.1 of * the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA * *//**@CFILE tport.c Transport interface implementation. * * See tport.docs for more detailed description of tport interface. * * @author Pekka Pessi <Pekka.Pessi@nokia.com> * @author Ismo Puustinen <Ismo.H.Puustinen@nokia.com> * @author Tat Chan <Tat.Chan@nokia.com> * @author Kai Vehmanen <kai.vehmanen@nokia.com> * @author Martti Mela <Martti.Mela@nokia.com> * * @date Created: Thu Jul 20 12:54:32 2000 ppessi */#include "config.h"#include <sofia-sip/string0.h>#include <sofia-sip/su.h>#include <sofia-sip/su_errno.h>#include <sofia-sip/su_alloc.h>#include <sofia-sip/su_tagarg.h>#include <sofia-sip/su_localinfo.h>typedef struct tport_nat_s tport_nat_t;#define SU_WAKEUP_ARG_T         struct tport_s#define SU_TIMER_ARG_T          struct tport_s#define SU_MSG_ARG_T            union tport_su_msg_arg#include <sofia-sip/su_wait.h>#include <sofia-sip/msg.h>#include <sofia-sip/msg_addr.h>#include <sofia-sip/hostdomain.h>#include <stdlib.h>#include <time.h>#include <assert.h>#include <errno.h>#include <limits.h>#ifndef IPPROTO_SCTP#define IPPROTO_SCTP (132)#endif#include "sofia-sip/tport.h"#include "sofia-sip/su_uniqueid.h"#include <sofia-sip/rbtree.h>#include "tport_internal.h"#if HAVE_FUNC#elif HAVE_FUNCTION#define __func__ __FUNCTION__#elsestatic char const __func__[] = "tport";#endif#define STACK_RECV(tp, msg, now)		       \  (tp)->tp_master->mr_tpac->tpac_recv((tp)->tp_master->mr_stack, (tp), \				      (msg), (tp)->tp_magic, (now))#define STACK_ERROR(tp, errcode, dstname) \  (tp)->tp_master->mr_tpac->tpac_error((tp)->tp_master->mr_stack, (tp), \				       (errcode), (dstname))#define STACK_ADDRESS(tp)		       \  (tp)->tp_master->mr_tpac->tpac_address((tp)->tp_master->mr_stack, (tp))#define TP_STACK   tp_master->mr_stack/* Define macros for rbtree implementation */#define TP_LEFT(tp) ((tp)->tp_left)#define TP_RIGHT(tp) ((tp)->tp_right)#define TP_PARENT(tp) ((tp)->tp_dad)#define TP_SET_RED(tp) ((tp)->tp_black = 0)#define TP_SET_BLACK(tp) ((tp)->tp_black = 1)#define TP_IS_RED(tp) ((tp) && (tp)->tp_black == 0)#define TP_IS_BLACK(tp) (!(tp) || (tp)->tp_black == 1)#define TP_COPY_COLOR(dst, src) ((dst)->tp_black = (src)->tp_black)#define TP_INSERT(tp) ((void)0)#define TP_REMOVE(tp) ((tp)->tp_left = (tp)->tp_right = (tp)->tp_dad = NULL)su_inline int tp_cmp(tport_t const *a, tport_t const *b){  if (a == b)    return 0;    if (a->tp_addrlen != b->tp_addrlen)    return (int)(a->tp_addrlen - b->tp_addrlen);  return memcmp(a->tp_addr, b->tp_addr, a->tp_addrlen);}su_inline int tprb_is_inserted(tport_t const *a){  return a->tp_dad != 0 || a->tp_left != 0 || a->tp_right != 0;}RBTREE_PROTOS(su_inline, tprb, tport_t);RBTREE_BODIES(su_inline, tprb, tport_t, 	      TP_LEFT, TP_RIGHT, TP_PARENT,	      TP_IS_RED, TP_SET_RED, TP_IS_BLACK, TP_SET_BLACK, TP_COPY_COLOR,	      tp_cmp, TP_INSERT, TP_REMOVE);static void tplist_insert(tport_t **list, tport_t *tp){  if (*list == NULL)    *list = tp;  else    tp->tp_right = *list, (*list)->tp_left = tp, *list = tp;  for (tp = *list; tp; tp = tp->tp_right) {    assert(tp->tp_left == NULL || tp == tp->tp_left->tp_right);    assert(tp->tp_right == NULL || tp == tp->tp_right->tp_left);  }}static void tplist_remove(tport_t **list, tport_t *tp){  if (*list == tp) {    *list = tp->tp_right; assert(tp->tp_left == NULL);  }  else if (tp->tp_left) {    tp->tp_left->tp_right = tp->tp_right;  }  if (tp->tp_right) {    tp->tp_right->tp_left = tp->tp_left;  }  TP_REMOVE(tp);}enum {  /** Default per-thread read queue length */  THRP_PENDING = 8};struct tport_pending_s {  /* tport_pending_t       *p_left, *p_right, *p_parent; */  void               *p_client;  tport_pending_error_f *p_callback;  msg_t              *p_msg;  unsigned short      p_reported;  unsigned short      p_on_success;};/** Return true if transport is master. */int tport_is_master(tport_t const *self){  return     self &&     self->tp_master->mr_master == self;}/** Return true if transport is primary. */int tport_is_primary(tport_t const *self){  return     self &&     self->tp_pri->pri_primary == self;}/** Return true if transport is secondary. */int tport_is_secondary(tport_t const *self){  return     self &&     self->tp_master->mr_master != self &&     self->tp_pri->pri_primary != self;}/** Test if transport has been registered to su_root_t */int tport_is_registered(tport_t const *self){  return self->tp_index != 0;}/** Test if transport is stream. */int tport_is_stream(tport_t const *self){  return self->tp_addrinfo->ai_socktype == SOCK_STREAM;} /** Test if transport is dgram. */int tport_is_dgram(tport_t const *self){  return self->tp_addrinfo->ai_socktype == SOCK_DGRAM;} /** Test if transport is udp. */int tport_is_udp(tport_t const *self){  return self->tp_addrinfo->ai_protocol == IPPROTO_UDP;} /** Test if transport is tcp. */int tport_is_tcp(tport_t const *self){  return self->tp_addrinfo->ai_protocol == IPPROTO_TCP;} /** Return 1 if transport is reliable, 0 otherwise. * * (Note that this is part of external API). */int tport_is_reliable(tport_t const *self){  return self != NULL &&     (self->tp_addrinfo->ai_socktype == SOCK_STREAM ||      self->tp_addrinfo->ai_socktype == SOCK_SEQPACKET);}/** Return 0 if self is local, nonzero otherwise. * * The return valu is the tport_via enum. * * @sa TPTAG_PUBLIC(), enum tport_via. */int tport_is_public(tport_t const *self){  return self->tp_pri->pri_public;}/** Return true if transport supports IPv4 */int tport_has_ip4(tport_t const *self){  return self &&     (self->tp_addrinfo->ai_family == 0 ||      self->tp_addrinfo->ai_family == AF_INET);}#if SU_HAVE_IN6/** Return true if transport supports IPv6 */int tport_has_ip6(tport_t const *self){  return self &&     (self->tp_addrinfo->ai_family == 0 ||      self->tp_addrinfo->ai_family == AF_INET6);}#endif/** Return true if transport supports TLS. */int tport_has_tls(tport_t const *self){  return self && self->tp_pri->pri_has_tls;}/** Return true if transport is being updated. */int tport_is_updating(tport_t const *self){  tport_primary_t *pri;  if (tport_is_master(self)) {    for (pri = self->tp_master->mr_primaries; pri; pri = pri->pri_next)       if (pri->pri_updating)	return 1;  }  else if (tport_is_primary(self)) {    return self->tp_pri->pri_updating;  }  return 0;}/** Test if transport has been closed. * * @since New in @VERSION_1_12_4 */inline int tport_is_closed(tport_t const *self){  return self->tp_closed;}/** Test if transport has been shut down. * * @since New in @VERSION_1_12_4 */inline int tport_is_shutdown(tport_t const *self){  return self->tp_closed || self->tp_send_close || self->tp_recv_close;}/** Test if transport is bound */su_inline int tport_is_bound(tport_t const *self){  return self->tp_protoname != NULL;}/** Test if transport connection has been established. @NEW_1_12_5. */int tport_is_connected(tport_t const *self){  return self->tp_is_connected;}/** Test if transport can be used to send message. @NEW_1_12_7. */int tport_is_clear_to_send(tport_t const *self){  return    tport_is_master(self) ||     tport_is_primary(self) ||     (tport_is_secondary(self) &&     tport_is_registered(self) &&     self->tp_reusable &&     !self->tp_closed &&     !self->tp_send_close);}/** Return true if transport has message in send queue. @NEW_1_12_7. */int tport_has_queued(tport_t const *self){  return self && self->tp_queue && self->tp_queue[self->tp_qhead];}/** MTU for transport  */su_inline unsigned tport_mtu(tport_t const *self){  return self->tp_params->tpp_mtu;}su_inlineint tport_has_sigcomp(tport_t const *self){  return self->tp_name->tpn_comp != NULL;}/** Set IP TOS for socket */void tport_set_tos(su_socket_t socket, su_addrinfo_t *ai, int tos){  if (tos >= 0 &&       ai->ai_family == AF_INET &&       setsockopt(socket, IPPROTO_IP, IP_TOS, (const void*)&tos, sizeof(tos)) < 0) {    SU_DEBUG_3(("tport: setsockopt(IP_TOS): %s\n",		su_strerror(su_errno())));  }}static tport_t *tport_connect(tport_primary_t *pri, su_addrinfo_t *ai, 		       tp_name_t const *tpn);static int bind6only_check(tport_master_t *mr);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 **res);static int tport_get_local_addrinfo(tport_master_t *mr, 				    char const *port,				    su_addrinfo_t const *hints,				    su_addrinfo_t **return_ai);int tport_getaddrinfo(char const *node, char const *service,		      su_addrinfo_t const *hints,		      su_addrinfo_t **res);static void tport_freeaddrinfo(su_addrinfo_t *ai);staticint tport_addrinfo_copy(su_addrinfo_t *dst, void *addr, socklen_t addrlen,			su_addrinfo_t const *src);static int  tport_bind_client(tport_master_t *self, tp_name_t const *tpn,		    char const * const transports[], enum tport_via public,		    tagi_t *tags),  tport_bind_server(tport_master_t *, tp_name_t const *tpn,		    char const * const transports[],  enum tport_via public,		    tagi_t *tags),  tport_setname(tport_t *, char const *, su_addrinfo_t const *, char const *),  tport_wakeup_pri(su_root_magic_t *m, su_wait_t *w, tport_t *self),  tport_wakeup(su_root_magic_t *m, su_wait_t *w, tport_t *self),  tport_base_wakeup(tport_t *self, int events),  tport_connected(su_root_magic_t *m, su_wait_t *w, tport_t *self),  tport_resolve(tport_t *self, msg_t *msg, tp_name_t const *tpn),  tport_send_error(tport_t *, msg_t *, tp_name_t const *, char const *who),  tport_send_fatal(tport_t *, msg_t *, tp_name_t const *, char const *who),  tport_queue(tport_t *self, msg_t *msg),  tport_queue_rest(tport_t *self, msg_t *msg, msg_iovec_t iov[], size_t iovused),  tport_pending_error(tport_t *self, su_sockaddr_t const *dst, int error),  tport_pending_errmsg(tport_t *self, msg_t *msg, int error);static ssize_t tport_vsend(tport_t *self, msg_t *msg, tp_name_t const *tpn,			   msg_iovec_t iov[], size_t iovused,			   struct sigcomp_compartment *cc);tport_t *tport_by_addrinfo(tport_primary_t const *pri,			   su_addrinfo_t const *ai,			   tp_name_t const *tpn);void tport_peer_address(tport_t *self, msg_t *msg);static void tport_parse(tport_t *self, int complete, su_time_t now);static 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);static tport_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);static void tport_zap_primary(tport_primary_t *);static char *localipname(int pf, char *buf, size_t bufsiz);static int getprotohints(su_addrinfo_t *hints,			 char const *proto, int flags);/* Stack class used when transports are being destroyed */staticvoid tport_destroy_recv(tp_stack_t *stack, tport_t *tp, 			msg_t *msg, tp_magic_t *magic, 			su_time_t received){  msg_destroy(msg);}staticvoid tport_destroy_error(tp_stack_t *stack, tport_t *tp, 			 int errcode, char const *remote){}staticmsg_t *tport_destroy_alloc(tp_stack_t *stack, int flags, 			   char const data[], usize_t len,			   tport_t const *tp,			   tp_client_t *tpc){  return NULL;}/** Name for "any" transport. @internal */static char const tpn_any[] = "*";/** Create the master transport. * * Master transport object is used to bind the protocol using transport with * actual transport objects corresponding to TCP, UDP, etc.  * * @sa tport_tbind() * * @TAGS * TPTAG_LOG(), TPTAG_DUMP(), tags used with tport_set_params(), especially * TPTAG_QUEUESIZE(). */tport_t *tport_tcreate(tp_stack_t *stack,		       tp_stack_class_t const *tpac,		       su_root_t *root, 		       tag_type_t tag, tag_value_t value, ...){  tport_master_t *mr;  tp_name_t *tpn;  tport_params_t *tpp;  ta_list ta;  if (!stack || !tpac || !root) {    su_seterrno(EINVAL);    return NULL;  }  mr = su_home_clone(NULL, sizeof *mr);  if (!mr)    return NULL;  SU_DEBUG_7(("%s(): %p\n", "tport_create", (void *)mr));  mr->mr_stack = stack;  mr->mr_tpac = tpac;  mr->mr_root = root;  mr->mr_master->tp_master = mr;  mr->mr_master->tp_params = tpp = mr->mr_params;

⌨️ 快捷键说明

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