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

📄 tport.c

📁 Internet Phone, Chat, Conferencing
💻 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 <stdlib.h>#include <time.h>#include <assert.h>#include <errno.h>#include <limits.h>#include <sofia-sip/su.h>#if HAVE_NETINET_TCP_H#include <netinet/tcp.h>#endif#if !defined(EPROTONOSUPPORT) && defined(_WIN32)#define EPROTONOSUPPORT WSAEPROTONOSUPPORT#endif#if !defined(ENOBUFS) && defined(_WIN32)#define ENOBUFS WSAENOBUFS#endif#ifndef EBADMSG#define EBADMSG 117 /* XXX -- mela: number? */#endif#if !defined(EMSGSIZE) && defined(_WIN32)#define EMSGSIZE WSAEMSGSIZE#endif#if !defined(random) && defined(_WIN32)#define random rand#endif#ifndef SU_DEBUG#define SU_DEBUG 3#endif#define SU_LOG   tport_log#include <sofia-sip/su_debug.h>#include <sofia-sip/su_alloc.h>#include <sofia-sip/su_tagarg.h>#include <sofia-sip/su_localinfo.h>#ifndef NONE#define NONE ((void *)-1)#endiftypedef struct tport_master tport_master_t;typedef struct tport_nat_s tport_nat_t;#define SU_WAKEUP_ARG_T struct tport_s#define SU_TIMER_ARG_T  struct tport_master#define SU_ROOT_MAGIC_T struct tport_threadpool#define SU_MSG_ARG_T    union tport_su_msg_arg#define STUN_MAGIC_T    tport_master_t#include <sofia-sip/su_wait.h>#include <sofia-sip/msg.h>#include <sofia-sip/msg_addr.h>#if HAVE_IP_RECVERR || HAVE_IPV6_RECVERR#include <linux/types.h>#include <linux/errqueue.h>#include <sys/uio.h>#endif#if HAVE_SCTP && HAVE_NETINET_SCTP_H#include <netinet/sctp.h>#endif#if HAVE_TLS#include "tport_tls.h"#elsetypedef struct _tls_t tls_t;	/* dummy */#endif#if HAVE_SIGCOMP#include <sigcomp.h>#endif#ifndef SOL_TCP#define SOL_TCP IPPROTO_TCP#endif#ifndef IPPROTO_SCTP#define IPPROTO_SCTP (132)#endif#if !defined(MSG_NOSIGNAL) || defined(__CYGWIN__)#undef MSG_NOSIGNAL#define MSG_NOSIGNAL (0)#endif#if HAVE_SOFIA_STUN#include "sofia-sip/stun.h"#include "sofia-sip/stun_tag.h"#endif#if HAVE_UPNP#include "upnp_wrapper.h"#endif#include "sofia-sip/tport.h"#include "sofia-sip/su_uniqueid.h"#include <sofia-sip/rbtree.h>#if HAVE_FUNC#elif HAVE_FUNCTION#define __func__ __FUNCTION__#elsechar const __func__[] = "tport";#endiftypedef struct tport_pending_s tport_pending_t;typedef struct tport_threadpool tport_threadpool_t;typedef struct tport_sigcomp_handler tport_sigcomp_handler_t;typedef struct tport_sigcomp tport_sigcomp_t;typedef struct tport_primary tport_primary_t;struct sigcomp_state_handler;struct sigcomp_algorithm;struct sigcomp_udvm;struct sigcomp_magic;#if HAVE_SIGCOMP/** Per-socket SigComp data */struct tport_sigcomp {  struct sigcomp_udvm          *sc_udvm;  struct sigcomp_compartment   *sc_cc;  struct sigcomp_compressor    *sc_compressor;  struct sigcomp_buffer        *sc_output;  unsigned                      sc_compressed;   struct sigcomp_buffer        *sc_input;  unsigned                      sc_copied;    enum {    format_is_unknown,    format_is_sigcomp,    format_is_noncomp  } sc_infmt, sc_outfmt;};#endif/** Transport parameters */typedef struct {  unsigned tpp_mtu;		/**< Maximum packet size */  unsigned tpp_idle;		/**< Allowed connection idle time. */  unsigned tpp_timeout;		/**< Allowed idle time for message. */  unsigned tpp_sigcomp_lifetime;  /**< SigComp compartment lifetime  */  unsigned tpp_thrpsize;	/**< Size of thread pool */  unsigned tpp_thrprqsize;	/**< Length of per-thread recv queue */  unsigned tpp_qsize;		/**< Size of queue */  unsigned tpp_drop;		/**< Packet drop probablity */  unsigned tpp_conn_orient:1;   /**< Connection-orienteded */  unsigned tpp_sdwn_error:1;	/**< If true, shutdown is error. */  unsigned :0;} tport_params_t;/** Transport object. * * A transport object can be used in three roles, to represent transport * list (aka master transport), to represent available transports (aka * primary transport) and to represent actual transport connections (aka * secondary transport). */struct tport_s {  su_home_t           tp_home[1];       /**< Memory home */  int                 tp_refs;		/**< Number of references to tport */  tport_t *tp_left, *tp_right, *tp_dad; /**< Links in tport tree */  tport_master_t     *tp_master;        /**< Master transport */  tport_primary_t    *tp_pri;           /**< Primary transport */  tport_params_t     *tp_params;        /**< Transport parameters */  tp_magic_t         *tp_magic; 	/**< Context provided by consumer */  unsigned            tp_black:1;       /**< Used by red-black-tree */  unsigned            tp_conn_orient:1;	/**< Is connection-oriented */  unsigned            tp_connected : 1;	/**< Has real connection */  unsigned            tp_reusable:1;    /**< Can this connection be reused */  unsigned            tp_closed : 1;    /**< This transport is closed */  /**< Remote end has sent FIN (2) or we should not just read */  unsigned            tp_recv_close:2;  /** We will send FIN (1) or have sent FIN (2) */  unsigned            tp_send_close:2;   unsigned            tp_has_keepalive:1;  unsigned:0;  msg_t const        *tp_rlogged;       /**< Last logged when receiving */  msg_t const        *tp_slogged;       /**< Last logged when sending */  unsigned            tp_time;	        /**< When this transport was last used */  tp_name_t           tp_name[1];	/**< Transport name.					 * 					 * This is either our name (if primary)					 * or peer name (if secondary).					 */#define tp_protoname tp_name->tpn_proto#define tp_canon     tp_name->tpn_canon#define tp_host      tp_name->tpn_host#define tp_port      tp_name->tpn_port#define tp_ident     tp_name->tpn_ident  su_socket_t  	      tp_socket;	/**< Socket of this tport*/  int                 tp_index;		/**< Root registration index */  int                 tp_events;        /**< Subscribed events */  int                 tp_addrlen;       /**< Size fo tp_addr */  su_sockaddr_t       tp_addr[1];	/**< Peer address */#if HAVE_TLS  tls_t              *tp_tls;  char               *tp_tls_buffer;    /**< 2k Buffer  */#endif#if HAVE_SIGCOMP  tport_sigcomp_t     tp_sigcomp[1];#endif  #if HAVE_SOFIA_STUN#if 0  stun_socket_t      *tp_stun_socket;#endif  su_socket_t         tp_stun_socket;#endif  /* ==== Receive queue ================================================== */  msg_t   	     *tp_msg;		/**< Message being received */  /* ==== Pending messages =============================================== */  tport_pending_t    *tp_pending;       /**< Pending requests */  tport_pending_t    *tp_released;      /**< Released pends */  unsigned            tp_plen;          /**< Size of tp_pending */  unsigned            tp_pused;         /**< Used pends */  unsigned            tp_reported;      /**< Report counter */  /* ==== Send queue ===================================================== */  msg_t             **tp_queue;		/**< Messages being sent */  unsigned short      tp_qhead;		/**< Head of queue */  msg_iovec_t        *tp_unsent;	/**< Pointer to first unsent iovec */  unsigned            tp_unsentlen;	/**< Number of unsent iovecs */  msg_iovec_t        *tp_iov;		/**< Iovecs allocated for sending */  unsigned            tp_iovlen;	/**< Number of allocated iovecs */  /* ==== Statistics  ===================================================== */    struct {    uint64_t sent_bytes, sent_on_line, recv_bytes, recv_on_line;    uint64_t sent_msgs, recv_msgs;  } tp_stats;};/** Primary structure */struct tport_primary {  tport_t             pri_primary[1];   /**< Transport part */#if DOX  su_home_t           pri_home[1];  tport_t           **pri_stail;	/**< End of secondary list */#else#define pri_home      pri_primary->tp_home#define pri_master    pri_primary->tp_master#define pri_protoname pri_primary->tp_name->tpn_proto#endif  char                pri_ident[16];  tport_primary_t    *pri_next;	        /**< Next primary tport */  tport_t            *pri_secondary;	/**< Secondary tports */  tport_threadpool_t *pri_threadpool;   /**< Worker threads */  unsigned            pri_thrpsize;  unsigned            pri_family : 8;   /**< Network family (INET/INET6) */  unsigned            pri_socktype : 8; /**< Socket type  */  unsigned            pri_protocol : 8;	/**< IP protocol number  */  unsigned            pri_natted:1;	/**< Using natted address  */  unsigned:0;  tport_params_t      pri_params[1];      /**< Transport parameters */};/** Master structure */struct tport_master {  tport_t             mr_master[1];#if DOX  su_home_t           mr_home[1];#else#define mr_home mr_master->tp_home#endif  int                 mr_stun_step_ready; /**< for stun's callback */  tp_stack_t  	     *mr_stack;         /**< Transport consumer */  tp_stack_class_t                const *mr_tpac;		/**< Methods provided by stack */  int                 mr_log;	        /**< Do logging of parsed messages */  su_root_t    	     *mr_root;		/**< SU root pointer */  /**< Timer reclaiming unused connections and compartment */  su_timer_t         *mr_timer;		  /** File to dump received and sent data */  FILE               *mr_dump_file;	  tport_primary_t    *mr_primaries;     /**< List of primary contacts */  tport_params_t      mr_params[1];    unsigned            mr_boundserver:1; /**< Server has been bound */  unsigned            mr_bindv6only:1; /**< We can bind separately to IPv6/4 */  unsigned :0;#if HAVE_SIGCOMP  struct sigcomp_compartment   *mr_compartment;#endif  /* Delivery context */  struct tport_delivery {    tport_t              *d_tport;    msg_t                *d_msg;    tp_name_t             d_from[1];    struct sigcomp_udvm **d_udvm;  } mr_delivery[1];  struct tport_nat_s {    int initialized;    int bound;    int stun_enabled;    char *external_ip_address;#if HAVE_UPNP || HAVE_SOFIA_STUN    int try_stun;#endif#if HAVE_UPNP#endif#if HAVE_SOFIA_STUN    tport_master_t *tport;    char *stun_server;    /* stun_socket_t *stun_socket; */    stun_handle_t *stun;    su_socket_t stun_socket;    su_sockaddr_t sockaddr;#endif  }                   mr_nat[1];};#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_SIGCOMP_ACCEPT(tp, msg)				  \  (tp)->tp_master->mr_tpac->					  \  tpac_sigcomp_accept((tp)->tp_master->mr_stack, (tp), (msg))#define TP_STACK   tp_master->mr_stack#define TP_SCTP_MSG_MAX (32768)typedef long unsigned LU; 	/* for printf() and friends */char const tport_sigcomp_name[] = "sigcomp";#if HAVE_SIGCOMPstatic inlineint msg_is_compressed(msg_t *msg){  return msg &&     (msg_addrinfo(msg)->ai_flags & TP_AI_COMPRESSED) == TP_AI_COMPRESSED;}static inlinevoid msg_mark_as_compressed(msg_t *msg){  if (msg)    msg_addrinfo(msg)->ai_flags |= TP_AI_COMPRESSED;}static struct sigcomp_udvm *tport_init_udvm(tport_t *self);static int tport_recv_sigcomp_r(tport_t *, msg_t **, struct sigcomp_udvm *);static struct sigcomp_compartment *tport_primary_compartment(tport_master_t *);static inline void tport_try_accept_sigcomp(tport_t *self, msg_t *msg);staticchar const *tport_canonize_comp(char const *comp){  if (comp && strcasecmp(comp, tport_sigcomp_name) == 0)    return tport_sigcomp_name;  return NULL;}/** Check if transport can receive compressed messages */int tport_can_recv_sigcomp(tport_t const *self){  return self && self->tp_sigcomp->sc_infmt != format_is_noncomp;}/** Check if transport can send compressed messages */int tport_can_send_sigcomp(tport_t const *self){  return self && self->tp_sigcomp->sc_outfmt != format_is_noncomp;}/** Check if transport supports sigcomp */int tport_has_compression(tport_t const *self, char const *comp){  return    self && comp &&     self->tp_name->tpn_comp == tport_canonize_comp(comp);}/** Set/reset compression */int tport_set_compression(tport_t *self, char const *comp){  if (self == NULL)    ;  else if (comp == NULL) {    if (self->tp_sigcomp->sc_outfmt != format_is_sigcomp) {      self->tp_name->tpn_comp = NULL;      return 0;    }  }  else {    comp = tport_canonize_comp(comp);    if (comp && self->tp_sigcomp->sc_outfmt != format_is_noncomp) {      self->tp_name->tpn_comp = comp;      return 0;

⌨️ 快捷键说明

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