Changeset 54 for pjproject


Ignore:
Timestamp:
Nov 18, 2005 10:43:42 PM (19 years ago)
Author:
bennylp
Message:

The BIG transport modifications

Location:
pjproject/trunk/pjsip
Files:
15 edited

Legend:

Unmodified
Added
Removed
  • pjproject/trunk/pjsip/include/pjsip/sip_config.h

    r51 r54  
    6363#define PJSIP_POOL_LEN_DIALOG           1200 
    6464#define PJSIP_POOL_INC_DIALOG           512 
     65 
     66/* Transport manager hash table size (must be 2^n-1). */ 
     67#define PJSIP_TPMGR_HTABLE_SIZE         31 
     68 
     69/* Transport idle timeout before it's destroyed. */ 
     70#define PJSIP_TRANSPORT_IDLE_TIME       30 
     71 
     72/* Max entries to process in timer heap per poll. */ 
     73#define PJSIP_MAX_TIMED_OUT_ENTRIES     10 
    6574 
    6675/* Module related constants. */ 
  • pjproject/trunk/pjsip/include/pjsip/sip_endpoint.h

    r51 r54  
    260260 * @see pjsip_transport_get 
    261261 */ 
    262 PJ_DECL(void) pjsip_endpt_get_transport( pjsip_endpoint *endpt, 
    263                                          pj_pool_t *pool, 
    264                                          pjsip_transport_type_e type, 
    265                                          const pj_sockaddr_in *remote, 
    266                                          void *token, 
    267                                          pjsip_transport_completion_callback *cb); 
    268  
    269 /** 
    270  * Create listener a new transport listener. A listener is transport object 
    271  * that is capable of receiving SIP messages. For UDP listener, normally 
    272  * application should use #pjsip_endpt_create_udp_listener instead if the  
    273  * application has already created the socket. 
    274  * This function, like all other endpoint functions, is thread safe. 
    275  * 
    276  * @param endpt     The endpoint instance. 
    277  * @param type      Transport type (eg. UDP, TCP, etc.) 
    278  * @param addr      The bound address of the transport. 
    279  * @param addr_name The address to be advertised in SIP messages. For example, 
    280  *                  the bound address can be 0.0.0.0, but the advertised address 
    281  *                  normally will be the IP address of the host. 
    282  * 
    283  * @return          Zero if listener is created successfully. 
    284  */ 
    285 PJ_DECL(pj_status_t) pjsip_endpt_create_listener( pjsip_endpoint *endpt, 
     262PJ_DECL(pj_status_t) pjsip_endpt_alloc_transport( pjsip_endpoint *endpt, 
    286263                                                  pjsip_transport_type_e type, 
    287                                                   pj_sockaddr_in *addr, 
    288                                                   const pj_sockaddr_in *addr_name); 
    289  
    290 /** 
    291  * Create UDP listener. For UDP, normally the application would create the 
    292  * socket by itself (for STUN purpose), then it can register the socket as 
    293  * listener by calling this function. 
    294  * This function, like all other endpoint functions, is thread safe. 
    295  * 
    296  * @param endpt     The endpoint instance. 
    297  * @param sock      The socket handle. 
    298  * @param addr_name The address to be advertised in SIP message. If the socket 
    299  *                  has been resolved with STUN, then application may specify  
    300  *                  the mapped address in this parameter. 
    301  * 
    302  * @return          Zero if listener is created successfully. 
    303  */ 
    304 PJ_DECL(pj_status_t) pjsip_endpt_create_udp_listener( pjsip_endpoint *endpt, 
    305                                                       pj_sock_t sock, 
    306                                                       const pj_sockaddr_in *addr_name); 
     264                                                  const pj_sockaddr_in *remote, 
     265                                                  pjsip_transport **p_transport); 
    307266 
    308267/** 
  • pjproject/trunk/pjsip/include/pjsip/sip_errno.h

    r51 r54  
    5555/** 
    5656 * @hideinitializer 
     57 * Invalid message (syntax error) 
     58 */ 
     59#define PJSIP_EINVALIDMSG       (PJSIP_ERRNO_START_PJSIP + 0) 
     60/** 
     61 * @hideinitializer 
    5762 * Missing required header(s). 
    5863 */ 
     
    98103 */ 
    99104#define PJSIP_EINVALIDVIA       (PJSIP_ERRNO_START_PJSIP + 9) 
     105/** 
     106 * @hideinitializer 
     107 * Multiple Via headers in response. 
     108 */ 
     109#define PJSIP_EMULTIPLEVIA      (PJSIP_ERRNO_START_PJSIP + 9) 
     110/** 
     111 * @hideinitializer 
     112 * SIP object is busy. 
     113 */ 
     114#define PJSIP_EBUSY             (PJSIP_ERRNO_START_PJSIP + 10) 
     115/** 
     116 * @hideinitializer 
     117 * SIP object with the same type already exists. 
     118 */ 
     119#define PJSIP_ETYPEEXISTS       (PJSIP_ERRNO_START_PJSIP + 11) 
     120 
    100121 
    101122 
  • pjproject/trunk/pjsip/include/pjsip/sip_misc.h

    r51 r54  
    179179 */ 
    180180PJ_DECL(pj_status_t) pjsip_get_response_addr(pj_pool_t *pool, 
    181                                              const pjsip_transport_t *tr, 
     181                                             const pjsip_transport *tr, 
    182182                                             const pjsip_via_hdr *via, 
    183183                                             pjsip_host_port *addr); 
  • pjproject/trunk/pjsip/include/pjsip/sip_private.h

    r51 r54  
    3636 
    3737 
    38 /**  
    39  * Create a new transport manager. 
    40  * @param pool The pool 
    41  * @param endpt The endpoint 
    42  * @param cb Callback to be called to receive messages from transport. 
    43  */ 
    44 PJ_DECL(pj_status_t) pjsip_transport_mgr_create( pj_pool_t *pool, 
    45                                                  pjsip_endpoint *endpt, 
    46                                                  void (*cb)(pjsip_endpoint *, 
    47                                                             pjsip_rx_data *), 
    48                                                  pjsip_transport_mgr **); 
    49  
    50  
    51 /** 
    52  * Destroy transport manager and release all transports. 
    53  * @param mgr Transport manager to be destroyed. 
    54  */ 
    55 PJ_DECL(pj_status_t) pjsip_transport_mgr_destroy( pjsip_transport_mgr *mgr ); 
    56  
    57 /** 
    58  * Poll for transport events. 
    59  * Incoming messages will be parsed by the transport manager, and the callback 
    60  * will be called for each of this message. 
    61  * @param endpt The endpoint. 
    62  * @param timeout Timeout value, or NULL to wait forever. 
    63  */ 
    64 PJ_DECL(int) pjsip_transport_mgr_handle_events( pjsip_transport_mgr *mgr, 
    65                                                 const pj_time_val *timeout ); 
    66  
    67 /** 
    68  * Get the pointer to the first transport iterator. 
    69  * @param mgr The transport manager. 
    70  * @param it  The iterator used for iterating the hash element. 
    71  * @return the iterator to the first transport, or NULL. 
    72  */ 
    73 PJ_DECL(pj_hash_iterator_t*) pjsip_transport_first( pjsip_transport_mgr *mgr, 
    74                                                     pj_hash_iterator_t *it ); 
    75  
    76  
    77 /** 
    78  * Get the next transport iterator. 
    79  * @param itr the iterator to the transport. 
    80  * @return the iterator pointed to the next transport, or NULL. 
    81  */ 
    82 PJ_DECL(pj_hash_iterator_t*) pjsip_transport_next( pjsip_transport_mgr *mgr, 
    83                                                    pj_hash_iterator_t *itr ); 
    84  
    85 /** 
    86  * Get the value of transport iterator. 
    87  * @param mgr the transport manager. 
    88  * @param itr the transport iterator. 
    89  * @return the transport associated with the iterator. 
    90  */ 
    91 PJ_DECL(pjsip_transport_t*) pjsip_transport_this( pjsip_transport_mgr *mgr, 
    92                                                   pj_hash_iterator_t *itr ); 
    9338 
    9439/**  
  • pjproject/trunk/pjsip/include/pjsip/sip_transaction.h

    r51 r54  
    112112    int                         current_addr;   /**< Address currently used. */ 
    113113 
    114     pjsip_transport_t          *transport;      /**< Transport to use.      */ 
     114    pjsip_transport            *transport;      /**< Transport to use.      */ 
    115115 
    116116    /* 
  • pjproject/trunk/pjsip/include/pjsip/sip_transport.h

    r51 r54  
    3030#include <pj/list.h> 
    3131#include <pj/ioqueue.h> 
     32#include <pj/timer.h> 
    3233 
    3334PJ_BEGIN_DECL 
     
    4344 * @{ 
    4445 */ 
     46 
     47/***************************************************************************** 
     48 * 
     49 * GENERAL TRANSPORT (NAMES, TYPES, ETC.) 
     50 * 
     51 *****************************************************************************/ 
     52 
     53/** 
     54 * Flags for SIP transports. 
     55 */ 
     56enum pjsip_transport_flags_e 
     57{ 
     58    PJSIP_TRANSPORT_RELIABLE        = 1,    /**< Transport is reliable.     */ 
     59    PJSIP_TRANSPORT_SECURE          = 2,    /**< Transport is secure.       */ 
     60    PJSIP_TRANSPORT_DATAGRAM        = 4,    /**< Datagram based transport.  */ 
     61}; 
     62 
     63/** 
     64 * Check if transport tp is reliable. 
     65 */ 
     66#define PJSIP_TRANSPORT_IS_RELIABLE(tp)     \ 
     67            ((tp)->flag & PJSIP_TRANSPORT_RELIABLE) 
     68 
     69/** 
     70 * Get the transport type from the transport name. 
     71 * 
     72 * @param name      Transport name, such as "TCP", or "UDP". 
     73 * 
     74 * @return          The transport type, or PJSIP_TRANSPORT_UNSPECIFIED if  
     75 *                  the name is not recognized as the name of supported  
     76 *                  transport. 
     77 */ 
     78PJ_DECL(pjsip_transport_type_e)  
     79pjsip_transport_get_type_from_name(const pj_str_t *name); 
     80 
     81/** 
     82 * Get the transport type for the specified flags. 
     83 * 
     84 * @param flag      The transport flag. 
     85 * 
     86 * @return          Transport type. 
     87 */ 
     88PJ_DECL(pjsip_transport_type_e)  
     89pjsip_transport_get_type_from_flag(unsigned flag); 
     90 
     91/** 
     92 * Get transport flag from type. 
     93 * 
     94 * @param type      Transport type. 
     95 * 
     96 * @return          Transport flags. 
     97 */ 
     98PJ_DECL(unsigned) 
     99pjsip_transport_get_flag_from_type( pjsip_transport_type_e type ); 
     100 
     101/** 
     102 * Get the default SIP port number for the specified type. 
     103 * 
     104 * @param type      Transport type. 
     105 * 
     106 * @return          The port number, which is the default SIP port number for 
     107 *                  the specified type. 
     108 */ 
     109PJ_DECL(int)  
     110pjsip_transport_get_default_port_for_type(pjsip_transport_type_e type); 
     111 
     112 
     113/***************************************************************************** 
     114 * 
     115 * RECEIVE DATA BUFFER. 
     116 * 
     117 *****************************************************************************/ 
    45118 
    46119/** 
     
    53126struct pjsip_rx_data 
    54127{ 
    55     //PJ_DECL_LIST_MEMBER(struct pjsip_rx_data); 
    56  
    57     /** Memory pool for this buffer. */ 
    58     pj_pool_t           *pool; 
    59  
    60     /** Ioqueue op key. */ 
    61     pj_ioqueue_op_key_t  op_key; 
    62  
    63     /** Time when the message was received. */ 
    64     pj_time_val          timestamp; 
    65  
    66     /** The packet buffer. */ 
    67     char                 packet[PJSIP_MAX_PKT_LEN]; 
    68  
    69     /** The length of the packet received. */ 
    70     int                  len; 
    71  
    72     /** The source address from which the packet was received. */ 
    73     pj_sockaddr_in       addr; 
    74  
    75     /** The length of the source address. */ 
    76     int                  addr_len; 
    77  
    78     /** The transport object which received this packet. */ 
    79     pjsip_transport_t   *transport; 
    80  
    81     /** The parsed message, if any. */ 
    82     pjsip_msg           *msg; 
    83  
    84     /** This the transaction key generated from the message. This key is only 
    85      *  available after the rdata has reached the endpoint.  
    86      */ 
    87     pj_str_t             key; 
    88  
    89     /** The Call-ID header as found in the message. */ 
    90     pj_str_t             call_id; 
    91  
    92     /** The From header as found in the message. */ 
    93     pjsip_from_hdr      *from; 
    94  
    95     /** The To header as found in the message. */ 
    96     pjsip_to_hdr        *to; 
    97  
    98     /** The topmost Via header as found in the message. */ 
    99     pjsip_via_hdr       *via; 
    100  
    101     /** The CSeq header as found in the message. */ 
    102     pjsip_cseq_hdr      *cseq; 
    103  
    104     /** Max forwards header. */ 
    105     pjsip_max_forwards_hdr *max_fwd; 
    106  
    107     /** The first route header. */ 
    108     pjsip_route_hdr     *route; 
    109  
    110     /** The first record-route header. */ 
    111     pjsip_rr_hdr        *record_route; 
    112  
    113     /** Content-type header. */ 
    114     pjsip_ctype_hdr     *ctype; 
    115  
    116     /** Content-length header. */ 
    117     pjsip_clen_hdr      *clen; 
    118  
    119     /** The first Require header. */ 
    120     pjsip_require_hdr   *require; 
    121  
    122     /** The list of error generated by the parser when parsing this message. */ 
    123     pjsip_parser_err_report parse_err; 
     128 
     129    /** 
     130     * tp_info is part of rdata that remains static for the duration of the 
     131     * buffer. It is initialized when the buffer was created by transport. 
     132     */ 
     133    struct  
     134    { 
     135        /** Memory pool for this buffer. */ 
     136        pj_pool_t               *pool; 
     137 
     138        /** The transport object which received this packet. */ 
     139        pjsip_transport         *transport; 
     140 
     141        /** Ioqueue key. */ 
     142        pj_ioqueue_op_key_t      op_key; 
     143 
     144    } tp_info; 
     145 
     146 
     147    /** 
     148     * pkt_info is initialized by transport when it receives an incoming 
     149     * packet. 
     150     */ 
     151    struct 
     152    { 
     153        /** Time when the message was received. */ 
     154        pj_time_val              timestamp; 
     155 
     156        /** Pointer to the original packet. */ 
     157        char                     packet[PJSIP_MAX_PKT_LEN]; 
     158 
     159        /** Zero termination for the packet. */ 
     160        pj_uint32_t              zero; 
     161 
     162        /** The length of the packet received. */ 
     163        int                      len; 
     164 
     165        /** The source address from which the packet was received. */ 
     166        pj_sockaddr_in           addr; 
     167 
     168        /** The length of the source address. */ 
     169        int                      addr_len; 
     170 
     171    } pkt_info; 
     172 
     173 
     174    /** 
     175     * msg_info is initialized by transport mgr (tpmgr) before this buffer 
     176     * is passed to endpoint. 
     177     */ 
     178    struct 
     179    { 
     180        /** Start of msg buffer. */ 
     181        char                    *msg_buf; 
     182 
     183        /** Length fo message. */ 
     184        int                      len; 
     185 
     186        /** The parsed message, if any. */ 
     187        pjsip_msg               *msg; 
     188 
     189        /** The Call-ID header as found in the message. */ 
     190        pj_str_t                 call_id; 
     191 
     192        /** The From header as found in the message. */ 
     193        pjsip_from_hdr          *from; 
     194 
     195        /** The To header as found in the message. */ 
     196        pjsip_to_hdr            *to; 
     197 
     198        /** The topmost Via header as found in the message. */ 
     199        pjsip_via_hdr           *via; 
     200 
     201        /** The CSeq header as found in the message. */ 
     202        pjsip_cseq_hdr          *cseq; 
     203 
     204        /** Max forwards header. */ 
     205        pjsip_max_forwards_hdr  *max_fwd; 
     206 
     207        /** The first route header. */ 
     208        pjsip_route_hdr         *route; 
     209 
     210        /** The first record-route header. */ 
     211        pjsip_rr_hdr            *record_route; 
     212 
     213        /** Content-type header. */ 
     214        pjsip_ctype_hdr         *ctype; 
     215 
     216        /** Content-length header. */ 
     217        pjsip_clen_hdr          *clen; 
     218 
     219        /** The first Require header. */ 
     220        pjsip_require_hdr       *require; 
     221 
     222        /** The list of error generated by the parser when parsing  
     223            this message.  
     224         */ 
     225        pjsip_parser_err_report parse_err; 
     226 
     227    } msg_info; 
     228 
     229 
     230    /** 
     231     * endpt_info is initialized by endpoint after this buffer reaches 
     232     * endpoint. 
     233     */ 
     234    struct 
     235    { 
     236        /**  
     237         * This the transaction key generated for the message.  
     238         */ 
     239        pj_str_t                 key; 
     240 
     241    } endpt_info; 
     242 
    124243}; 
    125244 
     245 
     246/***************************************************************************** 
     247 * 
     248 * TRANSMIT DATA BUFFER MANIPULATION. 
     249 * 
     250 *****************************************************************************/ 
    126251 
    127252/** 
     
    157282 
    158283    /** The transport manager for this buffer. */ 
    159     pjsip_transport_mgr *mgr; 
     284    pjsip_tpmgr         *mgr; 
    160285 
    161286    /** Ioqueue asynchronous operation key. */ 
    162287    pj_ioqueue_op_key_t  op_key; 
     288 
     289    /** Lock object. */ 
     290    pj_lock_t           *lock; 
    163291 
    164292    /** The message in this buffer. */ 
     
    175303    /** Reference counter. */ 
    176304    pj_atomic_t         *ref_cnt; 
     305 
     306    /** Being sent? */ 
     307    int                  is_pending; 
     308 
     309    /** Transport internal. */ 
     310    void                *token; 
     311    void               (*cb)(void*, pjsip_tx_data*, pj_status_t); 
    177312}; 
    178313 
     314 
     315/** 
     316 * Create a new, blank transmit buffer. The reference count is initialized 
     317 * to zero. 
     318 * 
     319 * @param mgr           The transport manager. 
     320 * @param tdata         Pointer to receive transmit data. 
     321 * 
     322 * @return              PJ_SUCCESS, or the appropriate error code. 
     323 * 
     324 * @see pjsip_endpt_create_tdata 
     325 */ 
     326pj_status_t pjsip_tx_data_create( pjsip_tpmgr *mgr, 
     327                                  pjsip_tx_data **tdata ); 
    179328 
    180329/** 
     
    194343 */ 
    195344PJ_DECL(void) pjsip_tx_data_dec_ref( pjsip_tx_data *tdata ); 
     345 
     346/** 
     347 * Check if transmit data buffer contains a valid message. 
     348 * 
     349 * @param tdata     The transmit buffer. 
     350 */ 
     351PJ_DECL(pj_bool_t) pjsip_tx_data_is_valid( pjsip_tx_data *tdata ); 
    196352 
    197353/** 
     
    208364 
    209365 
    210 /** 
    211  * Flags for SIP transports. 
    212  */ 
    213 enum pjsip_transport_flags_e 
     366/***************************************************************************** 
     367 * 
     368 * TRANSPORT 
     369 * 
     370 *****************************************************************************/ 
     371 
     372/** 
     373 * This structure represent the "public" interface of a SIP transport. 
     374 * Applications normally extend this structure to include transport 
     375 * specific members. 
     376 */ 
     377typedef struct pjsip_transport 
    214378{ 
    215     PJSIP_TRANSPORT_RELIABLE        = 1,    /**< Transport is reliable. */ 
    216     PJSIP_TRANSPORT_SECURE          = 2,    /**< Transport is secure. */ 
    217     PJSIP_TRANSPORT_IOQUEUE_BUSY    = 4,    /**< WTH?? */ 
     379    char                    obj_name[PJ_MAX_OBJ_NAME];  /**< Name. */ 
     380 
     381    pj_pool_t              *pool;           /**< Pool used by transport.    */ 
     382    pj_atomic_t            *ref_cnt;        /**< Reference counter.         */ 
     383    pj_lock_t              *lock;           /**< Lock object.               */ 
     384    int                     tracing;        /**< Tracing enabled?           */ 
     385 
     386    pjsip_transport_type_e  type;           /**< Transport type.            */ 
     387    char                    type_name[8];   /**< Type name.                 */ 
     388    unsigned                flag;           /**< #pjsip_transport_flags_e   */ 
     389 
     390    pj_sockaddr_in          local_addr;     /**< Bound address.             */ 
     391    pj_sockaddr_in          public_addr;    /**< STUN addres.               */ 
     392    pj_sockaddr_in          rem_addr;       /**< Remote addr (zero for UDP) */ 
     393 
     394    pjsip_tpmgr            *tpmgr;          /**< Transport manager.         */ 
     395    pj_timer_entry          idle_timer;     /**< Timer when ref cnt is zero.*/ 
     396 
     397    /** 
     398     * Function to be called by transport manager to send SIP message. 
     399     * 
     400     * @param transport     The transport to send the message. 
     401     * @param packet        The buffer to send. 
     402     * @param length        The length of the buffer to send. 
     403     * @param op_key        Completion token, which will be supplied to 
     404     *                      caller when pending send operation completes. 
     405     * @param rem_addr      The remote destination address. 
     406     * @param callback      If supplied, the callback will be called 
     407     *                      once a pending transmission has completed. If 
     408     *                      the function completes immediately (i.e. return 
     409     *                      code is not PJ_EPENDING), the callback will not 
     410     *                      be called. 
     411     * 
     412     * @return              Should return PJ_SUCCESS only if data has been 
     413     *                      succesfully queued to operating system for  
     414     *                      transmission. Otherwise it may return PJ_EPENDING 
     415     *                      if the underlying transport can not send the 
     416     *                      data immediately and will send it later, which in 
     417     *                      this case caller doesn't have to do anything  
     418     *                      except wait the calback to be called, if it  
     419     *                      supplies one. 
     420     *                      Other return values indicate the error code. 
     421     */ 
     422    pj_status_t (*send_msg)(pjsip_transport *transport,  
     423                            const void *packet,  
     424                            pj_size_t length, 
     425                            pj_ioqueue_op_key_t *op_key, 
     426                            const pj_sockaddr_in *rem_addr, 
     427                            void *token, 
     428                            void (*callback)(pjsip_transport *transport, 
     429                                             void *token,  
     430                                             pj_status_t status)); 
     431 
     432    /** 
     433     * Destroy this transport. 
     434     */ 
     435    pj_status_t (*destroy)(pjsip_transport *transport); 
     436 
     437    /* 
     438     * Application may extend this structure.. 
     439     */ 
     440} pjsip_transport; 
     441 
     442 
     443/** 
     444 * Register a transport. 
     445 */ 
     446PJ_DECL(pj_status_t) pjsip_transport_register( pjsip_tpmgr *mgr, 
     447                                               pjsip_transport *tp ); 
     448 
     449 
     450/** 
     451 * Unregister transport. This will eventually call the transport to 
     452 * destroy itself. 
     453 */ 
     454PJ_DECL(pj_status_t) pjsip_transport_unregister( pjsip_tpmgr *mgr, 
     455                                                 pjsip_transport *tp); 
     456 
     457/** 
     458 * Add ref. 
     459 */ 
     460PJ_DECL(pj_status_t) pjsip_transport_add_ref( pjsip_transport *tp ); 
     461 
     462/** 
     463 * Dec ref. 
     464 */ 
     465PJ_DECL(pj_status_t) pjsip_transport_dec_ref( pjsip_transport *tp ); 
     466 
     467 
     468/** 
     469 * Call for incoming message. 
     470 */ 
     471PJ_DECL(pj_ssize_t) pjsip_tpmgr_receive_packet(pjsip_tpmgr *mgr, 
     472                                               pjsip_rx_data *rdata); 
     473 
     474 
     475/***************************************************************************** 
     476 * 
     477 * TRANSPORT FACTORY 
     478 * 
     479 *****************************************************************************/ 
     480 
     481 
     482/** 
     483 * Transport factory. 
     484 */ 
     485typedef struct pjsip_tpfactory pjsip_tpfactory; 
     486 
     487/** 
     488 * Transport factory. 
     489 */ 
     490struct pjsip_tpfactory 
     491{ 
     492    /* This list is managed by transport manager. */ 
     493    PJ_DECL_LIST_MEMBER(struct pjsip_tpfactory); 
     494 
     495    pj_pool_t              *pool; 
     496    pj_lock_t              *lock; 
     497 
     498    pjsip_transport_type_e  type; 
     499    char                    type_name[8]; 
     500    unsigned                flag; 
     501 
     502    pj_sockaddr_in          local_addr; 
     503    pj_sockaddr_in          public_addr; 
     504 
     505    /** 
     506     * Create new outbound connection. 
     507     */ 
     508    pj_status_t (*create_transport)(pjsip_tpfactory *factory, 
     509                                    pjsip_tpmgr *mgr, 
     510                                    pjsip_endpoint *endpt, 
     511                                    pj_ioqueue_t *ioqueue, 
     512                                    const pj_sockaddr_in *rem_addr, 
     513                                    pjsip_transport **transport); 
     514 
     515    /* 
     516     * Application may extend this structure.. 
     517     */ 
    218518}; 
    219519 
    220 /** 
    221  * Get the transport type from the transport name. 
    222  * 
    223  * @param name      Transport name, such as "TCP", or "UDP". 
    224  * 
    225  * @return          The transport type, or PJSIP_TRANSPORT_UNSPECIFIED if  
    226  *                  the name is not recognized as the name of supported  
    227  *                  transport. 
    228  */ 
    229 PJ_DECL(pjsip_transport_type_e)  
    230 pjsip_transport_get_type_from_name(const pj_str_t *name); 
    231  
    232 /** 
    233  * Get the transport type for the specified flags. 
    234  * 
    235  * @param flag      The transport flag. 
    236  * 
    237  * @return          Transport type. 
    238  */ 
    239 PJ_DECL(pjsip_transport_type_e)  
    240 pjsip_transport_get_type_from_flag(unsigned flag); 
    241  
    242 /** 
    243  * Get the default SIP port number for the specified type. 
    244  * 
    245  * @param type      Transport type. 
    246  * 
    247  * @return          The port number, which is the default SIP port number for 
    248  *                  the specified type. 
    249  */ 
    250 PJ_DECL(int)  
    251 pjsip_transport_get_default_port_for_type(pjsip_transport_type_e type); 
    252  
    253  
    254 /** 
    255  * Add reference to transport. 
    256  * Transactions or dialogs that uses a particular transport must call this  
    257  * function to indicate that the transport is being used, thus preventing the 
    258  * transport from being closed. 
    259  * 
    260  * @param transport     The transport. 
    261  */ 
    262 PJ_DECL(void)  
    263 pjsip_transport_add_ref( pjsip_transport_t *transport ); 
    264  
    265 /** 
    266  * Decrease reference to transport. 
    267  * When the transport reference counter becomes zero, a timer will be started 
    268  * and when this timer expires and the reference counter is still zero, the 
    269  * transport will be released. 
    270  * 
    271  * @param transport     The transport 
    272  */ 
    273 PJ_DECL(void)  
    274 pjsip_transport_dec_ref( pjsip_transport_t *transport ); 
    275  
    276  
    277 /** 
    278  * Macro to check whether the transport is reliable. 
    279  * 
    280  * @param transport     The transport 
    281  * 
    282  * @return              non-zero (not necessarily 1) if transport is reliable. 
    283  */ 
    284 #define PJSIP_TRANSPORT_IS_RELIABLE(transport)  \ 
    285         (pjsip_transport_get_flag(transport) & PJSIP_TRANSPORT_RELIABLE) 
    286  
    287  
    288 /** 
    289  * Macro to check whether the transport is secure. 
    290  * 
    291  * @param transport     The transport 
    292  * 
    293  * @return              non-zero (not necessarily one) if transport is secure. 
    294  */ 
    295 #define PJSIP_TRANSPORT_IS_SECURE(transport)    \ 
    296         (pjsip_transport_get_flag(transport) & PJSIP_TRANSPORT_SECURE) 
    297  
    298 /** 
    299  * Get the transport type. 
    300  * 
    301  * @param tr            The transport. 
    302  * 
    303  * @return              Transport type. 
    304  */ 
    305 PJ_DECL(pjsip_transport_type_e)  
    306 pjsip_transport_get_type( const pjsip_transport_t * tr); 
    307  
    308 /** 
    309  * Get the transport type name (ie "UDP", or "TCP"). 
    310  * 
    311  * @param tr            The transport. 
    312  * @return              The string type. 
    313  */ 
    314 PJ_DECL(const char *)  
    315 pjsip_transport_get_type_name( const pjsip_transport_t * tr); 
    316  
    317 /** 
    318  * Get the transport's object name. 
    319  * 
    320  * @param tr            The transport. 
    321  * @return              The object name. 
    322  */ 
    323 PJ_DECL(const char*)  
    324 pjsip_transport_get_obj_name( const pjsip_transport_t *tr ); 
    325  
    326 /** 
    327  * Get the transport's reference counter. 
    328  * 
    329  * @param tr            The transport. 
    330  * @return              The reference count value. 
    331  */ 
    332 PJ_DECL(int)  
    333 pjsip_transport_get_ref_cnt( const pjsip_transport_t *tr ); 
    334  
    335 /** 
    336  * Get transport flag. 
    337  * 
    338  * @param tr            The transport. 
    339  * @return              Transport flag. 
    340  */ 
    341 PJ_DECL(unsigned)  
    342 pjsip_transport_get_flag( const pjsip_transport_t * tr ); 
    343  
    344 /** 
    345  * Get the local address of the transport, ie. the address which the socket 
    346  * is bound. 
    347  * 
    348  * @param tr            The transport. 
    349  * @return              The address. 
    350  */ 
    351 PJ_DECL(const pj_sockaddr_in *)  
    352 pjsip_transport_get_local_addr( pjsip_transport_t * tr ); 
    353  
    354 /** 
    355  * Get the address name of the transport. Address name can be an arbitrary 
    356  * address assigned to a transport. This is usefull for example when STUN 
    357  * is used, then the address name of an UDP transport can specify the public 
    358  * address of the transport. When the address name is not set, then value 
    359  * will be equal to the local/bound address. Application should normally 
    360  * prefer to use the address name instead of the local address. 
    361  * 
    362  * @param tr            The transport. 
    363  * @return              The address name. 
    364  */ 
    365 PJ_DECL(const pj_sockaddr_in*)  
    366 pjsip_transport_get_addr_name (pjsip_transport_t *tr); 
    367  
    368 /** 
    369  * Get the remote address of the transport. Not all transports will have  
    370  * a valid remote address. UDP transports, for example, will likely to have 
    371  * zero has their remote address, because UDP transport can be used to send 
    372  * and receive messages from multiple destinations. 
    373  * 
    374  * @param tr            The transport. 
    375  * @return              The address. 
    376  */ 
    377 PJ_DECL(const pj_sockaddr_in *)  
    378 pjsip_transport_get_remote_addr( const pjsip_transport_t * tr ); 
    379  
    380 /** 
    381  * Send a SIP message using the specified transport, to the address specified 
    382  * in the outgoing data. This function is only usefull for application when it 
    383  * wants to handle the message statelessly, because otherwise it should create 
    384  * a transaction and let the transaction handles the transmission of the  
    385  * message. 
    386  * 
    387  * This function will send the message immediately, so application must be 
    388  * sure that the transport is ready to do so before calling this function. 
    389  * 
    390  * @param tr            The transport to send the message. 
    391  * @param tdata         The outgoing message buffer. 
    392  * @param addr          The remote address. 
    393  * @param sent          If not null, it will be filled up with the length of 
    394  *                      data sent. 
    395  * 
    396  * @return              PJ_SUCCESS on success, or the appropriate error code. 
    397  */ 
    398 PJ_DECL(pj_status_t) pjsip_transport_send_msg( pjsip_transport_t *tr,  
    399                                                pjsip_tx_data *tdata, 
    400                                                const pj_sockaddr_in *addr, 
    401                                                pj_ssize_t *sent); 
     520 
     521 
     522/** 
     523 * Register a transport factory. 
     524 * 
     525 * @param mgr           The transport manager. 
     526 * @param factory       Transport factory. 
     527 * 
     528 * @return              PJ_SUCCESS if listener was successfully created. 
     529 */ 
     530PJ_DECL(pj_status_t) pjsip_tpmgr_register_tpfactory(pjsip_tpmgr *mgr, 
     531                                                    pjsip_tpfactory *tpf); 
     532 
     533/** 
     534 * Unregister factory. 
     535 */ 
     536PJ_DECL(pj_status_t) pjsip_tpmgr_unregister_tpfactory(pjsip_tpmgr *mgr, 
     537                                                      pjsip_tpfactory *tpf); 
     538 
     539 
     540/***************************************************************************** 
     541 * 
     542 * TRANSPORT MANAGER 
     543 * 
     544 *****************************************************************************/ 
     545 
     546/** 
     547 * Create a new transport manager. 
     548 * 
     549 * @param pool      Pool. 
     550 * @param endpt     Endpoint instance. 
     551 * @param cb        Callback to receive incoming message. 
     552 * @param p_mgr     Pointer to receive the new transport manager. 
     553 * 
     554 * @return          PJ_SUCCESS or the appropriate error code on error. 
     555 */ 
     556PJ_DECL(pj_status_t) pjsip_tpmgr_create( pj_pool_t *pool, 
     557                                         pjsip_endpoint * endpt, 
     558                                         pj_ioqueue_t *ioqueue, 
     559                                         pj_timer_heap_t *timer_heap, 
     560                                         void (*cb)(pjsip_endpoint*, 
     561                                                    pj_status_t, 
     562                                                    pjsip_rx_data *), 
     563                                         pjsip_tpmgr **p_mgr); 
     564 
     565 
     566/** 
     567 * Destroy transport manager. 
     568 */ 
     569PJ_DECL(pj_status_t) pjsip_tpmgr_destroy(pjsip_tpmgr *mgr); 
     570 
     571 
     572/** 
     573 * Dump transport info. 
     574 */ 
     575PJ_DECL(void) pjsip_tpmgr_dump_transports(pjsip_tpmgr *mgr); 
     576 
     577 
     578/***************************************************************************** 
     579 * 
     580 * PUBLIC API 
     581 * 
     582 *****************************************************************************/ 
     583 
     584 
     585/** 
     586 * Find transport to be used to send message to remote destination. If no 
     587 * suitable transport is found, a new one will be created. 
     588 */ 
     589PJ_DECL(pj_status_t) pjsip_tpmgr_alloc_transport( pjsip_tpmgr *mgr, 
     590                                           pjsip_transport_type_e type, 
     591                                           const pj_sockaddr_in *remote, 
     592                                           pjsip_transport **p_transport ); 
     593 
     594 
     595/** 
     596 * Send a SIP message using the specified transport. 
     597 */ 
     598PJ_DECL(pj_status_t) pjsip_transport_send( pjsip_transport *tr,  
     599                                           pjsip_tx_data *tdata, 
     600                                           const pj_sockaddr_in *addr, 
     601                                           void *token, 
     602                                           void (*cb)(void *token,  
     603                                                      pjsip_tx_data *tdata, 
     604                                                      pj_status_t)); 
    402605 
    403606 
     
    406609 */ 
    407610 
    408 /* 
    409  * PRIVATE FUNCTIONS!!! 
    410  * 
    411  * These functions are normally to be used by endpoint. Application should 
    412  * use the variant provided by the endpoint instance. 
    413  * 
    414  * Application normally wouldn't be able to call these functions because it 
    415  * has no reference of the transport manager (the instance of the transport 
    416  * manager is hidden by endpoint!). 
    417  */ 
    418  
    419 /* 
    420  * Create a new transmit buffer. 
    421  * 
    422  * @param mgr           The transport manager. 
    423  * @return              The transmit buffer data, or NULL on error. 
    424  */ 
    425 pj_status_t pjsip_tx_data_create( pjsip_transport_mgr *mgr, 
    426                                   pjsip_tx_data **tdata ); 
    427  
    428  
    429 /** 
    430  * Create listener. 
    431  * 
    432  * @param mgr           The transport manager. 
    433  * @param type          Transport type. 
    434  * @param local_addr    The address to bind. 
    435  * @param addr_name     If not null, sets the address name. If NULL,  
    436  *                      then the local address will be used. 
    437  * 
    438  * @return              PJ_SUCCESS if listener was successfully created. 
    439  */ 
    440 PJ_DECL(pj_status_t) pjsip_create_listener( pjsip_transport_mgr *mgr, 
    441                                             pjsip_transport_type_e type, 
    442                                             pj_sockaddr_in *local_addr, 
    443                                             const pj_sockaddr_in *addr_name); 
    444  
    445  
    446 /** 
    447  * Create UDP listener. 
    448  * 
    449  * @param mgr           The transport manager. 
    450  * @param sock          The UDP socket. 
    451  * @param addr_name     If not null, sets the address name. If NULL,  
    452  *                      then the local address will be used. 
    453  * 
    454  * @return              PJ_SUCCESS if listener was successfully created. 
    455  */ 
    456 PJ_DECL(pj_status_t) pjsip_create_udp_listener( pjsip_transport_mgr *mgr, 
    457                                                 pj_sock_t sock, 
    458                                                 const pj_sockaddr_in *addr_name); 
    459  
    460 /**  
    461  * Type of function to receive asynchronous transport completion for 
    462  * pjsip_transport_get() operation. 
    463  * 
    464  * @param tr            The transport. 
    465  * @param token         Token registered previously. 
    466  * @param status        Status of operation. 
    467  */ 
    468 typedef void pjsip_transport_completion_callback(pjsip_transport_t *tr,  
    469                                                  void *token,  
    470                                                  pj_status_t status); 
    471  
    472 /** 
    473  * Find transport to be used to send message to remote destination. If no 
    474  * suitable transport is found, a new one will be created. If transport 
    475  * can not be available immediately (for example, an outgoing TCP connec()), 
    476  * then the caller will be notified later via the callback. 
    477  * 
    478  * @param mgr           The transport manager. 
    479  * @param pool          Pool to allocate asychronous job (if required). 
    480  * @param type          The transport type. 
    481  * @param remote        The remote address. 
    482  * @param token         The token that will be passed to the callback. 
    483  * @param cb            The callback to be called to report the completion of  
    484  *                      the operation. 
    485  */ 
    486 PJ_DECL(void) pjsip_transport_get( pjsip_transport_mgr *mgr, 
    487                                    pj_pool_t *pool, 
    488                                    pjsip_transport_type_e type, 
    489                                    const pj_sockaddr_in *remote, 
    490                                    void *token, 
    491                                    pjsip_transport_completion_callback *cb); 
    492611 
    493612PJ_END_DECL 
  • pjproject/trunk/pjsip/include/pjsip/sip_types.h

    r51 r54  
    2626 * Opaque data structure for transports (sip_transport.h). 
    2727 */ 
    28 typedef struct pjsip_transport_t pjsip_transport_t; 
     28typedef struct pjsip_transport pjsip_transport; 
    2929 
    3030/** 
    3131 * Opaque data type for transport manager (sip_transport.h). 
    3232 */ 
    33 typedef struct pjsip_transport_mgr pjsip_transport_mgr; 
     33typedef struct pjsip_tpmgr pjsip_tpmgr; 
    3434 
    3535/** 
     
    4444    PJSIP_TRANSPORT_UDP, 
    4545 
    46 #if PJ_HAS_TCP 
    4746    /** TCP. */ 
    4847    PJSIP_TRANSPORT_TCP, 
     
    5352    /** SCTP. */ 
    5453    PJSIP_TRANSPORT_SCTP, 
    55 #endif 
    5654 
    5755} pjsip_transport_type_e; 
  • pjproject/trunk/pjsip/src/pjsip-ua/sip_dialog.c

    r51 r54  
    10801080     * We will rewrite the message with a new status code. 
    10811081     */ 
     1082    only if tdata is not pending!!! 
    10821083    tdata = dlg->invite_tsx->last_tx; 
    10831084    msg = tdata->msg; 
  • pjproject/trunk/pjsip/src/pjsip/sip_auth.c

    r51 r54  
    3636 
    3737/* A macro just to get rid of type mismatch between char and unsigned char */ 
    38 #define MD5_APPEND(pms,buf,len) md5_append(pms, (const unsigned char*)buf, len) 
     38#define MD5_APPEND(pms,buf,len) pj_md5_update(pms, (const pj_uint8_t*)buf, len) 
    3939 
    4040/* Logging. */ 
     
    8181    char ha2[MD5STRLEN]; 
    8282    unsigned char digest[16]; 
    83     md5_state_t pms; 
     83    pj_md5_context pms; 
    8484 
    8585    pj_assert(result->slen >= MD5STRLEN); 
     
    9191         *** ha1 = MD5(username ":" realm ":" password)  
    9292         ***/ 
    93         md5_init(&pms); 
     93        pj_md5_init(&pms); 
    9494        MD5_APPEND( &pms, cred_info->username.ptr, cred_info->username.slen); 
    9595        MD5_APPEND( &pms, ":", 1); 
     
    9797        MD5_APPEND( &pms, ":", 1); 
    9898        MD5_APPEND( &pms, cred_info->data.ptr, cred_info->data.slen); 
    99         md5_finish(&pms, digest); 
     99        pj_md5_final(&pms, digest); 
    100100 
    101101        digest2str(digest, ha1); 
     
    111111     *** ha2 = MD5(method ":" req_uri)  
    112112     ***/ 
    113     md5_init(&pms); 
     113    pj_md5_init(&pms); 
    114114    MD5_APPEND( &pms, method->ptr, method->slen); 
    115115    MD5_APPEND( &pms, ":", 1); 
    116116    MD5_APPEND( &pms, uri->ptr, uri->slen); 
    117     md5_finish(&pms, digest); 
     117    pj_md5_final(&pms, digest); 
    118118    digest2str(digest, ha2); 
    119119 
     
    127127     ***    response = MD5(ha1 ":" nonce ":" nc ":" cnonce ":" qop ":" ha2) 
    128128     ***/ 
    129     md5_init(&pms); 
     129    pj_md5_init(&pms); 
    130130    MD5_APPEND( &pms, ha1, MD5STRLEN); 
    131131    MD5_APPEND( &pms, ":", 1); 
     
    143143 
    144144    /* This is the final response digest. */ 
    145     md5_finish(&pms, digest); 
     145    pj_md5_final(&pms, digest); 
    146146     
    147147    /* Convert digest to string and store in chal->response. */ 
     
    735735    PJ_UNUSED_ARG(endpt); 
    736736 
    737     pj_assert(rdata->msg->type == PJSIP_RESPONSE_MSG); 
    738     pj_assert(rdata->msg->line.status.code == 401 || 
    739               rdata->msg->line.status.code == 407 ); 
     737    pj_assert(rdata->msg_info.msg->type == PJSIP_RESPONSE_MSG); 
     738    pj_assert(rdata->msg_info.msg->line.status.code == 401 || 
     739              rdata->msg_info.msg->line.status.code == 407 ); 
    740740 
    741741    /* 
    742742     * Respond to each authentication challenge. 
    743743     */ 
    744     hdr = rdata->msg->hdr.next; 
    745     while (hdr != &rdata->msg->hdr) { 
     744    hdr = rdata->msg_info.msg->hdr.next; 
     745    while (hdr != &rdata->msg_info.msg->hdr) { 
    746746        pjsip_auth_session *sess; 
    747747        const pjsip_www_authenticate_hdr *hchal; 
     
    751751        while (hdr->type != PJSIP_H_WWW_AUTHENTICATE && 
    752752               hdr->type != PJSIP_H_PROXY_AUTHENTICATE && 
    753                hdr != &rdata->msg->hdr) 
     753               hdr != &rdata->msg_info.msg->hdr) 
    754754        { 
    755755            hdr = hdr->next; 
    756756        } 
    757         if (hdr == &rdata->msg->hdr) 
     757        if (hdr == &rdata->msg_info.msg->hdr) 
    758758            break; 
    759759 
  • pjproject/trunk/pjsip/src/pjsip/sip_endpoint.c

    r51 r54  
    3333#include <pj/assert.h> 
    3434#include <pj/errno.h> 
    35  
     35#include <pj/lock.h> 
    3636 
    3737#define PJSIP_EX_NO_MEMORY  PJ_NO_MEMORY_EXCEPTION 
     
    6464 
    6565    /** Transport manager. */ 
    66     pjsip_transport_mgr *transport_mgr; 
     66    pjsip_tpmgr         *transport_mgr; 
     67 
     68    /** Ioqueue. */ 
     69    pj_ioqueue_t        *ioqueue; 
    6770 
    6871    /** DNS Resolver. */ 
     
    9699 * Prototypes. 
    97100 */ 
    98 static void endpt_transport_callback( pjsip_endpoint *, pjsip_rx_data *rdata ); 
     101static void endpt_transport_callback(pjsip_endpoint*,  
     102                                     pj_status_t, pjsip_rx_data*); 
    99103 
    100104 
     
    355359    pjsip_endpoint *endpt; 
    356360    pjsip_max_forwards_hdr *mf_hdr; 
     361    pj_lock_t *lock = NULL; 
    357362 
    358363    PJ_LOG(5, (THIS_FILE, "pjsip_endpt_create()")); 
     
    399404    } 
    400405 
     406    /* Set recursive lock for the timer heap. */ 
     407    status = pj_lock_create_recursive_mutex( endpt->pool, "edpt%p", &lock); 
     408    if (status != PJ_SUCCESS) { 
     409        goto on_error; 
     410    } 
     411    pj_timer_heap_set_lock(endpt->timer_heap, lock, PJ_TRUE); 
     412 
     413    /* Set maximum timed out entries to process in a single poll. */ 
     414    pj_timer_heap_set_max_timed_out_per_poll(endpt->timer_heap,  
     415                                             PJSIP_MAX_TIMED_OUT_ENTRIES); 
     416 
     417    /* Create ioqueue. */ 
     418    status = pj_ioqueue_create( endpt->pool, PJSIP_MAX_TRANSPORTS, &endpt->ioqueue); 
     419    if (status != PJ_SUCCESS) { 
     420        goto on_error; 
     421    } 
     422 
    401423    /* Create transport manager. */ 
    402     status = pjsip_transport_mgr_create( endpt->pool, 
    403                                          endpt, 
    404                                         &endpt_transport_callback, 
    405                                         &endpt->transport_mgr); 
     424    status = pjsip_tpmgr_create( endpt->pool, endpt, 
     425                                 endpt->ioqueue, endpt->timer_heap, 
     426                                &endpt_transport_callback, 
     427                                &endpt->transport_mgr); 
    406428    if (status != PJ_SUCCESS) { 
    407429        goto on_error; 
     
    446468on_error: 
    447469    if (endpt->transport_mgr) { 
    448         pjsip_transport_mgr_destroy(endpt->transport_mgr); 
     470        pjsip_tpmgr_destroy(endpt->transport_mgr); 
    449471        endpt->transport_mgr = NULL; 
    450472    } 
     
    471493 
    472494    /* Shutdown and destroy all transports. */ 
    473     pjsip_transport_mgr_destroy(endpt->transport_mgr); 
     495    pjsip_tpmgr_destroy(endpt->transport_mgr); 
    474496 
    475497    /* Delete endpoint mutex. */ 
     
    533555                                        const pj_time_val *max_timeout) 
    534556{ 
    535     pj_time_val timeout; 
    536     int i; 
     557    /* timeout is 'out' var. This just to make compiler happy. */ 
     558    pj_time_val timeout = { 0, 0}; 
    537559 
    538560    PJ_LOG(5, (THIS_FILE, "pjsip_endpt_handle_events()")); 
    539561 
    540562    /* Poll the timer. The timer heap has its own mutex for better  
    541      * granularity, so we don't need to lock end endpoint. We also keep 
    542      * polling the timer while we have events. 
     563     * granularity, so we don't need to lock end endpoint.  
    543564     */ 
    544     timeout.sec = timeout.msec = 0; /* timeout is 'out' var. This just to make compiler happy. */ 
    545     for (i=0; i<10; ++i) { 
    546         if (pj_timer_heap_poll( endpt->timer_heap, &timeout ) < 1) 
    547             break; 
    548     } 
     565    timeout.sec = timeout.msec = 0; 
     566    pj_timer_heap_poll( endpt->timer_heap, &timeout ); 
    549567 
    550568    /* If caller specifies maximum time to wait, then compare the value with 
     
    555573    } 
    556574 
    557     /* Poll events in the transport manager. */ 
    558     pjsip_transport_mgr_handle_events( endpt->transport_mgr, &timeout); 
     575    /* Poll ioqueue. */ 
     576    pj_ioqueue_poll( endpt->ioqueue, &timeout); 
    559577} 
    560578 
     
    659677{ 
    660678    pjsip_role_e role; 
    661     if (rdata->msg->type == PJSIP_REQUEST_MSG) { 
     679    if (rdata->msg_info.msg->type == PJSIP_REQUEST_MSG) { 
    662680        role = PJSIP_ROLE_UAS; 
    663681    } else { 
    664682        role = PJSIP_ROLE_UAC; 
    665683    } 
    666     pjsip_tsx_create_key(rdata->pool, &rdata->key, role, 
    667                          &rdata->cseq->method, rdata); 
     684    pjsip_tsx_create_key(rdata->tp_info.pool, &rdata->endpt_info.key, role, 
     685                         &rdata->msg_info.cseq->method, rdata); 
    668686} 
    669687 
     
    673691 */ 
    674692static void endpt_transport_callback( pjsip_endpoint *endpt, 
     693                                      pj_status_t status, 
    675694                                      pjsip_rx_data *rdata ) 
    676695{ 
    677     pjsip_msg *msg = rdata->msg; 
     696    pjsip_msg *msg = rdata->msg_info.msg; 
    678697    pjsip_transaction *tsx; 
    679698    pj_bool_t a_new_transaction_just_been_created = PJ_FALSE; 
    680699 
    681700    PJ_LOG(5, (THIS_FILE, "endpt_transport_callback(rdata=%p)", rdata)); 
     701 
     702    if (status != PJ_SUCCESS) { 
     703        const char *src_addr = pj_inet_ntoa(rdata->pkt_info.addr.sin_addr); 
     704        int port = pj_ntohs(rdata->pkt_info.addr.sin_port); 
     705        PJSIP_ENDPT_LOG_ERROR((endpt, "transport", status, 
     706                               "Src.addr=%s:%d, packet:--\n" 
     707                               "%s\n" 
     708                               "-- end of packet. Error", 
     709                               src_addr, port, rdata->msg_info.msg_buf)); 
     710        return; 
     711    } 
    682712 
    683713    /* For response, check that the value in Via sent-by match the transport. 
     
    688718        const pj_sockaddr_in *addr; 
    689719        const char *addr_addr; 
    690         int port = rdata->via->sent_by.port; 
     720        int port = rdata->msg_info.via->sent_by.port; 
    691721        pj_bool_t mismatch = PJ_FALSE; 
    692722        if (port == 0) { 
    693723            int type; 
    694             type = pjsip_transport_get_type(rdata->transport); 
     724            type = rdata->tp_info.transport->type; 
    695725            port = pjsip_transport_get_default_port_for_type(type); 
    696726        } 
    697         addr = pjsip_transport_get_addr_name(rdata->transport); 
     727        addr = &rdata->tp_info.transport->public_addr; 
    698728        addr_addr = pj_inet_ntoa(addr->sin_addr); 
    699         if (pj_strcmp2(&rdata->via->sent_by.host, addr_addr) != 0) 
     729        if (pj_strcmp2(&rdata->msg_info.via->sent_by.host, addr_addr) != 0) 
    700730            mismatch = PJ_TRUE; 
    701731        else if (port != pj_ntohs(addr->sin_port)) { 
     
    707737             * both the port in sent-by and rport. We try to be lenient here! 
    708738             */ 
    709             if (rdata->via->rport_param != pj_sockaddr_in_get_port(addr)) 
     739            if (rdata->msg_info.via->rport_param != pj_sockaddr_in_get_port(addr)) 
    710740                mismatch = PJ_TRUE; 
    711741            else { 
     
    730760    /* Find the transaction for the received message. */ 
    731761    PJ_LOG(5, (THIS_FILE, "finding tsx with key=%.*s",  
    732                          rdata->key.slen, rdata->key.ptr)); 
     762                         rdata->endpt_info.key.slen, rdata->endpt_info.key.ptr)); 
    733763 
    734764    /* Start lock mutex in the endpoint. */ 
     
    736766 
    737767    /* Find the transaction in the hash table. */ 
    738     tsx = pj_hash_get( endpt->tsx_table, rdata->key.ptr, rdata->key.slen ); 
     768    tsx = pj_hash_get( endpt->tsx_table, rdata->endpt_info.key.ptr, rdata->endpt_info.key.slen ); 
    739769 
    740770    /* Unlock mutex. */ 
     
    753783            /* Inform TU about the 200 message, only if it's INVITE. */ 
    754784            if (PJSIP_IS_STATUS_IN_CLASS(msg->line.status.code, 200) && 
    755                 rdata->cseq->method.id == PJSIP_INVITE_METHOD)  
     785                rdata->msg_info.cseq->method.id == PJSIP_INVITE_METHOD)  
    756786            { 
    757787                pjsip_event e; 
     
    777807         * For non-ACK request message, create a new transaction. 
    778808         */ 
    779         } else if (rdata->msg->line.req.method.id != PJSIP_ACK_METHOD) { 
     809        } else if (rdata->msg_info.msg->line.req.method.id != PJSIP_ACK_METHOD) { 
    780810 
    781811            pj_status_t status; 
     
    806836        pjsip_tsx_on_rx_msg( tsx, rdata ); 
    807837 
    808     } else if (rdata->msg->line.req.method.id == PJSIP_ACK_METHOD) { 
     838    } else if (rdata->msg_info.msg->line.req.method.id == PJSIP_ACK_METHOD) { 
    809839        /* 
    810840         * This is an ACK message, but the INVITE transaction could not 
     
    915945 * Find/create transport. 
    916946 */ 
    917 PJ_DEF(void) pjsip_endpt_get_transport( pjsip_endpoint *endpt, 
    918                                         pj_pool_t *pool, 
    919                                         pjsip_transport_type_e type, 
    920                                         const pj_sockaddr_in *remote, 
    921                                         void *token, 
    922                                         pjsip_transport_completion_callback *cb) 
    923 { 
    924     PJ_LOG(5, (THIS_FILE, "pjsip_endpt_get_transport()")); 
    925     pjsip_transport_get( endpt->transport_mgr, pool, type, 
    926                          remote, token, cb); 
    927 } 
    928  
    929  
    930 PJ_DEF(pj_status_t) pjsip_endpt_create_listener( pjsip_endpoint *endpt, 
    931                                                  pjsip_transport_type_e type, 
    932                                                  pj_sockaddr_in *addr, 
    933                                                  const pj_sockaddr_in *addr_name) 
    934 { 
    935     PJ_LOG(5, (THIS_FILE, "pjsip_endpt_create_listener()")); 
    936     return pjsip_create_listener( endpt->transport_mgr, type, addr, addr_name ); 
    937 } 
    938  
    939 PJ_DEF(pj_status_t) pjsip_endpt_create_udp_listener( pjsip_endpoint *endpt, 
    940                                                      pj_sock_t sock, 
    941                                                      const pj_sockaddr_in *addr_name) 
    942 { 
    943     PJ_LOG(5, (THIS_FILE, "pjsip_endpt_create_udp_listener()")); 
    944     return pjsip_create_udp_listener( endpt->transport_mgr, sock, addr_name ); 
    945 } 
     947PJ_DECL(pj_status_t) pjsip_endpt_alloc_transport( pjsip_endpoint *endpt, 
     948                                                  pjsip_transport_type_e type, 
     949                                                  const pj_sockaddr_in *remote, 
     950                                                  pjsip_transport **p_transport) 
     951{ 
     952    PJ_LOG(5, (THIS_FILE, "pjsip_endpt_alloc_transport()")); 
     953    return pjsip_tpmgr_alloc_transport( endpt->transport_mgr, type, remote, 
     954                                        p_transport); 
     955} 
     956 
    946957 
    947958PJ_DEF(void) pjsip_endpt_dump( pjsip_endpoint *endpt, pj_bool_t detail ) 
     
    949960#if PJ_LOG_MAX_LEVEL >= 3 
    950961    unsigned count; 
    951     pj_hash_iterator_t itr_val; 
    952     pj_hash_iterator_t *itr; 
    953962 
    954963    PJ_LOG(5, (THIS_FILE, "pjsip_endpt_dump()")); 
     
    10151024 
    10161025    /* Transports.  
    1017      * Note: transport is not properly locked in this function. 
    1018      *       See pjsip_transport_first, pjsip_transport_next. 
    10191026     */ 
    1020     itr = pjsip_transport_first( endpt->transport_mgr, &itr_val ); 
    1021     if (itr) { 
    1022         PJ_LOG(3, (THIS_FILE, " Dumping transports:")); 
    1023  
    1024         do { 
    1025             char src_addr[128], dst_addr[128]; 
    1026             int src_port, dst_port; 
    1027             const pj_sockaddr_in *addr; 
    1028             pjsip_transport_t *t; 
    1029  
    1030             t = pjsip_transport_this(endpt->transport_mgr, itr); 
    1031             addr = pjsip_transport_get_local_addr(t); 
    1032             pj_native_strcpy(src_addr, pj_inet_ntoa(addr->sin_addr)); 
    1033             src_port = pj_ntohs(addr->sin_port); 
    1034  
    1035             addr = pjsip_transport_get_remote_addr(t); 
    1036             pj_native_strcpy(dst_addr, pj_inet_ntoa(addr->sin_addr)); 
    1037             dst_port = pj_ntohs(addr->sin_port); 
    1038  
    1039             PJ_LOG(3, (THIS_FILE, "  %s %s %s:%d --> %s:%d (refcnt=%d)",  
    1040                        pjsip_transport_get_type_name(t), 
    1041                        pjsip_transport_get_obj_name(t), 
    1042                        src_addr, src_port, 
    1043                        dst_addr, dst_port, 
    1044                        pjsip_transport_get_ref_cnt(t))); 
    1045  
    1046             itr = pjsip_transport_next(endpt->transport_mgr, itr); 
    1047         } while (itr); 
    1048     } 
     1027    pjsip_tpmgr_dump_transports( endpt->transport_mgr ); 
    10491028 
    10501029    /* Timer. */ 
  • pjproject/trunk/pjsip/src/pjsip/sip_misc.c

    r51 r54  
    430430 
    431431    /* rdata must be a request message. */ 
    432     req_msg = rdata->msg; 
     432    req_msg = rdata->msg_info.msg; 
    433433    pj_assert(req_msg->type == PJSIP_REQUEST_MSG); 
    434434 
     
    450450 
    451451    /* Set TX data attributes. */ 
    452     tdata->rx_timestamp = rdata->timestamp; 
     452    tdata->rx_timestamp = rdata->pkt_info.timestamp; 
    453453 
    454454    /* Copy all the via headers, in order. */ 
    455     via = rdata->via; 
     455    via = rdata->msg_info.via; 
    456456    while (via) { 
    457457        pjsip_msg_add_hdr( msg, pjsip_hdr_clone(tdata->pool, via)); 
     
    479479 
    480480    /* Copy From header. */ 
    481     hdr = pjsip_hdr_clone(tdata->pool, rdata->from); 
     481    hdr = pjsip_hdr_clone(tdata->pool, rdata->msg_info.from); 
    482482    pjsip_msg_add_hdr( msg, hdr); 
    483483 
    484484    /* Copy To header. */ 
    485     hdr = pjsip_hdr_clone(tdata->pool, rdata->to); 
     485    hdr = pjsip_hdr_clone(tdata->pool, rdata->msg_info.to); 
    486486    pjsip_msg_add_hdr( msg, hdr); 
    487487 
    488488    /* Copy CSeq header. */ 
    489     hdr = pjsip_hdr_clone(tdata->pool, rdata->cseq); 
     489    hdr = pjsip_hdr_clone(tdata->pool, rdata->msg_info.cseq); 
    490490    pjsip_msg_add_hdr( msg, hdr); 
    491491 
     
    515515 
    516516    /* rdata must be a final response. */ 
    517     pj_assert(rdata->msg->type==PJSIP_RESPONSE_MSG && 
    518               rdata->msg->line.status.code >= 300); 
     517    pj_assert(rdata->msg_info.msg->type==PJSIP_RESPONSE_MSG && 
     518              rdata->msg_info.msg->line.status.code >= 300); 
    519519 
    520520    /* Log this action. */ 
     
    543543    to = (pjsip_to_hdr*)pjsip_msg_find_remove_hdr( invite_msg,  
    544544                                                   PJSIP_H_TO, NULL); 
    545     pj_strdup(tdata->pool, &to->tag, &rdata->to->tag); 
     545    pj_strdup(tdata->pool, &to->tag, &rdata->msg_info.to->tag); 
    546546    pjsip_msg_add_hdr( ack_msg, (pjsip_hdr*)to ); 
    547547 
     
    675675 */ 
    676676PJ_DEF(pj_status_t) pjsip_get_response_addr(pj_pool_t *pool, 
    677                                             const pjsip_transport_t *req_transport, 
     677                                            const pjsip_transport *req_transport, 
    678678                                            const pjsip_via_hdr *via, 
    679679                                            pjsip_host_port *send_addr) 
     
    688688     * - otherwise send to the address in sent-by. 
    689689     */ 
    690     send_addr->flag = pjsip_transport_get_flag(req_transport); 
    691     send_addr->type = pjsip_transport_get_type(req_transport); 
     690    send_addr->flag = req_transport->flag; 
     691    send_addr->type = req_transport->type; 
    692692 
    693693    if (PJSIP_TRANSPORT_IS_RELIABLE(req_transport)) { 
    694694        const pj_sockaddr_in *remote_addr; 
    695         remote_addr = pjsip_transport_get_remote_addr(req_transport); 
     695        remote_addr = &req_transport->rem_addr; 
    696696        pj_strdup2(pool, &send_addr->host,  
    697697                   pj_inet_ntoa(remote_addr->sin_addr)); 
  • pjproject/trunk/pjsip/src/pjsip/sip_parser.c

    r51 r54  
    559559 
    560560    context.scanner = &scanner; 
    561     context.pool = rdata->pool; 
     561    context.pool = rdata->tp_info.pool; 
    562562    context.rdata = rdata; 
    563563 
    564564    PJ_TRY { 
    565         rdata->msg = int_parse_msg(&context, &rdata->parse_err); 
     565        rdata->msg_info.msg = int_parse_msg(&context, &rdata->msg_info.parse_err); 
    566566    }  
    567567    PJ_DEFAULT { 
    568         rdata->msg = NULL; 
     568        rdata->msg_info.msg = NULL; 
    569569    } 
    570570    PJ_END 
    571571 
    572572    pj_scan_fini(&scanner); 
    573     return rdata->msg; 
     573    return rdata->msg_info.msg; 
    574574} 
    575575 
     
    12591259 
    12601260    if (ctx->rdata) 
    1261         ctx->rdata->call_id = hdr->id; 
     1261        ctx->rdata->msg_info.call_id = hdr->id; 
    12621262 
    12631263    return (pjsip_hdr*)hdr; 
     
    13401340 
    13411341    if (ctx->rdata) 
    1342         ctx->rdata->clen = hdr; 
     1342        ctx->rdata->msg_info.clen = hdr; 
    13431343 
    13441344    return (pjsip_hdr*)hdr; 
     
    13681368 
    13691369    if (ctx->rdata) 
    1370         ctx->rdata->ctype = hdr; 
     1370        ctx->rdata->msg_info.ctype = hdr; 
    13711371 
    13721372    return (pjsip_hdr*)hdr; 
     
    13891389 
    13901390    if (ctx->rdata) 
    1391         ctx->rdata->cseq = hdr; 
     1391        ctx->rdata->msg_info.cseq = hdr; 
    13921392 
    13931393    return (pjsip_hdr*)hdr; 
     
    14331433    parse_hdr_fromto(ctx->scanner, ctx->pool, hdr); 
    14341434    if (ctx->rdata) 
    1435         ctx->rdata->from = hdr; 
     1435        ctx->rdata->msg_info.from = hdr; 
    14361436 
    14371437    return (pjsip_hdr*)hdr; 
     
    14441444    parse_generic_array_hdr(hdr, ctx->scanner); 
    14451445 
    1446     if (ctx->rdata && ctx->rdata->require == NULL) 
    1447         ctx->rdata->require = hdr; 
     1446    if (ctx->rdata && ctx->rdata->msg_info.require == NULL) 
     1447        ctx->rdata->msg_info.require = hdr; 
    14481448 
    14491449    return (pjsip_hdr*)hdr; 
     
    14751475 
    14761476    if (ctx->rdata) 
    1477         ctx->rdata->to = hdr; 
     1477        ctx->rdata->msg_info.to = hdr; 
    14781478 
    14791479    return (pjsip_hdr*)hdr; 
     
    15291529 
    15301530    if (ctx->rdata) 
    1531         ctx->rdata->max_fwd = hdr; 
     1531        ctx->rdata->msg_info.max_fwd = hdr; 
    15321532 
    15331533    return (pjsip_hdr*)hdr; 
     
    15791579    parse_hdr_end(scanner); 
    15801580 
    1581     if (ctx->rdata && ctx->rdata->record_route==NULL) 
    1582         ctx->rdata->record_route = first; 
     1581    if (ctx->rdata && ctx->rdata->msg_info.record_route==NULL) 
     1582        ctx->rdata->msg_info.record_route = first; 
    15831583 
    15841584    return (pjsip_hdr*)first; 
     
    16071607    parse_hdr_end(scanner); 
    16081608 
    1609     if (ctx->rdata && ctx->rdata->route==NULL) 
    1610         ctx->rdata->route = first; 
     1609    if (ctx->rdata && ctx->rdata->msg_info.route==NULL) 
     1610        ctx->rdata->msg_info.route = first; 
    16111611 
    16121612    return (pjsip_hdr*)first; 
     
    16601660    parse_hdr_end(scanner); 
    16611661 
    1662     if (ctx->rdata && ctx->rdata->via == NULL) 
    1663         ctx->rdata->via = first; 
     1662    if (ctx->rdata && ctx->rdata->msg_info.via == NULL) 
     1663        ctx->rdata->msg_info.via = first; 
    16641664 
    16651665    return (pjsip_hdr*)first; 
  • pjproject/trunk/pjsip/src/pjsip/sip_transaction.c

    r51 r54  
    193193 
    194194    PJ_ASSERT_RETURN(pool && str && method && rdata, PJ_EINVAL); 
    195     PJ_ASSERT_RETURN(rdata->msg, PJ_EINVAL); 
    196     PJ_ASSERT_RETURN(rdata->via, PJSIP_EMISSINGHDR); 
    197     PJ_ASSERT_RETURN(rdata->cseq, PJSIP_EMISSINGHDR); 
    198     PJ_ASSERT_RETURN(rdata->from, PJSIP_EMISSINGHDR); 
    199  
    200     host = &rdata->via->sent_by.host; 
    201     req_uri = (pjsip_uri*)rdata->msg->line.req.uri; 
     195    PJ_ASSERT_RETURN(rdata->msg_info.msg, PJ_EINVAL); 
     196    PJ_ASSERT_RETURN(rdata->msg_info.via, PJSIP_EMISSINGHDR); 
     197    PJ_ASSERT_RETURN(rdata->msg_info.cseq, PJSIP_EMISSINGHDR); 
     198    PJ_ASSERT_RETURN(rdata->msg_info.from, PJSIP_EMISSINGHDR); 
     199 
     200    host = &rdata->msg_info.via->sent_by.host; 
     201    req_uri = (pjsip_uri*)rdata->msg_info.msg->line.req.uri; 
    202202 
    203203    /* Calculate length required. */ 
    204204    len_required = 9 +                      /* CSeq number */ 
    205                    rdata->from->tag.slen +   /* From tag. */ 
    206                    rdata->call_id.slen +    /* Call-ID */ 
     205                   rdata->msg_info.from->tag.slen +   /* From tag. */ 
     206                   rdata->msg_info.call_id.slen +    /* Call-ID */ 
    207207                   host->slen +             /* Via host. */ 
    208208                   9 +                      /* Via port. */ 
     
    232232 
    233233    /* Add CSeq (only the number). */ 
    234     len = pj_utoa(rdata->cseq->cseq, p); 
     234    len = pj_utoa(rdata->msg_info.cseq->cseq, p); 
    235235    p += len; 
    236236    *p++ = SEPARATOR; 
    237237 
    238238    /* Add From tag. */ 
    239     len = rdata->from->tag.slen; 
    240     pj_memcpy( p, rdata->from->tag.ptr, len); 
     239    len = rdata->msg_info.from->tag.slen; 
     240    pj_memcpy( p, rdata->msg_info.from->tag.ptr, len); 
    241241    p += len; 
    242242    *p++ = SEPARATOR; 
    243243 
    244244    /* Add Call-ID. */ 
    245     len = rdata->call_id.slen; 
    246     pj_memcpy( p, rdata->call_id.ptr, len ); 
     245    len = rdata->msg_info.call_id.slen; 
     246    pj_memcpy( p, rdata->msg_info.call_id.ptr, len ); 
    247247    p += len; 
    248248    *p++ = SEPARATOR; 
     
    258258    *p++ = ':'; 
    259259 
    260     len = pj_utoa(rdata->via->sent_by.port, p); 
     260    len = pj_utoa(rdata->msg_info.via->sent_by.port, p); 
    261261    p += len; 
    262262    *p++ = SEPARATOR; 
     
    325325     * handled as RFC2543. 
    326326     */ 
    327     const pj_str_t *branch = &rdata->via->branch_param; 
     327    const pj_str_t *branch = &rdata->msg_info.via->branch_param; 
    328328 
    329329    if (pj_strncmp(branch,&rfc3261_branch,PJSIP_RFC3261_BRANCH_LEN)==0) { 
     
    643643 * has completed, with or without error. 
    644644 */ 
    645 static void tsx_transport_callback(pjsip_transport_t *tr,  
     645static void tsx_transport_callback(pjsip_transport *tr,  
    646646                                   void *token,  
    647647                                   pj_status_t status) 
     
    657657    if (status == PJ_SUCCESS) { 
    658658        PJ_LOG(4, (tsx->obj_name, "%s connected to %s:%d", 
    659                                   pjsip_transport_get_type_name(tr), 
     659                                  tr->type_name, 
    660660                                  addr, tsx->dest_name.port)); 
    661661    } else { 
    662662        PJ_LOG(4, (tsx->obj_name, "%s unable to connect to %s:%d, status=%d",  
    663                                   pjsip_transport_get_type_name(tr), 
     663                                  tr->type_name, 
    664664                                  addr, tsx->dest_name.port, status)); 
    665665    } 
     
    878878                                        pjsip_rx_data *rdata) 
    879879{ 
    880     pjsip_msg *msg = rdata->msg; 
     880    pjsip_msg *msg = rdata->msg_info.msg; 
    881881    pj_str_t *branch; 
    882882    pjsip_cseq_hdr *cseq; 
     
    890890 
    891891    /* Keep shortcut to message */ 
    892     msg = rdata->msg; 
     892    msg = rdata->msg_info.msg; 
    893893 
    894894    /* Role is UAS */ 
     
    909909 
    910910    /* Duplicate branch parameter for transaction. */ 
    911     branch = &rdata->via->branch_param; 
     911    branch = &rdata->msg_info.via->branch_param; 
    912912    pj_strdup(tsx->pool, &tsx->branch, branch); 
    913913 
     
    916916 
    917917    /* Save CSeq */ 
    918     cseq = rdata->cseq; 
     918    cseq = rdata->msg_info.cseq; 
    919919    tsx->cseq = cseq->cseq; 
    920920 
     
    932932     * then return the response using the same transport. 
    933933     */ 
    934     if (PJSIP_TRANSPORT_IS_RELIABLE(rdata->transport) ||  
    935         rdata->via->rport_param >= 0)  
     934    if (PJSIP_TRANSPORT_IS_RELIABLE(rdata->tp_info.transport) ||  
     935        rdata->msg_info.via->rport_param >= 0)  
    936936    { 
    937         tsx->transport = rdata->transport; 
     937        tsx->transport = rdata->tp_info.transport; 
    938938        pjsip_transport_add_ref(tsx->transport); 
    939939        tsx->transport_state = PJSIP_TSX_TRANSPORT_STATE_FINAL; 
     
    944944                pjsip_transport_get_type(tsx->transport); 
    945945        pj_memcpy(&tsx->remote_addr.entry[0].addr,  
    946                   &rdata->addr, rdata->addr_len); 
     946                  &rdata->pkt_info.addr, rdata->pkt_info.addr_len); 
    947947         
    948948    } else { 
    949949        pj_status_t status; 
    950950 
    951         status = pjsip_get_response_addr(tsx->pool, rdata->transport, 
    952                                          rdata->via, &tsx->dest_name); 
     951        status = pjsip_get_response_addr(tsx->pool, rdata->tp_info.transport, 
     952                                         rdata->msg_info.via, &tsx->dest_name); 
    953953        if (status != PJ_SUCCESS) { 
    954954            tsx->transport_state = PJSIP_TSX_TRANSPORT_STATE_FINAL; 
     
    12131213            /* Don't update Via sent-by on retransmission. */ 
    12141214            if (via->sent_by.host.slen == 0) { 
    1215                 addr_name = pjsip_transport_get_addr_name(tsx->transport); 
     1215                addr_name = &tsx->transport->public_addr; 
    12161216                pj_strdup2(tdata->pool, &via->transport,  
    1217                         pjsip_transport_get_type_name(tsx->transport)); 
     1217                           tsx->transport->type_name); 
    12181218                pj_strdup2(tdata->pool, &via->sent_by.host,  
    12191219                           pj_inet_ntoa(addr_name->sin_addr)); 
     
    13971397         */ 
    13981398        /* Keep last_tx for authorization. */ 
    1399         code = event->body.rx_msg.rdata->msg->line.status.code; 
     1399        code = event->body.rx_msg.rdata->msg_info.msg->line.status.code; 
    14001400        if (tsx->method.id != PJSIP_INVITE_METHOD && code!=401 && code!=407) { 
    14011401            pjsip_tx_data_dec_ref(tsx->last_tx); 
     
    16661666        } 
    16671667 
    1668         tsx->status_code = event->body.rx_msg.rdata->msg->line.status.code; 
     1668        tsx->status_code = event->body.rx_msg.rdata->msg_info.msg->line.status.code; 
    16691669    } else { 
    16701670        tsx->status_code = PJSIP_SC_TSX_TIMEOUT; 
     
    17631763 
    17641764    if (event->type == PJSIP_EVENT_RX_MSG) { 
    1765         pjsip_msg *msg = event->body.rx_msg.rdata->msg; 
     1765        pjsip_msg *msg = event->body.rx_msg.rdata->msg_info.msg; 
    17661766        pjsip_cseq_hdr *cseq = pjsip_msg_find_hdr( msg, PJSIP_H_CSEQ, NULL ); 
    17671767 
     
    18561856             * TU doesn't need to be informed. 
    18571857             */ 
    1858             pjsip_msg *msg = event->body.rx_msg.rdata->msg; 
     1858            pjsip_msg *msg = event->body.rx_msg.rdata->msg_info.msg; 
    18591859            pj_assert(msg->type == PJSIP_RESPONSE_MSG); 
    18601860            if (msg->type==PJSIP_RESPONSE_MSG && 
     
    19221922 
    19231923        pjsip_method_e method_id =  
    1924             event->body.rx_msg.rdata->msg->line.req.method.id; 
     1924            event->body.rx_msg.rdata->msg_info.msg->line.req.method.id; 
    19251925 
    19261926        /* Must be a request message. */ 
    1927         pj_assert(event->body.rx_msg.rdata->msg->type == PJSIP_REQUEST_MSG); 
     1927        pj_assert(event->body.rx_msg.rdata->msg_info.msg->type == PJSIP_REQUEST_MSG); 
    19281928 
    19291929        /* Must be an ACK request or a late INVITE retransmission. */ 
  • pjproject/trunk/pjsip/src/pjsip/sip_transport.c

    r51 r54  
    3030#include <pj/pool.h> 
    3131#include <pj/assert.h> 
    32  
    33 #define MGR_IDLE_CHECK_INTERVAL 30 
    34 #define MGR_HASH_TABLE_SIZE     PJSIP_MAX_DIALOG_COUNT 
    35 #define BACKLOG                 5 
    36 #define DEFAULT_SO_SNDBUF       (8 * 1024 * 1024) 
    37 #define DEFAULT_SO_RCVBUF       (8 * 1024 * 1024) 
    38  
    39 #define LOG_TRANSPORT_MGR       "trmgr"  
    40 #define THIS_FILE               "sip_transport" 
    41  
    42 static void destroy_transport( pjsip_transport_mgr *mgr, pjsip_transport_t *tr ); 
    43  
    44  
    45 /** 
    46  * New TCP socket for accept. 
    47  */ 
    48 typedef struct incoming_socket_rec 
    49 { 
    50     pj_sock_t           sock; 
    51     pj_sockaddr_in      remote; 
    52     pj_sockaddr_in      local; 
    53     int                 addrlen; 
    54 } incoming_socket_rec; 
    55  
    56 /** 
    57  * SIP Transport. 
    58  */ 
    59 struct pjsip_transport_t 
    60 { 
    61     /** Standard list members, for chaining the transport in the  
    62      *  listener list.  
    63      */ 
    64     PJ_DECL_LIST_MEMBER(struct pjsip_transport_t); 
    65  
    66     /** Transport's pool. */ 
    67     pj_pool_t           *pool; 
    68  
    69     /** Mutex */ 
    70     pj_mutex_t          *tr_mutex; 
    71  
    72     /** Transport name for logging purpose */ 
    73     char                 obj_name[PJ_MAX_OBJ_NAME]; 
    74  
    75     /** Socket handle */ 
    76     pj_sock_t            sock; 
    77  
    78     /** Transport type. */ 
    79     pjsip_transport_type_e type; 
    80  
    81     /** Flags to keep various states (see pjsip_transport_flags_e). */ 
    82     pj_uint32_t          flag; 
    83  
    84     /** I/O Queue key */ 
    85     pj_ioqueue_key_t    *key; 
    86  
    87     /** Accept key. */ 
    88     pj_ioqueue_op_key_t  accept_op; 
    89  
    90     /** Receive data buffer */ 
    91     pjsip_rx_data       *rdata; 
    92  
    93     /** Pointer to transport manager */ 
    94     pjsip_transport_mgr *mgr; 
    95  
    96     /** Reference counter, to prevent this transport from being closed while 
    97      *  it's being used.  
    98      */ 
    99     pj_atomic_t          *ref_cnt; 
    100  
    101     /** Local address. */ 
    102     pj_sockaddr_in       local_addr; 
    103  
    104     /** Address name (what to put in Via address field). */ 
    105     pj_sockaddr_in       addr_name; 
    106  
    107     /** Remote address (can be zero for UDP and for listeners). UDP listener 
    108      *  bound to local loopback interface (127.0.0.1) has remote address set 
    109      *  to 127.0.0.1 to prevent client from using it to send to remote hosts, 
    110      *  because remote host then will receive 127.0.0.1 as the packet's  
    111      *  source address. 
    112      */ 
    113     pj_sockaddr_in       remote_addr; 
    114  
    115     /** Struct to save incoming socket information. */ 
    116     incoming_socket_rec  accept_data; 
    117  
    118     /** When this transport should be closed. */ 
    119     pj_time_val          close_time; 
    120  
    121     /** List of callbacks to be called when client attempt to use this  
    122      *  transport while it's not connected (i.e. still connecting).  
    123      */ 
    124     pj_list              cb_list; 
    125 }; 
    126  
     32#include <pj/lock.h> 
     33 
     34 
     35#define THIS_FILE    "transport" 
    12736 
    12837/* 
    12938 * Transport manager. 
    13039 */ 
    131 struct pjsip_transport_mgr  
    132 { 
    133     pj_hash_table_t *transport_table; 
    134     pj_mutex_t      *mutex; 
     40struct pjsip_tpmgr  
     41{ 
     42    pj_hash_table_t *table; 
     43    pj_lock_t       *lock; 
    13544    pjsip_endpoint  *endpt; 
    13645    pj_ioqueue_t    *ioqueue; 
    137     pj_time_val      next_idle_check; 
    138     pj_size_t        send_buf_size; 
    139     pj_size_t        recv_buf_size; 
    140     void           (*message_callback)(pjsip_endpoint*, pjsip_rx_data *rdata); 
     46    pj_timer_heap_t *timer_heap; 
     47    pjsip_tpfactory  factory_list; 
     48    void           (*msg_cb)(pjsip_endpoint*, pj_status_t, pjsip_rx_data*); 
    14149}; 
    14250 
    143 /* 
    144  * Transport role. 
    145  */ 
    146 typedef enum transport_role_e 
    147 { 
    148     TRANSPORT_ROLE_LISTENER, 
    149     TRANSPORT_ROLE_TRANSPORT, 
    150 } transport_role_e; 
     51 
     52 
     53/***************************************************************************** 
     54 * 
     55 * GENERAL TRANSPORT (NAMES, TYPES, ETC.) 
     56 * 
     57 *****************************************************************************/ 
     58 
     59/* 
     60 * Transport names. 
     61 */ 
     62const struct 
     63{ 
     64    pjsip_transport_type_e type; 
     65    pj_uint16_t            port; 
     66    pj_str_t               name; 
     67    unsigned               flag; 
     68} transport_names[] =  
     69{ 
     70    { PJSIP_TRANSPORT_UNSPECIFIED, 0, {NULL, 0}, 0}, 
     71    { PJSIP_TRANSPORT_UDP, 5060, {"UDP", 3}, PJSIP_TRANSPORT_DATAGRAM}, 
     72    { PJSIP_TRANSPORT_TCP, 5060, {"TCP", 3}, PJSIP_TRANSPORT_RELIABLE}, 
     73    { PJSIP_TRANSPORT_TLS, 5061, {"TLS", 3}, PJSIP_TRANSPORT_RELIABLE | PJSIP_TRANSPORT_SECURE}, 
     74    { PJSIP_TRANSPORT_SCTP, 5060, {"SCTP", 4}, PJSIP_TRANSPORT_RELIABLE} 
     75}; 
     76 
     77 
     78/* 
     79 * Get transport type from name. 
     80 */ 
     81PJ_DEF(pjsip_transport_type_e)  
     82pjsip_transport_get_type_from_name(const pj_str_t *name) 
     83{ 
     84    unsigned i; 
     85 
     86    for (i=0; i<PJ_ARRAY_SIZE(transport_names); ++i) { 
     87        if (pj_stricmp(name, &transport_names[i].name) == 0) { 
     88            return transport_names[i].type; 
     89        } 
     90    } 
     91 
     92    pj_assert(!"Invalid transport name"); 
     93    return PJSIP_TRANSPORT_UNSPECIFIED; 
     94} 
     95 
     96 
     97/* 
     98 * Get the transport type for the specified flags. 
     99 */ 
     100PJ_DEF(pjsip_transport_type_e)  
     101pjsip_transport_get_type_from_flag(unsigned flag) 
     102{ 
     103    unsigned i; 
     104 
     105    for (i=0; i<PJ_ARRAY_SIZE(transport_names); ++i) { 
     106        if (transport_names[i].flag == flag) { 
     107            return transport_names[i].type; 
     108        } 
     109    } 
     110 
     111    pj_assert(!"Invalid transport type"); 
     112    return PJSIP_TRANSPORT_UNSPECIFIED; 
     113} 
     114 
     115PJ_DEF(unsigned) 
     116pjsip_transport_get_flag_from_type( pjsip_transport_type_e type ) 
     117{ 
     118    PJ_ASSERT_RETURN(type < PJ_ARRAY_SIZE(transport_names), 0); 
     119    return transport_names[type].flag; 
     120} 
     121 
     122/* 
     123 * Get the default SIP port number for the specified type. 
     124 */ 
     125PJ_DEF(int)  
     126pjsip_transport_get_default_port_for_type(pjsip_transport_type_e type) 
     127{ 
     128    PJ_ASSERT_RETURN(type < PJ_ARRAY_SIZE(transport_names), 5060); 
     129    return transport_names[type].port; 
     130} 
     131 
     132 
     133/***************************************************************************** 
     134 * 
     135 * TRANSMIT DATA BUFFER MANIPULATION. 
     136 * 
     137 *****************************************************************************/ 
     138 
     139/* 
     140 * Create new transmit buffer. 
     141 */ 
     142PJ_DEF(pj_status_t) pjsip_tx_data_create( pjsip_tpmgr *mgr, 
     143                                          pjsip_tx_data **p_tdata ) 
     144{ 
     145    pj_pool_t *pool; 
     146    pjsip_tx_data *tdata; 
     147    pj_status_t status; 
     148 
     149    PJ_ASSERT_RETURN(mgr && p_tdata, PJ_EINVAL); 
     150 
     151    PJ_LOG(5, ("", "pjsip_tx_data_create")); 
     152 
     153    pool = pjsip_endpt_create_pool( mgr->endpt, "tdta%p", 
     154                                    PJSIP_POOL_LEN_TDATA, 
     155                                    PJSIP_POOL_INC_TDATA ); 
     156    if (!pool) 
     157        return PJ_ENOMEM; 
     158 
     159    tdata = pj_pool_zalloc(pool, sizeof(pjsip_tx_data)); 
     160    tdata->pool = pool; 
     161    tdata->mgr = mgr; 
     162    pj_snprintf(tdata->obj_name, PJ_MAX_OBJ_NAME, "tdta%p", tdata); 
     163 
     164    status = pj_atomic_create(tdata->pool, 0, &tdata->ref_cnt); 
     165    if (status != PJ_SUCCESS) { 
     166        pjsip_endpt_destroy_pool( mgr->endpt, tdata->pool ); 
     167        return status; 
     168    } 
     169     
     170    //status = pj_lock_create_simple_mutex(pool, "tdta%p", &tdata->lock); 
     171    status = pj_lock_create_null_mutex(pool, "tdta%p", &tdata->lock); 
     172    if (status != PJ_SUCCESS) { 
     173        pjsip_endpt_destroy_pool( mgr->endpt, tdata->pool ); 
     174        return status; 
     175    } 
     176 
     177    pj_ioqueue_op_key_init(&tdata->op_key, sizeof(tdata->op_key)); 
     178 
     179    *p_tdata = tdata; 
     180    return PJ_SUCCESS; 
     181} 
     182 
     183 
     184/* 
     185 * Add reference to tx buffer. 
     186 */ 
     187PJ_DEF(void) pjsip_tx_data_add_ref( pjsip_tx_data *tdata ) 
     188{ 
     189    pj_atomic_inc(tdata->ref_cnt); 
     190} 
     191 
     192/* 
     193 * Decrease transport data reference, destroy it when the reference count 
     194 * reaches zero. 
     195 */ 
     196PJ_DEF(void) pjsip_tx_data_dec_ref( pjsip_tx_data *tdata ) 
     197{ 
     198    pj_assert( pj_atomic_get(tdata->ref_cnt) > 0); 
     199    if (pj_atomic_dec_and_get(tdata->ref_cnt) <= 0) { 
     200        PJ_LOG(5,(tdata->obj_name, "destroying txdata")); 
     201        pj_atomic_destroy( tdata->ref_cnt ); 
     202        pj_lock_destroy( tdata->lock ); 
     203        pjsip_endpt_destroy_pool( tdata->mgr->endpt, tdata->pool ); 
     204    } 
     205} 
     206 
     207/* 
     208 * Invalidate the content of the print buffer to force the message to be 
     209 * re-printed when sent. 
     210 */ 
     211PJ_DEF(void) pjsip_tx_data_invalidate_msg( pjsip_tx_data *tdata ) 
     212{ 
     213    tdata->buf.cur = tdata->buf.start; 
     214} 
     215 
     216PJ_DEF(pj_bool_t) pjsip_tx_data_is_valid( pjsip_tx_data *tdata ) 
     217{ 
     218    return tdata->buf.cur != tdata->buf.start; 
     219} 
     220 
     221 
     222 
     223/***************************************************************************** 
     224 * 
     225 * TRANSPORT KEY 
     226 * 
     227 *****************************************************************************/ 
    151228 
    152229/* 
    153230 * Transport key for indexing in the hash table. 
    154  * WATCH OUT FOR ALIGNMENT PROBLEM HERE! 
    155231 */ 
    156232typedef struct transport_key 
     
    162238} transport_key; 
    163239 
    164 /* 
    165  * Transport callback. 
    166  */ 
    167 struct transport_callback 
    168 { 
    169     PJ_DECL_LIST_MEMBER(struct transport_callback); 
    170  
    171     /** User defined token to be passed to the callback. */ 
    172     void *token; 
    173  
    174     /** The callback function. */ 
    175     void (*cb)(pjsip_transport_t *tr, void *token, pj_status_t status); 
    176  
    177 }; 
    178  
    179 /* 
    180  * Transport names. 
    181  */ 
    182 const struct 
    183 { 
    184     pjsip_transport_type_e type; 
    185     pj_uint16_t            port; 
    186     pj_str_t               name; 
    187 } transport_names[] =  
    188 { 
    189     { PJSIP_TRANSPORT_UNSPECIFIED, 0, {NULL, 0}}, 
    190     { PJSIP_TRANSPORT_UDP, 5060, {"UDP", 3}}, 
    191 #if PJ_HAS_TCP 
    192     { PJSIP_TRANSPORT_TCP, 5060, {"TCP", 3}}, 
    193     { PJSIP_TRANSPORT_TLS, 5061, {"TLS", 3}}, 
    194     { PJSIP_TRANSPORT_SCTP, 5060, {"SCTP", 4}} 
    195 #endif 
    196 }; 
    197  
    198 static void on_ioqueue_read(pj_ioqueue_key_t *key,  
    199                             pj_ioqueue_op_key_t *op_key,  
    200                             pj_ssize_t bytes_read); 
    201 static void on_ioqueue_write(pj_ioqueue_key_t *key,  
    202                              pj_ioqueue_op_key_t *op_key,  
    203                              pj_ssize_t bytes_sent); 
    204 static void on_ioqueue_accept(pj_ioqueue_key_t *key,  
    205                               pj_ioqueue_op_key_t *op_key,  
    206                               pj_sock_t newsock, 
    207                               int status); 
    208 static void on_ioqueue_connect(pj_ioqueue_key_t *key,  
    209                                int status); 
    210  
    211 static pj_ioqueue_callback ioqueue_transport_callback =  
    212 { 
    213     &on_ioqueue_read, 
    214     &on_ioqueue_write, 
    215     &on_ioqueue_accept, 
    216     &on_ioqueue_connect 
    217 }; 
    218  
    219 static void init_key_from_transport(transport_key *key,  
    220                                     const pjsip_transport_t *tr) 
    221 { 
    222     /* This is to detect alignment problems. */ 
    223     pj_assert(sizeof(transport_key) == 8); 
    224  
    225     key->type = (pj_uint8_t)tr->type; 
    226     key->zero = 0; 
    227     key->addr = pj_sockaddr_in_get_addr(&tr->remote_addr).s_addr; 
    228     key->port = pj_sockaddr_in_get_port(&tr->remote_addr); 
    229     /* 
    230     if (key->port == 0) { 
    231         key->port = pj_sockaddr_in_get_port(&tr->local_addr); 
    232     } 
    233     */ 
    234 } 
    235  
    236 #if PJ_HAS_TCP 
    237 static void init_tcp_key(transport_key *key, pjsip_transport_type_e type, 
    238                          const pj_sockaddr_in *addr) 
    239 { 
    240     /* This is to detect alignment problems. */ 
    241     pj_assert(sizeof(transport_key) == 8); 
    242  
    243     key->type = (pj_uint8_t)type; 
    244     key->zero = 0; 
    245     key->addr = pj_sockaddr_in_get_addr(addr).s_addr; 
    246     key->port = pj_sockaddr_in_get_port(addr); 
    247 } 
    248 #endif 
    249  
    250 static void init_udp_key(transport_key *key, pjsip_transport_type_e type, 
    251                           const pj_sockaddr_in *addr) 
    252 { 
    253     PJ_UNUSED_ARG(addr); 
    254  
    255     /* This is to detect alignment problems. */ 
    256     pj_assert(sizeof(transport_key) == 8); 
    257  
    258     pj_memset(key, 0, sizeof(*key)); 
    259     key->type = (pj_uint8_t)type; 
    260  
    261 #if 0   /* Not sure why we need to make 127.0.0.1 a special case */ 
    262     if (addr->sin_addr.s_addr == inet_addr("127.0.0.1")) { 
    263         /* This looks more complicated than it is because key->addr uses 
    264          * the host version of the address (i.e. converted with ntohl()). 
    265          */ 
    266         pj_str_t localaddr = pj_str("127.0.0.1"); 
    267         pj_sockaddr_in addr; 
    268         pj_sockaddr_set_str_addr(&addr, &localaddr); 
    269         key->addr = pj_sockaddr_in_get_addr(&addr); 
    270     } 
    271 #endif 
    272 } 
    273  
    274 /* 
    275  * Get type format name (for pool name). 
    276  */ 
    277 static const char *transport_get_name_format( int type ) 
    278 { 
    279     switch (type) { 
    280     case PJSIP_TRANSPORT_UDP: 
    281         return " udp%p"; 
    282 #if PJ_HAS_TCP 
    283     case PJSIP_TRANSPORT_TCP: 
    284         return " tcp%p"; 
    285     case PJSIP_TRANSPORT_TLS: 
    286         return " tls%p"; 
    287     case PJSIP_TRANSPORT_SCTP: 
    288         return "sctp%p"; 
    289 #endif 
    290     } 
    291     pj_assert(0); 
    292     return 0; 
    293 } 
    294  
    295 /* 
    296  * Get the default SIP port number for the specified type. 
    297  */ 
    298 PJ_DEF(int) pjsip_transport_get_default_port_for_type(pjsip_transport_type_e type) 
    299 { 
    300     return transport_names[type].port; 
    301 } 
    302  
    303 /* 
    304  * Get transport name. 
    305  */ 
    306 static const char *get_type_name(int type) 
    307 { 
    308     return transport_names[type].name.ptr; 
    309 } 
    310  
    311 /* 
    312  * Get transport type from name. 
    313  */ 
    314 PJ_DEF(pjsip_transport_type_e)  
    315 pjsip_transport_get_type_from_name(const pj_str_t *name) 
    316 { 
    317     unsigned i; 
    318  
    319     for (i=0; i<PJ_ARRAY_SIZE(transport_names); ++i) { 
    320         if (pj_stricmp(name, &transport_names[i].name) == 0) { 
    321             return transport_names[i].type; 
    322         } 
    323     } 
    324     return PJSIP_TRANSPORT_UNSPECIFIED; 
    325 } 
    326  
    327 /* 
    328  * Create new transmit buffer. 
    329  */ 
    330 pj_status_t pjsip_tx_data_create( pjsip_transport_mgr *mgr, 
    331                                   pjsip_tx_data **p_tdata ) 
    332 { 
    333     pj_pool_t *pool; 
    334     pjsip_tx_data *tdata; 
     240 
     241/***************************************************************************** 
     242 * 
     243 * TRANSPORT 
     244 * 
     245 *****************************************************************************/ 
     246 
     247static void transport_send_callback(pjsip_transport *transport, 
     248                                    void *token, 
     249                                    pj_status_t status) 
     250{ 
     251    pjsip_tx_data *tdata = token; 
     252 
     253    PJ_UNUSED_ARG(transport); 
     254 
     255    /* Mark pending off so that app can resend/reuse txdata from inside 
     256     * the callback. 
     257     */ 
     258    tdata->is_pending = 0; 
     259 
     260    /* Call callback, if any. */ 
     261    if (tdata->cb) { 
     262        (*tdata->cb)(tdata->token, tdata, status); 
     263    } 
     264 
     265    /* Decrement reference count. */ 
     266    pjsip_tx_data_dec_ref(tdata); 
     267} 
     268 
     269/* 
     270 * Send a SIP message using the specified transport. 
     271 */ 
     272PJ_DEF(pj_status_t) pjsip_transport_send(  pjsip_transport *tr,  
     273                                           pjsip_tx_data *tdata, 
     274                                           const pj_sockaddr_in *addr, 
     275                                           void *token, 
     276                                           void (*cb)(void *token,  
     277                                                      pjsip_tx_data *tdata, 
     278                                                      pj_status_t)) 
     279{ 
    335280    pj_status_t status; 
    336281 
    337     PJ_LOG(5, ("", "pjsip_tx_data_create")); 
    338  
    339     PJ_ASSERT_RETURN(mgr && p_tdata, PJ_EINVAL); 
    340  
    341     pool = pjsip_endpt_create_pool( mgr->endpt, "ptdt%p", 
    342                                     PJSIP_POOL_LEN_TDATA, 
    343                                     PJSIP_POOL_INC_TDATA ); 
    344     if (!pool) { 
    345         return PJ_ENOMEM; 
    346     } 
    347     tdata = pj_pool_calloc(pool, 1, sizeof(pjsip_tx_data)); 
    348     tdata->pool = pool; 
    349     tdata->mgr = mgr; 
    350     pj_sprintf(tdata->obj_name,"txd%p", tdata); 
    351  
    352     status = pj_atomic_create(tdata->pool, 0, &tdata->ref_cnt); 
    353     if (status != PJ_SUCCESS) { 
    354         pjsip_endpt_destroy_pool( mgr->endpt, tdata->pool ); 
    355         return status; 
    356     } 
    357      
    358     *p_tdata = tdata; 
    359     return PJ_SUCCESS; 
    360 } 
    361  
    362 /* 
    363  * Add reference to tx buffer. 
    364  */ 
    365 PJ_DEF(void) pjsip_tx_data_add_ref( pjsip_tx_data *tdata ) 
    366 { 
    367     pj_atomic_inc(tdata->ref_cnt); 
    368 } 
    369  
    370 /* 
    371  * Decrease transport data reference, destroy it when the reference count 
    372  * reaches zero. 
    373  */ 
    374 PJ_DEF(void) pjsip_tx_data_dec_ref( pjsip_tx_data *tdata ) 
    375 { 
    376     pj_assert( pj_atomic_get(tdata->ref_cnt) > 0); 
    377     if (pj_atomic_dec_and_get(tdata->ref_cnt) <= 0) { 
    378         PJ_LOG(6,(tdata->obj_name, "destroying txdata")); 
    379         pj_atomic_destroy( tdata->ref_cnt ); 
    380         pjsip_endpt_destroy_pool( tdata->mgr->endpt, tdata->pool ); 
    381     } 
    382 } 
    383  
    384 /* 
    385  * Invalidate the content of the print buffer to force the message to be 
    386  * re-printed when sent. 
    387  */ 
    388 PJ_DEF(void) pjsip_tx_data_invalidate_msg( pjsip_tx_data *tdata ) 
    389 { 
    390     tdata->buf.cur = tdata->buf.start; 
    391 } 
    392  
    393 /* 
    394  * Get the transport type. 
    395  */ 
    396 PJ_DEF(pjsip_transport_type_e) pjsip_transport_get_type( const pjsip_transport_t * tr) 
    397 { 
    398     return tr->type; 
    399 } 
    400  
    401 /* 
    402  * Get transport type from transport flag. 
    403  */ 
    404 PJ_DEF(pjsip_transport_type_e) pjsip_get_transport_type_from_flag(unsigned flag) 
    405 { 
    406 #if PJ_HAS_TCP 
    407     if (flag & PJSIP_TRANSPORT_SECURE) { 
    408         return PJSIP_TRANSPORT_TLS; 
    409     } else if (flag & PJSIP_TRANSPORT_RELIABLE) { 
    410         return PJSIP_TRANSPORT_TCP; 
    411     } else  
    412 #else 
    413     PJ_UNUSED_ARG(flag); 
    414 #endif 
    415     { 
    416         return PJSIP_TRANSPORT_UDP; 
    417     } 
    418 } 
    419  
    420 /* 
    421  * Get the transport type name. 
    422  */ 
    423 PJ_DEF(const char *) pjsip_transport_get_type_name( const pjsip_transport_t * tr) 
    424 { 
    425     return get_type_name(tr->type); 
    426 } 
    427  
    428 /* 
    429  * Get the transport's object name. 
    430  */ 
    431 PJ_DEF(const char*) pjsip_transport_get_obj_name( const pjsip_transport_t *tr ) 
    432 { 
    433     return tr->obj_name; 
    434 } 
    435  
    436 /* 
    437  * Get the transport's reference counter. 
    438  */ 
    439 PJ_DEF(int) pjsip_transport_get_ref_cnt( const pjsip_transport_t *tr ) 
    440 { 
    441     return pj_atomic_get(tr->ref_cnt); 
    442 } 
    443  
    444 /* 
    445  * Get transport local address. 
    446  */ 
    447 PJ_DEF(const pj_sockaddr_in*) pjsip_transport_get_local_addr( pjsip_transport_t *tr ) 
    448 { 
    449     return &tr->local_addr; 
    450 } 
    451  
    452 /* 
    453  * Get address name. 
    454  */ 
    455 PJ_DEF(const pj_sockaddr_in*) pjsip_transport_get_addr_name (pjsip_transport_t *tr) 
    456 { 
    457     return &tr->addr_name; 
    458 } 
    459  
    460 /* 
    461  * Get transport remote address. 
    462  */ 
    463 PJ_DEF(const pj_sockaddr_in*) pjsip_transport_get_remote_addr( const pjsip_transport_t *tr ) 
    464 { 
    465     return &tr->remote_addr; 
    466 } 
    467  
    468 /* 
    469  * Get transport flag. 
    470  */ 
    471 PJ_DEF(unsigned) pjsip_transport_get_flag( const pjsip_transport_t * tr ) 
    472 { 
    473     return tr->flag; 
    474 } 
    475  
    476 /* 
    477  * Add reference to the specified transport. 
    478  */ 
    479 PJ_DEF(void) pjsip_transport_add_ref( pjsip_transport_t * tr ) 
    480 { 
    481     pj_atomic_inc(tr->ref_cnt); 
    482 } 
    483  
    484 /* 
    485  * Decrease the reference time of the transport. 
    486  */ 
    487 PJ_DEF(void) pjsip_transport_dec_ref( pjsip_transport_t *tr ) 
    488 { 
    489     pj_assert(tr->ref_cnt > 0); 
    490     if (pj_atomic_dec_and_get(tr->ref_cnt) == 0) { 
    491         pj_gettimeofday(&tr->close_time); 
    492         tr->close_time.sec += PJSIP_TRANSPORT_CLOSE_TIMEOUT; 
    493     } 
    494 } 
    495  
    496 /* 
    497  * Open the underlying transport. 
    498  */ 
    499 static pj_status_t create_socket( pjsip_transport_type_e type, 
    500                                   pj_sockaddr_in *local, 
    501                                   pj_sock_t *p_sock) 
    502 { 
    503     int sock_family; 
    504     int sock_type; 
    505     int sock_proto; 
    506     int len; 
    507     pj_status_t status; 
    508     pj_sock_t sock; 
    509  
    510     /* Set socket parameters */ 
    511     if (type == PJSIP_TRANSPORT_UDP) { 
    512         sock_family = PJ_AF_INET; 
    513         sock_type = PJ_SOCK_DGRAM; 
    514         sock_proto = 0; 
    515  
    516 #if PJ_HAS_TCP 
    517     } else if (type == PJSIP_TRANSPORT_TCP) { 
    518         sock_family = PJ_AF_INET; 
    519         sock_type = PJ_SOCK_STREAM; 
    520         sock_proto = 0; 
    521 #endif 
    522     } else { 
    523         return PJ_EINVAL; 
    524     } 
    525  
    526     /* Create socket. */ 
    527     status = pj_sock_socket( sock_family, sock_type, sock_proto, &sock); 
    528     if (status != PJ_SUCCESS) 
    529         return status; 
    530  
    531     /* Bind the socket to the requested address, or if no address is 
    532      * specified, let the operating system chooses the address. 
    533      */ 
    534     if (/*local->sin_addr.s_addr != 0 &&*/ local->sin_port != 0) { 
    535         /* Bind to the requested address. */ 
    536         status = pj_sock_bind(sock, local, sizeof(*local)); 
    537         if (status != PJ_SUCCESS) { 
    538             pj_sock_close(sock); 
    539             return status; 
    540         } 
    541     } else if (type == PJSIP_TRANSPORT_UDP) { 
    542         /* Only for UDP sockets: bind to any address so that the operating  
    543          * system allocates the port for us. For TCP, let the OS implicitly 
    544          * bind the socket with connect() syscall (if we bind now, then we'll 
    545          * get 0.0.0.0 as local address). 
    546          */ 
    547         pj_memset(local, 0, sizeof(*local)); 
    548         local->sin_family = PJ_AF_INET; 
    549         status = pj_sock_bind(sock, local, sizeof(*local)); 
    550         if (status != PJ_SUCCESS) { 
    551             pj_sock_close(sock); 
    552             return status; 
    553         } 
    554  
    555         /* Get the local address. */ 
    556         len = sizeof(pj_sockaddr_in); 
    557         status = pj_sock_getsockname(sock, local, &len); 
    558         if (status != PJ_SUCCESS) { 
    559             pj_sock_close(sock); 
    560             return status; 
    561         } 
    562     } 
    563  
    564     *p_sock = sock; 
    565     return PJ_SUCCESS; 
    566 } 
    567  
    568 /* 
    569  * Close the transport. 
    570  */ 
    571 static void destroy_socket( pjsip_transport_t * tr) 
    572 { 
    573     pj_assert( pj_atomic_get(tr->ref_cnt) == 0); 
    574     pj_sock_close(tr->sock); 
    575     tr->sock = -1; 
    576 } 
    577  
    578 /* 
    579  * Create a new transport object. 
    580  */ 
    581 static pj_status_t create_transport( pjsip_transport_mgr *mgr, 
    582                                      pjsip_transport_type_e type, 
    583                                      pj_sock_t sock_hnd, 
    584                                      const pj_sockaddr_in *local_addr, 
    585                                      const pj_sockaddr_in *addr_name, 
    586                                      pjsip_transport_t **p_transport ) 
    587 { 
    588     pj_pool_t *tr_pool=NULL, *rdata_pool=NULL; 
    589     pjsip_transport_t *tr = NULL; 
    590     pj_status_t status; 
    591  
    592     /* Allocate pool for transport from endpoint. */ 
    593     tr_pool = pjsip_endpt_create_pool( mgr->endpt, 
    594                                        transport_get_name_format(type), 
    595                                        PJSIP_POOL_LEN_TRANSPORT, 
    596                                        PJSIP_POOL_INC_TRANSPORT ); 
    597     if (!tr_pool) { 
    598         status = PJ_ENOMEM; 
    599         goto on_error; 
    600     } 
    601  
    602     /* Allocate pool for rdata from endpoint. */ 
    603     rdata_pool = pjsip_endpt_create_pool( mgr->endpt, 
    604                                              "prdt%p", 
    605                                              PJSIP_POOL_LEN_RDATA, 
    606                                              PJSIP_POOL_INC_RDATA ); 
    607     if (!rdata_pool) { 
    608         status = PJ_ENOMEM; 
    609         goto on_error; 
    610     } 
    611  
    612     /* Allocate and initialize the transport. */ 
    613     tr = pj_pool_calloc(tr_pool, 1, sizeof(*tr)); 
    614     tr->pool = tr_pool; 
    615     tr->type = type; 
    616     tr->mgr = mgr; 
    617     tr->sock = sock_hnd; 
    618     pj_memcpy(&tr->local_addr, local_addr, sizeof(pj_sockaddr_in)); 
    619     pj_list_init(&tr->cb_list); 
    620     pj_sprintf(tr->obj_name, transport_get_name_format(type), tr); 
    621  
    622     if (type != PJSIP_TRANSPORT_UDP) { 
    623         tr->flag |= PJSIP_TRANSPORT_RELIABLE; 
    624     } 
    625  
    626     /* Address name. */ 
    627     if (addr_name == NULL) { 
    628         addr_name = &tr->local_addr; 
    629     }  
    630     pj_memcpy(&tr->addr_name, addr_name, sizeof(*addr_name)); 
    631  
    632     /* Create atomic */ 
    633     status = pj_atomic_create(tr_pool, 0, &tr->ref_cnt); 
    634     if (status != PJ_SUCCESS) 
    635         goto on_error; 
    636      
    637     /* Init rdata in the transport. */ 
    638     tr->rdata = pj_pool_alloc(rdata_pool, sizeof(*tr->rdata)); 
    639     tr->rdata->pool = rdata_pool; 
    640     tr->rdata->len = 0; 
    641     tr->rdata->transport = tr; 
    642      
    643     /* Init transport mutex. */ 
    644     status = pj_mutex_create_recursive(tr_pool, "mtr%p", &tr->tr_mutex); 
    645     if (status != PJ_SUCCESS) 
    646         goto on_error; 
    647  
    648     /* Register to I/O Queue */ 
    649     status = pj_ioqueue_register_sock( tr_pool, mgr->ioqueue,  
    650                                        tr->sock, tr, 
    651                                        &ioqueue_transport_callback, 
    652                                        &tr->key); 
    653     if (status != PJ_SUCCESS) 
    654         goto on_error; 
    655  
    656     *p_transport = tr; 
    657     return PJ_SUCCESS; 
    658  
    659 on_error: 
    660     if (tr && tr->tr_mutex) { 
    661         pj_mutex_destroy(tr->tr_mutex); 
    662     } 
    663     if (tr_pool) { 
    664         pjsip_endpt_destroy_pool(mgr->endpt, tr_pool); 
    665     } 
    666     if (rdata_pool) { 
    667         pjsip_endpt_destroy_pool(mgr->endpt, rdata_pool); 
    668     } 
    669     return status; 
    670 } 
    671  
    672 /* 
    673  * Destroy transport. 
    674  */ 
    675 static void destroy_transport( pjsip_transport_mgr *mgr, pjsip_transport_t *tr) 
    676 { 
    677     transport_key hash_key; 
    678  
    679     /* Remove from I/O queue. */ 
    680     pj_ioqueue_unregister( tr->key ); 
    681  
    682     /* Remove from hash table */ 
    683     init_key_from_transport(&hash_key, tr); 
    684     pj_hash_set(NULL, mgr->transport_table, &hash_key, sizeof(hash_key), NULL); 
    685  
    686     /* Close transport. */ 
    687     destroy_socket(tr); 
    688  
    689     /* Destroy the transport mutex. */ 
    690     pj_mutex_destroy(tr->tr_mutex); 
    691  
    692     /* Destroy atomic */ 
    693     pj_atomic_destroy( tr->ref_cnt ); 
    694  
    695     /* Release the pool associated with the rdata. */ 
    696     pjsip_endpt_destroy_pool(mgr->endpt, tr->rdata->pool ); 
    697  
    698     /* Release the pool associated with the transport. */ 
    699     pjsip_endpt_destroy_pool(mgr->endpt, tr->pool ); 
    700 } 
    701  
    702  
    703 static pj_status_t transport_send_msg( pjsip_transport_t *tr,  
    704                                        pjsip_tx_data *tdata, 
    705                                        const pj_sockaddr_in *addr,  
    706                                        pj_ssize_t *p_sent) 
    707 { 
    708     const char *buf = tdata->buf.start; 
    709     pj_ssize_t size; 
    710     pj_status_t status; 
    711  
    712     /* Can only send if tdata is not being sent! */ 
    713     if (pj_ioqueue_is_pending(tr->key, &tdata->op_key)) 
     282    PJ_ASSERT_RETURN(tr && tdata && addr, PJ_EINVAL); 
     283 
     284    /* Is it currently being sent? */ 
     285    if (tdata->is_pending) { 
     286        pj_assert(!"Invalid operation step!"); 
    714287        return PJSIP_EPENDINGTX; 
     288    } 
    715289 
    716290    /* Allocate buffer if necessary. */ 
     
    721295    } 
    722296 
    723     /* Print the message if it's not printed */ 
    724     if (tdata->buf.cur <= tdata->buf.start) { 
     297    /* Do we need to reprint? */ 
     298    if (!pjsip_tx_data_is_valid(tdata)) { 
     299        pj_ssize_t size; 
     300 
    725301        size = pjsip_msg_print( tdata->msg, tdata->buf.start,  
    726302                                tdata->buf.end - tdata->buf.start); 
     
    733309    } 
    734310 
    735     /* Send the message. */ 
    736     buf = tdata->buf.start; 
    737     size = tdata->buf.cur - tdata->buf.start; 
    738  
    739     if (tr->type == PJSIP_TRANSPORT_UDP) { 
    740         PJ_LOG(4,(tr->obj_name, "sendto %s:%d, %d bytes, data:\n" 
    741                   "----------- begin msg ------------\n" 
    742                   "%s" 
    743                   "------------ end msg -------------", 
    744                   pj_inet_ntoa(addr->sin_addr),  
    745                   pj_sockaddr_in_get_port(addr), 
    746                   size, buf)); 
    747  
    748         status = pj_ioqueue_sendto( tr->key, &tdata->op_key, 
    749                                     buf, &size, 0, addr, sizeof(*addr)); 
    750     }  
    751 #if PJ_HAS_TCP 
    752     else { 
    753         PJ_LOG(4,(tr->obj_name, "sending %d bytes, data:\n" 
    754                   "----------- begin msg ------------\n" 
    755                   "%s" 
    756                   "------------ end msg -------------", 
    757                   size, buf)); 
    758  
    759         status = pj_ioqueue_send(tr->key, &tdata->op_key, buf, &size, 0); 
    760     } 
    761 #else 
    762     else { 
    763         pj_assert(!"Unsupported transport"); 
    764         status = PJSIP_EUNSUPTRANSPORT; 
    765     } 
    766 #endif 
    767  
    768     *p_sent = size; 
     311    /* Save callback data. */ 
     312    tdata->token = token; 
     313    tdata->cb = cb; 
     314 
     315    /* Add reference counter. */ 
     316    pjsip_tx_data_add_ref(tdata); 
     317 
     318    /* Mark as pending. */ 
     319    tdata->is_pending = 1; 
     320 
     321    /* Send to transport. */ 
     322    status = (*tr->send_msg)(tr, tdata->buf.start,  
     323                             tdata->buf.cur - tdata->buf.start, 
     324                             &tdata->op_key, 
     325                             addr, tdata, &transport_send_callback); 
     326 
     327    if (status != PJ_EPENDING) { 
     328        tdata->is_pending = 0; 
     329        pjsip_tx_data_dec_ref(tdata); 
     330    } 
     331 
    769332    return status; 
    770333} 
    771334 
    772 /* 
    773  * Send a SIP message using the specified transport, to the address specified 
    774  * in the outgoing data. 
    775  */ 
    776 PJ_DEF(pj_status_t) pjsip_transport_send_msg( pjsip_transport_t *tr, 
    777                                               pjsip_tx_data *tdata, 
    778                                               const pj_sockaddr_in *addr, 
    779                                               pj_ssize_t *sent) 
    780 { 
    781     PJ_LOG(5, (tr->obj_name, "pjsip_transport_send_msg(tdata=%s)", tdata->obj_name)); 
    782  
    783     return transport_send_msg(tr, tdata, addr, sent ); 
    784 } 
    785  
    786 /////////////////////////////////////////////////////////////////////////////// 
     335static void transport_idle_callback(pj_timer_heap_t *timer_heap, 
     336                                    struct pj_timer_entry *entry) 
     337{ 
     338    pjsip_transport *tp = entry->user_data; 
     339    pj_assert(tp != NULL); 
     340 
     341    PJ_UNUSED_ARG(timer_heap); 
     342 
     343    entry->id = PJ_FALSE; 
     344    pjsip_transport_unregister(tp->tpmgr, tp); 
     345} 
     346 
     347/* 
     348 * Add ref. 
     349 */ 
     350PJ_DEF(pj_status_t) pjsip_transport_add_ref( pjsip_transport *tp ) 
     351{ 
     352    PJ_ASSERT_RETURN(tp != NULL, PJ_EINVAL); 
     353 
     354    if (pj_atomic_inc_and_get(tp->ref_cnt) == 1) { 
     355        pj_lock_acquire(tp->tpmgr->lock); 
     356        /* Verify again. */ 
     357        if (pj_atomic_get(tp->ref_cnt) == 1) { 
     358            if (tp->idle_timer.id != PJ_FALSE) { 
     359                pj_timer_heap_cancel(tp->tpmgr->timer_heap, &tp->idle_timer); 
     360                tp->idle_timer.id = PJ_FALSE; 
     361            } 
     362        } 
     363        pj_lock_release(tp->tpmgr->lock); 
     364    } 
     365 
     366    return PJ_SUCCESS; 
     367} 
     368 
     369/* 
     370 * Dec ref. 
     371 */ 
     372PJ_DEF(pj_status_t) pjsip_transport_dec_ref( pjsip_transport *tp ) 
     373{ 
     374    PJ_ASSERT_RETURN(tp != NULL, PJ_EINVAL); 
     375 
     376    pj_assert(pj_atomic_get(tp->ref_cnt) > 0); 
     377 
     378    if (pj_atomic_dec_and_get(tp->ref_cnt) == 0) { 
     379        pj_lock_acquire(tp->tpmgr->lock); 
     380        /* Verify again. */ 
     381        if (pj_atomic_get(tp->ref_cnt) == 0) { 
     382            pj_time_val delay = { PJSIP_TRANSPORT_IDLE_TIME, 0 }; 
     383 
     384            pj_assert(tp->idle_timer.id == 0); 
     385            tp->idle_timer.id = PJ_TRUE; 
     386            pj_timer_heap_schedule(tp->tpmgr->timer_heap, &tp->idle_timer, &delay); 
     387        } 
     388        pj_lock_release(tp->tpmgr->lock); 
     389    } 
     390 
     391    return PJ_SUCCESS; 
     392} 
     393 
     394 
     395/** 
     396 * Register a transport. 
     397 */ 
     398PJ_DEF(pj_status_t) pjsip_transport_register( pjsip_tpmgr *mgr, 
     399                                              pjsip_transport *tp ) 
     400{ 
     401    transport_key key; 
     402 
     403    /* Init. */ 
     404    tp->tpmgr = mgr; 
     405    pj_memset(&tp->idle_timer, 0, sizeof(tp->idle_timer)); 
     406    tp->idle_timer.user_data = tp; 
     407    tp->idle_timer.cb = &transport_idle_callback; 
     408 
     409    /*  
     410     * Register to hash table. 
     411     */ 
     412    key.type = (pj_uint8_t)tp->type; 
     413    key.zero = 0; 
     414    key.addr = pj_ntohl(tp->rem_addr.sin_addr.s_addr); 
     415    key.port = pj_ntohs(tp->rem_addr.sin_port); 
     416 
     417    pj_lock_acquire(mgr->lock); 
     418    pj_hash_set(tp->pool, mgr->table, &key, sizeof(key), tp); 
     419    pj_lock_release(mgr->lock); 
     420 
     421    return PJ_SUCCESS; 
     422} 
     423 
     424 
     425/** 
     426 * Unregister transport. 
     427 */ 
     428PJ_DEF(pj_status_t) pjsip_transport_unregister( pjsip_tpmgr *mgr, 
     429                                                pjsip_transport *tp) 
     430{ 
     431    transport_key key; 
     432 
     433    PJ_ASSERT_RETURN(pj_atomic_get(tp->ref_cnt) == 0, PJSIP_EBUSY); 
     434 
     435    pj_lock_acquire(tp->lock); 
     436    pj_lock_acquire(mgr->lock); 
     437 
     438    /* 
     439     * Unregister timer, if any. 
     440     */ 
     441    pj_assert(tp->idle_timer.id == PJ_FALSE); 
     442    if (tp->idle_timer.id != PJ_FALSE) { 
     443        pj_timer_heap_cancel(mgr->timer_heap, &tp->idle_timer); 
     444        tp->idle_timer.id = PJ_FALSE; 
     445    } 
     446 
     447    /* 
     448     * Unregister from hash table. 
     449     */ 
     450    key.type = (pj_uint8_t)tp->type; 
     451    key.zero = 0; 
     452    key.addr = pj_ntohl(tp->rem_addr.sin_addr.s_addr); 
     453    key.port = pj_ntohs(tp->rem_addr.sin_port); 
     454 
     455    pj_hash_set(tp->pool, mgr->table, &key, sizeof(key), NULL); 
     456 
     457    pj_lock_release(mgr->lock); 
     458 
     459    /* Destroy. */ 
     460    return tp->destroy(tp); 
     461} 
     462 
     463 
     464 
     465/***************************************************************************** 
     466 * 
     467 * TRANSPORT FACTORY 
     468 * 
     469 *****************************************************************************/ 
     470 
     471 
     472PJ_DEF(pj_status_t) pjsip_tpmgr_register_tpfactory( pjsip_tpmgr *mgr, 
     473                                                    pjsip_tpfactory *tpf) 
     474{ 
     475    pjsip_tpfactory *p; 
     476    pj_status_t status; 
     477 
     478    pj_lock_acquire(mgr->lock); 
     479 
     480    /* Check that no factory with the same type has been registered. */ 
     481    status = PJ_SUCCESS; 
     482    for (p=mgr->factory_list.next; p!=&mgr->factory_list; p=p->next) { 
     483        if (p->type == tpf->type) { 
     484            status = PJSIP_ETYPEEXISTS; 
     485            break; 
     486        } 
     487        if (p == tpf) { 
     488            status = PJ_EEXISTS; 
     489            break; 
     490        } 
     491    } 
     492 
     493    if (status != PJ_SUCCESS) { 
     494        pj_lock_release(mgr->lock); 
     495        return status; 
     496    } 
     497 
     498    pj_list_insert_before(&mgr->factory_list, tpf); 
     499 
     500    pj_lock_release(mgr->lock); 
     501 
     502    return PJ_SUCCESS; 
     503} 
     504 
     505 
     506/** 
     507 * Unregister factory. 
     508 */ 
     509PJ_DEF(pj_status_t) pjsip_tpmgr_unregister_tpfactory( pjsip_tpmgr *mgr, 
     510                                                      pjsip_tpfactory *tpf) 
     511{ 
     512    pj_lock_acquire(mgr->lock); 
     513 
     514    pj_assert(pj_list_find_node(&mgr->factory_list, tpf) == tpf); 
     515    pj_list_erase(tpf); 
     516 
     517    pj_lock_release(mgr->lock); 
     518 
     519    return PJ_SUCCESS; 
     520} 
     521 
     522 
     523/***************************************************************************** 
     524 * 
     525 * TRANSPORT MANAGER 
     526 * 
     527 *****************************************************************************/ 
    787528 
    788529/* 
    789530 * Create a new transport manager. 
    790531 */ 
    791 PJ_DEF(pj_status_t) pjsip_transport_mgr_create( pj_pool_t *pool, 
    792                                                 pjsip_endpoint * endpt, 
    793                                                 void (*cb)(pjsip_endpoint*, 
    794                                                            pjsip_rx_data *), 
    795                                                 pjsip_transport_mgr **p_mgr) 
    796 { 
    797     pjsip_transport_mgr *mgr; 
     532PJ_DEF(pj_status_t) pjsip_tpmgr_create( pj_pool_t *pool, 
     533                                        pjsip_endpoint *endpt, 
     534                                        pj_ioqueue_t *ioqueue, 
     535                                        pj_timer_heap_t *timer_heap, 
     536                                        void (*cb)(pjsip_endpoint*, 
     537                                                   pj_status_t, 
     538                                                   pjsip_rx_data *), 
     539                                        pjsip_tpmgr **p_mgr) 
     540{ 
     541    pjsip_tpmgr *mgr; 
    798542    pj_status_t status; 
    799543 
    800     PJ_LOG(5, (LOG_TRANSPORT_MGR, "pjsip_transport_mgr_create()")); 
    801  
    802     mgr = pj_pool_alloc(pool, sizeof(*mgr)); 
     544    PJ_ASSERT_RETURN(pool && endpt && cb && p_mgr, PJ_EINVAL); 
     545 
     546    PJ_LOG(5, (THIS_FILE, "pjsip_tpmgr_create()")); 
     547 
     548    mgr = pj_pool_zalloc(pool, sizeof(*mgr)); 
    803549    mgr->endpt = endpt; 
    804     mgr->message_callback = cb; 
    805     mgr->send_buf_size = DEFAULT_SO_SNDBUF; 
    806     mgr->recv_buf_size = DEFAULT_SO_RCVBUF; 
    807  
    808     mgr->transport_table = pj_hash_create(pool, MGR_HASH_TABLE_SIZE); 
    809     if (!mgr->transport_table) { 
     550    mgr->msg_cb = cb; 
     551    mgr->ioqueue = ioqueue; 
     552    mgr->timer_heap = timer_heap; 
     553    pj_list_init(&mgr->factory_list); 
     554 
     555    mgr->table = pj_hash_create(pool, PJSIP_TPMGR_HTABLE_SIZE); 
     556    if (!mgr->table) 
    810557        return PJ_ENOMEM; 
    811     } 
    812     status = pj_ioqueue_create(pool, PJSIP_MAX_TRANSPORTS, &mgr->ioqueue); 
    813     if (status != PJ_SUCCESS) { 
     558 
     559    status = pj_lock_create_recursive_mutex(pool, "tmgr%p", &mgr->lock); 
     560    if (status != PJ_SUCCESS) 
    814561        return status; 
    815     } 
    816     status = pj_mutex_create_recursive(pool, "tmgr%p", &mgr->mutex); 
    817     if (status != PJ_SUCCESS) { 
    818         pj_ioqueue_destroy(mgr->ioqueue); 
    819         return status; 
    820     } 
    821     pj_gettimeofday(&mgr->next_idle_check); 
    822     mgr->next_idle_check.sec += MGR_IDLE_CHECK_INTERVAL; 
    823562 
    824563    *p_mgr = mgr; 
    825     return status; 
    826 } 
    827  
    828 /* 
     564    return PJ_SUCCESS; 
     565} 
     566 
     567/* 
     568 * pjsip_tpmgr_destroy() 
     569 * 
    829570 * Destroy transport manager. 
    830571 */ 
    831 PJ_DEF(pj_status_t) pjsip_transport_mgr_destroy( pjsip_transport_mgr *mgr ) 
     572PJ_DEF(pj_status_t) pjsip_tpmgr_destroy( pjsip_tpmgr *mgr ) 
    832573{ 
    833574    pj_hash_iterator_t itr_val; 
    834575    pj_hash_iterator_t *itr; 
    835576     
    836     PJ_LOG(5, (LOG_TRANSPORT_MGR, "pjsip_transport_mgr_destroy()")); 
    837  
    838     pj_mutex_lock(mgr->mutex); 
    839  
    840     itr = pjsip_transport_first(mgr, &itr_val); 
     577    PJ_LOG(5, (THIS_FILE, "pjsip_tpmgr_destroy()")); 
     578 
     579    pj_lock_acquire(mgr->lock); 
     580 
     581    itr = pj_hash_first(mgr->table, &itr_val); 
    841582    while (itr != NULL) { 
    842583        pj_hash_iterator_t *next; 
    843         pjsip_transport_t *transport; 
     584        pjsip_transport *transport; 
    844585         
    845         transport = pjsip_transport_this(mgr, itr); 
    846  
    847         next = pjsip_transport_next(mgr, itr); 
     586        transport = pj_hash_this(mgr->table, itr); 
     587 
     588        next = pj_hash_next(mgr->table, itr); 
    848589 
    849590        pj_atomic_set(transport->ref_cnt, 0); 
    850         destroy_transport( mgr, transport); 
     591        pjsip_transport_unregister(mgr, transport); 
    851592 
    852593        itr = next; 
     
    854595    pj_ioqueue_destroy(mgr->ioqueue); 
    855596 
    856     pj_mutex_unlock(mgr->mutex); 
     597    pj_lock_release(mgr->lock); 
    857598 
    858599    return PJ_SUCCESS; 
    859600} 
    860601 
    861 /* 
    862  * Create listener 
    863  */ 
    864 static pj_status_t create_listener( pjsip_transport_mgr *mgr, 
    865                                     pjsip_transport_type_e type, 
    866                                     pj_sock_t sock_hnd, 
    867                                     pj_sockaddr_in *local_addr, 
    868                                     const pj_sockaddr_in *addr_name) 
    869 { 
    870     pjsip_transport_t *tr; 
    871     struct transport_key *hash_key; 
    872     const pj_str_t loopback_addr = { "127.0.0.1", 9 }; 
    873     pj_status_t status; 
    874  
    875     if (mgr->send_buf_size != 0) { 
    876         int opt_val = mgr->send_buf_size; 
    877         status = pj_sock_setsockopt( sock_hnd, PJ_SOL_SOCKET,  
    878                                      PJ_SO_SNDBUF,  
    879                                      &opt_val, sizeof(opt_val)); 
    880  
    881         if (status != PJ_SUCCESS) { 
    882             return status; 
    883         } 
    884     } 
    885  
    886     if (mgr->recv_buf_size != 0) { 
    887         int opt_val = mgr->recv_buf_size; 
    888         status = pj_sock_setsockopt( sock_hnd, PJ_SOL_SOCKET,  
    889                                      PJ_SO_RCVBUF,  
    890                                      &opt_val, sizeof(opt_val)); 
    891         if (status != PJ_SUCCESS) { 
    892             return status; 
    893         } 
    894     } 
    895  
    896     status = create_transport(mgr, type, sock_hnd, local_addr, addr_name, &tr); 
    897     if (status != PJ_SUCCESS) { 
    898         pj_sock_close(sock_hnd); 
    899         return status; 
    900     } 
    901 #if PJ_HAS_TCP 
    902     if (type == PJSIP_TRANSPORT_TCP) { 
    903  
    904         status = pj_sock_listen(tr->sock, BACKLOG); 
    905         if (status != 0) { 
    906             destroy_transport(mgr, tr); 
    907             return status; 
    908         } 
    909          
    910         /* Discard immediate connections. */ 
    911         do { 
    912             tr->accept_data.addrlen = sizeof(tr->accept_data.local); 
    913             status = pj_ioqueue_accept(tr->key, &tr->accept_op, 
    914                                        &tr->accept_data.sock,  
    915                                        &tr->accept_data.local,  
    916                                        &tr->accept_data.remote, 
    917                                        &tr->accept_data.addrlen); 
    918             if (status==PJ_SUCCESS) { 
    919                 pj_sock_close(tr->accept_data.sock); 
    920             } else if (status != PJ_EPENDING) { 
    921                 destroy_transport(mgr, tr); 
    922                 return status; 
    923             } 
    924         } while (status==PJ_SUCCESS); 
    925  
    926     } else  
    927 #endif 
    928     if (type == PJSIP_TRANSPORT_UDP) { 
    929         pj_ssize_t bytes; 
    930  
    931         /* Discard immediate data. */ 
    932         do { 
    933             tr->rdata->addr_len = sizeof(tr->rdata->addr); 
    934             bytes = PJSIP_MAX_PKT_LEN; 
    935             status = pj_ioqueue_recvfrom( tr->key, &tr->rdata->op_key, 
    936                                           tr->rdata->packet, &bytes, 0, 
    937                                           &tr->rdata->addr,  
    938                                           &tr->rdata->addr_len); 
    939             if (status == PJ_SUCCESS) { 
    940                 ; 
    941             } else if (status != PJ_EPENDING) { 
    942                 destroy_transport(mgr, tr); 
    943                 return status; 
    944             } 
    945         } while (status == PJ_SUCCESS); 
    946     } 
    947  
    948     pj_atomic_set(tr->ref_cnt, 1); 
    949  
    950     /* Listeners normally have no remote address */ 
    951     pj_memset(&tr->remote_addr, 0, sizeof(tr->remote_addr)); 
    952  
    953     /* Set remote address to 127.0.0.1 for UDP socket bound to 127.0.0.1.  
    954      * See further comments on struct pjsip_transport_t definition. 
     602 
     603/* 
     604 * pjsip_tpmgr_receive_packet() 
     605 * 
     606 * Called by tranports when they receive a new packet. 
     607 */ 
     608PJ_DEF(pj_ssize_t) pjsip_tpmgr_receive_packet( pjsip_tpmgr *mgr, 
     609                                               pjsip_rx_data *rdata) 
     610{ 
     611    pjsip_transport *tr = rdata->tp_info.transport; 
     612    pj_str_t s; 
     613 
     614    char *current_pkt; 
     615    pj_size_t remaining_len; 
     616    pj_size_t total_processed = 0; 
     617 
     618    /* Check size. */ 
     619    pj_assert(rdata->pkt_info.len > 0); 
     620    if (rdata->pkt_info.len <= 0) 
     621        return -1; 
     622     
     623    current_pkt = rdata->pkt_info.packet; 
     624    remaining_len = rdata->pkt_info.len; 
     625     
     626    /* Must NULL terminate buffer. This is the requirement of the  
     627     * parser etc.  
    955628     */ 
    956     if (type == PJSIP_TRANSPORT_UDP &&  
    957         local_addr->sin_addr.s_addr == pj_inet_addr(&loopback_addr).s_addr) 
    958     { 
    959         pj_str_t localaddr = pj_str("127.0.0.1"); 
    960         pj_sockaddr_in_set_str_addr( &tr->remote_addr, &localaddr); 
    961     } 
    962     hash_key = pj_pool_alloc(tr->pool, sizeof(transport_key)); 
    963     init_key_from_transport(hash_key, tr); 
    964  
    965     pj_mutex_lock(mgr->mutex); 
    966     pj_hash_set(tr->pool, mgr->transport_table,  
    967                 hash_key, sizeof(transport_key), tr); 
    968     pj_mutex_unlock(mgr->mutex); 
    969  
    970     PJ_LOG(4,(tr->obj_name, "Listening at %s %s:%d",  
    971                          get_type_name(tr->type),  
    972                          pj_inet_ntoa(tr->local_addr.sin_addr), 
    973                          pj_sockaddr_in_get_port(&tr->local_addr))); 
    974     PJ_LOG(4,(tr->obj_name, "Listener public address is at %s %s:%d",  
    975                          get_type_name(tr->type),  
    976                          pj_inet_ntoa(tr->addr_name.sin_addr), 
    977                          pj_sockaddr_in_get_port(&tr->addr_name))); 
    978     return PJ_SUCCESS; 
    979 } 
    980  
    981 /* 
    982  * Create listener. 
    983  */ 
    984 PJ_DEF(pj_status_t) pjsip_create_listener( pjsip_transport_mgr *mgr, 
    985                                            pjsip_transport_type_e type, 
    986                                            pj_sockaddr_in *local_addr, 
    987                                            const pj_sockaddr_in *addr_name) 
    988 { 
    989     pj_sock_t sock_hnd; 
    990     pj_status_t status; 
    991  
    992     PJ_LOG(5, (LOG_TRANSPORT_MGR, "pjsip_create_listener(type=%d)", type)); 
    993  
    994     status = create_socket(type, local_addr, &sock_hnd); 
    995     if (status != PJ_SUCCESS) { 
    996         return status; 
    997     } 
    998  
    999     return create_listener(mgr, type, sock_hnd, local_addr, addr_name); 
    1000 } 
    1001  
    1002 /* 
    1003  * Create UDP listener. 
    1004  */ 
    1005 PJ_DEF(pj_status_t) pjsip_create_udp_listener( pjsip_transport_mgr *mgr, 
    1006                                                pj_sock_t sock, 
    1007                                                const pj_sockaddr_in *addr_name) 
    1008 { 
    1009     pj_sockaddr_in local_addr; 
    1010     pj_status_t status; 
    1011     int addrlen = sizeof(local_addr); 
    1012  
    1013     status = pj_sock_getsockname(sock, (pj_sockaddr_t*)&local_addr, &addrlen); 
    1014     if (status != PJ_SUCCESS) 
    1015         return status; 
    1016  
    1017     return create_listener(mgr, PJSIP_TRANSPORT_UDP, sock,  
    1018                            &local_addr, addr_name); 
    1019 } 
    1020  
    1021 /* 
    1022  * Find transport to be used to send message to remote destination. If no 
    1023  * suitable transport is found, a new one will be created. 
    1024  */ 
    1025 PJ_DEF(void) pjsip_transport_get( pjsip_transport_mgr *mgr, 
    1026                                   pj_pool_t *pool, 
    1027                                   pjsip_transport_type_e type, 
    1028                                   const pj_sockaddr_in *remote, 
    1029                                   void *token, 
    1030                                   pjsip_transport_completion_callback *cb) 
    1031 { 
    1032     transport_key search_key, *hash_key; 
    1033     pjsip_transport_t *tr; 
    1034     pj_sockaddr_in local; 
    1035     pj_sock_t sock_hnd; 
    1036     pj_status_t status; 
    1037     struct transport_callback *cb_rec; 
    1038  
    1039     PJ_LOG(5, (LOG_TRANSPORT_MGR, "pjsip_transport_get()")); 
    1040  
    1041     /* Create the callback record. 
    1042      */ 
    1043     cb_rec = pj_pool_calloc(pool, 1, sizeof(*cb_rec)); 
    1044     cb_rec->token = token; 
    1045     cb_rec->cb = cb; 
    1046  
    1047     /* Create key for hash table look-up. 
    1048      * The key creation is different for TCP and UDP. 
    1049      */ 
    1050 #if PJ_HAS_TCP 
    1051     if (type==PJSIP_TRANSPORT_TCP) { 
    1052         init_tcp_key(&search_key, type, remote); 
    1053     } else  
    1054 #endif 
    1055     if (type==PJSIP_TRANSPORT_UDP) { 
    1056         init_udp_key(&search_key, type, remote); 
    1057     } 
    1058  
    1059     /* Start lock the manager. */ 
    1060     pj_mutex_lock(mgr->mutex); 
    1061  
    1062     /* Lookup the transport in the hash table. */ 
    1063     tr = pj_hash_get(mgr->transport_table, &search_key, sizeof(transport_key)); 
    1064  
    1065     if (tr) { 
    1066         /* Transport found. If the transport is still busy (i.e. connecting 
    1067          * is in progress), then just register the callback. Otherwise 
    1068          * report via the callback if callback is specified.  
     629    current_pkt[remaining_len] = '\0'; 
     630 
     631    /* Process all message fragments. */ 
     632    while (total_processed < remaining_len) { 
     633 
     634        pjsip_msg *msg; 
     635        pj_size_t msg_fragment_size = 0; 
     636 
     637        /* Initialize default fragment size. */ 
     638        msg_fragment_size = remaining_len; 
     639 
     640        /* Null terminate packet. */ 
     641 
     642        /* Clear and init msg_info in rdata.  
     643         * Endpoint might inspect the values there when we call the callback 
     644         * to report some errors. 
    1069645         */ 
    1070         pj_mutex_unlock(mgr->mutex); 
    1071         pj_mutex_lock(tr->tr_mutex); 
    1072  
    1073         if (tr->flag & PJSIP_TRANSPORT_IOQUEUE_BUSY) { 
    1074             /* Transport is busy. Just register the callback. */ 
    1075             pj_list_insert_before(&tr->cb_list, cb_rec); 
    1076  
    1077         } else { 
    1078             /* Transport is ready. Call callback now. 
    1079              */ 
    1080             (*cb_rec->cb)(tr, cb_rec->token, PJ_SUCCESS); 
    1081         } 
    1082         pj_mutex_unlock(tr->tr_mutex); 
    1083  
    1084         return; 
    1085     } 
    1086  
    1087  
    1088     /* Transport not found. Create new one. */ 
    1089     pj_memset(&local, 0, sizeof(local)); 
    1090     local.sin_family = PJ_AF_INET; 
    1091     status = create_socket(type, &local, &sock_hnd); 
    1092     if (status != PJ_SUCCESS) { 
    1093         pj_mutex_unlock(mgr->mutex); 
    1094         (*cb_rec->cb)(NULL, cb_rec->token, status); 
    1095         return; 
    1096     } 
    1097     status = create_transport(mgr, type, sock_hnd, &local, NULL, &tr); 
    1098     if (status != PJ_SUCCESS) { 
    1099         pj_mutex_unlock(mgr->mutex); 
    1100         (*cb_rec->cb)(NULL, cb_rec->token, status); 
    1101         return; 
    1102     } 
    1103  
    1104 #if PJ_HAS_TCP 
    1105     if (type == PJSIP_TRANSPORT_TCP) { 
    1106         pj_memcpy(&tr->remote_addr, remote, sizeof(pj_sockaddr_in)); 
    1107         status = pj_ioqueue_connect(tr->key, &tr->remote_addr,  
    1108                                     sizeof(pj_sockaddr_in)); 
    1109         pj_assert(status != 0); 
    1110         if (status != PJ_EPENDING) { 
    1111             PJ_TODO(HANDLE_IMMEDIATE_CONNECT); 
    1112             destroy_transport(mgr, tr); 
    1113             pj_mutex_unlock(mgr->mutex); 
    1114             (*cb_rec->cb)(NULL, cb_rec->token, status); 
    1115             return; 
    1116         } 
    1117     } else  
    1118 #endif 
    1119     if (type == PJSIP_TRANSPORT_UDP) { 
    1120         pj_ssize_t size; 
    1121  
    1122         do { 
    1123             tr->rdata->addr_len = sizeof(tr->rdata->addr); 
    1124             size = PJSIP_MAX_PKT_LEN; 
    1125             status = pj_ioqueue_recvfrom( tr->key, &tr->rdata->op_key, 
    1126                                           tr->rdata->packet, &size, 0, 
    1127                                           &tr->rdata->addr,  
    1128                                           &tr->rdata->addr_len); 
    1129             if (status == PJ_SUCCESS) 
    1130                 ; 
    1131             else if (status != PJ_EPENDING) { 
    1132                 destroy_transport(mgr, tr); 
    1133                 pj_mutex_unlock(mgr->mutex); 
    1134                 (*cb_rec->cb)(NULL, cb_rec->token, status); 
    1135                 return; 
    1136             } 
    1137  
    1138             /* Bug here. 
    1139              * If data is immediately available, although not likely, it will 
    1140              * be dropped because we don't expect to have data right after 
    1141              * the socket is created, do we ?! 
    1142              */ 
    1143             PJ_TODO(FIXED_BUG_ON_IMMEDIATE_TRANSPORT_DATA); 
    1144  
    1145         } while (status == PJ_SUCCESS); 
    1146  
    1147         //Bug: cb will never be called! 
    1148         //     Must force status to PJ_SUCCESS; 
    1149         //status = PJ_IOQUEUE_PENDING; 
    1150  
    1151         status = PJ_SUCCESS; 
    1152  
    1153     } else { 
    1154         pj_mutex_unlock(mgr->mutex); 
    1155         (*cb_rec->cb)(NULL, cb_rec->token, PJSIP_EUNSUPTRANSPORT); 
    1156         return; 
    1157     } 
    1158  
    1159     pj_assert(status==PJ_EPENDING || status==PJ_SUCCESS); 
    1160     pj_mutex_lock(tr->tr_mutex); 
    1161     hash_key = pj_pool_alloc(tr->pool, sizeof(transport_key)); 
    1162     pj_memcpy(hash_key, &search_key, sizeof(transport_key)); 
    1163     pj_hash_set(tr->pool, mgr->transport_table,  
    1164                 hash_key, sizeof(transport_key), tr); 
    1165     if (status == PJ_SUCCESS) { 
    1166         pj_mutex_unlock(tr->tr_mutex); 
    1167         pj_mutex_unlock(mgr->mutex); 
    1168         (*cb_rec->cb)(tr, cb_rec->token, PJ_SUCCESS); 
    1169     } else { 
    1170         pj_list_insert_before(&tr->cb_list, cb_rec); 
    1171         pj_mutex_unlock(tr->tr_mutex); 
    1172         pj_mutex_unlock(mgr->mutex); 
    1173     } 
    1174  
    1175 } 
    1176  
    1177 #if PJ_HAS_TCP 
    1178 /* 
    1179  * Handle completion of asynchronous accept() operation. 
    1180  * This function is called by handle_events() function. 
    1181  */ 
    1182 static void handle_new_connection( pjsip_transport_mgr *mgr, 
    1183                                    pjsip_transport_t *listener, 
    1184                                    pj_status_t status ) 
    1185 { 
    1186     pjsip_transport_t *tr; 
    1187     transport_key *hash_key; 
    1188     pj_ssize_t size; 
    1189  
    1190     pj_assert (listener->type == PJSIP_TRANSPORT_TCP); 
    1191  
    1192     if (status != PJ_SUCCESS) { 
    1193         PJSIP_ENDPT_LOG_ERROR((mgr->endpt, listener->obj_name, status, 
    1194                                "Error in accept() completion")); 
    1195         goto on_return; 
    1196     } 
    1197  
    1198     PJ_LOG(4,(listener->obj_name, "incoming tcp connection from %s:%d", 
    1199               pj_inet_ntoa(listener->accept_data.remote.sin_addr), 
    1200               pj_sockaddr_in_get_port(&listener->accept_data.remote))); 
    1201  
    1202     status = create_transport(mgr, listener->type,  
    1203                               listener->accept_data.sock, 
    1204                               &listener->accept_data.local, 
    1205                               NULL, &tr); 
    1206     if (status != PJ_SUCCESS) { 
    1207         PJSIP_ENDPT_LOG_ERROR((mgr->endpt, listener->obj_name, status, 
    1208                                "Error in creating new incoming TCP")); 
    1209         goto on_return; 
    1210     } 
    1211  
    1212     /* 
    1213     tr->rdata->addr_len = sizeof(tr->rdata->addr); 
    1214     status = pj_ioqueue_recvfrom( mgr->ioqueue, tr->key,  
    1215                                   tr->rdata->packet, PJSIP_MAX_PKT_LEN, 
    1216                                   &tr->rdata->addr,  
    1217                                   &tr->rdata->addr_len); 
    1218     */ 
    1219     tr->rdata->addr = listener->accept_data.remote; 
    1220     tr->rdata->addr_len = listener->accept_data.addrlen; 
    1221  
    1222     size = PJSIP_MAX_PKT_LEN; 
    1223     status = pj_ioqueue_recv(tr->key, &tr->rdata->op_key,  
    1224                              tr->rdata->packet, &size, 0); 
    1225     if (status != PJ_EPENDING) { 
    1226         PJSIP_ENDPT_LOG_ERROR((mgr->endpt, listener->obj_name, status, 
    1227                                "Error in receiving data")); 
    1228         PJ_TODO(IMMEDIATE_DATA); 
    1229         destroy_transport(mgr, tr); 
    1230         goto on_return; 
    1231     } 
    1232  
    1233     pj_memcpy(&tr->remote_addr, &listener->accept_data.remote,  
    1234               listener->accept_data.addrlen); 
    1235     hash_key = pj_pool_alloc(tr->pool, sizeof(transport_key)); 
    1236     init_key_from_transport(hash_key, tr); 
    1237  
    1238     pj_mutex_lock(mgr->mutex); 
    1239     pj_hash_set(tr->pool, mgr->transport_table, hash_key,  
    1240                 sizeof(transport_key), tr); 
    1241     pj_mutex_unlock(mgr->mutex); 
    1242  
    1243 on_return: 
    1244     /* Re-initiate asynchronous accept() */ 
    1245     listener->accept_data.addrlen = sizeof(listener->accept_data.local); 
    1246     status = pj_ioqueue_accept(listener->key, &listener->accept_op, 
    1247                                &listener->accept_data.sock,  
    1248                                &listener->accept_data.local,  
    1249                                &listener->accept_data.remote, 
    1250                                &listener->accept_data.addrlen); 
    1251     if (status != PJ_EPENDING) { 
    1252         PJSIP_ENDPT_LOG_ERROR((mgr->endpt, listener->obj_name, status, 
    1253                                "Error in receiving data")); 
    1254         PJ_TODO(IMMEDIATE_ACCEPT); 
    1255         return; 
    1256     } 
    1257 } 
    1258  
    1259 /* 
    1260  * Handle completion of asynchronous connect() function. 
    1261  * This function is called by the handle_events() function. 
    1262  */ 
    1263 static void handle_connect_completion( pjsip_transport_mgr *mgr, 
    1264                                        pjsip_transport_t *tr, 
    1265                                        pj_status_t status ) 
    1266 { 
    1267     struct transport_callback new_list; 
    1268     struct transport_callback *cb_rec; 
    1269     pj_ssize_t recv_size; 
    1270  
    1271     PJ_UNUSED_ARG(mgr); 
    1272  
    1273     /* On connect completion, we must call all registered callbacks in 
    1274      * the transport. 
    1275      */ 
    1276  
    1277     /* Initialize new list. */ 
    1278     pj_list_init(&new_list); 
    1279  
    1280     /* Hold transport's mutex. We don't want other thread to register a  
    1281      * callback while we're dealing with it.  
    1282     */ 
    1283     pj_mutex_lock(tr->tr_mutex); 
    1284  
    1285     /* Copy callback list to new list so that we can call the callbacks 
    1286      * without holding the mutex. 
    1287      */ 
    1288     pj_list_merge_last(&new_list, &tr->cb_list); 
    1289  
    1290     /* Clear transport's busy flag. */ 
    1291     tr->flag &= ~PJSIP_TRANSPORT_IOQUEUE_BUSY; 
    1292  
    1293     /* If success, update local address.  
    1294      * Local address is only available after connect() has returned. 
    1295      */ 
    1296     if (status == PJ_SUCCESS) { 
    1297         int addrlen = sizeof(tr->local_addr); 
    1298          
    1299         status = pj_sock_getsockname(tr->sock,  
    1300                                      (pj_sockaddr_t*)&tr->local_addr,  
    1301                                      &addrlen); 
    1302         if (status == PJ_SUCCESS) { 
    1303             pj_memcpy(&tr->addr_name, &tr->local_addr, sizeof(tr->addr_name)); 
    1304         } 
    1305     } 
    1306  
    1307     /* Unlock mutex. */ 
    1308     pj_mutex_unlock(tr->tr_mutex); 
    1309  
    1310     /* Call all registered callbacks. */ 
    1311     cb_rec = new_list.next; 
    1312     while (cb_rec != &new_list) { 
    1313         struct transport_callback *next; 
    1314         next = cb_rec->next; 
    1315         (*cb_rec->cb)(tr, cb_rec->token, status); 
    1316         cb_rec = next; 
    1317     } 
    1318  
    1319     /* Success? */ 
    1320     if (status != PJ_SUCCESS) { 
    1321         destroy_transport(mgr, tr); 
    1322         PJ_TODO(WTF); 
    1323         return; 
    1324     } 
    1325  
    1326     /* Initiate read operation to socket. */ 
    1327     recv_size = PJSIP_MAX_PKT_LEN; 
    1328     status = pj_ioqueue_recv( tr->key, &tr->rdata->op_key, tr->rdata->packet,  
    1329                               &recv_size, 0); 
    1330     if (status != PJ_EPENDING) { 
    1331         destroy_transport(mgr, tr); 
    1332         PJ_TODO(IMMEDIATE_DATA); 
    1333         return; 
    1334     } 
    1335 } 
    1336 #endif /* PJ_HAS_TCP */ 
    1337  
    1338 /* 
    1339  * Handle incoming data. 
    1340  * This function is called when the transport manager receives 'notification' 
    1341  * from the I/O Queue that the receive operation has completed. 
    1342  * This function will then attempt to parse the message, and hands over the 
    1343  * message to the endpoint. 
    1344  */ 
    1345 static void handle_received_data( pjsip_transport_mgr *mgr, 
    1346                                   pjsip_transport_t *tr, 
    1347                                   pj_ssize_t size ) 
    1348 { 
    1349     pjsip_msg *msg; 
    1350     pjsip_rx_data *rdata = tr->rdata; 
    1351     pj_pool_t *rdata_pool; 
    1352     pjsip_hdr *hdr; 
    1353     pj_str_t s; 
    1354     char *src_addr; 
    1355     int src_port; 
    1356     pj_size_t msg_fragment_size = 0; 
    1357  
    1358     /* Check size. */ 
    1359     if (size < 1) { 
    1360         if (tr->type != PJSIP_TRANSPORT_UDP) { 
    1361             /* zero bytes indicates transport has been closed for TCP. 
    1362              * But alas, we can't destroy it now since transactions may still 
    1363              * have reference to it. In that case, just do nothing, the  
    1364              * transaction will receive error when it tries to send anything. 
    1365              * But alas!! UAC transactions wont send anything!!. 
    1366              * So this is a bug! 
    1367              */ 
    1368             if (pj_atomic_get(tr->ref_cnt)==0) { 
    1369                 PJ_LOG(4,(tr->obj_name, "connection closed")); 
    1370                 destroy_transport(mgr, tr); 
    1371             } else { 
    1372                 PJ_TODO(HANDLE_TCP_TRANSPORT_CLOSED); 
    1373                 //PJ_TODO(SIGNAL_TRANSACTIONS_ON_TRANSPORT_CLOSED); 
    1374             } 
    1375             return; 
    1376         } else { 
    1377             /* On Windows machines, UDP recv() will return zero upon receiving 
    1378              * ICMP port unreachable message. 
    1379              */ 
    1380             PJ_LOG(4,(tr->obj_name, "Ignored zero length UDP packet (port unreachable?)")); 
    1381             goto on_return; 
    1382         } 
    1383     } 
    1384      
    1385     /* Save received time. */ 
    1386     pj_gettimeofday(&rdata->timestamp); 
    1387      
    1388     /* Update length. */ 
    1389     rdata->len += size; 
    1390  
    1391     /* Null terminate packet, this is the requirement of the parser. */ 
    1392     rdata->packet[rdata->len] = '\0'; 
    1393  
    1394     /* Get source address and port for logging purpose. */ 
    1395     src_addr = pj_inet_ntoa(rdata->addr.sin_addr); 
    1396     src_port = pj_sockaddr_in_get_port(&rdata->addr); 
    1397  
    1398     /* Print the whole data to the log. */ 
    1399     PJ_LOG(4,(tr->obj_name, "%d bytes recvfrom %s:%d:\n" 
    1400                     "----------- begin msg ------------\n" 
    1401                     "%s" 
    1402                     "------------ end msg -------------",  
    1403                rdata->len, src_addr, src_port, rdata->packet)); 
    1404  
    1405  
    1406     /* Process all message fragments. */ 
    1407     while (rdata->len > 0) { 
    1408  
    1409         msg_fragment_size = rdata->len; 
    1410 #if PJ_HAS_TCP 
     646        pj_memset(&rdata->msg_info, 0, sizeof(rdata->msg_info)); 
     647        pj_list_init(&rdata->msg_info.parse_err); 
     648        rdata->msg_info.msg_buf = current_pkt; 
     649        rdata->msg_info.len = remaining_len; 
     650 
    1411651        /* For TCP transport, check if the whole message has been received. */ 
    1412         if (tr->type != PJSIP_TRANSPORT_UDP) { 
     652        if ((tr->flag & PJSIP_TRANSPORT_DATAGRAM) == 0) { 
    1413653            pj_status_t msg_status; 
    1414             msg_status = pjsip_find_msg(rdata->packet, rdata->len, PJ_FALSE,  
     654            msg_status = pjsip_find_msg(current_pkt, remaining_len, PJ_FALSE,  
    1415655                                        &msg_fragment_size); 
    1416656            if (msg_status != PJ_SUCCESS) { 
    1417                 if (rdata->len == PJSIP_MAX_PKT_LEN) { 
    1418                     PJSIP_ENDPT_LOG_ERROR((mgr->endpt, tr->obj_name,  
    1419                                            PJSIP_EOVERFLOW, 
    1420                                            "Buffer discarded for %s:%d", 
    1421                                            src_addr, src_port)); 
    1422                     goto on_return; 
     657                if (remaining_len == PJSIP_MAX_PKT_LEN) { 
     658                    mgr->msg_cb(mgr->endpt, PJSIP_EOVERFLOW, rdata); 
     659                    /* Exhaust all data. */ 
     660                    return rdata->pkt_info.len; 
    1423661                } else { 
    1424                     goto tcp_read_packet; 
     662                    /* Not enough data in packet. */ 
     663                    return total_processed; 
    1425664                } 
    1426665            } 
    1427666        } 
    1428 #endif 
    1429  
    1430         /* Clear parser error report */ 
    1431         pj_list_init(&rdata->parse_err); 
     667 
     668        /* Update msg_info. */ 
     669        rdata->msg_info.len = msg_fragment_size; 
    1432670 
    1433671        /* Parse the message. */ 
    1434         PJ_LOG(5,(tr->obj_name, "Parsing %d bytes from %s:%d", msg_fragment_size, 
    1435                 src_addr, src_port)); 
    1436  
    1437         msg = pjsip_parse_rdata( rdata->packet, msg_fragment_size, rdata); 
     672        rdata->msg_info.msg = msg =  
     673            pjsip_parse_rdata( current_pkt, msg_fragment_size, rdata); 
    1438674        if (msg == NULL) { 
    1439             PJ_LOG(3,(tr->obj_name, "Bad message (%d bytes from %s:%d)", msg_fragment_size, 
    1440                     src_addr, src_port)); 
     675            mgr->msg_cb(mgr->endpt, PJSIP_EINVALIDMSG, rdata); 
    1441676            goto finish_process_fragment; 
    1442677        } 
    1443678 
    1444679        /* Perform basic header checking. */ 
    1445         if (rdata->call_id.ptr == NULL || rdata->from == NULL ||  
    1446             rdata->to == NULL || rdata->via == NULL || rdata->cseq == NULL)  
     680        if (rdata->msg_info.call_id.ptr == NULL ||  
     681            rdata->msg_info.from == NULL ||  
     682            rdata->msg_info.to == NULL ||  
     683            rdata->msg_info.via == NULL ||  
     684            rdata->msg_info.cseq == NULL)  
    1447685        { 
    1448             PJ_LOG(3,(tr->obj_name, "Bad message from %s:%d: missing some header",  
    1449                     src_addr, src_port)); 
     686            mgr->msg_cb(mgr->endpt, PJSIP_EMISSINGHDR, rdata); 
    1450687            goto finish_process_fragment; 
    1451688        } 
    1452689 
    1453         /* If message is received from address that's different from the sent-by, 
     690        /* If message is received from address that's different from sent-by, 
    1454691         * MUST add received parameter to the via. 
    1455          * In our case, we add Via receive param for EVERY received message,  
    1456          * because it saves us from resolving the host HERE in case sent-by is in 
    1457          * FQDN format. And it doesn't hurt either. 
    1458692         */ 
    1459         s = pj_str(src_addr); 
    1460         pj_strdup(rdata->pool, &rdata->via->recvd_param, &s); 
     693        s = pj_str(pj_inet_ntoa(rdata->pkt_info.addr.sin_addr)); 
     694        if (pj_strcmp(&s, &rdata->msg_info.via->sent_by.host) != 0) { 
     695            pj_strdup(rdata->tp_info.pool,  
     696                      &rdata->msg_info.via->recvd_param, &s); 
     697        } 
    1461698 
    1462699        /* RFC 3581: 
    1463700         * If message contains "rport" param, put the received port there. 
    1464701         */ 
    1465         if (rdata->via->rport_param == 0) { 
    1466             rdata->via->rport_param = pj_sockaddr_in_get_port(&rdata->addr); 
     702        if (rdata->msg_info.via->rport_param == 0) { 
     703            rdata->msg_info.via->rport_param =  
     704                pj_ntohs(rdata->pkt_info.addr.sin_port); 
    1467705        } 
    1468706 
     
    1470708        */ 
    1471709        if (msg->type == PJSIP_RESPONSE_MSG) { 
    1472             hdr = (pjsip_hdr*)rdata->via->next; 
    1473             if (hdr != &rdata->msg->hdr) { 
     710            pjsip_hdr *hdr; 
     711            hdr = (pjsip_hdr*)rdata->msg_info.via->next; 
     712            if (hdr != &msg->hdr) { 
    1474713                hdr = pjsip_msg_find_hdr(msg, PJSIP_H_VIA, hdr); 
    1475714                if (hdr) { 
    1476                     PJ_LOG(3,(tr->obj_name, "Bad message from %s:%d: " 
    1477                                             "multiple Via in response message", 
    1478                                             src_addr, src_port)); 
     715                    mgr->msg_cb(mgr->endpt, PJSIP_EMULTIPLEVIA, rdata); 
    1479716                    goto finish_process_fragment; 
    1480717                } 
     
    1483720 
    1484721        /* Call the transport manager's upstream message callback. 
    1485         */ 
    1486         (*mgr->message_callback)(mgr->endpt, rdata); 
     722         */ 
     723        mgr->msg_cb(mgr->endpt, PJ_SUCCESS, rdata); 
     724 
    1487725 
    1488726finish_process_fragment: 
    1489         rdata->len -= msg_fragment_size; 
    1490         if (rdata->len > 0) { 
    1491             pj_memmove(rdata->packet, rdata->packet+msg_fragment_size, rdata->len); 
    1492             PJ_LOG(4,(tr->obj_name, "Processing next fragment, size=%d bytes", rdata->len)); 
    1493         } 
    1494  
    1495     }   /* while (rdata->len > 0) */ 
    1496  
    1497 on_return: 
    1498     /* Reset the pool and rdata */ 
    1499     rdata_pool = rdata->pool; 
    1500     pj_pool_reset(rdata_pool); 
    1501     rdata = pj_pool_alloc( rdata_pool, sizeof(*rdata) ); 
    1502     rdata->len = 0; 
    1503     rdata->transport = tr; 
    1504     rdata->pool = rdata_pool; 
    1505     tr->rdata = rdata; 
    1506  
    1507     /* Read the next packet. */ 
    1508     rdata->addr_len = sizeof(rdata->addr); 
    1509     if (tr->type == PJSIP_TRANSPORT_UDP) { 
    1510         pj_ssize_t size = PJSIP_MAX_PKT_LEN; 
    1511         pj_ioqueue_recvfrom(tr->key, &tr->rdata->op_key, 
    1512                             tr->rdata->packet, &size, 0,  
    1513                             &rdata->addr, &rdata->addr_len); 
    1514         PJ_TODO(HANDLE_IMMEDIATE_DATA); 
    1515     } 
    1516  
    1517 #if PJ_HAS_TCP 
    1518     /* The next 'if' should have been 'else if', but we need to put the 
    1519        label inside the '#if PJ_HAS_TCP' block to avoid 'unreferenced label' warning. 
     727        total_processed += msg_fragment_size; 
     728        current_pkt += msg_fragment_size; 
     729        remaining_len -= msg_fragment_size; 
     730 
     731    }   /* while (rdata->pkt_info.len > 0) */ 
     732 
     733 
     734    return total_processed; 
     735} 
     736 
     737 
     738/* 
     739 * pjsip_tpmgr_alloc_transport() 
     740 * 
     741 * Get transport suitable to communicate to remote. Create a new one 
     742 * if necessary. 
     743 */ 
     744PJ_DEF(pj_status_t) pjsip_tpmgr_alloc_transport( pjsip_tpmgr *mgr, 
     745                                                 pjsip_transport_type_e type, 
     746                                                 const pj_sockaddr_in *remote, 
     747                                                 pjsip_transport **p_transport) 
     748{ 
     749    transport_key key; 
     750    pjsip_transport *transport; 
     751    pjsip_tpfactory *factory; 
     752    pj_status_t status; 
     753 
     754    pj_lock_acquire(mgr->lock); 
     755 
     756    /* First try to get exact destination. */ 
     757    key.type = (pj_uint8_t)type; 
     758    key.zero = 0; 
     759    key.addr = pj_ntohl(remote->sin_addr.s_addr); 
     760    key.port = pj_ntohs(remote->sin_port); 
     761 
     762    transport = pj_hash_get(mgr->table, &key, sizeof(key)); 
     763    if (transport != NULL) { 
     764        unsigned flag = pjsip_transport_get_flag_from_type(type); 
     765         
     766        /* For datagram transports, try lookup with zero address. */ 
     767        if (flag & PJSIP_TRANSPORT_DATAGRAM) { 
     768            key.addr = 0; 
     769            key.port = 0; 
     770 
     771            transport = pj_hash_get(mgr->table, &key, sizeof(key)); 
     772        } 
     773    } 
     774     
     775    if (transport != NULL) { 
     776        /* 
     777         * Transport found! 
     778         */ 
     779        pjsip_transport_add_ref(transport); 
     780        pj_lock_release(mgr->lock); 
     781        *p_transport = transport; 
     782        return PJ_SUCCESS; 
     783    } 
     784 
     785    /* 
     786     * Transport not found! 
     787     * Find factory that can create such transport. 
    1520788     */ 
    1521 tcp_read_packet: 
    1522     if (tr->type == PJSIP_TRANSPORT_TCP) { 
    1523         pj_ssize_t size = PJSIP_MAX_PKT_LEN - tr->rdata->len; 
    1524         pj_ioqueue_recv( tr->key, &tr->rdata->op_key, 
    1525                          tr->rdata->packet + tr->rdata->len, 
    1526                          &size, 0); 
    1527         PJ_TODO(HANDLE_IMMEDIATE_DATA_1); 
    1528     } 
    1529 #endif 
    1530 } 
    1531  
    1532 static void transport_mgr_on_idle( pjsip_transport_mgr *mgr ) 
    1533 { 
    1534     pj_time_val now; 
     789    factory = mgr->factory_list.next; 
     790    while (factory != &mgr->factory_list) { 
     791        if (factory->type == type) 
     792            break; 
     793        factory = factory->next; 
     794    } 
     795 
     796    if (factory == &mgr->factory_list) { 
     797        /* No factory can create the transport! */ 
     798        pj_lock_release(mgr->lock); 
     799        return PJSIP_EUNSUPTRANSPORT; 
     800    } 
     801 
     802    /* Request factory to create transport. */ 
     803    status = factory->create_transport(factory, mgr, mgr->endpt, 
     804                                       mgr->ioqueue, remote, p_transport); 
     805 
     806    pj_lock_release(mgr->lock); 
     807    return status; 
     808} 
     809 
     810/** 
     811 * Dump transport info. 
     812 */ 
     813PJ_DEF(void) pjsip_tpmgr_dump_transports(pjsip_tpmgr *mgr) 
     814{ 
     815#if PJ_LOG_MAX_LEVEL >= 3 
    1535816    pj_hash_iterator_t itr_val; 
    1536817    pj_hash_iterator_t *itr; 
    1537818 
    1538  
    1539     /* Get time for comparing transport's close time. */ 
    1540     pj_gettimeofday(&now); 
    1541     if (now.sec < mgr->next_idle_check.sec) { 
    1542         return; 
    1543     } 
    1544  
    1545     /* Acquire transport manager's lock. */ 
    1546     pj_mutex_lock(mgr->mutex); 
    1547  
    1548     /* Update next idle check. */ 
    1549     mgr->next_idle_check.sec += MGR_IDLE_CHECK_INTERVAL; 
    1550  
    1551     /* Iterate all transports, and close transports that are not used for 
    1552        some periods. 
    1553      */ 
    1554     itr = pjsip_transport_first(mgr, &itr_val); 
    1555     while (itr != NULL) { 
    1556         pj_hash_iterator_t *next; 
    1557         pjsip_transport_t *transport; 
    1558          
    1559         transport = pjsip_transport_this(mgr, itr); 
    1560  
    1561         next = pjsip_transport_next(mgr, itr); 
    1562  
    1563         if (pj_atomic_get(transport->ref_cnt)==0 &&  
    1564             PJ_TIME_VAL_LTE(transport->close_time, now)) 
    1565         { 
    1566             destroy_transport(mgr, transport); 
    1567         } 
    1568  
    1569         itr = next; 
    1570     } 
    1571  
    1572     /* Release transport manager's lock. */ 
    1573     pj_mutex_unlock(mgr->mutex); 
    1574 } 
    1575  
    1576 static void on_ioqueue_read(pj_ioqueue_key_t *key,  
    1577                             pj_ioqueue_op_key_t *op_key,  
    1578                             pj_ssize_t bytes_read) 
    1579 { 
    1580     pjsip_transport_t *t; 
    1581     t = pj_ioqueue_get_user_data(key); 
    1582  
    1583     handle_received_data( t->mgr, t, bytes_read ); 
    1584 } 
    1585  
    1586 static void on_ioqueue_write(pj_ioqueue_key_t *key,  
    1587                              pj_ioqueue_op_key_t *op_key,  
    1588                              pj_ssize_t bytes_sent) 
    1589 { 
    1590     PJ_UNUSED_ARG(key); 
    1591     PJ_UNUSED_ARG(bytes_sent); 
    1592  
    1593     /* Completion of write operation.  
    1594      * Do nothing. 
    1595      */ 
    1596 } 
    1597  
    1598 static void on_ioqueue_accept(pj_ioqueue_key_t *key,  
    1599                               pj_ioqueue_op_key_t *op_key,  
    1600                               pj_sock_t newsock, 
    1601                               int status) 
    1602 { 
    1603 #if PJ_HAS_TCP 
    1604     pjsip_transport_t *t; 
    1605     t = pj_ioqueue_get_user_data(key); 
    1606  
    1607     handle_new_connection( t->mgr, t, status ); 
    1608 #else 
    1609     PJ_UNUSED_ARG(key); 
    1610     PJ_UNUSED_ARG(status); 
     819    pj_lock_acquire(mgr->lock); 
     820 
     821    itr = pj_hash_first(mgr->table, &itr_val); 
     822    if (itr) { 
     823        PJ_LOG(3, (THIS_FILE, " Dumping transports:")); 
     824 
     825        do { 
     826            char src_addr[128], dst_addr[128]; 
     827            int src_port, dst_port; 
     828            pjsip_transport *t; 
     829 
     830            t = pj_hash_this(mgr->table, itr); 
     831            pj_native_strcpy(src_addr, pj_inet_ntoa(t->local_addr.sin_addr)); 
     832            src_port = pj_ntohs(t->local_addr.sin_port); 
     833 
     834            pj_native_strcpy(dst_addr, pj_inet_ntoa(t->rem_addr.sin_addr)); 
     835            dst_port = pj_ntohs(t->rem_addr.sin_port); 
     836 
     837            PJ_LOG(3, (THIS_FILE, "  %s %s %s:%d --> %s:%d (refcnt=%d)",  
     838                       t->type_name, 
     839                       t->obj_name, 
     840                       src_addr, src_port, 
     841                       dst_addr, dst_port, 
     842                       pj_atomic_get(t->ref_cnt))); 
     843 
     844            itr = pj_hash_next(mgr->table, itr); 
     845        } while (itr); 
     846    } 
     847 
     848    pj_lock_release(mgr->lock); 
    1611849#endif 
    1612850} 
    1613851 
    1614 static void on_ioqueue_connect(pj_ioqueue_key_t *key, int status) 
    1615 { 
    1616 #if PJ_HAS_TCP 
    1617     pjsip_transport_t *t; 
    1618     t = pj_ioqueue_get_user_data(key); 
    1619  
    1620     handle_connect_completion( t->mgr, t, status); 
    1621 #else 
    1622     PJ_UNUSED_ARG(key); 
    1623     PJ_UNUSED_ARG(status); 
    1624 #endif 
    1625 } 
    1626  
    1627  
    1628 /* 
    1629  * Poll for events. 
    1630  */ 
    1631 PJ_DEF(int) pjsip_transport_mgr_handle_events( pjsip_transport_mgr *mgr, 
    1632                                                const pj_time_val *req_timeout ) 
    1633 { 
    1634     int event_count; 
    1635     int break_loop; 
    1636     int result; 
    1637     pj_time_val timeout; 
    1638  
    1639     PJ_LOG(5, (LOG_TRANSPORT_MGR, "pjsip_transport_mgr_handle_events()")); 
    1640  
    1641     event_count = 0; 
    1642     break_loop = 0; 
    1643     timeout = *req_timeout; 
    1644     do { 
    1645         result = pj_ioqueue_poll( mgr->ioqueue, &timeout); 
    1646         if (result == 1) { 
    1647             ++event_count; 
    1648  
    1649             /* Break the loop. */ 
    1650             //if (timeout.msec==0 && timeout.sec==0) { 
    1651                 break_loop = 1; 
    1652             //} 
    1653  
    1654         } else { 
    1655             /* On idle, cleanup transport. */ 
    1656             transport_mgr_on_idle(mgr); 
    1657  
    1658             break_loop = 1; 
    1659         } 
    1660         timeout.sec = timeout.msec = 0; 
    1661     } while (!break_loop); 
    1662  
    1663     return event_count; 
    1664 } 
    1665  
    1666  
    1667 PJ_DEF(pj_hash_iterator_t*) pjsip_transport_first( pjsip_transport_mgr *mgr, 
    1668                                                    pj_hash_iterator_t *it ) 
    1669 { 
    1670     return pj_hash_first(mgr->transport_table, it); 
    1671 } 
    1672  
    1673 PJ_DEF(pj_hash_iterator_t*) pjsip_transport_next( pjsip_transport_mgr *mgr, 
    1674                                                   pj_hash_iterator_t *itr ) 
    1675 { 
    1676     return pj_hash_next(mgr->transport_table, itr); 
    1677 } 
    1678  
    1679 PJ_DEF(pjsip_transport_t*) pjsip_transport_this( pjsip_transport_mgr *mgr, 
    1680                                                  pj_hash_iterator_t *itr ) 
    1681 { 
    1682     return pj_hash_this(mgr->transport_table, itr); 
    1683 } 
Note: See TracChangeset for help on using the changeset viewer.