Changeset 107


Ignore:
Timestamp:
Jan 5, 2006 11:35:46 PM (18 years ago)
Author:
bennylp
Message:

Added loop transport to test transaction

Location:
pjproject/trunk
Files:
5 added
30 edited

Legend:

Unmodified
Added
Removed
  • pjproject/trunk/pjlib/include/pj/compat/socket.h

    r65 r107  
    8080#  define OSERR_EWOULDBLOCK    WSAEWOULDBLOCK 
    8181#  define OSERR_EINPROGRESS    WSAEINPROGRESS 
     82#  define OSERR_ECONNRESET     WSAECONNRESET 
    8283#else 
    8384#  define OSERR_EWOULDBLOCK    EWOULDBLOCK 
    8485#  define OSERR_EINPROGRESS    EINPROGRESS 
     86#  define OSERR_ECONNRESET     ECONNRESET 
    8587#endif 
    8688 
  • pjproject/trunk/pjlib/include/pj/list.h

    r66 r107  
    118118 
    119119/** 
     120 * Insert the node to the back of the list. This is just an alias for 
     121 * #pj_list_insert_before(). 
     122 * 
     123 * @param list  The list.  
     124 * @param node  The element to be inserted. 
     125 */ 
     126PJ_INLINE(void) pj_list_push_back(pj_list_type *list, pj_list_type *node) 
     127{ 
     128    pj_list_insert_before(list, node); 
     129} 
     130 
     131 
     132/** 
    120133 * Inserts all nodes in \a nodes to the target list. 
    121134 * 
     
    136149 */ 
    137150PJ_IDECL(void) pj_list_insert_after(pj_list_type *pos, pj_list_type *node); 
     151 
     152 
     153/** 
     154 * Insert the node to the front of the list. This is just an alias for 
     155 * #pj_list_insert_after(). 
     156 * 
     157 * @param list  The list.  
     158 * @param node  The element to be inserted. 
     159 */ 
     160PJ_INLINE(void) pj_list_push_front(pj_list_type *list, pj_list_type *node) 
     161{ 
     162    pj_list_insert_after(list, node); 
     163} 
     164 
    138165 
    139166/** 
  • pjproject/trunk/pjlib/src/pj/os_core_win32.c

    r106 r107  
    863863struct pj_rwmutex_t 
    864864{ 
    865     pj_mutex_t *read_lock, *write_lock; 
    866     int reader_count; 
     865    pj_mutex_t *read_lock; 
     866    /* write_lock must use semaphore, because write_lock may be released 
     867     * by thread other than the thread that acquire the write_lock in the 
     868     * first place. 
     869     */ 
     870    pj_sem_t   *write_lock; 
     871    pj_int32_t  reader_count; 
    867872}; 
    868873 
     
    886891        return status; 
    887892 
    888     status = pj_mutex_create_recursive(pool, name, &rwmutex->write_lock); 
     893    status = pj_sem_create(pool, name, 1, 1, &rwmutex->write_lock); 
    889894    if (status != PJ_SUCCESS) { 
    890895        pj_mutex_destroy(rwmutex->read_lock); 
     
    908913 
    909914    status = pj_mutex_lock(mutex->read_lock); 
    910     if (status != PJ_SUCCESS) 
     915    if (status != PJ_SUCCESS) { 
     916        pj_assert(!"This pretty much is unexpected"); 
    911917        return status; 
     918    } 
    912919 
    913920    mutex->reader_count++; 
     921 
     922    pj_assert(mutex->reader_count < 0x7FFFFFF0L); 
     923 
    914924    if (mutex->reader_count == 1) 
    915         pj_mutex_lock(mutex->write_lock); 
     925        pj_sem_wait(mutex->write_lock); 
    916926 
    917927    status = pj_mutex_unlock(mutex->read_lock); 
     
    926936{ 
    927937    PJ_ASSERT_RETURN(mutex, PJ_EINVAL); 
    928     return pj_mutex_lock(mutex->write_lock); 
     938    return pj_sem_wait(mutex->write_lock); 
    929939} 
    930940 
     
    940950 
    941951    status = pj_mutex_lock(mutex->read_lock); 
    942     if (status != PJ_SUCCESS) 
     952    if (status != PJ_SUCCESS) { 
     953        pj_assert(!"This pretty much is unexpected"); 
    943954        return status; 
     955    } 
    944956 
    945957    pj_assert(mutex->reader_count >= 1); 
     
    947959    --mutex->reader_count; 
    948960    if (mutex->reader_count == 0) 
    949         pj_mutex_unlock(mutex->write_lock); 
     961        pj_sem_post(mutex->write_lock); 
    950962 
    951963    status = pj_mutex_unlock(mutex->read_lock); 
     
    960972{ 
    961973    PJ_ASSERT_RETURN(mutex, PJ_EINVAL); 
    962     return pj_mutex_unlock(mutex->write_lock); 
     974    pj_assert(mutex->reader_count <= 1); 
     975    return pj_sem_post(mutex->write_lock); 
    963976} 
    964977 
     
    972985    PJ_ASSERT_RETURN(mutex, PJ_EINVAL); 
    973986    pj_mutex_destroy(mutex->read_lock); 
    974     pj_mutex_destroy(mutex->write_lock); 
     987    pj_sem_destroy(mutex->write_lock); 
    975988    return PJ_SUCCESS; 
    976989} 
  • pjproject/trunk/pjsip/build/pjsip_core.dsp

    r106 r107  
    125125 
    126126SOURCE=..\src\pjsip\sip_transaction.c 
     127 
     128!IF  "$(CFG)" == "pjsip_core - Win32 Release" 
     129 
    127130# PROP Exclude_From_Build 1 
     131 
     132!ELSEIF  "$(CFG)" == "pjsip_core - Win32 Debug" 
     133 
     134!ENDIF  
     135 
    128136# End Source File 
    129137# Begin Source File 
     
    133141# Begin Source File 
    134142 
     143SOURCE=..\src\pjsip\sip_transport_loop.c 
     144# End Source File 
     145# Begin Source File 
     146 
    135147SOURCE=..\src\pjsip\sip_transport_udp.c 
    136148# End Source File 
     
    142154 
    143155SOURCE=..\src\pjsip\sip_util.c 
     156# End Source File 
     157# Begin Source File 
     158 
     159SOURCE=..\src\pjsip\sip_util_proxy.c 
    144160# End Source File 
    145161# Begin Source File 
     
    222238# Begin Source File 
    223239 
     240SOURCE=..\include\pjsip\sip_transport_loop.h 
     241# End Source File 
     242# Begin Source File 
     243 
    224244SOURCE=..\include\pjsip\sip_transport_udp.h 
    225245# End Source File 
  • pjproject/trunk/pjsip/build/test_pjsip.dsp

    r106 r107  
    102102# Begin Source File 
    103103 
     104SOURCE="..\src\test-pjsip\transport_loop_test.c" 
     105# End Source File 
     106# Begin Source File 
     107 
    104108SOURCE="..\src\test-pjsip\transport_test.c" 
    105109# End Source File 
     
    107111 
    108112SOURCE="..\src\test-pjsip\transport_udp_test.c" 
     113# End Source File 
     114# Begin Source File 
     115 
     116SOURCE="..\src\test-pjsip\tsx_uac_test.c" 
    109117# End Source File 
    110118# Begin Source File 
  • pjproject/trunk/pjsip/include/pjsip/sip_config.h

    r105 r107  
    4646#define PJSIP_RFC3261_BRANCH_LEN        7 
    4747 
     48/* Transaction related constants. */ 
     49#define PJSIP_POOL_TSX_LAYER_LEN        4000 
     50#define PJSIP_POOL_TSX_LAYER_INC        4000 
     51#define PJSIP_MAX_TSX_COUNT             (16*1024) 
     52#define PJSIP_POOL_TSX_LEN              1536 //768 
     53#define PJSIP_POOL_TSX_INC              256 
     54#define PJSIP_MAX_TSX_KEY_LEN           (PJSIP_MAX_URL_SIZE*2) 
     55 
    4856/* Message/URL related constants. */ 
    4957#define PJSIP_MAX_CALL_ID_LEN           PJ_GUID_STRING_LENGTH 
     
    5260#define PJSIP_MAX_URL_SIZE              256 
    5361#define PJSIP_MAX_HNAME_LEN             64 
    54  
    55 /* Transction related constants. */ 
    56 #define PJSIP_MAX_TSX_COUNT             (16*1024) 
    57 #define PJSIP_POOL_LEN_TSX              1536 //768 
    58 #define PJSIP_POOL_INC_TSX              256 
    59 #define PJSIP_MAX_TSX_KEY_LEN           (PJSIP_MAX_URL_SIZE*2) 
    6062 
    6163/* Dialog related constants. */ 
  • pjproject/trunk/pjsip/include/pjsip/sip_endpoint.h

    r106 r107  
    210210 * @param pool      The pool to be destroyed. 
    211211 */ 
    212 PJ_DECL(void) pjsip_endpt_destroy_pool( pjsip_endpoint *endpt, 
     212PJ_DECL(void) pjsip_endpt_release_pool( pjsip_endpoint *endpt, 
    213213                                        pj_pool_t *pool ); 
    214214 
  • pjproject/trunk/pjsip/include/pjsip/sip_errno.h

    r106 r107  
    152152 */ 
    153153#define PJSIP_ENOTRESPONSEMSG   (PJSIP_ERRNO_START_PJSIP + 31)  /* 171031 */ 
     154/** 
     155 * @hideinitializer 
     156 * Invalid header field. 
     157 */ 
     158#define PJSIP_EINVALIDHDR       (PJSIP_ERRNO_START_PJSIP + 32)  /* 171032 */ 
    154159 
    155160 
  • pjproject/trunk/pjsip/include/pjsip/sip_msg.h

    r106 r107  
    500500     *  content type found in Content-Type header. 
    501501     * 
    502      *  For outgoing messages, application must fill in this member with 
     502     *  For outgoing messages, application may fill in this member with 
    503503     *  appropriate value, because the stack will generate Content-Type header 
    504504     *  based on the value specified here. 
     505     * 
     506     *  If the content_type is empty, no Content-Type AND Content-Length header 
     507     *  will be added to the message. The stack assumes that application adds 
     508     *  these headers themselves. 
    505509     */ 
    506510    pjsip_media_type content_type; 
     
    544548                      char *buf, pj_size_t size); 
    545549 
     550    /** Clone the data part only of this message body. Note that this only 
     551     *  duplicates the data part of the body instead of the whole message 
     552     *  body. If application wants to duplicate the entire message body 
     553     *  structure, it must call #pjsip_msg_body_clone(). 
     554     * 
     555     *  @param pool         Pool used to clone the data. 
     556     *  @param data         The data inside message body, to be cloned. 
     557     *  @param len          The length of the data. 
     558     * 
     559     *  @return             New data duplicated from the original data. 
     560     */ 
     561    void* (*clone_data)(pj_pool_t *pool, const void *data, unsigned len); 
     562 
    546563} pjsip_msg_body; 
    547564 
     
    561578PJ_DECL(int) pjsip_print_text_body( pjsip_msg_body *msg_body,  
    562579                                    char *buf, pj_size_t size); 
     580 
     581/** 
     582 * Clone the message body in src_body to the dst_body. This will duplicate 
     583 * the contents of the message body using the \a clone_data member of the 
     584 * source message body. 
     585 * 
     586 * @param pool          Pool to use to duplicate the message body. 
     587 * @param dst_body      Destination message body. 
     588 * @param src_body      Source message body to duplicate. 
     589 * 
     590 * @return              PJ_SUCCESS on success. 
     591 */ 
     592PJ_DECL(pj_status_t) pjsip_msg_body_clone(pj_pool_t *pool, 
     593                                          pjsip_msg_body *dst_body, 
     594                                          const pjsip_msg_body *src_body ); 
     595                                            
    563596 
    564597/** 
  • pjproject/trunk/pjsip/include/pjsip/sip_transaction.h

    r105 r107  
    2626 
    2727#include <pjsip/sip_msg.h> 
    28 #include <pjsip/sip_resolve.h> 
     28#include <pjsip/sip_util.h> 
    2929#include <pj/timer.h> 
    3030 
     
    3737 */ 
    3838 
    39 /* Forward decl. */ 
    40 struct pjsip_transaction; 
    41  
    42  
    43 /** 
    44  * Transaction state. 
     39/** 
     40 * This enumeration represents transaction state. 
    4541 */ 
    4642typedef enum pjsip_tsx_state_e 
    4743{ 
    48     PJSIP_TSX_STATE_NULL, 
    49     PJSIP_TSX_STATE_CALLING, 
    50     PJSIP_TSX_STATE_TRYING, 
    51     PJSIP_TSX_STATE_PROCEEDING, 
    52     PJSIP_TSX_STATE_COMPLETED, 
    53     PJSIP_TSX_STATE_CONFIRMED, 
    54     PJSIP_TSX_STATE_TERMINATED, 
    55     PJSIP_TSX_STATE_DESTROYED, 
    56     PJSIP_TSX_STATE_MAX, 
     44    PJSIP_TSX_STATE_NULL,       /**< For UAC, before any message is sent.   */ 
     45    PJSIP_TSX_STATE_CALLING,    /**< For UAC, just after request is sent.   */ 
     46    PJSIP_TSX_STATE_TRYING,     /**< For UAS, just after request is received.*/ 
     47    PJSIP_TSX_STATE_PROCEEDING, /**< For UAS/UAC, after provisional response.*/ 
     48    PJSIP_TSX_STATE_COMPLETED,  /**< For UAS/UAC, after final response.     */ 
     49    PJSIP_TSX_STATE_CONFIRMED,  /**< For UAS, after ACK is received.        */ 
     50    PJSIP_TSX_STATE_TERMINATED, /**< For UAS/UAC, before it's destroyed.    */ 
     51    PJSIP_TSX_STATE_DESTROYED,  /**< For UAS/UAC, will be destroyed now.    */ 
     52    PJSIP_TSX_STATE_MAX,        /**< Number of states.                      */ 
    5753} pjsip_tsx_state_e; 
    5854 
    5955 
    6056/** 
    61  * State of the transport in the transaction. 
    62  * The transport is progressing independently of the transaction. 
    63  */ 
    64 typedef enum pjsip_tsx_transport_state_e 
    65 { 
    66     PJSIP_TSX_TRANSPORT_STATE_NULL, 
    67     PJSIP_TSX_TRANSPORT_STATE_RESOLVING, 
    68     PJSIP_TSX_TRANSPORT_STATE_CONNECTING, 
    69     PJSIP_TSX_TRANSPORT_STATE_FINAL, 
    70 } pjsip_tsx_transport_state_e; 
    71  
    72  
    73 /** 
    74  * Transaction state. 
     57 * This structure describes SIP transaction object. The transaction object 
     58 * is used to handle both UAS and UAC transaction. 
    7559 */ 
    7660struct pjsip_transaction 
     
    8064     */ 
    8165    pj_pool_t                  *pool;           /**< Pool owned by the tsx. */ 
     66    pjsip_module               *tsx_user;       /**< Transaction user.      */ 
    8267    pjsip_endpoint             *endpt;          /**< Endpoint instance.     */ 
    8368    pj_mutex_t                 *mutex;          /**< Mutex for this tsx.    */ 
    84     char                        obj_name[PJ_MAX_OBJ_NAME];  /**< Tsx name.  */ 
    85     int                         tracing;        /**< Tracing enabled?       */ 
    8669 
    8770    /* 
    8871     * Transaction identification. 
    8972     */ 
     73    char                        obj_name[PJ_MAX_OBJ_NAME];  /**< Log info.  */ 
    9074    pjsip_role_e                role;           /**< Role (UAS or UAC)      */ 
    9175    pjsip_method                method;         /**< The method.            */ 
    9276    int                         cseq;           /**< The CSeq               */ 
    93     pj_str_t                    transaction_key;/**< hash table key.        */ 
     77    pj_str_t                    transaction_key;/**< Hash table key.        */ 
    9478    pj_str_t                    branch;         /**< The branch Id.         */ 
    9579 
     
    9983    int                         status_code;    /**< Last status code seen. */ 
    10084    pjsip_tsx_state_e           state;          /**< State.                 */ 
    101     int                         handle_ack;     /**< Should we handle ACK?  */ 
     85    int                         handle_200resp; /**< UAS 200/INVITE  retrsm.*/ 
     86    int                         tracing;        /**< Tracing enabled?       */ 
    10287 
    10388    /** Handler according to current state. */ 
     
    10792     * Transport. 
    10893     */ 
    109     pjsip_tsx_transport_state_e transport_state;/**< Transport's state.     */ 
    110     pjsip_host_info             dest_name;      /**< Destination address.   */ 
    111     pjsip_server_addresses      remote_addr;    /**< Addresses resolved.    */ 
    112     int                         current_addr;   /**< Address currently used. */ 
    113  
    11494    pjsip_transport            *transport;      /**< Transport to use.      */ 
     95    pj_sockaddr                 addr;           /**< Destination address.   */ 
     96    int                         addr_len;       /**< Address length.        */ 
     97    pjsip_response_addr         res_addr;       /**< Response address.      */ 
     98    unsigned                    transport_flag; /**< Miscelaneous flag.     */ 
    11599 
    116100    /* 
     
    118102     */ 
    119103    pjsip_tx_data              *last_tx;        /**< Msg kept for retrans.  */ 
    120     int                         has_unsent_msg; /**< Non-zero if tsx need to  
    121                                                      transmit msg once resolver 
    122                                                      completes.             */ 
    123104    int                         retransmit_count;/**< Retransmission count. */ 
    124105    pj_timer_entry              retransmit_timer;/**< Retransmit timer.     */ 
     
    126107 
    127108    /** Module specific data. */ 
    128     void                       *module_data[PJSIP_MAX_MODULE]; 
     109    void                       *mod_data[PJSIP_MAX_MODULE]; 
    129110}; 
    130111 
    131112 
    132113/** 
    133  * Create new transaction. Application would normally use  
    134  * #pjsip_endpt_create_tsx rather than this function. 
    135  * 
    136  * @param pool      Pool to use by the transaction. 
    137  * @param endpt     Endpoint. 
    138  * @param p_tsx     Pointer to return the transaction. 
    139  * 
    140  * @return          PJ_SUCCESS or the appropriate error code. 
    141  * 
    142  * @see pjsip_endpt_create_tsx 
    143  * 
    144  */ 
    145 PJ_DEF(pj_status_t) pjsip_tsx_create( pj_pool_t *pool, 
    146                                       pjsip_endpoint *endpt, 
    147                                       pjsip_transaction **p_tsx); 
    148  
    149 /**  
    150  * Init transaction as UAC from the specified transmit data (\c tdata). 
    151  * The transmit data must have a valid \c Request-Line and \c CSeq header. 
    152  * If \c Route headers are present, it will be used to calculate remote 
    153  * destination. 
     114 * Create and register transaction layer module to the specified endpoint. 
     115 * 
     116 * @param endpt     The endpoint instance. 
     117 * 
     118 * @return          PJ_SUCCESS on success. 
     119 */ 
     120PJ_DECL(pj_status_t) pjsip_tsx_layer_init(pjsip_endpoint *endpt); 
     121 
     122/** 
     123 * Get the instance of the transaction layer module. 
     124 * 
     125 * @return          The transaction layer module. 
     126 */ 
     127PJ_DECL(pjsip_module*) pjsip_tsx_layer_instance(void); 
     128 
     129/** 
     130 * Unregister and destroy transaction layer module. 
     131 * 
     132 * @return          PJ_SUCCESS on success. 
     133 */ 
     134PJ_DECL(pj_status_t) pjsip_tsx_layer_destroy(void); 
     135 
     136/** 
     137 * Find a transaction with the specified key. The transaction key normally 
     138 * is created by calling #pjsip_tsx_create_key() from an incoming message. 
     139 * 
     140 * @param key       The key string to find the transaction. 
     141 * @param lock      If non-zero, transaction will be locked before the 
     142 *                  function returns, to make sure that it's not deleted 
     143 *                  by other threads. 
     144 * 
     145 * @return          The matching transaction instance, or NULL if transaction 
     146 *                  can not be found. 
     147 */ 
     148PJ_DECL(pjsip_transaction*) pjsip_tsx_layer_find_tsx( const pj_str_t *key, 
     149                                                      pj_bool_t lock ); 
     150 
     151/** 
     152 * Create, initialize, and register a new transaction as UAC from the  
     153 * specified transmit data (\c tdata). The transmit data must have a valid 
     154 * \c Request-Line and \c CSeq header.  
    154155 * 
    155156 * If \c Via header does not exist, it will be created along with a unique 
    156157 * \c branch parameter. If it exists and contains branch parameter, then 
    157  * the \c branch parameter will be used as is as the transaction key. 
    158  * 
    159  * The \c Route headers in the transmit data, if present, are used to  
    160  * calculate remote destination. 
    161  * 
    162  * At the end of the function, the transaction will start resolving the 
    163  * addresses of remote server to contact. Transport will be acquired as soon 
    164  * as the resolving job completes. 
    165  * 
    166  * @param tsx       The transaction. 
    167  * @param tdata     The transmit data. 
     158 * the \c branch parameter will be used as is as the transaction key. If 
     159 * it exists but branch parameter doesn't exist, a unique branch parameter 
     160 * will be created. 
     161 * 
     162 * @param tsx_user  Module to be registered as transaction user of the new 
     163 *                  transaction, which will receive notification from the 
     164 *                  transaction via on_tsx_state() callback. 
     165 * @param tdata     The outgoing request message. 
     166 * @param p_tsx     On return will contain the new transaction instance. 
    168167 * 
    169168 * @return          PJ_SUCCESS if successfull. 
    170169 */ 
    171 PJ_DECL(pj_status_t) pjsip_tsx_init_uac( pjsip_transaction *tsx,  
    172                                          pjsip_tx_data *tdata); 
    173  
    174 /** 
    175  * Init transaction as UAS. 
    176  * 
    177  * @param tsx       The transaction to be initialized. 
     170PJ_DECL(pj_status_t) pjsip_tsx_create_uac( pjsip_module *tsx_user, 
     171                                           pjsip_tx_data *tdata, 
     172                                           pjsip_transaction **p_tsx); 
     173 
     174/** 
     175 * Create, initialize, and register a new transaction as UAS from the 
     176 * specified incoming request in \c rdata. 
     177 * 
     178 * @param tsx_user  Module to be registered as transaction user of the new 
     179 *                  transaction, which will receive notification from the 
     180 *                  transaction via on_tsx_state() callback. 
    178181 * @param rdata     The received incoming request. 
    179  * 
    180  * @return PJ_SUCCESS if successfull. 
    181  */ 
    182 PJ_DECL(pj_status_t) pjsip_tsx_init_uas( pjsip_transaction *tsx, 
    183                                          pjsip_rx_data *rdata); 
    184  
    185 /** 
    186  * Process incoming message for this transaction. 
    187  * 
    188  * @param tsx       The transaction. 
    189  * @param rdata     The incoming message. 
    190  */ 
    191 PJ_DECL(void) pjsip_tsx_on_rx_msg( pjsip_transaction *tsx, 
    192                                    pjsip_rx_data *rdata); 
    193  
    194 /** 
    195  * Transmit message with this transaction. 
     182 * @param p_tsx     On return will contain the new transaction instance. 
     183 * 
     184 * @return          PJ_SUCCESS if successfull. 
     185 */ 
     186PJ_DECL(pj_status_t) pjsip_tsx_create_uas( pjsip_module *tsx_user, 
     187                                           pjsip_rx_data *rdata, 
     188                                           pjsip_transaction **p_tsx ); 
     189 
     190/** 
     191 * Transmit message in tdata with this transaction. It is possible to 
     192 * pass NULL in tdata for UAC transaction, which in this case the request 
     193 * message which was specified in #pjsip_tsx_create_uac() will be sent. 
    196194 * 
    197195 * @param tsx       The transaction. 
    198196 * @param tdata     The outgoing message. 
    199  */ 
    200 PJ_DECL(void) pjsip_tsx_on_tx_msg( pjsip_transaction *tsx, 
    201                                    pjsip_tx_data *tdata); 
    202  
    203  
    204 /** 
    205  * Transmit ACK message for 2xx/INVITE with this transaction. The ACK for 
    206  * non-2xx/INVITE is automatically sent by the transaction. 
    207  * This operation is only valid if the transaction is configured to handle ACK 
    208  * (tsx->handle_ack is non-zero). If this attribute is not set, then the 
    209  * transaction will comply with RFC-3261, i.e. it will set itself to  
    210  * TERMINATED state when it receives 2xx/INVITE. 
    211  * 
    212  * @param tsx       The transaction. 
    213  * @param tdata     The ACK request. 
    214  */ 
    215 PJ_DECL(void) pjsip_tsx_on_tx_ack( pjsip_transaction *tsx, 
    216                                    pjsip_tx_data *tdata); 
    217  
    218 /** 
    219  * Force terminate transaction. 
    220  * 
    221  * @param tsx       The transaction. 
    222  * @param code      The status code to report. 
    223  */ 
    224 PJ_DECL(void) pjsip_tsx_terminate( pjsip_transaction *tsx, 
    225                                    int code ); 
     197 * 
     198 * @return          PJ_SUCCESS if successfull. 
     199 */ 
     200PJ_DECL(pj_status_t) pjsip_tsx_send_msg( pjsip_transaction *tsx, 
     201                                         pjsip_tx_data *tdata); 
     202 
    226203 
    227204/** 
     
    245222 
    246223/** 
     224 * Force terminate transaction. 
     225 * 
     226 * @param tsx       The transaction. 
     227 * @param code      The status code to report. 
     228 */ 
     229PJ_DECL(pj_status_t) pjsip_tsx_terminate( pjsip_transaction *tsx, 
     230                                          int st_code ); 
     231 
     232 
     233/** 
     234 * Get the transaction instance in the incoming message. If the message 
     235 * has a corresponding transaction, this function will return non NULL 
     236 * value. 
     237 * 
     238 * @param rdata     The incoming message buffer. 
     239 * 
     240 * @return          The transaction instance associated with this message, 
     241 *                  or NULL if the message doesn't match any transactions. 
     242 */ 
     243PJ_DECL(pjsip_transaction*) pjsip_rdata_get_tsx( pjsip_rx_data *rdata ); 
     244 
     245 
     246/** 
    247247 * @} 
    248248 */ 
     
    263263 
    264264 
    265 /* Thread Local Storage ID for transaction lock (initialized by endpoint) */ 
    266 extern long pjsip_tsx_lock_tls_id; 
    267  
    268265PJ_END_DECL 
    269266 
  • pjproject/trunk/pjsip/include/pjsip/sip_transport.h

    r106 r107  
    172172 
    173173        /** The length of the packet received. */ 
    174         int                      len; 
     174        pj_ssize_t               len; 
    175175 
    176176        /** The source address from which the packet was received. */ 
     
    252252    { 
    253253        /**  
    254          * This the transaction key generated for the message.  
     254         * Data attached by modules to this message.  
    255255         */ 
    256         pj_str_t                 key; 
     256        void    *mod_data[PJSIP_MAX_MODULE]; 
    257257 
    258258    } endpt_info; 
  • pjproject/trunk/pjsip/include/pjsip/sip_transport_udp.h

    • Property svn:keywords set to Id
  • pjproject/trunk/pjsip/include/pjsip/sip_types.h

    r105 r107  
    5252    /** SCTP. */ 
    5353    PJSIP_TRANSPORT_SCTP, 
     54 
     55    /** Loopback (stream, reliable) */ 
     56    PJSIP_TRANSPORT_LOOP, 
     57 
     58    /** Loopback (datagram, unreliable) */ 
     59    PJSIP_TRANSPORT_LOOP_DGRAM, 
    5460 
    5561} pjsip_transport_type_e; 
  • pjproject/trunk/pjsip/include/pjsip/sip_util.h

    r106 r107  
    329329 
    330330/** 
     331 * This composite function sends response message statelessly to an incoming 
     332 * request message. Internally it calls #pjsip_endpt_create_response() and 
     333 * #pjsip_endpt_send_response(). 
     334 * 
     335 * @param endpt     The endpoint instance. 
     336 * @param rdata     The incoming request message. 
     337 * @param st_code   Status code of the response. 
     338 * @param st_text   Optional status text of the response. 
     339 * @param hdr_list  Optional header list to be added to the response. 
     340 * @param body      Optional message body to be added to the response. 
     341 * 
     342 * @return          PJ_SUCCESS if response message has successfully been 
     343 *                  created. 
     344 */ 
     345PJ_DECL(pj_status_t) pjsip_endpt_respond_stateless(pjsip_endpoint *endpt, 
     346                                                   pjsip_rx_data *rdata, 
     347                                                   int st_code, 
     348                                                   const pj_str_t *st_text, 
     349                                                   const pjsip_hdr *hdr_list, 
     350                                                   const pjsip_msg_body *body); 
     351                                                     
     352 
     353/** 
    331354 * Send outgoing request and initiate UAC transaction for the request. 
    332355 * This is an auxiliary function to be used by application to send arbitrary 
     
    353376                                               void (*cb)(void*,pjsip_event*)); 
    354377 
     378/** 
     379 * Create new request message to be forwarded upstream to new destination URI  
     380 * in uri. The new request is a full/deep clone of the request received in  
     381 * rdata, unless if other copy mechanism is specified in the options.  
     382 * The branch parameter, if not NULL, will be used as the branch-param in  
     383 * the Via header. If it is NULL, then a unique branch parameter will be used. 
     384 * 
     385 * @param endpt     The endpoint instance. 
     386 * @param rdata     The incoming request message. 
     387 * @param uri       The URI where the request will be forwarded to. 
     388 * @param branch    Optional branch parameter. 
     389 * @param options   Optional option flags when duplicating the message. 
     390 * @param tdata     The result. 
     391 * 
     392 * @return          PJ_SUCCESS on success. 
     393 */ 
     394PJ_DECL(pj_status_t) pjsip_endpt_create_request_fwd( pjsip_endpoint *endpt, 
     395                                                     pjsip_rx_data *rdata,  
     396                                                     const pjsip_uri *uri, 
     397                                                     const pj_str_t *branch, 
     398                                                     unsigned options, 
     399                                                     pjsip_tx_data **tdata); 
     400 
     401/** 
     402 * Create new response message to be forwarded downstream by the proxy from  
     403 * the response message found in rdata. Note that this function practically  
     404 * will clone the response as is, i.e. without checking the validity of the  
     405 * response or removing top most Via header. This function will perform  
     406 * full/deep clone of the response, unless other copy mechanism is used in  
     407 * the options. 
     408 * 
     409 * @param endpt     The endpoint instance. 
     410 * @param rdata     The incoming response message. 
     411 * @param options   Optional option flags when duplicate the message. 
     412 * @param tdata     The result 
     413 * 
     414 * @return          PJ_SUCCESS on success. 
     415 */ 
     416PJ_DECL(pj_status_t) pjsip_endpt_create_response_fwd( pjsip_endpoint *endpt, 
     417                                                      pjsip_rx_data *rdata,  
     418                                                      unsigned options, 
     419                                                      pjsip_tx_data **tdata); 
     420 
     421 
     422/** 
     423 * Create a globally unique branch parameter based on the information in  
     424 * the incoming request message. This function guarantees that subsequent  
     425 * retransmissions of the same request will generate the same branch id. 
     426 * This function can also be used in the loop detection process.  
     427 * If the same request arrives back in the proxy with the same URL, it will 
     428 * calculate into the same branch id. 
     429 * Note that the returned string was allocated from rdata's pool. 
     430 * 
     431 * @param rdata     The incoming request message. 
     432 * 
     433 * @return          Unique branch-ID string. 
     434 */ 
     435PJ_DECL(pj_str_t) pjsip_calculate_branch_id( pjsip_rx_data *rdata ); 
     436 
    355437 
    356438/** 
  • pjproject/trunk/pjsip/include/pjsip_core.h

    r106 r107  
    3333#include <pjsip/sip_transport.h> 
    3434#include <pjsip/sip_transport_udp.h> 
     35#include <pjsip/sip_transport_loop.h> 
    3536#include <pjsip/sip_uri.h> 
    3637#include <pjsip/sip_util.h> 
  • pjproject/trunk/pjsip/src/pjsip/sip_endpoint.c

    r106 r107  
    491491 * recycled. 
    492492 */ 
    493 PJ_DEF(void) pjsip_endpt_destroy_pool( pjsip_endpoint *endpt, pj_pool_t *pool ) 
    494 { 
    495     PJ_LOG(5, (THIS_FILE, "pjsip_endpt_destroy_pool(%s)", pj_pool_getobjname(pool))); 
     493PJ_DEF(void) pjsip_endpt_release_pool( pjsip_endpoint *endpt, pj_pool_t *pool ) 
     494{ 
     495    PJ_LOG(5, (THIS_FILE, "pjsip_endpt_release_pool(%s)", pj_pool_getobjname(pool))); 
    496496 
    497497    pj_mutex_lock(endpt->mutex); 
  • pjproject/trunk/pjsip/src/pjsip/sip_errno.c

    • Property svn:keywords set to Id
    r106 r107  
    1 /* $Id: $ */ 
     1/* $Id$ */ 
    22/*  
    33 * Copyright (C) 2003-2006 Benny Prijono <benny@prijono.org> 
     
    4848    { PJSIP_ENOTREQUESTMSG,     "Expecting request message"}, 
    4949    { PJSIP_ENOTRESPONSEMSG,    "Expecting response message"}, 
     50    { PJSIP_EINVALIDHDR,        "Invalid header field"}, 
    5051 
    5152    /* Transport errors */ 
  • pjproject/trunk/pjsip/src/pjsip/sip_msg.c

    r106 r107  
    2020#include <pjsip/sip_parser.h> 
    2121#include <pjsip/print_util.h> 
     22#include <pjsip/sip_errno.h> 
    2223#include <pj/string.h> 
    2324#include <pj/pool.h> 
     
    366367    /* Process message body. */ 
    367368    if (msg->body) { 
    368         pj_str_t ctype_hdr = { "Content-Type: ", 14}; 
    369         int len; 
    370         const pjsip_media_type *media = &msg->body->content_type; 
    371         char *clen_pos; 
    372  
    373         /* Add Content-Type header. */ 
    374         if ( (end-p) < 24+media->type.slen+media->subtype.slen+media->param.slen) { 
    375             return -1; 
     369        char *clen_pos = NULL; 
     370 
     371        /* Automaticly adds Content-Type and Content-Length headers, only 
     372         * if content_type is set in the message body. 
     373         */ 
     374        if (msg->body->content_type.type.slen) { 
     375            pj_str_t ctype_hdr = { "Content-Type: ", 14}; 
     376            const pjsip_media_type *media = &msg->body->content_type; 
     377 
     378            /* Add Content-Type header. */ 
     379            if ( (end-p) < 24 + media->type.slen + media->subtype.slen +  
     380                           media->param.slen)  
     381            { 
     382                return -1; 
     383            } 
     384            pj_memcpy(p, ctype_hdr.ptr, ctype_hdr.slen); 
     385            p += ctype_hdr.slen; 
     386            p += print_media_type(p, media); 
     387            *p++ = '\r'; 
     388            *p++ = '\n'; 
     389 
     390            /* Add Content-Length header. */ 
     391            if ((end-p) < clen_hdr.slen + 12 + 2) { 
     392                return -1; 
     393            } 
     394            pj_memcpy(p, clen_hdr.ptr, clen_hdr.slen); 
     395            p += clen_hdr.slen; 
     396             
     397            /* Print blanks after "Content-Type:", this is where we'll put 
     398             * the content length value after we know the length of the 
     399             * body. 
     400             */ 
     401            pj_memset(p, ' ', 12); 
     402            clen_pos = p; 
     403            p += 12; 
     404            *p++ = '\r'; 
     405            *p++ = '\n'; 
    376406        } 
    377         pj_memcpy(p, ctype_hdr.ptr, ctype_hdr.slen); 
    378         p += ctype_hdr.slen; 
    379         p += print_media_type(p, media); 
    380         *p++ = '\r'; 
    381         *p++ = '\n'; 
    382  
    383         /* Add Content-Length header. */ 
    384         if ((end-p) < clen_hdr.slen+12+2) { 
    385             return -1; 
    386         } 
    387         pj_memcpy(p, clen_hdr.ptr, clen_hdr.slen); 
    388         p += clen_hdr.slen; 
    389          
    390         /* Print blanks after "Content-Type:", this is where we'll put 
    391          * the content length value after we know the length of the 
    392          * body. 
    393          */ 
    394         pj_memset(p, ' ', 12); 
    395         clen_pos = p; 
    396         p += 12; 
    397         *p++ = '\r'; 
    398         *p++ = '\n'; 
    399407         
    400408        /* Add blank newline. */ 
     
    412420         * Content-Length header. 
    413421         */ 
    414         len = pj_utoa(len, clen_pos); 
    415         clen_pos[len] = ' '; 
     422        if (clen_pos) { 
     423            len = pj_utoa(len, clen_pos); 
     424            clen_pos[len] = ' '; 
     425        } 
    416426 
    417427    } else { 
     
    14651475/////////////////////////////////////////////////////////////////////////////// 
    14661476/* 
    1467  * General purpose function to textual data in a SIP body.  
     1477 * Message body manipulations. 
    14681478 */ 
    14691479PJ_DEF(int) pjsip_print_text_body(pjsip_msg_body *msg_body, char *buf, pj_size_t size) 
     
    14741484    return msg_body->len; 
    14751485} 
     1486 
     1487PJ_DEF(pj_status_t) pjsip_msg_body_clone( pj_pool_t *pool, 
     1488                                          pjsip_msg_body *dst_body, 
     1489                                          const pjsip_msg_body *src_body ) 
     1490{ 
     1491    /* First check if clone_data field is initialized. */ 
     1492    PJ_ASSERT_RETURN( src_body->clone_data!=NULL, PJ_EINVAL ); 
     1493 
     1494    /* Duplicate content-type */ 
     1495    pj_strdup(pool, &dst_body->content_type.type,  
     1496                    &src_body->content_type.type); 
     1497    pj_strdup(pool, &dst_body->content_type.subtype,  
     1498                    &src_body->content_type.subtype); 
     1499    pj_strdup(pool, &dst_body->content_type.param, 
     1500                    &src_body->content_type.param); 
     1501 
     1502    /* Duplicate data. */ 
     1503    dst_body->data = (*src_body->clone_data)(pool, src_body->data,  
     1504                                             src_body->len ); 
     1505 
     1506    /* Length. */ 
     1507    dst_body->len = src_body->len; 
     1508 
     1509    /* Function pointers. */ 
     1510    dst_body->print_body = src_body->print_body; 
     1511    dst_body->clone_data = src_body->clone_data; 
     1512 
     1513    return PJ_SUCCESS; 
     1514} 
     1515 
  • pjproject/trunk/pjsip/src/pjsip/sip_transaction.c

    r106 r107  
    1818 */ 
    1919#include <pjsip/sip_transaction.h> 
    20 #include <pjsip/sip_transport.h> 
    21 #include <pjsip/sip_config.h> 
    2220#include <pjsip/sip_util.h> 
    23 #include <pjsip/sip_event.h> 
     21#include <pjsip/sip_module.h> 
    2422#include <pjsip/sip_endpoint.h> 
    2523#include <pjsip/sip_errno.h> 
     24#include <pjsip/sip_event.h> 
     25#include <pj/hash.h> 
     26#include <pj/pool.h> 
     27#include <pj/os.h> 
     28#include <pj/string.h> 
     29#include <pj/assert.h> 
     30#include <pj/guid.h> 
    2631#include <pj/log.h> 
    27 #include <pj/string.h> 
    28 #include <pj/os.h> 
    29 #include <pj/guid.h> 
    30 #include <pj/pool.h> 
    31 #include <pj/assert.h> 
    32  
    33 #if 0   // XXX JUNK 
    34     /* Initialize TLS ID for transaction lock. */ 
    35     status = pj_thread_local_alloc(&pjsip_tsx_lock_tls_id); 
    36     if (status != PJ_SUCCESS) { 
    37         goto on_error; 
    38     } 
    39     pj_thread_local_set(pjsip_tsx_lock_tls_id, NULL); 
    40  
    41  
    42     /* Create hash table for transaction. */ 
    43     endpt->tsx_table = pj_hash_create( endpt->pool, PJSIP_MAX_TSX_COUNT ); 
    44     if (!endpt->tsx_table) { 
    45         status = PJ_ENOMEM; 
    46         goto on_error; 
    47     } 
    48  
    49  
    50 /* 
    51  * Create a new transaction. 
    52  * Endpoint must then initialize the new transaction as either UAS or UAC, and 
    53  * register it to the hash table. 
    54  */ 
    55 PJ_DEF(pj_status_t) pjsip_endpt_create_tsx(pjsip_endpoint *endpt, 
    56                                            pjsip_transaction **p_tsx) 
    57 { 
    58     pj_pool_t *pool; 
    59  
    60     PJ_ASSERT_RETURN(endpt && p_tsx, PJ_EINVAL); 
    61  
    62     PJ_LOG(5, (THIS_FILE, "pjsip_endpt_create_tsx()")); 
    63  
    64     /* Request one pool for the transaction. Mutex is locked there. */ 
    65     pool = pjsip_endpt_create_pool(endpt, "ptsx%p",  
    66                                       PJSIP_POOL_LEN_TSX, PJSIP_POOL_INC_TSX); 
    67     if (pool == NULL) { 
    68         return PJ_ENOMEM; 
    69     } 
    70  
    71     /* Create the transaction. */ 
    72     return pjsip_tsx_create(pool, endpt, p_tsx); 
    73 } 
    74  
    75  
    76 /* 
    77  * Register the transaction to the endpoint. 
    78  * This will put the transaction to the transaction hash table. Before calling 
    79  * this function, the transaction must be INITIALIZED as either UAS or UAC, so 
    80  * that the transaction key is built. 
    81  */ 
    82 PJ_DEF(void) pjsip_endpt_register_tsx( pjsip_endpoint *endpt, 
    83                                        pjsip_transaction *tsx) 
    84 { 
    85     PJ_LOG(5, (THIS_FILE, "pjsip_endpt_register_tsx(%s)", tsx->obj_name)); 
    86  
    87     pj_assert(tsx->transaction_key.slen != 0); 
    88     //pj_assert(tsx->state != PJSIP_TSX_STATE_NULL); 
    89  
    90     /* Lock hash table mutex. */ 
    91     pj_mutex_lock(endpt->tsx_table_mutex); 
    92  
    93     /* Register the transaction to the hash table. */ 
    94     pj_hash_set( tsx->pool, endpt->tsx_table, tsx->transaction_key.ptr, 
    95                  tsx->transaction_key.slen, tsx); 
    96  
    97     /* Unlock mutex. */ 
    98     pj_mutex_unlock(endpt->tsx_table_mutex); 
    99 } 
    100  
    101 /* 
    102  * Find transaction by the key. 
    103  */ 
    104 PJ_DEF(pjsip_transaction*) pjsip_endpt_find_tsx( pjsip_endpoint *endpt, 
    105                                                   const pj_str_t *key ) 
    106 { 
    107     pjsip_transaction *tsx; 
    108  
    109     PJ_LOG(5, (THIS_FILE, "pjsip_endpt_find_tsx()")); 
    110  
    111     /* Start lock mutex in the endpoint. */ 
    112     pj_mutex_lock(endpt->tsx_table_mutex); 
    113  
    114     /* Find the transaction in the hash table. */ 
    115     tsx = pj_hash_get( endpt->tsx_table, key->ptr, key->slen ); 
    116  
    117     /* Unlock mutex. */ 
    118     pj_mutex_unlock(endpt->tsx_table_mutex); 
    119  
    120     return tsx; 
    121 } 
    122  
    123 /* 
    124  * Create key. 
    125  */ 
    126 static void rdata_create_key( pjsip_rx_data *rdata) 
    127 { 
    128     pjsip_role_e role; 
    129     if (rdata->msg_info.msg->type == PJSIP_REQUEST_MSG) { 
    130         role = PJSIP_ROLE_UAS; 
    131     } else { 
    132         role = PJSIP_ROLE_UAC; 
    133     } 
    134     pjsip_tsx_create_key(rdata->tp_info.pool, &rdata->endpt_info.key, role, 
    135                          &rdata->msg_info.cseq->method, rdata); 
    136 } 
    137  
    138  
    139 /* 
    140  * This is the callback that is called by the transport manager when it  
    141  * receives a message from the network. 
    142  */ 
    143 static void endpt_transport_callback( pjsip_endpoint *endpt, 
    144                                       pj_status_t status, 
    145                                       pjsip_rx_data *rdata ) 
    146 { 
    147     pjsip_msg *msg = rdata->msg_info.msg; 
    148     pjsip_transaction *tsx; 
    149     pj_bool_t a_new_transaction_just_been_created = PJ_FALSE; 
    150  
    151     PJ_LOG(5, (THIS_FILE, "endpt_transport_callback(rdata=%p)", rdata)); 
    152  
    153     if (status != PJ_SUCCESS) { 
    154         const char *src_addr = rdata->pkt_info.src_name; 
    155         int port = rdata->pkt_info.src_port; 
    156         PJSIP_ENDPT_LOG_ERROR((endpt, "transport", status, 
    157                                "Src.addr=%s:%d, packet:--\n" 
    158                                "%s\n" 
    159                                "-- end of packet. Error", 
    160                                src_addr, port, rdata->msg_info.msg_buf)); 
    161         return; 
    162     } 
    163  
    164     /* For response, check that the value in Via sent-by match the transport. 
    165      * If not matched, silently drop the response. 
    166      * Ref: RFC3261 Section 18.1.2 Receiving Response 
    167      */ 
    168     if (msg->type == PJSIP_RESPONSE_MSG) { 
    169         const pj_str_t *addr_addr; 
    170         int port = rdata->msg_info.via->sent_by.port; 
    171         pj_bool_t mismatch = PJ_FALSE; 
    172         if (port == 0) { 
    173             int type; 
    174             type = rdata->tp_info.transport->key.type; 
    175             port = pjsip_transport_get_default_port_for_type(type); 
    176         } 
    177         addr_addr = &rdata->tp_info.transport->local_name.host; 
    178         if (pj_strcmp(&rdata->msg_info.via->sent_by.host, addr_addr) != 0) 
    179             mismatch = PJ_TRUE; 
    180         else if (port != rdata->tp_info.transport->local_name.port) { 
    181             /* Port or address mismatch, we should discard response */ 
    182             /* But we saw one implementation (we don't want to name it to  
    183              * protect the innocence) which put wrong sent-by port although 
    184              * the "rport" parameter is correct. 
    185              * So we discard the response only if the port doesn't match 
    186              * both the port in sent-by and rport. We try to be lenient here! 
    187              */ 
    188             if (rdata->msg_info.via->rport_param != rdata->tp_info.transport->local_name.port) 
    189                 mismatch = PJ_TRUE; 
    190             else { 
    191                 PJ_LOG(4,(THIS_FILE, "Response %p has mismatch port in sent-by" 
    192                                     " but the rport parameter is correct", 
    193                                     rdata)); 
    194             } 
    195         } 
    196  
    197         if (mismatch) { 
    198             pjsip_event e; 
    199  
    200             PJSIP_EVENT_INIT_DISCARD_MSG(e, rdata, PJSIP_EINVALIDVIA); 
    201             endpt_do_event( endpt, &e ); 
    202             return; 
    203         } 
    204     } 
    205  
    206     /* Create key for transaction lookup. */ 
    207     rdata_create_key( rdata); 
    208  
    209     /* Find the transaction for the received message. */ 
    210     PJ_LOG(5, (THIS_FILE, "finding tsx with key=%.*s",  
    211                          rdata->endpt_info.key.slen, rdata->endpt_info.key.ptr)); 
    212  
    213     /* Start lock mutex in the endpoint. */ 
    214     pj_mutex_lock(endpt->tsx_table_mutex); 
    215  
    216     /* Find the transaction in the hash table. */ 
    217     tsx = pj_hash_get( endpt->tsx_table, rdata->endpt_info.key.ptr, rdata->endpt_info.key.slen ); 
    218  
    219     /* Unlock mutex. */ 
    220     pj_mutex_unlock(endpt->tsx_table_mutex); 
    221  
    222     /* If the transaction is not found... */ 
    223     if (tsx == NULL || tsx->state == PJSIP_TSX_STATE_TERMINATED) { 
    224  
    225         /*  
    226          * For response message, discard the message, except if the response is 
    227          * an 2xx class response to INVITE, which in this case it must be 
    228          * passed to TU to be acked. 
    229          */ 
    230         if (msg->type == PJSIP_RESPONSE_MSG) { 
    231  
    232             /* Inform TU about the 200 message, only if it's INVITE. */ 
    233             if (PJSIP_IS_STATUS_IN_CLASS(msg->line.status.code, 200) && 
    234                 rdata->msg_info.cseq->method.id == PJSIP_INVITE_METHOD)  
    235             { 
    236                 pjsip_event e; 
    237  
    238                 /* Should not happen for UA. Tsx theoritically lives until 
    239                  * all responses are absorbed. 
    240                  */ 
    241                 pj_assert(0); 
    242  
    243                 PJSIP_EVENT_INIT_RX_200_MSG(e, rdata); 
    244                 endpt_do_event( endpt, &e ); 
    245  
    246             } else { 
    247                 /* Just discard the response, inform TU. */ 
    248                 pjsip_event e; 
    249  
    250                 PJSIP_EVENT_INIT_DISCARD_MSG(e, rdata,  
    251                     PJSIP_ERRNO_FROM_SIP_STATUS(PJSIP_SC_CALL_TSX_DOES_NOT_EXIST)); 
    252                 endpt_do_event( endpt, &e ); 
    253             } 
    254  
    255         /* 
    256          * For non-ACK request message, create a new transaction. 
    257          */ 
    258         } else if (rdata->msg_info.msg->line.req.method.id != PJSIP_ACK_METHOD) { 
    259  
    260             pj_status_t status; 
    261  
    262             /* Create transaction, mutex is locked there. */ 
    263             status = pjsip_endpt_create_tsx(endpt, &tsx); 
    264             if (status != PJ_SUCCESS) { 
    265                 PJSIP_ENDPT_LOG_ERROR((endpt, THIS_FILE, status, 
    266                                        "Unable to create transaction")); 
    267                 return; 
    268             } 
    269  
    270             /* Initialize transaction as UAS. */ 
    271             pjsip_tsx_init_uas( tsx, rdata ); 
    272  
    273             /* Register transaction, mutex is locked there. */ 
    274             pjsip_endpt_register_tsx( endpt, tsx ); 
    275  
    276             a_new_transaction_just_been_created = PJ_TRUE; 
    277         } 
    278     } 
    279  
    280     /* If transaction is found (or newly created), pass the message. 
    281      * Otherwise if it's an ACK request, pass directly to TU. 
    282      */ 
    283     if (tsx && tsx->state != PJSIP_TSX_STATE_TERMINATED) { 
    284         /* Dispatch message to transaction. */ 
    285         pjsip_tsx_on_rx_msg( tsx, rdata ); 
    286  
    287     } else if (rdata->msg_info.msg->line.req.method.id == PJSIP_ACK_METHOD) { 
    288         /* 
    289          * This is an ACK message, but the INVITE transaction could not 
    290          * be found (possibly because the branch parameter in Via in ACK msg 
    291          * is different than the branch in original INVITE). This happens with 
    292          * SER! 
    293          */ 
    294         pjsip_event event; 
    295  
    296         PJSIP_EVENT_INIT_RX_ACK_MSG(event,rdata); 
    297         endpt_do_event( endpt, &event ); 
    298     } 
    299  
    300     /* 
    301      * If a new request message has just been receieved, but no modules 
    302      * seem to be able to handle the request message, then terminate the 
    303      * transaction. 
    304      * 
    305      * Ideally for cases like "unsupported method", we should be able to 
    306      * answer the request statelessly. But we can not do that since the 
    307      * endpoint shoule be able to be used as both user agent and proxy stack, 
    308      * and a proxy stack should be able to handle arbitrary methods. 
    309      */ 
    310     if (a_new_transaction_just_been_created && tsx->status_code < 100) { 
    311         /* Certainly no modules has sent any response message. 
    312          * Check that any modules has attached a module data. 
    313          */ 
    314         int i; 
    315         for (i=0; i<PJSIP_MAX_MODULE; ++i) { 
    316             if (tsx->module_data[i] != NULL) { 
    317                 break; 
    318             } 
    319         } 
    320         if (i == PJSIP_MAX_MODULE) { 
    321             /* No modules have attached itself to the transaction.  
    322              * Terminate the transaction with 501/Not Implemented. 
    323              */ 
    324             pjsip_tx_data *tdata; 
    325             pj_status_t status; 
    326              
    327             if (tsx->method.id == PJSIP_OPTIONS_METHOD) { 
    328                 status = pjsip_endpt_create_response(endpt, rdata, 200,  
    329                                                      &tdata); 
    330             } else { 
    331                 status = pjsip_endpt_create_response(endpt, rdata,  
    332                                                      PJSIP_SC_METHOD_NOT_ALLOWED, 
    333                                                      &tdata); 
    334             } 
    335  
    336             if (status != PJ_SUCCESS) { 
    337                 PJSIP_ENDPT_LOG_ERROR((endpt, THIS_FILE, status, 
    338                                        "Unable to create response")); 
    339                 return; 
    340             } 
    341  
    342             if (endpt->allow_hdr) { 
    343                 pjsip_msg_add_hdr( tdata->msg,  
    344                                    pjsip_hdr_shallow_clone(tdata->pool, endpt->allow_hdr)); 
    345             } 
    346             pjsip_tsx_on_tx_msg( tsx, tdata ); 
    347  
    348         } else { 
    349             /* 
    350              * If a module has registered itself in the transaction but it 
    351              * hasn't responded the request, chances are the module wouldn't 
    352              * respond to the request at all. We terminate the request here 
    353              * with 500/Internal Server Error, to be safe. 
    354              */ 
    355             pjsip_tx_data *tdata; 
    356             pj_status_t status; 
    357  
    358             status = pjsip_endpt_create_response(endpt, rdata, 500, &tdata); 
    359             if (status != PJ_SUCCESS) { 
    360                 PJSIP_ENDPT_LOG_ERROR((endpt, THIS_FILE, status, 
    361                                        "Unable to create response")); 
    362                 return; 
    363             } 
    364  
    365             pjsip_tsx_on_tx_msg(tsx, tdata); 
    366         } 
    367     } 
    368 } 
    369  
    370  
    371  
    372     /* Transaction tables. */ 
    373     count = pj_hash_count(endpt->tsx_table); 
    374     PJ_LOG(3, (THIS_FILE, " Number of transactions: %u", count)); 
    375  
    376     if (count && detail) { 
    377         pj_hash_iterator_t it_val; 
    378         pj_hash_iterator_t *it; 
    379         pj_time_val now; 
    380  
    381         PJ_LOG(3, (THIS_FILE, " Dumping transaction tables:")); 
    382  
    383         pj_gettimeofday(&now); 
    384         it = pj_hash_first(endpt->tsx_table, &it_val); 
    385  
    386         while (it != NULL) { 
    387             int timeout_diff; 
    388  
    389             /* Get the transaction. No need to lock transaction's mutex 
    390              * since we already hold endpoint mutex, so that no transactions 
    391              * will be deleted. 
    392              */ 
    393             pjsip_transaction *tsx = pj_hash_this(endpt->tsx_table, it); 
    394  
    395             const char *role = (tsx->role == PJSIP_ROLE_UAS ? "UAS" : "UAC"); 
    396          
    397             if (tsx->timeout_timer._timer_id != -1) { 
    398                 if (tsx->timeout_timer._timer_value.sec > now.sec) { 
    399                     timeout_diff = tsx->timeout_timer._timer_value.sec - now.sec; 
    400                 } else { 
    401                     timeout_diff = now.sec - tsx->timeout_timer._timer_value.sec; 
    402                     timeout_diff = 0 - timeout_diff; 
    403                 } 
    404             } else { 
    405                 timeout_diff = -1; 
    406             } 
    407  
    408             PJ_LOG(3, (THIS_FILE, "  %s %s %10.*s %.9u %s t=%ds",  
    409                        tsx->obj_name, role,  
    410                        tsx->method.name.slen, tsx->method.name.ptr, 
    411                        tsx->cseq, 
    412                        pjsip_tsx_state_str(tsx->state), 
    413                        timeout_diff)); 
    414  
    415             it = pj_hash_next(endpt->tsx_table, it); 
    416         } 
    417     } 
    418  
    419  
    420  
    421 #endif  // XXX JUNK 
    422  
    423 /* Thread Local Storage ID for transaction lock (initialized by endpoint) */ 
    424 long pjsip_tsx_lock_tls_id; 
    425  
    426 /* State names */ 
     32 
     33/***************************************************************************** 
     34 ** 
     35 ** Declarations and static variable definitions section. 
     36 ** 
     37 ***************************************************************************** 
     38 
     39/* Prototypes. */ 
     40static pj_status_t mod_tsx_layer_load(pjsip_endpoint *endpt); 
     41static pj_status_t mod_tsx_layer_start(void); 
     42static pj_status_t mod_tsx_layer_stop(void); 
     43static pj_status_t mod_tsx_layer_unload(void); 
     44static pj_bool_t   mod_tsx_layer_on_rx_request(pjsip_rx_data *rdata); 
     45static pj_bool_t   mod_tsx_layer_on_rx_response(pjsip_rx_data *rdata); 
     46 
     47/* Transaction layer module definition. */ 
     48static struct mod_tsx_layer 
     49{ 
     50    struct pjsip_module  mod; 
     51    pj_pool_t           *pool; 
     52    pjsip_endpoint      *endpt; 
     53    pj_mutex_t          *mutex; 
     54    pj_hash_table_t     *htable; 
     55} mod_tsx_layer =  
     56{   { 
     57        NULL, NULL,                     /* List's prev and next.    */ 
     58        { "mod-tsx-layer", 13 },        /* Module name.             */ 
     59        -1,                             /* Module ID                */ 
     60        PJSIP_MOD_PRIORITY_TSX_LAYER,   /* Priority.                */ 
     61        NULL,                           /* User_data.               */ 
     62        0,                              /* Methods count.           */ 
     63        { NULL },                       /* Array of methods.        */ 
     64        mod_tsx_layer_load,             /* load().                  */ 
     65        mod_tsx_layer_start,            /* start()                  */ 
     66        mod_tsx_layer_stop,             /* stop()                   */ 
     67        mod_tsx_layer_unload,           /* unload()                 */ 
     68        mod_tsx_layer_on_rx_request,    /* on_rx_request()          */ 
     69        mod_tsx_layer_on_rx_response,   /* on_rx_response()         */ 
     70        NULL 
     71    } 
     72}; 
     73 
     74/* Thread Local Storage ID for transaction lock */ 
     75static long pjsip_tsx_lock_tls_id; 
     76 
     77/* Transaction state names */ 
    42778static const char *state_str[] =  
    42879{ 
     
    44091static const char *role_name[] =  
    44192{ 
    442     "Client", 
    443     "Server" 
     93    "UAC", 
     94    "UAS" 
     95}; 
     96 
     97/* Transport flag. */ 
     98enum 
     99{ 
     100    TSX_HAS_PENDING_TRANSPORT   = 1, 
     101    TSX_HAS_PENDING_RESCHED     = 2, 
     102    TSX_HAS_PENDING_SEND        = 4, 
     103    TSX_HAS_PENDING_DESTROY     = 8, 
    444104}; 
    445105 
     
    469129}; 
    470130 
    471 /* Function Prototypes */ 
    472 static pj_status_t pjsip_tsx_on_state_null(     pjsip_transaction *tsx,  
     131 
     132/* Prototypes. */ 
     133static void        lock_tsx(pjsip_transaction *tsx, struct tsx_lock_data *lck); 
     134static pj_status_t unlock_tsx( pjsip_transaction *tsx,  
     135                               struct tsx_lock_data *lck); 
     136static pj_status_t tsx_on_state_null(           pjsip_transaction *tsx,  
    473137                                                pjsip_event *event); 
    474 static pj_status_t pjsip_tsx_on_state_calling(  pjsip_transaction *tsx,  
     138static pj_status_t tsx_on_state_calling(        pjsip_transaction *tsx,  
    475139                                                pjsip_event *event); 
    476 static pj_status_t pjsip_tsx_on_state_trying(   pjsip_transaction *tsx,  
     140static pj_status_t tsx_on_state_trying(         pjsip_transaction *tsx,  
    477141                                                pjsip_event *event); 
    478 static pj_status_t pjsip_tsx_on_state_proceeding_uas( pjsip_transaction *tsx,  
     142static pj_status_t tsx_on_state_proceeding_uas( pjsip_transaction *tsx,  
    479143                                                pjsip_event *event); 
    480 static pj_status_t pjsip_tsx_on_state_proceeding_uac( pjsip_transaction *tsx, 
     144static pj_status_t tsx_on_state_proceeding_uac( pjsip_transaction *tsx, 
    481145                                                pjsip_event *event); 
    482 static pj_status_t pjsip_tsx_on_state_completed_uas( pjsip_transaction *tsx,  
     146static pj_status_t tsx_on_state_completed_uas(  pjsip_transaction *tsx,  
    483147                                                pjsip_event *event); 
    484 static pj_status_t pjsip_tsx_on_state_completed_uac( pjsip_transaction *tsx, 
     148static pj_status_t tsx_on_state_completed_uac(  pjsip_transaction *tsx, 
    485149                                                pjsip_event *event); 
    486 static pj_status_t pjsip_tsx_on_state_confirmed(pjsip_transaction *tsx,  
     150static pj_status_t tsx_on_state_confirmed(      pjsip_transaction *tsx,  
    487151                                                pjsip_event *event); 
    488 static pj_status_t pjsip_tsx_on_state_terminated(pjsip_transaction *tsx,  
     152static pj_status_t tsx_on_state_terminated(     pjsip_transaction *tsx,  
    489153                                                pjsip_event *event); 
    490 static pj_status_t pjsip_tsx_on_state_destroyed(pjsip_transaction *tsx,  
     154static pj_status_t tsx_on_state_destroyed(      pjsip_transaction *tsx,  
    491155                                                pjsip_event *event); 
    492  
    493 static void         tsx_timer_callback( pj_timer_heap_t *theap,  
    494                                         pj_timer_entry *entry); 
    495 static int          tsx_send_msg( pjsip_transaction *tsx,  
    496                                   pjsip_tx_data *tdata); 
    497 static void         lock_tsx( pjsip_transaction *tsx, struct  
    498                                tsx_lock_data *lck ); 
    499 static pj_status_t  unlock_tsx( pjsip_transaction *tsx,  
    500                                struct tsx_lock_data *lck ); 
     156static void        tsx_timer_callback( pj_timer_heap_t *theap,  
     157                                       pj_timer_entry *entry); 
     158static pj_status_t tsx_create( pjsip_module *tsx_user, 
     159                               pjsip_transaction **p_tsx); 
     160static void        tsx_destroy( pjsip_transaction *tsx ); 
     161static void        tsx_resched_retransmission( pjsip_transaction *tsx ); 
     162static pj_status_t tsx_retransmit( pjsip_transaction *tsx, int resched); 
     163static int         tsx_send_msg( pjsip_transaction *tsx,  
     164                                 pjsip_tx_data *tdata); 
     165static void        tsx_on_rx_msg( pjsip_transaction *tsx, 
     166                                  pjsip_rx_data *rdata ); 
     167 
    501168 
    502169/* State handlers for UAC, indexed by state */ 
     
    504171                                                          pjsip_event *) =  
    505172{ 
    506     &pjsip_tsx_on_state_null, 
    507     &pjsip_tsx_on_state_calling, 
    508     &pjsip_tsx_on_state_trying, 
    509     &pjsip_tsx_on_state_proceeding_uac, 
    510     &pjsip_tsx_on_state_completed_uac, 
    511     &pjsip_tsx_on_state_confirmed, 
    512     &pjsip_tsx_on_state_terminated, 
    513     &pjsip_tsx_on_state_destroyed, 
     173    &tsx_on_state_null, 
     174    &tsx_on_state_calling, 
     175    NULL, 
     176    &tsx_on_state_proceeding_uac, 
     177    &tsx_on_state_completed_uac, 
     178    &tsx_on_state_confirmed, 
     179    &tsx_on_state_terminated, 
     180    &tsx_on_state_destroyed, 
    514181}; 
    515182 
     
    518185                                                          pjsip_event *) =  
    519186{ 
    520     &pjsip_tsx_on_state_null, 
    521     &pjsip_tsx_on_state_calling, 
    522     &pjsip_tsx_on_state_trying, 
    523     &pjsip_tsx_on_state_proceeding_uas, 
    524     &pjsip_tsx_on_state_completed_uas, 
    525     &pjsip_tsx_on_state_confirmed, 
    526     &pjsip_tsx_on_state_terminated, 
    527     &pjsip_tsx_on_state_destroyed, 
     187    &tsx_on_state_null, 
     188    NULL, 
     189    &tsx_on_state_trying, 
     190    &tsx_on_state_proceeding_uas, 
     191    &tsx_on_state_completed_uas, 
     192    &tsx_on_state_confirmed, 
     193    &tsx_on_state_terminated, 
     194    &tsx_on_state_destroyed, 
    528195}; 
    529196 
     197/***************************************************************************** 
     198 ** 
     199 ** Utilities 
     200 ** 
     201 ***************************************************************************** 
     202 */ 
    530203/* 
    531204 * Get transaction state name. 
     
    543216    return role_name[role]; 
    544217} 
    545  
    546  
    547  
    548 /* 
    549  * Unregister the transaction from the hash table, and destroy the resources 
    550  * from the transaction. 
    551  */ 
    552 PJ_DEF(void) pjsip_endpt_destroy_tsx( pjsip_endpoint *endpt, 
    553                                       pjsip_transaction *tsx) 
    554 { 
    555     PJ_LOG(5, (THIS_FILE, "pjsip_endpt_destroy_tsx(%s)", tsx->obj_name)); 
    556  
    557     pj_assert(tsx->state == PJSIP_TSX_STATE_DESTROYED); 
    558  
    559     /* No need to lock transaction.  
    560      * This function typically is called from the transaction callback, which 
    561      * means that transaction mutex is being held. 
    562      */ 
    563     pj_assert( pj_mutex_is_locked(tsx->mutex) ); 
    564  
    565     /* Lock endpoint. */ 
    566     pj_mutex_lock( endpt->tsx_table_mutex ); 
    567  
    568     /* Unregister from the hash table. */ 
    569     pj_hash_set( NULL, endpt->tsx_table, tsx->transaction_key.ptr,  
    570                  tsx->transaction_key.slen, NULL); 
    571  
    572     /* Unlock endpoint mutex. */ 
    573     pj_mutex_unlock( endpt->tsx_table_mutex ); 
    574  
    575     /* Destroy transaction mutex. */ 
    576     pj_mutex_destroy( tsx->mutex ); 
    577  
    578     /* Release the pool for the transaction. */ 
    579     pj_pool_release(tsx->pool); 
    580  
    581     PJ_LOG(4, (THIS_FILE, "tsx%p destroyed", tsx)); 
    582 } 
    583  
    584218 
    585219 
     
    644278    *p++ = SEPARATOR; 
    645279 
    646     /* Add Request-URI */ 
    647     /* This is BUG! 
    648      * Response doesn't have Request-URI! 
    649      * 
    650     len = req_uri->vptr->print( PJSIP_URI_IN_REQ_URI, req_uri, p, end-p ); 
    651     p += len; 
    652     *p++ = SEPARATOR; 
    653      */ 
    654  
    655280    /* Add method, except when method is INVITE or ACK. */ 
    656281    if (method->id != PJSIP_INVITE_METHOD && method->id != PJSIP_ACK_METHOD) { 
     
    771396} 
    772397 
    773  
    774 /* 
    775  * Create new transaction. 
    776  */ 
    777 PJ_DEF(pj_status_t) pjsip_tsx_create( pj_pool_t *pool, 
    778                                       pjsip_endpoint *endpt, 
    779                                       pjsip_transaction **p_tsx) 
    780 { 
     398/***************************************************************************** 
     399 ** 
     400 ** Transaction layer module 
     401 ** 
     402 ***************************************************************************** 
     403 
     404/* 
     405 * Create transaction layer module and registers it to the endpoint. 
     406 */ 
     407PJ_DEF(pj_status_t) pjsip_tsx_layer_init(pjsip_endpoint *endpt) 
     408{ 
     409    pj_pool_t *pool; 
     410    pj_status_t status; 
     411 
     412 
     413    PJ_ASSERT_RETURN(mod_tsx_layer.endpt==NULL, PJ_EINVALIDOP); 
     414 
     415 
     416    /* Initialize TLS ID for transaction lock. */ 
     417    status = pj_thread_local_alloc(&pjsip_tsx_lock_tls_id); 
     418    if (status != PJ_SUCCESS) 
     419        return status; 
     420 
     421    pj_thread_local_set(pjsip_tsx_lock_tls_id, NULL); 
     422 
     423    /* 
     424     * Initialize transaction layer structure. 
     425     */ 
     426 
     427    /* Create pool for the module. */ 
     428    pool = pjsip_endpt_create_pool(endpt, "tsxlayer",  
     429                                   PJSIP_POOL_TSX_LAYER_LEN, 
     430                                   PJSIP_POOL_TSX_LAYER_INC ); 
     431    if (!pool) 
     432        return PJ_ENOMEM; 
     433 
     434     
     435    /* Initialize some attributes. */ 
     436    mod_tsx_layer.pool = pool; 
     437    mod_tsx_layer.endpt = endpt; 
     438 
     439 
     440    /* Create hash table. */ 
     441    mod_tsx_layer.htable = pj_hash_create( pool, PJSIP_MAX_TSX_COUNT ); 
     442    if (!mod_tsx_layer.htable) { 
     443        pjsip_endpt_release_pool(endpt, pool); 
     444        return PJ_ENOMEM; 
     445    } 
     446 
     447    /* Create mutex. */ 
     448    status = pj_mutex_create_recursive(pool, "tsxlayer", &mod_tsx_layer.mutex); 
     449    if (status != PJ_SUCCESS) { 
     450        pjsip_endpt_release_pool(endpt, pool); 
     451        return status; 
     452    } 
     453 
     454    /* 
     455     * Register transaction layer module to endpoint. 
     456     */ 
     457    status = pjsip_endpt_register_module( endpt, &mod_tsx_layer.mod ); 
     458    if (status != PJ_SUCCESS) { 
     459        pj_mutex_destroy(mod_tsx_layer.mutex); 
     460        pjsip_endpt_release_pool(endpt, pool); 
     461        return status; 
     462    } 
     463 
     464    return PJ_SUCCESS; 
     465} 
     466 
     467 
     468/* 
     469 * Get the instance of transaction layer module. 
     470 */ 
     471PJ_DEF(pjsip_module*) pjsip_tsx_layer_instance(void) 
     472{ 
     473    return &mod_tsx_layer.mod; 
     474} 
     475 
     476 
     477/* 
     478 * Unregister and destroy transaction layer module. 
     479 */ 
     480PJ_DEF(pj_status_t) pjsip_tsx_layer_destroy(void) 
     481{ 
     482    /* Are we registered? */ 
     483    PJ_ASSERT_RETURN(mod_tsx_layer.endpt!=NULL, PJ_EINVALIDOP); 
     484 
     485    /* Unregister from endpoint.  
     486     * Clean-ups will be done in the unload() module callback. 
     487     */ 
     488    return pjsip_endpt_unregister_module( mod_tsx_layer.endpt,  
     489                                          &mod_tsx_layer.mod); 
     490} 
     491 
     492 
     493/* 
     494 * Register the transaction to the hash table. 
     495 */ 
     496static void mod_tsx_layer_register_tsx( pjsip_transaction *tsx) 
     497{ 
     498    pj_assert(tsx->transaction_key.slen != 0); 
     499    //pj_assert(tsx->state != PJSIP_TSX_STATE_NULL); 
     500 
     501    /* Lock hash table mutex. */ 
     502    pj_mutex_lock(mod_tsx_layer.mutex); 
     503 
     504    /* Register the transaction to the hash table. */ 
     505    pj_hash_set( tsx->pool, mod_tsx_layer.htable, tsx->transaction_key.ptr, 
     506                 tsx->transaction_key.slen, tsx); 
     507 
     508    /* Unlock mutex. */ 
     509    pj_mutex_unlock(mod_tsx_layer.mutex); 
     510} 
     511 
     512 
     513/* 
     514 * Unregister the transaction from the hash table. 
     515 */ 
     516static void mod_tsx_layer_unregister_tsx( pjsip_transaction *tsx) 
     517{ 
     518    pj_assert(tsx->transaction_key.slen != 0); 
     519    //pj_assert(tsx->state != PJSIP_TSX_STATE_NULL); 
     520 
     521    /* Lock hash table mutex. */ 
     522    pj_mutex_lock(mod_tsx_layer.mutex); 
     523 
     524    /* Register the transaction to the hash table. */ 
     525    pj_hash_set( NULL, mod_tsx_layer.htable, tsx->transaction_key.ptr, 
     526                 tsx->transaction_key.slen, NULL); 
     527 
     528    /* Unlock mutex. */ 
     529    pj_mutex_unlock(mod_tsx_layer.mutex); 
     530} 
     531 
     532 
     533/* 
     534 * Find a transaction. 
     535 */ 
     536PJ_DEF(pjsip_transaction*) pjsip_tsx_layer_find_tsx( const pj_str_t *key, 
     537                                                     pj_bool_t lock ) 
     538{ 
     539    pjsip_transaction *tsx; 
     540 
     541    pj_mutex_lock(mod_tsx_layer.mutex); 
     542    tsx = pj_hash_get( mod_tsx_layer.htable, key->ptr, key->slen ); 
     543    pj_mutex_unlock(mod_tsx_layer.mutex); 
     544 
     545 
     546    /* Race condition! 
     547     * Transaction may gets deleted before we have chance to lock it. 
     548     */ 
     549    PJ_TODO(FIX_RACE_CONDITION_HERE); 
     550    if (tsx && lock) 
     551        pj_mutex_lock(tsx->mutex); 
     552 
     553    return tsx; 
     554} 
     555 
     556 
     557/* This module callback is called when module is being loaded by 
     558 * endpoint. It does nothing for this module. 
     559 */ 
     560static pj_status_t mod_tsx_layer_load(pjsip_endpoint *endpt) 
     561{ 
     562    PJ_UNUSED_ARG(endpt); 
     563    return PJ_SUCCESS; 
     564} 
     565 
     566 
     567/* This module callback is called when module is being started by 
     568 * endpoint. It does nothing for this module. 
     569 */ 
     570static pj_status_t mod_tsx_layer_start(void) 
     571{ 
     572    return PJ_SUCCESS; 
     573} 
     574 
     575 
     576/* This module callback is called when module is being stopped by 
     577 * endpoint.  
     578 */ 
     579static pj_status_t mod_tsx_layer_stop(void) 
     580{ 
     581    pj_hash_iterator_t it_buf, *it; 
     582 
     583    pj_mutex_lock(mod_tsx_layer.mutex); 
     584 
     585    /* Destroy all transactions. */ 
     586    it = pj_hash_first(mod_tsx_layer.htable, &it_buf); 
     587    while (it) { 
     588        pjsip_transaction *tsx = pj_hash_this(mod_tsx_layer.htable, it); 
     589        if (tsx) 
     590            tsx_destroy(tsx); 
     591        it = pj_hash_next(mod_tsx_layer.htable, it); 
     592    } 
     593 
     594    pj_mutex_unlock(mod_tsx_layer.mutex); 
     595    return PJ_SUCCESS; 
     596} 
     597 
     598 
     599/* This module callback is called when module is being unloaded by 
     600 * endpoint. 
     601 */ 
     602static pj_status_t mod_tsx_layer_unload(void) 
     603{ 
     604    /* Destroy mutex. */ 
     605    pj_mutex_destroy(mod_tsx_layer.mutex); 
     606 
     607    /* Release pool. */ 
     608    pjsip_endpt_release_pool(mod_tsx_layer.endpt, mod_tsx_layer.pool); 
     609 
     610    /* Mark as unregistered. */ 
     611    mod_tsx_layer.endpt = NULL; 
     612 
     613    return PJ_SUCCESS; 
     614} 
     615 
     616 
     617/* This module callback is called when endpoint has received an 
     618 * incoming request message. 
     619 */ 
     620static pj_bool_t mod_tsx_layer_on_rx_request(pjsip_rx_data *rdata) 
     621{ 
     622    pj_str_t key; 
     623    pjsip_transaction *tsx; 
     624 
     625    pjsip_tsx_create_key(rdata->tp_info.pool, &key, PJSIP_ROLE_UAS, 
     626                         &rdata->msg_info.cseq->method, rdata); 
     627 
     628    /* Find transaction. */ 
     629    pj_mutex_lock( mod_tsx_layer.mutex ); 
     630    tsx = pj_hash_get( mod_tsx_layer.htable, key.ptr, key.slen ); 
     631    if (tsx == NULL || tsx->state == PJSIP_TSX_STATE_TERMINATED) { 
     632        /* Transaction not found. 
     633         * Reject the request so that endpoint passes the request to 
     634         * upper layer modules. 
     635         */ 
     636        pj_mutex_unlock( mod_tsx_layer.mutex); 
     637        return PJ_FALSE; 
     638    } 
     639 
     640    /* Unlock hash table. */ 
     641    pj_mutex_unlock( mod_tsx_layer.mutex ); 
     642 
     643    /* Race condition! 
     644     * Transaction may gets deleted before we have chance to lock it 
     645     * in tsx_on_rx_msg(). 
     646     */ 
     647    PJ_TODO(FIX_RACE_CONDITION_HERE); 
     648 
     649    /* Pass the message to the transaction. */ 
     650    tsx_on_rx_msg(tsx, rdata ); 
     651 
     652    return PJ_TRUE; 
     653} 
     654 
     655 
     656/* This module callback is called when endpoint has received an 
     657 * incoming response message. 
     658 */ 
     659static pj_bool_t mod_tsx_layer_on_rx_response(pjsip_rx_data *rdata) 
     660{ 
     661    pj_str_t key; 
     662    pjsip_transaction *tsx; 
     663 
     664    pjsip_tsx_create_key(rdata->tp_info.pool, &key, PJSIP_ROLE_UAC, 
     665                         &rdata->msg_info.cseq->method, rdata); 
     666 
     667    /* Find transaction. */ 
     668    pj_mutex_lock( mod_tsx_layer.mutex ); 
     669    tsx = pj_hash_get( mod_tsx_layer.htable, key.ptr, key.slen ); 
     670    if (tsx == NULL || tsx->state == PJSIP_TSX_STATE_TERMINATED) { 
     671        /* Transaction not found. 
     672         * Reject the request so that endpoint passes the request to 
     673         * upper layer modules. 
     674         */ 
     675        pj_mutex_unlock( mod_tsx_layer.mutex); 
     676        return PJ_FALSE; 
     677    } 
     678 
     679    /* Unlock hash table. */ 
     680    pj_mutex_unlock( mod_tsx_layer.mutex ); 
     681 
     682    /* Race condition! 
     683     * Transaction may gets deleted before we have chance to lock it 
     684     * in tsx_on_rx_msg(). 
     685     */ 
     686    PJ_TODO(FIX_RACE_CONDITION_HERE); 
     687 
     688    /* Pass the message to the transaction. */ 
     689    tsx_on_rx_msg(tsx, rdata ); 
     690 
     691    return PJ_TRUE; 
     692} 
     693 
     694 
     695/* 
     696 * Get transaction instance in the rdata. 
     697 */ 
     698PJ_DEF(pjsip_transaction*) pjsip_rdata_get_tsx( pjsip_rx_data *rdata ) 
     699{ 
     700    return rdata->endpt_info.mod_data[mod_tsx_layer.mod.id]; 
     701} 
     702 
     703 
     704/***************************************************************************** 
     705 ** 
     706 ** Transaction 
     707 ** 
     708 ***************************************************************************** 
     709 
     710/* 
     711 * Lock transaction and set the value of Thread Local Storage. 
     712 */ 
     713static void lock_tsx(pjsip_transaction *tsx, struct tsx_lock_data *lck) 
     714{ 
     715    struct tsx_lock_data *prev_data; 
     716 
     717    pj_mutex_lock(tsx->mutex); 
     718    prev_data = (struct tsx_lock_data *)  
     719                    pj_thread_local_get(pjsip_tsx_lock_tls_id); 
     720    lck->prev = prev_data; 
     721    lck->tsx = tsx; 
     722    lck->is_alive = 1; 
     723    pj_thread_local_set(pjsip_tsx_lock_tls_id, lck); 
     724} 
     725 
     726 
     727/* 
     728 * Unlock transaction. 
     729 * This will selectively unlock the mutex ONLY IF the transaction has not been  
     730 * destroyed. The function knows whether the transaction has been destroyed 
     731 * because when transaction is destroyed the is_alive flag for the transaction 
     732 * will be set to zero. 
     733 */ 
     734static pj_status_t unlock_tsx( pjsip_transaction *tsx,  
     735                               struct tsx_lock_data *lck) 
     736{ 
     737    pj_assert( (void*)pj_thread_local_get(pjsip_tsx_lock_tls_id) == lck); 
     738    pj_assert( lck->tsx == tsx ); 
     739    pj_thread_local_set(pjsip_tsx_lock_tls_id, lck->prev); 
     740    if (lck->is_alive) 
     741        pj_mutex_unlock(tsx->mutex); 
     742 
     743    return lck->is_alive ? PJ_SUCCESS : PJSIP_ETSXDESTROYED; 
     744} 
     745 
     746 
     747/* Create and initialize basic transaction structure. 
     748 * This function is called by both UAC and UAS creation. 
     749 */ 
     750static pj_status_t tsx_create( pjsip_module *tsx_user, 
     751                               pjsip_transaction **p_tsx) 
     752{ 
     753    pj_pool_t *pool; 
    781754    pjsip_transaction *tsx; 
    782755    pj_status_t status; 
    783756 
    784     tsx = pj_pool_calloc(pool, 1, sizeof(pjsip_transaction)); 
    785  
     757    pool = pjsip_endpt_create_pool( mod_tsx_layer.endpt, "tsx",  
     758                                    PJSIP_POOL_TSX_LEN, PJSIP_POOL_TSX_INC ); 
     759    if (!pool) 
     760        return PJ_ENOMEM; 
     761 
     762    tsx = pj_pool_zalloc(pool, sizeof(pjsip_transaction)); 
    786763    tsx->pool = pool; 
    787     tsx->endpt = endpt; 
     764    tsx->tsx_user = tsx_user; 
     765    tsx->endpt = mod_tsx_layer.endpt; 
     766 
     767    pj_sprintf(tsx->obj_name, "tsx%p", tsx); 
     768 
     769    tsx->handle_200resp = 1; 
    788770    tsx->retransmit_timer.id = TSX_TIMER_RETRANSMISSION; 
    789771    tsx->retransmit_timer._timer_id = -1; 
     
    794776    tsx->timeout_timer.user_data = tsx; 
    795777    tsx->timeout_timer.cb = &tsx_timer_callback; 
    796     pj_sprintf(tsx->obj_name, "tsx%p", tsx); 
    797     status = pj_mutex_create_recursive(pool, "mtsx%p", &tsx->mutex); 
     778     
     779    status = pj_mutex_create_recursive(pool, "tsx%p", &tsx->mutex); 
    798780    if (status != PJ_SUCCESS) { 
     781        pjsip_endpt_release_pool(mod_tsx_layer.endpt, pool); 
    799782        return status; 
    800783    } 
     
    804787} 
    805788 
    806 /* 
    807  * Lock transaction and set the value of Thread Local Storage. 
    808  */ 
    809 static void lock_tsx(pjsip_transaction *tsx, struct tsx_lock_data *lck) 
    810 { 
    811     struct tsx_lock_data *prev_data; 
    812  
    813     pj_mutex_lock(tsx->mutex); 
    814     prev_data = (struct tsx_lock_data *)  
    815                     pj_thread_local_get(pjsip_tsx_lock_tls_id); 
    816     lck->prev = prev_data; 
    817     lck->tsx = tsx; 
    818     lck->is_alive = 1; 
    819     pj_thread_local_set(pjsip_tsx_lock_tls_id, lck); 
    820 } 
    821  
    822  
    823 /* 
    824  * Unlock transaction. 
    825  * This will selectively unlock the mutex ONLY IF the transaction has not been  
    826  * destroyed. The function knows whether the transaction has been destroyed 
    827  * because when transaction is destroyed the is_alive flag for the transaction 
    828  * will be set to zero. 
    829  */ 
    830 static pj_status_t unlock_tsx( pjsip_transaction *tsx,  
    831                                struct tsx_lock_data *lck) 
    832 { 
    833     pj_assert( (void*)pj_thread_local_get(pjsip_tsx_lock_tls_id) == lck); 
    834     pj_assert( lck->tsx == tsx ); 
    835     pj_thread_local_set(pjsip_tsx_lock_tls_id, lck->prev); 
    836     if (lck->is_alive) 
    837         pj_mutex_unlock(tsx->mutex); 
    838  
    839     return lck->is_alive ? PJ_SUCCESS : PJSIP_ETSXDESTROYED; 
    840 } 
     789 
     790/* Destroy transaction. */ 
     791static void tsx_destroy( pjsip_transaction *tsx ) 
     792{ 
     793    pj_mutex_destroy(tsx->mutex); 
     794    pjsip_endpt_release_pool(tsx->endpt, tsx->pool); 
     795} 
     796 
     797 
     798/* 
     799 * Callback when timer expires. 
     800 */ 
     801static void tsx_timer_callback( pj_timer_heap_t *theap, pj_timer_entry *entry) 
     802{ 
     803    pjsip_event event; 
     804    pjsip_transaction *tsx = entry->user_data; 
     805    struct tsx_lock_data lck; 
     806 
     807    PJ_UNUSED_ARG(theap); 
     808 
     809    PJ_LOG(5,(tsx->obj_name, "got timer event (%s timer)",  
     810             (entry->id==TSX_TIMER_RETRANSMISSION ? "Retransmit":"Timeout"))); 
     811 
     812 
     813    if (entry->id == TSX_TIMER_RETRANSMISSION) { 
     814        PJSIP_EVENT_INIT_TIMER(event, &tsx->retransmit_timer); 
     815    } else { 
     816        PJSIP_EVENT_INIT_TIMER(event, &tsx->timeout_timer); 
     817    } 
     818 
     819    /* Dispatch event to transaction. */ 
     820    lock_tsx(tsx, &lck); 
     821    (*tsx->state_handler)(tsx, &event); 
     822    unlock_tsx(tsx, &lck); 
     823} 
     824 
    841825 
    842826/* 
     
    848832                           void *event_src ) 
    849833{ 
    850     pjsip_event e; 
    851  
    852834    PJ_LOG(4, (tsx->obj_name, "STATE %s-->%s, cause = %s", 
    853835               state_str[tsx->state], state_str[state],  
     
    865847 
    866848    /* Inform TU */ 
    867     PJSIP_EVENT_INIT_TSX_STATE(e, tsx, event_src_type, event_src); 
    868     pjsip_endpt_send_tsx_event( tsx->endpt, &e  ); 
     849    if (tsx->tsx_user && tsx->tsx_user->on_tsx_state) { 
     850        pjsip_event e; 
     851        PJSIP_EVENT_INIT_TSX_STATE(e, tsx, event_src_type, event_src); 
     852        (*tsx->tsx_user->on_tsx_state)(tsx, &e); 
     853    } 
     854     
    869855 
    870856    /* When the transaction is terminated, release transport, and free the 
     
    872858     */ 
    873859    if (state == PJSIP_TSX_STATE_TERMINATED) { 
     860        pj_time_val timeout = {0, 0}; 
    874861 
    875862        /* Decrement transport reference counter. */ 
    876         if (tsx->transport &&  
    877             tsx->transport_state == PJSIP_TSX_TRANSPORT_STATE_FINAL)  
    878         { 
     863        if (tsx->transport) { 
    879864            pjsip_transport_dec_ref( tsx->transport ); 
    880865            tsx->transport = NULL; 
     
    896881        } 
    897882 
    898         /* If transport is not pending, reschedule timeout timer to 
    899          * destroy this transaction. 
    900          */ 
    901         if (tsx->transport_state == PJSIP_TSX_TRANSPORT_STATE_FINAL) { 
    902             pj_time_val timeout = {0, 0}; 
     883        /* Reschedule timeout timer to destroy this transaction. */ 
     884        if (tsx->transport_flag & TSX_HAS_PENDING_TRANSPORT) { 
     885            tsx->transport_flag |= TSX_HAS_PENDING_DESTROY; 
     886        } else { 
    903887            pjsip_endpt_schedule_timer( tsx->endpt, &tsx->timeout_timer,  
    904888                                        &timeout); 
    905889        } 
     890 
    906891 
    907892    } else if (state == PJSIP_TSX_STATE_DESTROYED) { 
     
    915900            lck = lck->prev; 
    916901        } 
    917     } 
    918 } 
    919  
    920 /* 
    921  * Look-up destination address and select which transport to be used to send 
    922  * the request message. The procedure used here follows the guidelines on  
    923  * sending the request in RFC3261 chapter 8.1.2. 
    924  * 
    925  * This function also modifies the message (request line and Route headers) 
    926  * accordingly. 
    927  */ 
    928 static pj_status_t tsx_process_route( pjsip_transaction *tsx, 
    929                                       pjsip_tx_data *tdata, 
    930                                       pjsip_host_info *send_addr ) 
    931 { 
    932     pjsip_route_hdr *route_hdr; 
    933      
    934     pj_assert(tdata->msg->type == PJSIP_REQUEST_MSG); 
    935  
    936     /* Get the first "Route" header from the message. If the message doesn't 
    937      * have any "Route" headers but the endpoint has, then copy the "Route" 
    938      * headers from the endpoint first. 
    939      */ 
    940     route_hdr = pjsip_msg_find_hdr(tdata->msg, PJSIP_H_ROUTE, NULL); 
    941     if (!route_hdr) { 
    942         const pjsip_route_hdr *hdr_list; 
    943         const pjsip_route_hdr *hdr; 
    944         hdr_list = (const pjsip_route_hdr*)pjsip_endpt_get_routing(tsx->endpt); 
    945         hdr = hdr_list->next; 
    946         while (hdr != hdr_list { 
    947             route_hdr = pjsip_hdr_shallow_clone(tdata->pool, hdr); 
    948             pjsip_msg_add_hdr(tdata->msg, (pjsip_hdr*)route_hdr); 
    949             hdr = hdr->next; 
    950         } 
    951     } 
    952  
    953     return pjsip_get_request_addr(tdata, send_addr);   
    954 } 
    955  
    956  
    957 /* 
    958  * Callback from the transport job. 
    959  * This callback is called when asychronous transport connect() operation 
    960  * has completed, with or without error. 
    961  */ 
    962 static void tsx_transport_callback(pjsip_transport *tr,  
    963                                    void *token,  
    964                                    pj_status_t status) 
    965 { 
    966     char addr[PJ_MAX_HOSTNAME]; 
    967     pjsip_transaction *tsx = token; 
    968     struct tsx_lock_data lck; 
    969  
    970     pj_memcpy(addr, tsx->dest_name.addr.host.ptr, tsx->dest_name.addr.host.slen); 
    971     addr[tsx->dest_name.addr.host.slen] = '\0'; 
    972  
    973  
    974     if (status == PJ_SUCCESS) { 
    975         PJ_LOG(4, (tsx->obj_name, "%s connected to %s:%d", 
    976                                   tr->type_name, 
    977                                   addr, tsx->dest_name.addr.port)); 
    978     } else { 
    979         PJ_LOG(4, (tsx->obj_name, "%s unable to connect to %s:%d, status=%d",  
    980                                   tr->type_name, 
    981                                   addr, tsx->dest_name.addr.port, status)); 
    982     } 
    983  
    984     /* Lock transaction. */ 
    985     lock_tsx(tsx, &lck); 
    986  
    987     if (status != PJ_SUCCESS) { 
    988         tsx->transport_state = PJSIP_TSX_TRANSPORT_STATE_FINAL; 
    989         tsx->status_code = PJSIP_SC_TSX_TRANSPORT_ERROR; 
    990  
    991         tsx_set_state(tsx, PJSIP_TSX_STATE_TERMINATED, 
    992                       PJSIP_EVENT_TRANSPORT_ERROR, (void*)status); 
    993  
    994         /* Unlock transaction. */ 
    995         unlock_tsx(tsx, &lck); 
    996         return; 
    997     } 
    998  
    999     /* See if transaction has already been terminated.  
    1000      * If so, schedule to destroy the transaction. 
    1001      */ 
    1002     if (tsx->state == PJSIP_TSX_STATE_TERMINATED) { 
    1003         pj_time_val timeout = {0, 0}; 
    1004         pjsip_endpt_schedule_timer( tsx->endpt, &tsx->timeout_timer,  
    1005                                     &timeout); 
    1006  
    1007         /* Unlock transaction. */ 
    1008         unlock_tsx(tsx, &lck); 
    1009         return; 
    1010     } 
    1011  
    1012     /* Add reference counter to the transport. */ 
    1013     pjsip_transport_add_ref(tr); 
    1014  
    1015     /* Mark transport as ready. */ 
    1016     tsx->transport_state = PJSIP_TSX_TRANSPORT_STATE_FINAL; 
    1017     tsx->transport = tr; 
    1018  
    1019     /* If there's a pending message to send, send it now. */ 
    1020     if (tsx->has_unsent_msg) { 
    1021         tsx_send_msg( tsx, tsx->last_tx ); 
    1022     } 
    1023  
    1024     /* Unlock transaction. */ 
    1025     unlock_tsx(tsx, &lck); 
    1026 } 
    1027  
    1028 /* 
    1029  * Callback from the resolver job. 
    1030  */ 
    1031 static void tsx_resolver_callback(pj_status_t status, 
    1032                                   void *token, 
    1033                                   const struct pjsip_server_addresses *addr) 
    1034 { 
    1035     pjsip_transaction *tsx = token; 
    1036     struct tsx_lock_data lck; 
    1037     pjsip_transport *tp; 
    1038  
    1039     PJ_LOG(4, (tsx->obj_name, "resolver job complete, status=%d", status)); 
    1040  
    1041     if (status != PJ_SUCCESS || addr->count == 0) { 
    1042         lock_tsx(tsx, &lck); 
    1043         tsx->status_code = PJSIP_SC_TSX_RESOLVE_ERROR; 
    1044         tsx_set_state(tsx, PJSIP_TSX_STATE_TERMINATED,  
    1045                       PJSIP_EVENT_TRANSPORT_ERROR, (void*)status); 
    1046         unlock_tsx(tsx, &lck); 
    1047         return; 
    1048     } 
    1049  
    1050     /* Lock transaction. */ 
    1051     lock_tsx(tsx, &lck); 
    1052  
    1053     /* Copy server addresses. */ 
    1054     pj_memcpy(&tsx->remote_addr, addr, sizeof(*addr)); 
    1055  
    1056     /* Create/find the transport for the remote address. */ 
    1057     tsx->transport_state = PJSIP_TSX_TRANSPORT_STATE_CONNECTING; 
    1058     status = pjsip_endpt_alloc_transport( tsx->endpt, addr->entry[0].type, 
    1059                                           &addr->entry[0].addr, 
    1060                                           addr->entry[0].addr_len, 
    1061                                           &tp); 
    1062     tsx_transport_callback(tp, tsx, status); 
    1063  
    1064     /* Unlock transaction */ 
    1065     unlock_tsx(tsx, &lck); 
    1066  
    1067     /* There should be nothing to do after this point. 
    1068      * Execution for the transaction will resume when the callback for the  
    1069      * transport is called. 
    1070      */ 
    1071 } 
    1072  
    1073 /* 
    1074  * Initialize the transaction as UAC transaction. 
    1075  */ 
    1076 PJ_DEF(pj_status_t) pjsip_tsx_init_uac( pjsip_transaction *tsx,  
    1077                                         pjsip_tx_data *tdata) 
    1078 { 
     902 
     903        /* Unregister transaction. */ 
     904        mod_tsx_layer_unregister_tsx(tsx); 
     905 
     906        /* Destroy transaction. */ 
     907        tsx_destroy(tsx); 
     908    } 
     909} 
     910 
     911 
     912/* 
     913 * Create, initialize, and register UAC transaction. 
     914 */ 
     915PJ_DEF(pj_status_t) pjsip_tsx_create_uac( pjsip_module *tsx_user, 
     916                                          pjsip_tx_data *tdata, 
     917                                          pjsip_transaction **p_tsx) 
     918{ 
     919    pjsip_transaction *tsx; 
    1079920    pjsip_msg *msg; 
    1080921    pjsip_cseq_hdr *cseq; 
    1081922    pjsip_via_hdr *via; 
     923    struct tsx_lock_data lck; 
    1082924    pj_status_t status; 
    1083     struct tsx_lock_data lck; 
    1084  
    1085     PJ_LOG(4,(tsx->obj_name, "initializing tsx as UAC (tdata=%p)", tdata)); 
     925 
     926    PJ_ASSERT_RETURN(tdata!=NULL && p_tsx!=NULL, PJ_EINVAL); 
     927 
     928    /* Keep shortcut */ 
     929    msg = tdata->msg; 
     930 
     931    /* Make sure CSeq header is present. */ 
     932    cseq = pjsip_msg_find_hdr(msg, PJSIP_H_CSEQ, NULL); 
     933    if (!cseq) { 
     934        pj_assert(!"CSeq header not present in outgoing message!"); 
     935        return PJSIP_EMISSINGHDR; 
     936    } 
     937 
     938 
     939    /* Create transaction instance. */ 
     940    status = tsx_create( tsx_user, &tsx); 
     941    if (status != PJ_SUCCESS) 
     942        return status; 
     943 
    1086944 
    1087945    /* Lock transaction. */ 
    1088946    lock_tsx(tsx, &lck); 
    1089947 
    1090     /* Keep shortcut */ 
    1091     msg = tdata->msg; 
    1092  
    1093948    /* Role is UAC. */ 
    1094949    tsx->role = PJSIP_ROLE_UAC; 
     
    1096951    /* Save method. */ 
    1097952    pjsip_method_copy( tsx->pool, &tsx->method, &msg->line.req.method); 
     953 
     954    /* Save CSeq. */ 
     955    tsx->cseq = cseq->cseq; 
    1098956 
    1099957    /* Generate Via header if it doesn't exist. */ 
     
    1104962    } 
    1105963 
     964    /* Generate branch parameter if it doesn't exist. */ 
    1106965    if (via->branch_param.slen == 0) { 
    1107966        pj_str_t tmp; 
     
    1116975        /* Save branch parameter. */ 
    1117976        tsx->branch = via->branch_param; 
     977 
    1118978    } else { 
    1119979        /* Copy branch parameter. */ 
     
    1121981    } 
    1122982 
    1123  
    1124     /* Generate transaction key. */ 
    1125     status = create_tsx_key_3261( tsx->pool, &tsx->transaction_key, 
    1126                                   PJSIP_ROLE_UAC, &tsx->method,  
    1127                                   &via->branch_param); 
    1128     if (status != PJ_SUCCESS) { 
    1129         unlock_tsx(tsx, &lck); 
    1130         return status; 
    1131     } 
     983   /* Generate transaction key. */ 
     984    create_tsx_key_3261( tsx->pool, &tsx->transaction_key, 
     985                         PJSIP_ROLE_UAC, &tsx->method,  
     986                         &via->branch_param); 
    1132987 
    1133988    PJ_LOG(6, (tsx->obj_name, "tsx_key=%.*s", tsx->transaction_key.slen, 
    1134989               tsx->transaction_key.ptr)); 
    1135  
    1136     /* Save CSeq. */ 
    1137     cseq = pjsip_msg_find_hdr(msg, PJSIP_H_CSEQ, NULL); 
    1138     if (!cseq) { 
    1139         pj_assert(!"CSeq header not present in outgoing message!"); 
    1140         unlock_tsx(tsx, &lck); 
    1141         return PJSIP_EMISSINGHDR; 
    1142     } 
    1143     tsx->cseq = cseq->cseq; 
    1144  
    1145990 
    1146991    /* Begin with State_Null. 
     
    1148993     */ 
    1149994    tsx->state = PJSIP_TSX_STATE_NULL; 
    1150     tsx->state_handler = &pjsip_tsx_on_state_null; 
    1151  
    1152     /* Get destination name from the message. */ 
    1153     status = tsx_process_route(tsx, tdata, &tsx->dest_name); 
    1154     if (status != PJ_SUCCESS) { 
    1155         tsx->transport_state = PJSIP_TSX_TRANSPORT_STATE_FINAL; 
    1156         tsx->status_code = PJSIP_SC_TSX_TRANSPORT_ERROR; 
    1157         tsx_set_state(tsx, PJSIP_TSX_STATE_TERMINATED,  
    1158                       PJSIP_EVENT_TRANSPORT_ERROR, (void*)status); 
    1159         unlock_tsx(tsx, &lck); 
    1160         return status; 
    1161     } 
    1162  
    1163     /* Resolve destination. 
    1164      * This will start asynchronous resolver job, and when it finishes,  
    1165      * the callback will be called. 
    1166      */ 
    1167     PJ_LOG(5,(tsx->obj_name, "tsx resolving destination %.*s:%d", 
    1168                              tsx->dest_name.addr.host.slen,  
    1169                              tsx->dest_name.addr.host.ptr, 
    1170                              tsx->dest_name.addr.port)); 
    1171  
    1172     tsx->transport_state = PJSIP_TSX_TRANSPORT_STATE_RESOLVING; 
    1173     pjsip_endpt_resolve( tsx->endpt, tsx->pool, &tsx->dest_name,  
    1174                          tsx, &tsx_resolver_callback); 
    1175  
    1176     /* There should be nothing to do after this point.  
    1177      * Execution for the transaction will resume when the resolver callback is 
    1178      * called. 
    1179      */ 
    1180  
    1181     /* Unlock transaction and return. 
    1182      * If transaction has been destroyed WITHIN the current thread, the  
    1183      * unlock_tsx() function will return -1. 
    1184      */ 
    1185     return unlock_tsx(tsx, &lck); 
    1186 } 
    1187  
    1188  
    1189 /* 
    1190  * Initialize the transaction as UAS transaction. 
    1191  */ 
    1192 PJ_DEF(pj_status_t) pjsip_tsx_init_uas( pjsip_transaction *tsx,  
    1193                                         pjsip_rx_data *rdata) 
    1194 { 
    1195     pjsip_msg *msg = rdata->msg_info.msg; 
     995    tsx->state_handler = &tsx_on_state_null; 
     996 
     997    /* Save the message. */ 
     998    tsx->last_tx = tdata; 
     999    pjsip_tx_data_add_ref(tsx->last_tx); 
     1000 
     1001 
     1002    /* Register transaction to hash table. */ 
     1003    mod_tsx_layer_register_tsx(tsx); 
     1004 
     1005 
     1006    /* Unlock transaction and return. */ 
     1007    unlock_tsx(tsx, &lck); 
     1008 
     1009    *p_tsx = tsx; 
     1010    return PJ_SUCCESS; 
     1011} 
     1012 
     1013 
     1014/* 
     1015 * Create, initialize, and register UAS transaction. 
     1016 */ 
     1017PJ_DEF(pj_status_t) pjsip_tsx_create_uas( pjsip_module *tsx_user, 
     1018                                          pjsip_rx_data *rdata, 
     1019                                          pjsip_transaction **p_tsx) 
     1020{ 
     1021    pjsip_transaction *tsx; 
     1022    pjsip_msg *msg; 
    11961023    pj_str_t *branch; 
    11971024    pjsip_cseq_hdr *cseq; 
     
    11991026    struct tsx_lock_data lck; 
    12001027 
    1201     PJ_LOG(4,(tsx->obj_name, "initializing tsx as UAS (rdata=%p)", rdata)); 
     1028    PJ_ASSERT_RETURN(rdata!=NULL && p_tsx!=NULL, PJ_EINVAL); 
     1029 
     1030    /* Keep shortcut to message */ 
     1031    msg = rdata->msg_info.msg; 
     1032     
     1033    /* Make sure this is a request message. */ 
     1034    PJ_ASSERT_RETURN(msg->type == PJSIP_REQUEST_MSG, PJSIP_ENOTREQUESTMSG); 
     1035 
     1036    /* Make sure CSeq header is present. */ 
     1037    cseq = rdata->msg_info.cseq; 
     1038    if (!cseq) 
     1039        return PJSIP_EMISSINGHDR; 
     1040 
     1041    /* Make sure Via header is present. */ 
     1042    if (rdata->msg_info.via == NULL) 
     1043        return PJSIP_EMISSINGHDR; 
     1044 
     1045 
     1046    /*  
     1047     * Create transaction instance.  
     1048     */ 
     1049    status = tsx_create( tsx_user, &tsx); 
     1050    if (status != PJ_SUCCESS) 
     1051        return status; 
     1052 
    12021053 
    12031054    /* Lock transaction. */ 
    12041055    lock_tsx(tsx, &lck); 
    12051056 
    1206     /* Keep shortcut to message */ 
    1207     msg = rdata->msg_info.msg; 
    1208  
    12091057    /* Role is UAS */ 
    12101058    tsx->role = PJSIP_ROLE_UAS; 
     
    12121060    /* Save method. */ 
    12131061    pjsip_method_copy( tsx->pool, &tsx->method, &msg->line.req.method); 
     1062 
     1063    /* Save CSeq */ 
     1064    tsx->cseq = cseq->cseq; 
    12141065 
    12151066    /* Get transaction key either from branch for RFC3261 message, or 
     
    12191070                                  PJSIP_ROLE_UAS, &tsx->method, rdata); 
    12201071    if (status != PJ_SUCCESS) { 
    1221         unlock_tsx(tsx, &lck); 
     1072        tsx_destroy(tsx); 
    12221073        return status; 
    12231074    } 
     
    12301081               tsx->transaction_key.ptr)); 
    12311082 
    1232     /* Save CSeq */ 
    1233     cseq = rdata->msg_info.cseq; 
    1234     tsx->cseq = cseq->cseq; 
    1235  
    1236     /* Begin with state NULL 
     1083 
     1084    /* Begin with state TRYING. 
    12371085     * Manually set-up the state becase we don't want to call the callback. 
    12381086     */ 
    1239     tsx->state = PJSIP_TSX_STATE_NULL;  
    1240     tsx->state_handler = &pjsip_tsx_on_state_null; 
    1241  
    1242     /* Get the transport to send the response.  
    1243      * According to section 18.2.2 of RFC3261, if the transport is reliable 
    1244      * then the response must be sent using that transport. 
     1087    tsx->state = PJSIP_TSX_STATE_TRYING;  
     1088    tsx->state_handler = &tsx_on_state_trying; 
     1089 
     1090    /* Get response address. */ 
     1091    status = pjsip_get_response_addr( tsx->pool, rdata, &tsx->res_addr ); 
     1092    if (status != PJ_SUCCESS) { 
     1093        tsx_destroy(tsx); 
     1094        return status; 
     1095    } 
     1096 
     1097    /* If it's decided that we should use current transport, keep the 
     1098     * transport. 
    12451099     */ 
    1246     /* In addition, RFC 3581 says, if Via has "rport" parameter specified, 
    1247      * then return the response using the same transport. 
    1248      */ 
    1249     if (PJSIP_TRANSPORT_IS_RELIABLE(rdata->tp_info.transport) ||  
    1250         rdata->msg_info.via->rport_param >= 0)  
    1251     { 
    1252         tsx->transport = rdata->tp_info.transport; 
     1100    if (tsx->res_addr.transport) { 
     1101        tsx->transport = tsx->res_addr.transport; 
    12531102        pjsip_transport_add_ref(tsx->transport); 
    1254         tsx->transport_state = PJSIP_TSX_TRANSPORT_STATE_FINAL; 
    1255  
    1256         tsx->current_addr = 0; 
    1257         tsx->remote_addr.count = 1; 
    1258         tsx->remote_addr.entry[0].type = tsx->transport->key.type; 
    1259         pj_memcpy(&tsx->remote_addr.entry[0].addr,  
    1260                   &rdata->pkt_info.src_addr, rdata->pkt_info.src_addr_len); 
    1261          
    1262     } else { 
    1263         pj_status_t status; 
    1264  
    1265         status = pjsip_get_response_addr(tsx->pool, rdata->tp_info.transport, 
    1266                                          rdata->msg_info.via, &tsx->dest_name); 
    1267         if (status != PJ_SUCCESS) { 
    1268             tsx->transport_state = PJSIP_TSX_TRANSPORT_STATE_FINAL; 
    1269             tsx->status_code = PJSIP_SC_TSX_TRANSPORT_ERROR; 
    1270             tsx_set_state(tsx, PJSIP_TSX_STATE_TERMINATED,  
    1271                           PJSIP_EVENT_TRANSPORT_ERROR, (void*)status); 
    1272             unlock_tsx(tsx, &lck); 
    1273             return status; 
    1274         } 
    1275  
    1276         /* Resolve destination. 
    1277          * This will start asynchronous resolver job, and when it finishes,  
    1278          * the callback will be called. 
    1279          */ 
    1280         PJ_LOG(5,(tsx->obj_name, "tsx resolving destination %.*s:%d", 
    1281                                  tsx->dest_name.addr.host.slen,  
    1282                                  tsx->dest_name.addr.host.ptr, 
    1283                                  tsx->dest_name.addr.port)); 
    1284  
    1285         tsx->transport_state = PJSIP_TSX_TRANSPORT_STATE_RESOLVING; 
    1286         pjsip_endpt_resolve( tsx->endpt, tsx->pool, &tsx->dest_name,  
    1287                              tsx, &tsx_resolver_callback); 
    1288     } 
    1289      
    1290     /* There should be nothing to do after this point.  
    1291      * Execution for the transaction will resume when the resolver callback is 
    1292      * called. 
    1293      */ 
    1294  
    1295     /* Unlock transaction and return. 
    1296      * If transaction has been destroyed WITHIN the current thread, the  
    1297      * unlock_tsx() function will return -1. 
    1298      */ 
    1299     return unlock_tsx(tsx, &lck); 
    1300 } 
    1301  
    1302 /* 
    1303  * Callback when timer expires. 
    1304  */ 
    1305 static void tsx_timer_callback( pj_timer_heap_t *theap, pj_timer_entry *entry) 
    1306 { 
    1307     pjsip_event event; 
    1308     pjsip_transaction *tsx = entry->user_data; 
     1103        pj_memcpy(&tsx->addr, &tsx->res_addr.addr, tsx->res_addr.addr_len); 
     1104        tsx->addr_len = tsx->res_addr.addr_len; 
     1105    } 
     1106 
     1107 
     1108    /* Register the transaction. */ 
     1109    mod_tsx_layer_register_tsx(tsx); 
     1110 
     1111 
     1112    /* Unlock transaction and return. */ 
     1113    unlock_tsx(tsx, &lck); 
     1114 
     1115    *p_tsx = tsx; 
     1116    return PJ_SUCCESS; 
     1117} 
     1118 
     1119 
     1120/* 
     1121 * Forcely terminate transaction. 
     1122 */ 
     1123PJ_DEF(pj_status_t) pjsip_tsx_terminate( pjsip_transaction *tsx, int code ) 
     1124{ 
    13091125    struct tsx_lock_data lck; 
    13101126 
    1311     PJ_UNUSED_ARG(theap); 
    1312  
    1313     PJ_LOG(5,(tsx->obj_name, "got timer event (%s timer)",  
    1314              (entry->id==TSX_TIMER_RETRANSMISSION ? "Retransmit" : "Timeout"))); 
    1315  
    1316  
    1317     if (entry->id == TSX_TIMER_RETRANSMISSION) { 
    1318         PJSIP_EVENT_INIT_TIMER(event, &tsx->retransmit_timer); 
    1319     } else { 
    1320         PJSIP_EVENT_INIT_TIMER(event, &tsx->timeout_timer); 
    1321     } 
    1322  
    1323     /* Dispatch event to transaction. */ 
     1127    PJ_ASSERT_RETURN(tsx != NULL, PJ_EINVAL); 
     1128    PJ_ASSERT_RETURN(code >= 200, PJ_EINVAL); 
     1129 
    13241130    lock_tsx(tsx, &lck); 
    1325     (*tsx->state_handler)(tsx, &event); 
     1131    tsx->status_code = code; 
     1132    tsx_set_state( tsx, PJSIP_TSX_STATE_TERMINATED, PJSIP_EVENT_USER, NULL); 
    13261133    unlock_tsx(tsx, &lck); 
    1327 } 
    1328  
    1329 /* 
    1330  * Transmit ACK message for 2xx/INVITE with this transaction. The ACK for 
    1331  * non-2xx/INVITE is automatically sent by the transaction. 
    1332  * This operation is only valid if the transaction is configured to handle ACK 
    1333  * (tsx->handle_ack is non-zero). If this attribute is not set, then the 
    1334  * transaction will comply with RFC-3261, i.e. it will set itself to  
    1335  * TERMINATED state when it receives 2xx/INVITE. 
    1336  */ 
    1337 PJ_DEF(void) pjsip_tsx_on_tx_ack( pjsip_transaction *tsx, pjsip_tx_data *tdata) 
    1338 { 
    1339     pjsip_msg *msg; 
    1340     pjsip_host_info dest_addr; 
    1341     pjsip_via_hdr *via; 
    1342     struct tsx_lock_data lck; 
    1343     pj_status_t status = PJ_SUCCESS; 
    1344  
    1345     /* Lock tsx. */ 
    1346     lock_tsx(tsx, &lck); 
    1347  
    1348     pj_assert(tsx->handle_ack != 0); 
    1349      
    1350     msg = tdata->msg; 
    1351  
    1352     /* Generate branch parameter if it doesn't exist. */ 
    1353     via = pjsip_msg_find_hdr(msg, PJSIP_H_VIA, NULL); 
    1354     if (via == NULL) { 
    1355         via = pjsip_via_hdr_create(tdata->pool); 
    1356         pjsip_msg_add_hdr(msg, (pjsip_hdr*) via); 
    1357     } 
    1358  
    1359     if (via->branch_param.slen == 0) { 
    1360         via->branch_param = tsx->branch; 
    1361     } else { 
    1362         pj_assert( pj_strcmp(&via->branch_param, &tsx->branch) == 0 ); 
    1363     } 
    1364  
    1365     /* Get destination name from the message. */ 
    1366     status = tsx_process_route(tsx, tdata, &dest_addr); 
    1367     if (status != 0){ 
    1368         goto on_error; 
    1369     } 
    1370  
    1371     /* Compare message's destination name with transaction's destination name. 
    1372      * If NOT equal, then we'll have to resolve the destination. 
    1373      */ 
    1374     if (dest_addr.type == tsx->dest_name.type && 
    1375         dest_addr.flag == tsx->dest_name.flag && 
    1376         dest_addr.addr.port == tsx->dest_name.addr.port && 
    1377         pj_stricmp(&dest_addr.addr.host, &tsx->dest_name.addr.host) == 0) 
    1378     { 
    1379         /* Equal destination. We can use current transport. */ 
    1380         pjsip_tsx_on_tx_msg(tsx, tdata); 
    1381         unlock_tsx(tsx, &lck); 
    1382         return; 
    1383  
    1384     } 
    1385  
    1386     /* New destination; we'll have to resolve host and create new transport. */ 
    1387     pj_memcpy(&tsx->dest_name, &dest_addr, sizeof(dest_addr)); 
    1388     pj_strdup(tsx->pool, &tsx->dest_name.addr.host, &dest_addr.addr.host); 
    1389  
    1390     PJ_LOG(5,(tsx->obj_name, "tsx resolving destination %.*s:%d", 
    1391                              tsx->dest_name.addr.host.slen,  
    1392                              tsx->dest_name.addr.host.ptr, 
    1393                              tsx->dest_name.addr.port)); 
    1394  
    1395     tsx->transport_state = PJSIP_TSX_TRANSPORT_STATE_RESOLVING; 
    1396     pjsip_transport_dec_ref(tsx->transport); 
    1397     tsx->transport = NULL; 
    1398  
    1399     /* Put the message in queue. */ 
    1400     pjsip_tsx_on_tx_msg(tsx, tdata); 
    1401  
    1402     /* This is a bug! 
    1403      * We shouldn't change transaction's state before actually sending the 
    1404      * message. Otherwise transaction will terminate before message is sent, 
    1405      * and timeout timer will be scheduled. 
    1406      */ 
    1407     PJ_TODO(TSX_DONT_CHANGE_STATE_BEFORE_SENDING_ACK) 
    1408  
    1409     /*  
    1410      * This will start asynchronous resolver job, and when it finishes,  
    1411      * the callback will be called. 
    1412      */ 
    1413  
    1414     tsx->transport_state = PJSIP_TSX_TRANSPORT_STATE_RESOLVING; 
    1415     pjsip_endpt_resolve( tsx->endpt, tsx->pool, &tsx->dest_name,  
    1416                          tsx, &tsx_resolver_callback); 
    1417  
    1418     unlock_tsx(tsx, &lck); 
    1419  
    1420     /* There should be nothing to do after this point.  
    1421      * Execution for the transaction will resume when the resolver callback is 
    1422      * called. 
    1423      */ 
    1424     return; 
    1425  
    1426 on_error: 
    1427     /* Failure condition.  
    1428      * Send TERMINATED event. 
    1429      */ 
    1430     tsx->status_code = PJSIP_SC_TSX_TRANSPORT_ERROR; 
    1431  
    1432     tsx_set_state( tsx, PJSIP_TSX_STATE_TERMINATED,  
    1433                    PJSIP_EVENT_TRANSPORT_ERROR, (void*)status); 
    1434  
    1435     unlock_tsx(tsx, &lck); 
     1134 
     1135    return PJ_SUCCESS; 
    14361136} 
    14371137 
     
    14401140 * This function is called by TU to send a message. 
    14411141 */ 
    1442 PJ_DEF(void) pjsip_tsx_on_tx_msg( pjsip_transaction *tsx, 
    1443                                   pjsip_tx_data *tdata ) 
     1142PJ_DEF(pj_status_t) pjsip_tsx_send_msg( pjsip_transaction *tsx,  
     1143                                        pjsip_tx_data *tdata ) 
    14441144{ 
    14451145    pjsip_event event; 
    14461146    struct tsx_lock_data lck; 
    14471147    pj_status_t status; 
     1148 
     1149    if (tdata == NULL) 
     1150        tdata = tsx->last_tx; 
     1151 
     1152    PJ_ASSERT_RETURN(tdata != NULL, PJ_EINVALIDOP); 
    14481153 
    14491154    PJ_LOG(5,(tsx->obj_name, "Request to transmit msg on state %s (tdata=%p)", 
     
    14561161    status = (*tsx->state_handler)(tsx, &event); 
    14571162    unlock_tsx(tsx, &lck); 
    1458 } 
     1163 
     1164    return status; 
     1165} 
     1166 
    14591167 
    14601168/* 
     
    14621170 * transaction is received. 
    14631171 */ 
    1464 PJ_DEF(void) pjsip_tsx_on_rx_msg( pjsip_transaction *tsx, 
    1465                                   pjsip_rx_data *rdata) 
     1172static void tsx_on_rx_msg( pjsip_transaction *tsx, pjsip_rx_data *rdata) 
    14661173{ 
    14671174    pjsip_event event; 
     
    14721179              state_str[tsx->state], rdata)); 
    14731180 
     1181    /* Put the transaction in the rdata's mod_data. */ 
     1182    rdata->endpt_info.mod_data[mod_tsx_layer.mod.id] = tsx; 
     1183 
     1184    /* Init event. */ 
    14741185    PJSIP_EVENT_INIT_RX_MSG(event, tsx, rdata); 
    14751186 
     
    14801191} 
    14811192 
    1482 /* 
    1483  * Forcely terminate transaction. 
    1484  */ 
    1485 PJ_DEF(void) pjsip_tsx_terminate( pjsip_transaction *tsx, int code ) 
    1486 { 
     1193 
     1194/* Callback called by send message framework */ 
     1195static void send_msg_callback( pjsip_send_state *send_state, 
     1196                               pj_ssize_t sent, pj_bool_t *cont ) 
     1197{ 
     1198    pjsip_transaction *tsx = send_state->token; 
    14871199    struct tsx_lock_data lck; 
    14881200 
    14891201    lock_tsx(tsx, &lck); 
    1490     tsx->status_code = code; 
    1491     tsx_set_state( tsx, PJSIP_TSX_STATE_TERMINATED,  
    1492                    PJSIP_EVENT_USER, NULL); 
     1202 
     1203    if (sent > 0) { 
     1204        /* Successfully sent! */ 
     1205        pj_assert(send_state->cur_transport != NULL); 
     1206 
     1207        if (tsx->transport != send_state->cur_transport) { 
     1208            if (tsx->transport) { 
     1209                pjsip_transport_dec_ref(tsx->transport); 
     1210                tsx->transport = NULL; 
     1211            } 
     1212            tsx->transport = send_state->cur_transport; 
     1213            pjsip_transport_add_ref(tsx->transport); 
     1214        } 
     1215 
     1216        /* Clear pending transport flag. */ 
     1217        tsx->transport_flag &= ~(TSX_HAS_PENDING_TRANSPORT); 
     1218 
     1219        /* Pending destroy? */ 
     1220        if (tsx->transport_flag & TSX_HAS_PENDING_DESTROY) { 
     1221            tsx_set_state( tsx, PJSIP_TSX_STATE_DESTROYED,  
     1222                           PJSIP_EVENT_UNKNOWN, NULL ); 
     1223            unlock_tsx(tsx, &lck); 
     1224            return; 
     1225        } 
     1226 
     1227        /* Need to transmit a message? */ 
     1228        if (tsx->transport_flag & TSX_HAS_PENDING_SEND) { 
     1229            tsx->transport_flag &= ~(TSX_HAS_PENDING_SEND); 
     1230            tsx_send_msg(tsx, tsx->last_tx); 
     1231        } 
     1232 
     1233        /* Need to reschedule retransmission? */ 
     1234        if (tsx->transport_flag & TSX_HAS_PENDING_RESCHED) { 
     1235            tsx->transport_flag &= ~(TSX_HAS_PENDING_RESCHED); 
     1236            tsx_resched_retransmission(tsx); 
     1237        } 
     1238 
     1239    } else { 
     1240        /* Failed to send! */ 
     1241        pj_assert(sent != 0); 
     1242 
     1243        /* If transaction is using the same transport as the failed one,  
     1244         * release the transport. 
     1245         */ 
     1246        if (send_state->cur_transport==tsx->transport && 
     1247            tsx->transport != NULL) 
     1248        { 
     1249            pjsip_transport_dec_ref(tsx->transport); 
     1250            tsx->transport = NULL; 
     1251        } 
     1252 
     1253        if (!*cont) { 
     1254            PJ_LOG(4,(tsx->obj_name, "Failed to send message! status=%d", 
     1255                      -sent)); 
     1256 
     1257            /* Clear pending transport flag. */ 
     1258            tsx->transport_flag &= ~(TSX_HAS_PENDING_TRANSPORT); 
     1259 
     1260            /* Terminate transaction. */ 
     1261            tsx->status_code = PJSIP_SC_TSX_TRANSPORT_ERROR; 
     1262            tsx_set_state( tsx, PJSIP_TSX_STATE_TERMINATED,  
     1263                           PJSIP_EVENT_TRANSPORT_ERROR, send_state->tdata ); 
     1264        } 
     1265    } 
    14931266 
    14941267    unlock_tsx(tsx, &lck); 
    14951268} 
    14961269 
    1497 /* 
    1498  * Transport send completion callback. 
    1499  */ 
    1500 static void tsx_on_send_complete(void *token, pjsip_tx_data *tdata, 
    1501                                  pj_ssize_t bytes_sent) 
    1502 { 
    1503     PJ_UNUSED_ARG(token); 
    1504     PJ_UNUSED_ARG(tdata); 
    1505  
    1506     if (bytes_sent <= 0) { 
    1507         PJ_TODO(HANDLE_TRANSPORT_ERROR); 
    1508     } 
     1270 
     1271/* Transport callback. */ 
     1272static void transport_callback(void *token, pjsip_tx_data *tdata, 
     1273                               pj_ssize_t sent) 
     1274{ 
     1275    if (sent < 0) { 
     1276        pjsip_transaction *tsx = token; 
     1277        struct tsx_lock_data lck; 
     1278 
     1279        PJ_LOG(4,(tsx->obj_name, "Failed to send message! status=%d", 
     1280                  -sent)); 
     1281 
     1282        lock_tsx(tsx, &lck); 
     1283 
     1284        /* Dereference transport. */ 
     1285        pjsip_transport_dec_ref(tsx->transport); 
     1286        tsx->transport = NULL; 
     1287 
     1288        /* Terminate transaction. */ 
     1289        tsx->status_code = PJSIP_SC_TSX_TRANSPORT_ERROR; 
     1290        tsx_set_state( tsx, PJSIP_TSX_STATE_TERMINATED,  
     1291                       PJSIP_EVENT_TRANSPORT_ERROR, tdata ); 
     1292 
     1293        unlock_tsx(tsx, &lck); 
     1294   } 
    15091295} 
    15101296 
    15111297/* 
    15121298 * Send message to the transport. 
    1513  * If transport is not yet available, then do nothing. The message will be 
    1514  * transmitted when transport connection completion callback is called. 
    15151299 */ 
    15161300static pj_status_t tsx_send_msg( pjsip_transaction *tsx,  
    15171301                                 pjsip_tx_data *tdata) 
    15181302{ 
    1519     pj_status_t status = PJ_SUCCESS; 
    1520  
    1521     PJ_LOG(5,(tsx->obj_name, "sending msg (tdata=%p)", tdata)); 
    1522  
    1523     if (tsx->transport_state == PJSIP_TSX_TRANSPORT_STATE_FINAL) { 
    1524         pjsip_event before_tx_event; 
    1525  
    1526         pj_assert(tsx->transport != NULL); 
    1527  
    1528         /* Make sure Via transport info is filled up properly for 
    1529          * requests.  
     1303    pj_status_t status = PJ_EBUG; 
     1304 
     1305    PJ_ASSERT_RETURN(tsx && tdata, PJ_EINVAL); 
     1306 
     1307    /* Send later if transport is still pending. */ 
     1308    if (tsx->transport_flag & TSX_HAS_PENDING_TRANSPORT) { 
     1309        tsx->transport_flag |= TSX_HAS_PENDING_SEND; 
     1310        return PJ_SUCCESS; 
     1311    } 
     1312 
     1313    if (tdata->msg->type == PJSIP_REQUEST_MSG) { 
     1314        /* If we have the transport, send the message using that transport. 
     1315         * Otherwise perform full transport resolution. 
    15301316         */ 
    1531         if (tdata->msg->type == PJSIP_REQUEST_MSG) { 
    1532             pjsip_via_hdr *via = (pjsip_via_hdr*)  
    1533                 pjsip_msg_find_hdr(tdata->msg, PJSIP_H_VIA, NULL); 
    1534  
    1535             /* For request message, set "rport" parameter by default. */ 
    1536             if (tdata->msg->type == PJSIP_REQUEST_MSG) 
    1537                 via->rport_param = 0; 
    1538  
    1539             /* Don't update Via sent-by on retransmission. */ 
    1540             if (via->sent_by.host.slen == 0) { 
    1541                 pj_strdup2(tdata->pool, &via->transport,  
    1542                            tsx->transport->type_name); 
    1543                 pj_strdup(tdata->pool, &via->sent_by.host,  
    1544                           &tsx->transport->local_name.host); 
    1545                 via->sent_by.port = tsx->transport->local_name.port; 
     1317        if (tsx->transport) { 
     1318            status = pjsip_transport_send( tsx->transport, tdata, &tsx->addr, 
     1319                                           tsx->addr_len, tsx,  
     1320                                           &transport_callback); 
     1321            if (status == PJ_EPENDING) 
     1322                status = PJ_SUCCESS; 
     1323 
     1324            if (status != PJ_SUCCESS) { 
     1325                /* On error, release transport to force using full transport 
     1326                 * resolution procedure. 
     1327                 */ 
     1328                if (tsx->transport) { 
     1329                    pjsip_transport_dec_ref(tsx->transport); 
     1330                    tsx->transport = NULL; 
     1331                } 
     1332                tsx->addr_len = 0; 
    15461333            } 
    15471334        } 
    1548  
    1549         /* Notify everybody we're about to send message. */ 
    1550         PJSIP_EVENT_INIT_PRE_TX_MSG(before_tx_event, tsx, tdata,  
    1551                                     tsx->retransmit_count); 
    1552         pjsip_endpt_send_tsx_event( tsx->endpt, &before_tx_event ); 
    1553  
    1554         tsx->has_unsent_msg = 0; 
    1555         status = pjsip_transport_send(tsx->transport, tdata, 
    1556                         &tsx->remote_addr.entry[tsx->current_addr].addr, 
    1557                         tsx->remote_addr.entry[tsx->current_addr].addr_len, 
    1558                         tsx, &tsx_on_send_complete); 
    1559         if (status != PJ_SUCCESS && status != PJ_EPENDING) { 
    1560             PJ_TODO(HANDLE_TRANSPORT_ERROR); 
    1561             goto on_error; 
    1562         } 
     1335         
     1336        if (!tsx->transport) { 
     1337            tsx->transport_flag |= TSX_HAS_PENDING_TRANSPORT; 
     1338            status = pjsip_endpt_send_request_stateless(tsx->endpt, tdata, tsx, 
     1339                                                        &send_msg_callback); 
     1340            if (status == PJ_EPENDING) 
     1341                status = PJ_SUCCESS; 
     1342        } 
     1343 
    15631344    } else { 
    1564         tsx->has_unsent_msg = 1; 
    1565     } 
    1566  
    1567     return 0; 
    1568  
    1569 on_error: 
    1570     tsx->status_code = PJSIP_SC_TSX_TRANSPORT_ERROR; 
    1571     tsx_set_state( tsx, PJSIP_TSX_STATE_TERMINATED,  
    1572                    PJSIP_EVENT_TRANSPORT_ERROR, (void*)status); 
     1345        /* If we have the transport, send the message using that transport. 
     1346         * Otherwise perform full transport resolution. 
     1347         */ 
     1348        if (tsx->transport) { 
     1349            status = pjsip_transport_send( tsx->transport, tdata,  
     1350                                           &tsx->addr, tsx->addr_len, 
     1351                                           tsx, &transport_callback); 
     1352            if (status == PJ_EPENDING) 
     1353                status = PJ_SUCCESS; 
     1354 
     1355            if (status != PJ_SUCCESS) { 
     1356                if (tsx->transport) { 
     1357                    pjsip_transport_dec_ref(tsx->transport); 
     1358                    tsx->transport = NULL; 
     1359                } 
     1360                tsx->addr_len = 0; 
     1361                tsx->res_addr.transport = NULL; 
     1362                tsx->res_addr.addr_len = 0; 
     1363            } 
     1364 
     1365        }  
     1366 
     1367        if (!tsx->transport) { 
     1368            tsx->transport_flag |= TSX_HAS_PENDING_TRANSPORT; 
     1369            status = pjsip_endpt_send_response( tsx->endpt, &tsx->res_addr,  
     1370                                                tdata, tsx,  
     1371                                                &send_msg_callback); 
     1372            if (status == PJ_EPENDING) 
     1373                status = PJ_SUCCESS; 
     1374        } 
     1375    } 
     1376 
    15731377    return status; 
    15741378} 
    15751379 
     1380 
    15761381/* 
    15771382 * Retransmit last message sent. 
    15781383 */ 
    1579 static pj_status_t pjsip_tsx_retransmit( pjsip_transaction *tsx, 
    1580                                          int should_restart_timer) 
     1384static void tsx_resched_retransmission( pjsip_transaction *tsx ) 
     1385{ 
     1386    pj_time_val timeout; 
     1387    int msec_time; 
     1388 
     1389    pj_assert((tsx->transport_flag & TSX_HAS_PENDING_TRANSPORT) == 0); 
     1390 
     1391    msec_time = (1 << (tsx->retransmit_count)) * PJSIP_T1_TIMEOUT; 
     1392 
     1393    if (msec_time>PJSIP_T2_TIMEOUT && tsx->method.id!=PJSIP_INVITE_METHOD) 
     1394        msec_time = PJSIP_T2_TIMEOUT; 
     1395 
     1396    timeout.sec = msec_time / 1000; 
     1397    timeout.msec = msec_time % 1000; 
     1398    pjsip_endpt_schedule_timer( tsx->endpt, &tsx->retransmit_timer,  
     1399                                &timeout); 
     1400} 
     1401 
     1402/* 
     1403 * Retransmit last message sent. 
     1404 */ 
     1405static pj_status_t tsx_retransmit( pjsip_transaction *tsx, int resched) 
    15811406{ 
    15821407    pj_status_t status; 
    15831408 
     1409    PJ_ASSERT_RETURN(tsx->last_tx!=NULL, PJ_EBUG); 
     1410 
    15841411    PJ_LOG(4,(tsx->obj_name, "retransmiting (tdata=%p, count=%d, restart?=%d)",  
    1585               tsx->last_tx, tsx->retransmit_count, should_restart_timer)); 
    1586  
    1587     pj_assert(tsx->last_tx != NULL); 
     1412              tsx->last_tx, tsx->retransmit_count, resched)); 
    15881413 
    15891414    ++tsx->retransmit_count; 
    15901415 
    15911416    status = tsx_send_msg( tsx, tsx->last_tx); 
    1592     if (status != PJ_SUCCESS) { 
     1417    if (status != PJ_SUCCESS) 
    15931418        return status; 
    1594     } 
    15951419     
    15961420    /* Restart timer T1. */ 
    1597     if (should_restart_timer) { 
    1598         pj_time_val timeout; 
    1599         int msec_time = (1 << (tsx->retransmit_count)) * PJSIP_T1_TIMEOUT; 
    1600  
    1601         if (tsx->method.id!=PJSIP_INVITE_METHOD && msec_time>PJSIP_T2_TIMEOUT)  
    1602             msec_time = PJSIP_T2_TIMEOUT; 
    1603  
    1604         timeout.sec = msec_time / 1000; 
    1605         timeout.msec = msec_time % 1000; 
    1606         pjsip_endpt_schedule_timer( tsx->endpt, &tsx->retransmit_timer,  
    1607                                     &timeout); 
     1421    if (resched) { 
     1422        if (tsx->transport_flag & TSX_HAS_PENDING_TRANSPORT) { 
     1423            tsx->transport_flag |= TSX_HAS_PENDING_RESCHED; 
     1424        } else { 
     1425            tsx_resched_retransmission(tsx); 
     1426        } 
    16081427    } 
    16091428 
     
    16111430} 
    16121431 
     1432 
    16131433/* 
    16141434 * Handler for events in state Null. 
    16151435 */ 
    1616 static pj_status_t pjsip_tsx_on_state_null( pjsip_transaction *tsx,  
    1617                                             pjsip_event *event ) 
     1436static pj_status_t tsx_on_state_null( pjsip_transaction *tsx,  
     1437                                      pjsip_event *event ) 
    16181438{ 
    16191439    pj_status_t status; 
    16201440 
    1621     pj_assert( tsx->state == PJSIP_TSX_STATE_NULL); 
    1622     pj_assert( tsx->last_tx == NULL ); 
    1623     pj_assert( tsx->has_unsent_msg == 0); 
     1441    pj_assert(tsx->state == PJSIP_TSX_STATE_NULL); 
    16241442 
    16251443    if (tsx->role == PJSIP_ROLE_UAS) { 
    16261444 
    1627         /* Set state to Trying. */ 
    1628         pj_assert(event->type == PJSIP_EVENT_RX_MSG); 
    1629         tsx_set_state( tsx, PJSIP_TSX_STATE_TRYING,  
    1630                        PJSIP_EVENT_RX_MSG, event->body.rx_msg.rdata ); 
     1445        /* UAS doesn't have STATE_NULL. 
     1446         * State has moved from NULL after transaction is initialized. 
     1447         */ 
     1448        pj_assert(!"Bug bug bug!!"); 
     1449        return PJ_EBUG; 
    16311450 
    16321451    } else { 
    1633         pjsip_tx_data *tdata = event->body.tx_msg.tdata; 
     1452        pjsip_tx_data *tdata; 
     1453 
     1454        /* Must be transmit event. */ 
     1455        PJ_ASSERT_RETURN(event->type == PJSIP_EVENT_TX_MSG, PJ_EBUG); 
     1456 
     1457        /* Get the txdata */ 
     1458        tdata = event->body.tx_msg.tdata; 
    16341459 
    16351460        /* Save the message for retransmission. */ 
    1636         tsx->last_tx = tdata; 
    1637         pjsip_tx_data_add_ref(tdata); 
     1461        if (tsx->last_tx && tsx->last_tx != tdata) { 
     1462            pjsip_tx_data_dec_ref(tsx->last_tx); 
     1463            tsx->last_tx = NULL; 
     1464        } 
     1465        if (tsx->last_tx != tdata) { 
     1466            tsx->last_tx = tdata; 
     1467            pjsip_tx_data_add_ref(tdata); 
     1468        } 
    16381469 
    16391470        /* Send the message. */ 
     
    16521483         * transport is being used. 
    16531484         */ 
    1654         if (tsx->transport_state == PJSIP_TSX_TRANSPORT_STATE_FINAL && 
    1655             PJSIP_TRANSPORT_IS_RELIABLE(tsx->transport)==0)  
    1656         { 
    1657             pjsip_endpt_schedule_timer(tsx->endpt, &tsx->retransmit_timer,  
    1658                                        &t1_timer_val); 
     1485        if (!PJSIP_TRANSPORT_IS_RELIABLE(tsx->transport))  { 
    16591486            tsx->retransmit_count = 0; 
     1487            if (tsx->transport_flag & TSX_HAS_PENDING_TRANSPORT) { 
     1488                tsx->transport_flag |= TSX_HAS_PENDING_RESCHED; 
     1489            } else { 
     1490                pjsip_endpt_schedule_timer(tsx->endpt, &tsx->retransmit_timer, 
     1491                                           &t1_timer_val); 
     1492            } 
    16601493        } 
    16611494 
     
    16681501} 
    16691502 
     1503 
    16701504/* 
    16711505 * State Calling is for UAC after it sends request but before any responses 
    16721506 * is received. 
    16731507 */ 
    1674 static pj_status_t pjsip_tsx_on_state_calling( pjsip_transaction *tsx,  
    1675                                                pjsip_event *event ) 
     1508static pj_status_t tsx_on_state_calling( pjsip_transaction *tsx,  
     1509                                         pjsip_event *event ) 
    16761510{ 
    16771511    pj_assert(tsx->state == PJSIP_TSX_STATE_CALLING); 
     
    16841518 
    16851519        /* Retransmit the request. */ 
    1686         status = pjsip_tsx_retransmit( tsx, 1 ); 
     1520        status = tsx_retransmit( tsx, 1 ); 
    16871521        if (status != PJ_SUCCESS) { 
    16881522            return status; 
     
    17061540 
    17071541        /* Transaction is destroyed */ 
    1708         return PJSIP_ETSXDESTROYED; 
     1542        //return PJSIP_ETSXDESTROYED; 
    17091543 
    17101544    } else if (event->type == PJSIP_EVENT_RX_MSG) { 
    1711         int code; 
     1545        pjsip_msg *msg; 
     1546        //int code; 
     1547 
     1548        /* Get message instance */ 
     1549        msg = event->body.rx_msg.rdata->msg_info.msg; 
     1550 
     1551        /* Better be a response message. */ 
     1552        if (msg->type != PJSIP_RESPONSE_MSG) 
     1553            return PJSIP_ENOTRESPONSEMSG; 
    17121554 
    17131555        /* Cancel retransmission timer A. */ 
     
    17231565         */ 
    17241566        /* Keep last_tx for authorization. */ 
    1725         code = event->body.rx_msg.rdata->msg_info.msg->line.status.code; 
    1726         if (tsx->method.id != PJSIP_INVITE_METHOD && code!=401 && code!=407) { 
    1727             pjsip_tx_data_dec_ref(tsx->last_tx); 
    1728             tsx->last_tx = NULL; 
    1729         } 
     1567        //blp: always keep last_tx until transaction is destroyed 
     1568        //code = msg->line.status.code; 
     1569        //if (tsx->method.id != PJSIP_INVITE_METHOD && code!=401 && code!=407) { 
     1570        //    pjsip_tx_data_dec_ref(tsx->last_tx); 
     1571        //    tsx->last_tx = NULL; 
     1572        //} 
    17301573 
    17311574        /* Processing is similar to state Proceeding. */ 
    1732         pjsip_tsx_on_state_proceeding_uac( tsx, event); 
     1575        tsx_on_state_proceeding_uac( tsx, event); 
    17331576 
    17341577    } else { 
    1735         pj_assert(0); 
     1578        pj_assert(!"Unexpected event"); 
    17361579        return PJ_EBUG; 
    17371580    } 
     
    17391582    return PJ_SUCCESS; 
    17401583} 
     1584 
    17411585 
    17421586/* 
     
    17461590 *       non-INVITE client transaction (bug in RFC?). 
    17471591 */ 
    1748 static pj_status_t pjsip_tsx_on_state_trying( pjsip_transaction *tsx,  
    1749                                               pjsip_event *event) 
     1592static pj_status_t tsx_on_state_trying( pjsip_transaction *tsx,  
     1593                                        pjsip_event *event) 
    17501594{ 
    17511595    pj_status_t status; 
     
    17621606     * response because we haven't sent any!). 
    17631607     */ 
    1764     //pj_assert(event->type == PJSIP_EVENT_TX_MSG); 
    17651608    if (event->type != PJSIP_EVENT_TX_MSG) { 
    17661609        return PJ_SUCCESS; 
     
    17701613     * "Proceeding" state. 
    17711614     */ 
    1772     status = pjsip_tsx_on_state_proceeding_uas( tsx, event); 
     1615    status = tsx_on_state_proceeding_uas( tsx, event); 
    17731616 
    17741617    /* Inform the TU of the state transision if state is still State_Trying */ 
    17751618    if (status==PJ_SUCCESS && tsx->state == PJSIP_TSX_STATE_TRYING) { 
     1619 
    17761620        tsx_set_state( tsx, PJSIP_TSX_STATE_PROCEEDING,  
    17771621                       PJSIP_EVENT_TX_MSG, event->body.tx_msg.tdata); 
     1622 
    17781623    } 
    17791624 
    17801625    return status; 
    17811626} 
     1627 
    17821628 
    17831629/* 
     
    17851631 * This state happens after the TU sends provisional response. 
    17861632 */ 
    1787 static pj_status_t pjsip_tsx_on_state_proceeding_uas( pjsip_transaction *tsx, 
    1788                                                       pjsip_event *event) 
     1633static pj_status_t tsx_on_state_proceeding_uas( pjsip_transaction *tsx, 
     1634                                                pjsip_event *event) 
    17891635{ 
    17901636    pj_assert(tsx->state == PJSIP_TSX_STATE_PROCEEDING ||  
     
    17991645        pj_status_t status; 
    18001646 
    1801         /* Send last response. */ 
    1802         status = pjsip_tsx_retransmit( tsx, 0 ); 
    1803         if (status != PJ_SUCCESS) { 
    1804             return status; 
     1647        /* Must have last response sent. */ 
     1648        PJ_ASSERT_RETURN(tsx->last_tx != NULL, PJ_EBUG); 
     1649 
     1650        /* Send last response */ 
     1651        if (tsx->transport_flag & TSX_HAS_PENDING_TRANSPORT) { 
     1652            tsx->transport_flag |= TSX_HAS_PENDING_SEND; 
     1653        } else { 
     1654            status = tsx_send_msg(tsx, tsx->last_tx); 
     1655            if (status != PJ_SUCCESS) 
     1656                return status; 
    18051657        } 
    18061658         
     
    18161668 
    18171669        /* This can only be a response message. */ 
    1818         pj_assert(msg->type == PJSIP_RESPONSE_MSG); 
    1819  
    1820         /* Status code must be higher than last sent. */ 
    1821         pj_assert(msg->line.status.code >= tsx->status_code); 
     1670        PJ_ASSERT_RETURN(msg->type==PJSIP_RESPONSE_MSG, PJSIP_ENOTRESPONSEMSG); 
    18221671 
    18231672        /* Update last status */ 
     
    18481697                pjsip_tx_data_add_ref( tdata ); 
    18491698            } 
     1699 
    18501700            tsx_set_state( tsx, PJSIP_TSX_STATE_PROCEEDING,  
    18511701                           PJSIP_EVENT_TX_MSG, tdata ); 
     
    18531703        } else if (PJSIP_IS_STATUS_IN_CLASS(tsx->status_code, 200)) { 
    18541704 
    1855             if (tsx->method.id == PJSIP_INVITE_METHOD && tsx->handle_ack==0) { 
     1705            if (tsx->method.id == PJSIP_INVITE_METHOD && tsx->handle_200resp==0) { 
    18561706 
    18571707                /* 2xx class message is not saved, because retransmission  
     
    18621712 
    18631713                /* Transaction is destroyed. */ 
    1864                 return PJSIP_ETSXDESTROYED; 
     1714                //return PJSIP_ETSXDESTROYED; 
    18651715 
    18661716            } else { 
     
    18691719                if (tsx->method.id == PJSIP_INVITE_METHOD) { 
    18701720                    tsx->retransmit_count = 0; 
    1871                     pjsip_endpt_schedule_timer( tsx->endpt,  
    1872                                                 &tsx->retransmit_timer,  
    1873                                                 &t1_timer_val); 
     1721                    if (tsx->transport_flag & TSX_HAS_PENDING_TRANSPORT) { 
     1722                        tsx->transport_flag |= TSX_HAS_PENDING_RESCHED; 
     1723                    } else { 
     1724                        pjsip_endpt_schedule_timer( tsx->endpt,  
     1725                                                    &tsx->retransmit_timer, 
     1726                                                    &t1_timer_val); 
     1727                    } 
    18741728                } 
    18751729 
     
    18851739                 * reliable transport. 
    18861740                 */ 
    1887                 if (PJSIP_TRANSPORT_IS_RELIABLE(tsx->transport)==0) { 
     1741                if (!PJSIP_TRANSPORT_IS_RELIABLE(tsx->transport)) { 
    18881742                    timeout = timeout_timer_val; 
    18891743                } else { 
     
    19161770             * timer G will be scheduled (retransmission). 
    19171771             */ 
    1918             if (PJSIP_TRANSPORT_IS_RELIABLE(tsx->transport)==0) { 
     1772            if (!PJSIP_TRANSPORT_IS_RELIABLE(tsx->transport)) { 
    19191773                pjsip_cseq_hdr *cseq = pjsip_msg_find_hdr( msg, PJSIP_H_CSEQ, 
    19201774                                                           NULL); 
    19211775                if (cseq->method.id == PJSIP_INVITE_METHOD) { 
    19221776                    tsx->retransmit_count = 0; 
    1923                     pjsip_endpt_schedule_timer(tsx->endpt,  
    1924                                                &tsx->retransmit_timer,  
    1925                                                &t1_timer_val); 
     1777                    if (tsx->transport_flag & TSX_HAS_PENDING_TRANSPORT) { 
     1778                        tsx->transport_flag |= TSX_HAS_PENDING_RESCHED; 
     1779                    } else { 
     1780                        pjsip_endpt_schedule_timer(tsx->endpt,  
     1781                                                   &tsx->retransmit_timer,  
     1782                                                   &t1_timer_val); 
     1783                    } 
    19261784                } 
    19271785            } 
     
    19381796    } else if (event->type == PJSIP_EVENT_TIMER &&  
    19391797               event->body.timer.entry == &tsx->retransmit_timer) { 
     1798 
    19401799        /* Retransmission timer elapsed. */ 
    19411800        pj_status_t status; 
    19421801 
     1802        /* Must not be triggered while transport is pending. */ 
     1803        pj_assert((tsx->transport_flag & TSX_HAS_PENDING_TRANSPORT) == 0); 
     1804 
    19431805        /* Must have last response to retransmit. */ 
    19441806        pj_assert(tsx->last_tx != NULL); 
    19451807 
    19461808        /* Retransmit the last response. */ 
    1947         status = pjsip_tsx_retransmit( tsx, 1 ); 
     1809        status = tsx_retransmit( tsx, 1 ); 
    19481810        if (status != PJ_SUCCESS) { 
    19491811            return status; 
     
    19541816 
    19551817        /* Timeout timer. should not happen? */ 
    1956         pj_assert(0); 
     1818        pj_assert(!"Should not happen(?)"); 
    19571819 
    19581820        tsx->status_code = PJSIP_SC_TSX_TIMEOUT; 
     
    19641826 
    19651827    } else { 
    1966         pj_assert(0); 
     1828        pj_assert(!"Unexpected event"); 
    19671829        return PJ_EBUG; 
    19681830    } 
     
    19701832    return PJ_SUCCESS; 
    19711833} 
     1834 
    19721835 
    19731836/* 
     
    19761839 * UAS. 
    19771840 */ 
    1978 static pj_status_t pjsip_tsx_on_state_proceeding_uac(pjsip_transaction *tsx,  
    1979                                                      pjsip_event *event) 
     1841static pj_status_t tsx_on_state_proceeding_uac(pjsip_transaction *tsx,  
     1842                                               pjsip_event *event) 
    19801843{ 
    19811844 
     
    19841847 
    19851848    if (event->type != PJSIP_EVENT_TIMER) { 
     1849        pjsip_msg *msg; 
     1850 
    19861851        /* Must be incoming response, because we should not retransmit 
    19871852         * request once response has been received. 
     
    19921857        } 
    19931858 
    1994         tsx->status_code = event->body.rx_msg.rdata->msg_info.msg->line.status.code; 
     1859        msg = event->body.rx_msg.rdata->msg_info.msg; 
     1860 
     1861        /* Must be a response message. */ 
     1862        if (msg->type != PJSIP_RESPONSE_MSG) { 
     1863            pj_assert(!"Expecting response message!"); 
     1864            return PJSIP_ENOTRESPONSEMSG; 
     1865        } 
     1866 
     1867        tsx->status_code = msg->line.status.code; 
    19951868    } else { 
    19961869        tsx->status_code = PJSIP_SC_TSX_TIMEOUT; 
     
    20111884         * handled in TU). For non-INVITE, state moves to Completed. 
    20121885         */ 
    2013         if (tsx->method.id == PJSIP_INVITE_METHOD && tsx->handle_ack == 0) { 
     1886        if (tsx->method.id == PJSIP_INVITE_METHOD) { 
    20141887            tsx_set_state( tsx, PJSIP_TSX_STATE_TERMINATED,  
    20151888                           PJSIP_EVENT_RX_MSG, event->body.rx_msg.rdata ); 
    2016             return PJSIP_ETSXDESTROYED; 
     1889            //return PJSIP_ETSXDESTROYED; 
    20171890 
    20181891        } else { 
     
    20471920        /* Generate and send ACK for INVITE. */ 
    20481921        if (tsx->method.id == PJSIP_INVITE_METHOD) { 
    2049             pjsip_endpt_create_ack( tsx->endpt, tsx->last_tx,  
    2050                                     event->body.rx_msg.rdata ); 
     1922            pjsip_tx_data *ack; 
     1923 
     1924            status = pjsip_endpt_create_ack( tsx->endpt, tsx->last_tx,  
     1925                                             event->body.rx_msg.rdata, 
     1926                                             &ack); 
     1927            if (status != PJ_SUCCESS) 
     1928                return status; 
     1929 
     1930            if (ack != tsx->last_tx) { 
     1931                pjsip_tx_data_dec_ref(tsx->last_tx); 
     1932                tsx->last_tx = ack; 
     1933            } 
     1934 
    20511935            status = tsx_send_msg( tsx, tsx->last_tx); 
    20521936            if (status != PJ_SUCCESS) { 
     
    20561940 
    20571941        /* Start Timer D with TD/T4 timer if unreliable transport is used. */ 
    2058         if (PJSIP_TRANSPORT_IS_RELIABLE(tsx->transport) == 0) { 
     1942        if (!PJSIP_TRANSPORT_IS_RELIABLE(tsx->transport)) { 
    20591943            if (tsx->method.id == PJSIP_INVITE_METHOD) { 
    20601944                timeout = td_timer_val; 
     
    20731957    } else { 
    20741958        // Shouldn't happen because there's no timer for this state. 
    2075         pj_assert(0); 
     1959        pj_assert(!"Unexpected event"); 
    20761960        return PJ_EBUG; 
    20771961    } 
     
    20801964} 
    20811965 
     1966 
    20821967/* 
    20831968 * Handler for events in Completed state for UAS 
    20841969 */ 
    2085 static pj_status_t pjsip_tsx_on_state_completed_uas( pjsip_transaction *tsx,  
    2086                                                      pjsip_event *event) 
     1970static pj_status_t tsx_on_state_completed_uas( pjsip_transaction *tsx,  
     1971                                               pjsip_event *event) 
    20871972{ 
    20881973    pj_assert(tsx->state == PJSIP_TSX_STATE_COMPLETED); 
     
    20901975    if (event->type == PJSIP_EVENT_RX_MSG) { 
    20911976        pjsip_msg *msg = event->body.rx_msg.rdata->msg_info.msg; 
    2092         pjsip_cseq_hdr *cseq = pjsip_msg_find_hdr( msg, PJSIP_H_CSEQ, NULL ); 
     1977 
     1978        /* This must be a request message retransmission. */ 
     1979        if (msg->type != PJSIP_REQUEST_MSG) 
     1980            return PJSIP_ENOTREQUESTMSG; 
    20931981 
    20941982        /* On receive request retransmission, retransmit last response. */ 
    2095         if (cseq->method.id != PJSIP_ACK_METHOD) { 
     1983        if (msg->line.req.method.id != PJSIP_ACK_METHOD) { 
    20961984            pj_status_t status; 
    20971985 
    2098             status = pjsip_tsx_retransmit( tsx, 0 ); 
     1986            status = tsx_retransmit( tsx, 0 ); 
    20991987            if (status != PJ_SUCCESS) { 
    21001988                return status; 
     
    21232011            pj_status_t status; 
    21242012 
    2125             status = pjsip_tsx_retransmit( tsx, 1 ); 
     2013            status = tsx_retransmit( tsx, 1 ); 
    21262014            if (status != PJ_SUCCESS) { 
    21272015                return status; 
     
    21402028                               PJSIP_EVENT_TIMER, &tsx->timeout_timer ); 
    21412029 
    2142                 return PJSIP_ETSXDESTROYED; 
     2030                //return PJSIP_ETSXDESTROYED; 
    21432031 
    21442032            } else { 
     
    21462034                tsx_set_state( tsx, PJSIP_TSX_STATE_TERMINATED,  
    21472035                               PJSIP_EVENT_TIMER, &tsx->timeout_timer ); 
    2148                 return PJSIP_ETSXDESTROYED; 
     2036                //return PJSIP_ETSXDESTROYED; 
    21492037            } 
    21502038        } 
     
    21522040    } else { 
    21532041        /* Ignore request to transmit. */ 
    2154         pj_assert(event->body.tx_msg.tdata == tsx->last_tx); 
     2042        PJ_ASSERT_RETURN(event->type == PJSIP_EVENT_TX_MSG &&  
     2043                         event->body.tx_msg.tdata == tsx->last_tx,  
     2044                         PJ_EINVALIDOP); 
    21552045    } 
    21562046 
     
    21582048} 
    21592049 
     2050 
    21602051/* 
    21612052 * Handler for events in Completed state for UAC transaction. 
    21622053 */ 
    2163 static pj_status_t pjsip_tsx_on_state_completed_uac( pjsip_transaction *tsx, 
    2164                                                      pjsip_event *event) 
     2054static pj_status_t tsx_on_state_completed_uac( pjsip_transaction *tsx, 
     2055                                               pjsip_event *event) 
    21652056{ 
    21662057    pj_assert(tsx->state == PJSIP_TSX_STATE_COMPLETED); 
     
    21752066 
    21762067        /* Transaction has been destroyed. */ 
    2177         return PJSIP_ETSXDESTROYED; 
     2068        //return PJSIP_ETSXDESTROYED; 
    21782069 
    21792070    } else if (event->type == PJSIP_EVENT_RX_MSG) { 
     
    21892080                pj_status_t status; 
    21902081 
    2191                 status = pjsip_tsx_retransmit( tsx, 0 ); 
     2082                status = tsx_retransmit( tsx, 0 ); 
    21922083                if (status != PJ_SUCCESS) { 
    21932084                    return status; 
     
    22002091            /* Just drop the response. */ 
    22012092        } 
    2202     } else if (tsx->method.id == PJSIP_INVITE_METHOD && 
    2203                event->type == PJSIP_EVENT_TX_MSG && 
    2204                event->body.tx_msg.tdata->msg->line.req.method.id==PJSIP_ACK_METHOD) { 
    2205  
    2206         pj_status_t status; 
    2207  
    2208         /* Set last transmitted message. */ 
    2209         if (tsx->last_tx != event->body.tx_msg.tdata) { 
    2210             pjsip_tx_data_dec_ref( tsx->last_tx ); 
    2211             tsx->last_tx = event->body.tx_msg.tdata; 
    2212             pjsip_tx_data_add_ref( tsx->last_tx ); 
    2213         } 
    2214  
    2215         /* No state changed, but notify app.  
    2216          * Must notify now, so app has chance to put SDP in outgoing ACK msg. 
    2217          */ 
    2218         tsx_set_state( tsx, PJSIP_TSX_STATE_COMPLETED,  
    2219                        PJSIP_EVENT_TX_MSG, event->body.tx_msg.tdata ); 
    2220  
    2221         /* Send msg */ 
    2222         status = tsx_send_msg(tsx, event->body.tx_msg.tdata); 
    2223         if (status != PJ_SUCCESS) 
    2224             return status; 
    22252093 
    22262094    } else { 
    2227         pj_assert(0); 
    2228         return PJ_EBUG; 
     2095        pj_assert(!"Unexpected event"); 
     2096        return PJ_EINVALIDOP; 
    22292097    } 
    22302098 
     
    22322100} 
    22332101 
     2102 
    22342103/* 
    22352104 * Handler for events in state Confirmed. 
    22362105 */ 
    2237 static pj_status_t pjsip_tsx_on_state_confirmed( pjsip_transaction *tsx, 
    2238                                                  pjsip_event *event) 
     2106static pj_status_t tsx_on_state_confirmed( pjsip_transaction *tsx, 
     2107                                           pjsip_event *event) 
    22392108{ 
    22402109    pj_assert(tsx->state == PJSIP_TSX_STATE_CONFIRMED); 
     
    22472116    if (event->type == PJSIP_EVENT_RX_MSG) { 
    22482117 
    2249         pjsip_method_e method_id =  
    2250             event->body.rx_msg.rdata->msg_info.msg->line.req.method.id; 
    2251  
    2252         /* Must be a request message. */ 
    2253         pj_assert(event->body.rx_msg.rdata->msg_info.msg->type == PJSIP_REQUEST_MSG); 
     2118        pjsip_msg *msg = event->body.rx_msg.rdata->msg_info.msg; 
     2119 
     2120        /* Only expecting request message. */ 
     2121        if (msg->type != PJSIP_REQUEST_MSG) 
     2122            return PJSIP_ENOTREQUESTMSG; 
    22542123 
    22552124        /* Must be an ACK request or a late INVITE retransmission. */ 
    2256         pj_assert(method_id == PJSIP_ACK_METHOD || 
    2257                   method_id == PJSIP_INVITE_METHOD); 
    2258  
    2259         /* Just so that compiler won't complain about unused vars when 
    2260          * building release code. 
    2261          */ 
    2262         PJ_UNUSED_ARG(method_id); 
     2125        pj_assert(msg->line.req.method.id == PJSIP_ACK_METHOD ||  
     2126                  msg->line.req.method.id == PJSIP_INVITE_METHOD); 
    22632127 
    22642128    } else if (event->type == PJSIP_EVENT_TIMER) { 
     
    22712135 
    22722136        /* Transaction has been destroyed. */ 
    2273         return PJSIP_ETSXDESTROYED; 
     2137        //return PJSIP_ETSXDESTROYED; 
    22742138 
    22752139    } else { 
    2276         pj_assert(0); 
     2140        pj_assert(!"Unexpected event"); 
    22772141        return PJ_EBUG; 
    22782142    } 
     
    22812145} 
    22822146 
     2147 
    22832148/* 
    22842149 * Handler for events in state Terminated. 
    22852150 */ 
    2286 static pj_status_t pjsip_tsx_on_state_terminated( pjsip_transaction *tsx, 
    2287                                                   pjsip_event *event) 
     2151static pj_status_t tsx_on_state_terminated( pjsip_transaction *tsx, 
     2152                                            pjsip_event *event) 
    22882153{ 
    22892154    pj_assert(tsx->state == PJSIP_TSX_STATE_TERMINATED); 
    2290  
    2291     PJ_UNUSED_ARG(event); 
     2155    pj_assert(event->type == PJSIP_EVENT_TIMER); 
    22922156 
    22932157    /* Destroy this transaction */ 
     
    22992163 
    23002164 
    2301 static pj_status_t pjsip_tsx_on_state_destroyed(pjsip_transaction *tsx, 
    2302                                                 pjsip_event *event) 
     2165/* 
     2166 * Handler for events in state Destroyed. 
     2167 * Shouldn't happen! 
     2168 */ 
     2169static pj_status_t tsx_on_state_destroyed(pjsip_transaction *tsx, 
     2170                                          pjsip_event *event) 
    23032171{ 
    23042172    PJ_UNUSED_ARG(tsx); 
    23052173    PJ_UNUSED_ARG(event); 
    2306     return PJ_SUCCESS; 
    2307 } 
    2308  
     2174    pj_assert(!"Not expecting any events!!"); 
     2175    return PJ_EBUG; 
     2176} 
     2177 
  • pjproject/trunk/pjsip/src/pjsip/sip_transport.c

    r106 r107  
    7171    { PJSIP_TRANSPORT_TCP, 5060, {"TCP", 3}, PJSIP_TRANSPORT_RELIABLE}, 
    7272    { PJSIP_TRANSPORT_TLS, 5061, {"TLS", 3}, PJSIP_TRANSPORT_RELIABLE | PJSIP_TRANSPORT_SECURE}, 
    73     { PJSIP_TRANSPORT_SCTP, 5060, {"SCTP", 4}, PJSIP_TRANSPORT_RELIABLE} 
     73    { PJSIP_TRANSPORT_SCTP, 5060, {"SCTP", 4}, PJSIP_TRANSPORT_RELIABLE}, 
     74    { PJSIP_TRANSPORT_LOOP, 15060, {"LOOP", 4}, PJSIP_TRANSPORT_RELIABLE},  
     75    { PJSIP_TRANSPORT_LOOP_DGRAM, 15060, {"LOOP-DGRAM", 10}, PJSIP_TRANSPORT_DATAGRAM}, 
    7476}; 
    7577 
     
    195197    status = pj_atomic_create(tdata->pool, 0, &tdata->ref_cnt); 
    196198    if (status != PJ_SUCCESS) { 
    197         pjsip_endpt_destroy_pool( mgr->endpt, tdata->pool ); 
     199        pjsip_endpt_release_pool( mgr->endpt, tdata->pool ); 
    198200        return status; 
    199201    } 
     
    202204    status = pj_lock_create_null_mutex(pool, "tdta%p", &tdata->lock); 
    203205    if (status != PJ_SUCCESS) { 
    204         pjsip_endpt_destroy_pool( mgr->endpt, tdata->pool ); 
     206        pjsip_endpt_release_pool( mgr->endpt, tdata->pool ); 
    205207        return status; 
    206208    } 
     
    239241        pj_atomic_destroy( tdata->ref_cnt ); 
    240242        pj_lock_destroy( tdata->lock ); 
    241         pjsip_endpt_destroy_pool( tdata->mgr->endpt, tdata->pool ); 
     243        pjsip_endpt_release_pool( tdata->mgr->endpt, tdata->pool ); 
    242244        return PJSIP_EBUFDESTROYED; 
    243245    } else { 
     
    716718        } 
    717719 
    718         /* If message is received from address that's different from sent-by, 
    719          * MUST add received parameter to the via. 
    720          */ 
    721         if (pj_strcmp2(&rdata->msg_info.via->sent_by.host,  
    722                        rdata->pkt_info.src_name) != 0)  
    723         { 
    724             pj_strdup2(rdata->tp_info.pool,  
    725                        &rdata->msg_info.via->recvd_param,  
    726                        rdata->pkt_info.src_name); 
    727         } 
     720        /* Always add received parameter to the via. */ 
     721        pj_strdup2(rdata->tp_info.pool,  
     722                   &rdata->msg_info.via->recvd_param,  
     723                   rdata->pkt_info.src_name); 
    728724 
    729725        /* RFC 3581: 
  • pjproject/trunk/pjsip/src/pjsip/sip_transport_udp.c

    • Property svn:keywords set to Id
    r106 r107  
    1 /* $Id: $ */ 
     1/* $Id$ */ 
    22/*  
    33 * Copyright (C) 2003-2006 Benny Prijono <benny@prijono.org> 
     
    193193    struct udp_transport *tp = (struct udp_transport*)transport; 
    194194    pj_ssize_t size; 
     195    pj_status_t status; 
    195196 
    196197    PJ_ASSERT_RETURN(transport && tdata, PJ_EINVAL); 
     
    204205    /* Send to ioqueue! */ 
    205206    size = tdata->buf.cur - tdata->buf.start; 
    206     return pj_ioqueue_sendto(tp->key, (pj_ioqueue_op_key_t*)&tdata->op_key, 
    207                              tdata->buf.start, &size, 0, 
    208                              rem_addr, addr_len); 
     207    status = pj_ioqueue_sendto(tp->key, (pj_ioqueue_op_key_t*)&tdata->op_key, 
     208                               tdata->buf.start, &size, 0, 
     209                               rem_addr, addr_len); 
     210 
     211    if (status != PJ_EPENDING) 
     212        tdata->op_key.tdata = NULL; 
     213 
     214    return status; 
    209215} 
    210216 
     
    245251 
    246252    /* Destroy pool. */ 
    247     pjsip_endpt_destroy_pool(tp->base.endpt, tp->base.pool); 
     253    pjsip_endpt_release_pool(tp->base.endpt, tp->base.pool); 
    248254 
    249255    return PJ_SUCCESS; 
     
    420426 
    421427    /* Done. */ 
    422     *p_transport = &tp->base; 
     428    if (p_transport) 
     429        *p_transport = &tp->base; 
    423430    return PJ_SUCCESS; 
    424431 
  • pjproject/trunk/pjsip/src/pjsip/sip_util.c

    r106 r107  
    177177        target = pjsip_parse_uri( tdata->pool, tmp.ptr, tmp.slen, 0); 
    178178        if (target == NULL) { 
    179             PJ_LOG(4,(THIS_FILE, "Error creating request: invalid target %s",  
    180                       tmp.ptr)); 
     179            status = PJSIP_EINVALIDREQURI; 
    181180            goto on_error; 
    182181        } 
     
    188187                                     PJSIP_PARSE_URI_AS_NAMEADDR); 
    189188        if (from->uri == NULL) { 
    190             PJ_LOG(4,(THIS_FILE, "Error creating request: invalid 'From' URI '%s'", 
    191                                 tmp.ptr)); 
     189            status = PJSIP_EINVALIDHDR; 
    192190            goto on_error; 
    193191        } 
     
    200198                                   PJSIP_PARSE_URI_AS_NAMEADDR); 
    201199        if (to->uri == NULL) { 
    202             PJ_LOG(4,(THIS_FILE, "Error creating request: invalid 'To' URI '%s'", 
    203                                 tmp.ptr)); 
     200            status = PJSIP_EINVALIDHDR; 
    204201            goto on_error; 
    205202        } 
     
    212209                                            PJSIP_PARSE_URI_AS_NAMEADDR); 
    213210            if (contact->uri == NULL) { 
    214                 PJ_LOG(4,(THIS_FILE,  
    215                           "Error creating request: invalid 'Contact' URI '%s'", 
    216                           tmp.ptr)); 
     211                status = PJSIP_EINVALIDHDR; 
    217212                goto on_error; 
    218213            } 
     
    11701165            return PJ_SUCCESS; 
    11711166        } else { 
    1172             send_response_transport_cb(send_state, tdata, -status); 
     1167            pjsip_transport_dec_ref(send_state->cur_transport); 
    11731168            return status; 
    11741169        } 
     
    11801175} 
    11811176 
     1177/* 
     1178 * Send response 
     1179 */ 
     1180PJ_DEF(pj_status_t) pjsip_endpt_respond_stateless( pjsip_endpoint *endpt, 
     1181                                                   pjsip_rx_data *rdata, 
     1182                                                   int st_code, 
     1183                                                   const pj_str_t *st_text, 
     1184                                                   const pjsip_hdr *hdr_list, 
     1185                                                   const pjsip_msg_body *body) 
     1186{ 
     1187    pj_status_t status; 
     1188    pjsip_response_addr res_addr; 
     1189    pjsip_tx_data *tdata; 
     1190 
     1191    /* Create response message */ 
     1192    status = pjsip_endpt_create_response( endpt, rdata, st_code, st_text,  
     1193                                          &tdata); 
     1194    if (status != PJ_SUCCESS) 
     1195        return status; 
     1196 
     1197    /* Add the message headers, if any */ 
     1198    if (hdr_list) { 
     1199        const pjsip_hdr *hdr = hdr_list->next; 
     1200        while (hdr != hdr_list) { 
     1201            pjsip_msg_add_hdr( tdata->msg, pjsip_hdr_clone(tdata->pool, hdr) ); 
     1202            hdr = hdr->next; 
     1203        } 
     1204    } 
     1205 
     1206    /* Add the message body, if any. */ 
     1207    if (body) { 
     1208        tdata->msg->body = pj_pool_alloc(tdata->pool, sizeof(pjsip_msg_body)); 
     1209        status = pjsip_msg_body_clone( tdata->pool, tdata->msg->body, body ); 
     1210        if (status != PJ_SUCCESS) { 
     1211            pjsip_tx_data_dec_ref(tdata); 
     1212            return status; 
     1213        } 
     1214    } 
     1215 
     1216    /* Get where to send request. */ 
     1217    status = pjsip_get_response_addr( tdata->pool, rdata, &res_addr ); 
     1218    if (status != PJ_SUCCESS) { 
     1219        pjsip_tx_data_dec_ref(tdata); 
     1220        return status; 
     1221    } 
     1222 
     1223    /* Send! */ 
     1224    status = pjsip_endpt_send_response( endpt, &res_addr, tdata, NULL, NULL ); 
     1225 
     1226    return status; 
     1227} 
    11821228 
    11831229/* 
  • pjproject/trunk/pjsip/src/pjsip/sip_util_statefull.c

    • Property svn:keywords changed from "Id Revision" to Id
  • pjproject/trunk/pjsip/src/test-pjsip/msg_test.c

    r106 r107  
    4848    /* 'Normal' message with all headers. */ 
    4949    "INVITE sip:user@foo SIP/2.0\n" 
    50     "From: Hi I'm Joe <sip:joe.user@bar.otherdomain.com>;tag=1234578901234567890\r" 
     50    "From: Hi I'm Joe <sip:joe.user@bar.otherdomain.com>;tag=123457890123456\r" 
    5151    "To: Fellow User <sip:user@foo.bar.domain.com>\r\n" 
    5252    "Call-ID: 12345678901234567890@bar\r\n" 
     
    5858    "Route: <sip:bigbox3.site3.atlanta.com;lr>,\r\n" 
    5959    "  <sip:server10.biloxi.com;lr>\r" 
    60     "Record-Route: <sip:server10.biloxi.com>,\r\n" 
     60    "Record-Route: <sip:server10.biloxi.com>,\r\n" /* multiple routes+folding*/ 
    6161    "  <sip:bigbox3.site3.atlanta.com;lr>\n" 
    62     "Via: SIP/2.0/SCTP bigbox3.site3.atlanta.com;branch=z9hG4bK77ef4c2312983.1\n" 
    63     "Via: SIP/2.0/UDP pc33.atlanta.com;branch=z9hG4bKnashds8\n" 
     62    "Via: SIP/2.0/SCTP bigbox3.site3.atlanta.com;branch=z9hG4bK77ef4c230\n" 
     63    "Via: SIP/2.0/UDP pc33.atlanta.com;branch=z9hG4bKnashds8\n" /* folding. */ 
    6464    " ;received=192.0.2.1\r\n" 
    6565    "Via: SIP/2.0/UDP 10.2.1.1, SIP/2.0/TCP 192.168.1.1\n" 
    6666    "Organization: \r" 
    6767    "Max-Forwards: 70\n" 
    68     "X-Header: \r\n" 
     68    "X-Header: \r\n"        /* empty header */ 
     69    "P-Associated-URI:\r\n" /* empty header without space */ 
    6970    "\r\n", 
    7071    &create_msg0, 
     
    352353    pj_strdup2(pool, &url->host, "foo"); 
    353354 
    354     /* "From: Hi I'm Joe <sip:joe.user@bar.otherdomain.com>;tag=1234578901234567890\r" */ 
     355    /* "From: Hi I'm Joe <sip:joe.user@bar.otherdomain.com>;tag=123457890123456\r" */ 
    355356    fromto = pjsip_from_hdr_create(pool); 
    356357    pjsip_msg_add_hdr(msg, (pjsip_hdr*)fromto); 
    357     pj_strdup2(pool, &fromto->tag, "1234578901234567890"); 
     358    pj_strdup2(pool, &fromto->tag, "123457890123456"); 
    358359    name_addr = pjsip_name_addr_create(pool); 
    359360    fromto->uri = (pjsip_uri*)name_addr; 
     
    463464    url->lr_param = 1; 
    464465 
    465     /* "Via: SIP/2.0/SCTP bigbox3.site3.atlanta.com;branch=z9hG4bK77ef4c2312983.1\n" */ 
     466    /* "Via: SIP/2.0/SCTP bigbox3.site3.atlanta.com;branch=z9hG4bK77ef4c230\n" */ 
    466467    via = pjsip_via_hdr_create(pool); 
    467468    pjsip_msg_add_hdr(msg, (pjsip_hdr*)via); 
    468469    pj_strdup2(pool, &via->transport, "SCTP"); 
    469470    pj_strdup2(pool, &via->sent_by.host, "bigbox3.site3.atlanta.com"); 
    470     pj_strdup2(pool, &via->branch_param, "z9hG4bK77ef4c2312983.1"); 
     471    pj_strdup2(pool, &via->branch_param, "z9hG4bK77ef4c230"); 
    471472 
    472473    /* "Via: SIP/2.0/UDP pc33.atlanta.com;branch=z9hG4bKnashds8\n" 
     
    513514    str.ptr = "X-Header"; 
    514515    str.slen = 8; 
     516    generic = pjsip_generic_string_hdr_create(pool, &str); 
     517    pjsip_msg_add_hdr(msg, (pjsip_hdr*)generic); 
     518    str.ptr = NULL; 
     519    str.slen = 0; 
     520    generic->hvalue = str; 
     521 
     522    /* P-Associated-URI:\r\n */ 
     523    str.ptr = "P-Associated-URI"; 
     524    str.slen = 16; 
    515525    generic = pjsip_generic_string_hdr_create(pool, &str); 
    516526    pjsip_msg_add_hdr(msg, (pjsip_hdr*)generic); 
     
    678688        pool = pjsip_endpt_create_pool(endpt, NULL, POOL_SIZE, POOL_SIZE); 
    679689        status = test_entry( pool, &test_array[i] ); 
    680         pjsip_endpt_destroy_pool(endpt, pool); 
     690        pjsip_endpt_release_pool(endpt, pool); 
    681691 
    682692        if (status != PJ_SUCCESS) 
     
    692702            pool = pjsip_endpt_create_pool(endpt, NULL, POOL_SIZE, POOL_SIZE); 
    693703            status = test_entry( pool, &test_array[i] ); 
    694             pjsip_endpt_destroy_pool(endpt, pool); 
     704            pjsip_endpt_release_pool(endpt, pool); 
    695705 
    696706            if (status != PJ_SUCCESS) 
  • pjproject/trunk/pjsip/src/test-pjsip/test.c

    r106 r107  
    8282    PJ_LOG(3,("","")); 
    8383 
    84     DO_TEST(uri_test()); 
    85     DO_TEST(msg_test()); 
    86     DO_TEST(txdata_test()); 
    87     DO_TEST(transport_udp_test()); 
     84    //DO_TEST(uri_test()); 
     85    //DO_TEST(msg_test()); 
     86    //DO_TEST(txdata_test()); 
     87    //DO_TEST(transport_udp_test()); 
     88    DO_TEST(transport_loop_test()); 
     89    //DO_TEST(tsx_uac_test()); 
    8890 
    8991on_return: 
  • pjproject/trunk/pjsip/src/test-pjsip/test.h

    r106 r107  
    2424extern pjsip_endpoint *endpt; 
    2525 
    26 #define TEST_UDP_PORT   15060 
     26#define TEST_UDP_PORT       15060 
     27#define TEST_UDP_PORT_STR   "15060" 
    2728 
    2829/* The tests */ 
     
    3132int txdata_test(void); 
    3233int transport_udp_test(void); 
     34int transport_loop_test(void); 
     35int tsx_uac_test(void); 
    3336 
    3437/* Transport test helpers (transport_test.c). */ 
     
    3639int transport_send_recv_test( pjsip_transport_type_e tp_type, 
    3740                              pjsip_transport *ref_tp, 
    38                               const pj_sockaddr_in *rem_addr ); 
     41                              char *target_url ); 
    3942int transport_rt_test( pjsip_transport_type_e tp_type, 
    4043                       pjsip_transport *ref_tp, 
    41                        const pj_sockaddr_in *rem_addr ); 
     44                       char *target_url ); 
    4245 
    4346/* Test main entry */ 
  • pjproject/trunk/pjsip/src/test-pjsip/transport_test.c

    • Property svn:keywords changed from "Id Revision" to Id
    r106 r107  
    7676 */ 
    7777#define FROM_HDR    "Bob <sip:bob@example.com>" 
    78 #define TO_HDR      "Alice <sip:alice@example.com>" 
    7978#define CONTACT_HDR "Bob <sip:bob@127.0.0.1>" 
    8079#define CALL_ID_HDR "SendRecv-Test" 
     
    109108    &my_on_rx_request,                  /* on_rx_request()      */ 
    110109    &my_on_rx_response,                 /* on_rx_response()     */ 
    111     NULL,                               /* tsx_handler()        */ 
     110    NULL,                               /* on_tsx_state()       */ 
    112111}; 
    113112 
     
    189188int transport_send_recv_test( pjsip_transport_type_e tp_type, 
    190189                              pjsip_transport *ref_tp, 
    191                               const pj_sockaddr_in *rem_addr ) 
     190                              char *target_url ) 
    192191{ 
    193192    pj_status_t status; 
    194     char target_buf[80]; 
    195193    pj_str_t target, from, to, contact, call_id, body; 
    196194    pjsip_method method; 
     
    210208 
    211209    /* Create a request message. */ 
    212     pj_sprintf(target_buf, "sip:%s:%d", pj_inet_ntoa(rem_addr->sin_addr), 
    213                                         pj_ntohs(rem_addr->sin_port)); 
    214     target = pj_str(target_buf); 
     210    target = pj_str(target_url); 
    215211    from = pj_str(FROM_HDR); 
    216     to = pj_str(TO_HDR); 
     212    to = pj_str(target_url); 
    217213    contact = pj_str(CONTACT_HDR); 
    218214    call_id = pj_str(CALL_ID_HDR); 
     
    334330} rt_test_data[16]; 
    335331 
    336 static char      rt_target_uri[32]; 
     332static char      rt_target_uri[64]; 
    337333static pj_bool_t rt_stop; 
    338334static pj_str_t  rt_call_id; 
     
    350346        status = pjsip_endpt_create_response( endpt, rdata, 200, NULL, &tdata); 
    351347        if (status != PJ_SUCCESS) { 
     348            app_perror("    error creating response", status); 
    352349            return PJ_TRUE; 
    353350        } 
    354351        status = pjsip_get_response_addr( tdata->pool, rdata, &res_addr); 
    355352        if (status != PJ_SUCCESS) { 
     353            app_perror("    error in get response address", status); 
    356354            pjsip_tx_data_dec_ref(tdata); 
    357355            return PJ_TRUE; 
     
    359357        status = pjsip_endpt_send_response( endpt, &res_addr, tdata, NULL, NULL); 
    360358        if (status != PJ_SUCCESS) { 
     359            app_perror("    error sending response", status); 
    361360            pjsip_tx_data_dec_ref(tdata); 
    362361            return PJ_TRUE; 
     
    377376    target = pj_str(rt_target_uri); 
    378377    from = pj_str(FROM_HDR); 
    379     to = pj_str(TO_HDR); 
     378    to = pj_str(rt_target_uri); 
    380379    contact = pj_str(CONTACT_HDR); 
    381380    call_id = rt_test_data[thread_id].call_id; 
     
    431430static int rt_thread(void *arg) 
    432431{ 
    433     int thread_id = (int)arg; 
     432    int i, thread_id = (int)arg; 
    434433    pj_time_val poll_delay = { 0, 10 }; 
    435434 
     
    444443        pjsip_endpt_handle_events(endpt, &poll_delay); 
    445444    } 
     445 
     446    /* Exhaust responses. */ 
     447    for (i=0; i<100; ++i) 
     448        pjsip_endpt_handle_events(endpt, &poll_delay); 
     449 
    446450    return 0; 
    447451} 
     
    449453int transport_rt_test( pjsip_transport_type_e tp_type, 
    450454                       pjsip_transport *ref_tp, 
    451                        const pj_sockaddr_in *rem_addr ) 
     455                       char *target_url ) 
    452456{ 
    453457    enum { THREADS = 4, INTERVAL = 10 }; 
     
    484488 
    485489    /* Initialize static test data. */ 
    486     pj_sprintf(rt_target_uri, "sip:%s:%d", pj_inet_ntoa(rem_addr->sin_addr), 
    487                                            pj_ntohs(rem_addr->sin_port)); 
     490    pj_native_strcpy(rt_target_uri, target_url); 
    488491    rt_call_id = pj_str("RT-Call-Id/"); 
    489492    rt_stop = PJ_FALSE; 
     
    552555    PJ_LOG(3,("", "    average round-trip=%d usec", usec_rt)); 
    553556 
    554     pjsip_endpt_destroy_pool(endpt, pool); 
     557    pjsip_endpt_release_pool(endpt, pool); 
    555558 
    556559    if (is_reliable && (total_sent != total_recv)) { 
  • pjproject/trunk/pjsip/src/test-pjsip/transport_udp_test.c

    • Property svn:keywords changed from "Id Revision" to Id
    r106 r107  
    7777    pj_sockaddr_in_init(&rem_addr, pj_cstr(&s, "127.0.0.1"), TEST_UDP_PORT); 
    7878    for (i=0; i<SEND_RECV_LOOP; ++i) { 
    79         status = transport_send_recv_test(PJSIP_TRANSPORT_UDP, tp, &rem_addr); 
     79        status = transport_send_recv_test(PJSIP_TRANSPORT_UDP, tp,  
     80                                          "sip:alice@127.0.0.1:"TEST_UDP_PORT_STR); 
    8081        if (status != 0) 
    8182            return status; 
     
    8384 
    8485    /* Multi-threaded round-trip test. */ 
    85     status = transport_rt_test(PJSIP_TRANSPORT_UDP, tp, &rem_addr); 
     86    status = transport_rt_test(PJSIP_TRANSPORT_UDP, tp,  
     87                               "sip:alice@127.0.0.1:"TEST_UDP_PORT_STR); 
    8688    if (status != 0) 
    8789        return status; 
     
    9496    pjsip_transport_dec_ref(udp_tp); 
    9597 
     98    /* Force destroy this transport. */ 
     99    status = pjsip_transport_unregister( pjsip_endpt_get_tpmgr(endpt), udp_tp); 
     100    if (status != PJ_SUCCESS) 
     101        return -90; 
     102 
     103 
    96104    /* Done */ 
    97105    return 0; 
  • pjproject/trunk/pjsip/src/test-pjsip/txdata_test.c

    • Property svn:keywords changed from "Id Revision" to Id
  • pjproject/trunk/pjsip/src/test-pjsip/uri_test.c

    r106 r107  
    805805        } 
    806806    } 
    807     pjsip_endpt_destroy_pool(endpt, pool); 
     807    pjsip_endpt_release_pool(endpt, pool); 
    808808 
    809809    PJ_LOG(3,("", "  benchmarking...")); 
     
    819819                PJ_LOG(3,("uri_test", "  error %d when testing entry %d", 
    820820                          status, i)); 
    821                 pjsip_endpt_destroy_pool(endpt, pool); 
     821                pjsip_endpt_release_pool(endpt, pool); 
    822822                goto on_return; 
    823823            } 
    824824        } 
    825         pjsip_endpt_destroy_pool(endpt, pool); 
     825        pjsip_endpt_release_pool(endpt, pool); 
    826826    } 
    827827 
Note: See TracChangeset for help on using the changeset viewer.