Changeset 106


Ignore:
Timestamp:
Dec 30, 2005 11:50:15 PM (18 years ago)
Author:
bennylp
Message:

Basic module, transport, and sending messages

Location:
pjproject/trunk
Files:
4 added
29 edited

Legend:

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

    r65 r106  
    6868#endif 
    6969 
     70/** 
     71 * @hideinitializer 
     72 * If #PJ_ENABLE_EXTRA_CHECK is declared and non-zero, then  
     73 * #PJ_ASSERT_ON_FAIL macro will evaluate the expression in @a expr during 
     74 * run-time. If the expression yields false, assertion will be triggered 
     75 * and @a exec_on_fail will be executed. 
     76 * 
     77 * If #PJ_ENABLE_EXTRA_CHECK is not declared or is zero, then no run-time 
     78 * checking will be performed. The macro simply evaluates to pj_assert(expr). 
     79 */ 
     80#if defined(PJ_ENABLE_EXTRA_CHECK) && PJ_ENABLE_EXTRA_CHECK != 0 
     81#   define PJ_ASSERT_ON_FAIL(expr,exec_on_fail)    \ 
     82            do { \ 
     83                pj_assert(expr); \ 
     84                if (!(expr)) exec_on_fail; \ 
     85            } while (0) 
     86#else 
     87#   define PJ_ASSERT_ON_FAIL(expr,exec_on_fail)    pj_assert(expr) 
     88#endif 
     89 
    7090/** @} */ 
    7191 
  • pjproject/trunk/pjlib/include/pj/os.h

    r70 r106  
    505505 * @} 
    506506 */ 
     507 
     508/////////////////////////////////////////////////////////////////////////////// 
     509/** 
     510 * @defgroup PJ_RW_MUTEX Reader/Writer Mutex 
     511 * @ingroup PJ_OS 
     512 * @{ 
     513 * Reader/writer mutex is a classic synchronization object where multiple 
     514 * readers can acquire the mutex, but only a single writer can acquire the  
     515 * mutex. 
     516 */ 
     517typedef struct pj_rwmutex_t pj_rwmutex_t; 
     518 
     519/** 
     520 * Create reader/writer mutex. 
     521 * 
     522 * @param pool      Pool to allocate memory for the mutex. 
     523 * @param name      Name to be assigned to the mutex. 
     524 * @param mutex     Pointer to receive the newly created mutex. 
     525 * 
     526 * @return          PJ_SUCCESS on success, or the error code. 
     527 */ 
     528PJ_DECL(pj_status_t) pj_rwmutex_create(pj_pool_t *pool, const char *name, 
     529                                       pj_rwmutex_t **mutex); 
     530 
     531/** 
     532 * Lock the mutex for reading. 
     533 * 
     534 * @param mutex     The mutex. 
     535 * @return          PJ_SUCCESS on success, or the error code. 
     536 */ 
     537PJ_DECL(pj_status_t) pj_rwmutex_lock_read(pj_rwmutex_t *mutex); 
     538 
     539/** 
     540 * Lock the mutex for writing. 
     541 * 
     542 * @param mutex     The mutex. 
     543 * @return          PJ_SUCCESS on success, or the error code. 
     544 */ 
     545PJ_DECL(pj_status_t) pj_rwmutex_lock_write(pj_rwmutex_t *mutex); 
     546 
     547/** 
     548 * Release read lock. 
     549 * 
     550 * @param mutex     The mutex. 
     551 * @return          PJ_SUCCESS on success, or the error code. 
     552 */ 
     553PJ_DECL(pj_status_t) pj_rwmutex_unlock_read(pj_rwmutex_t *mutex); 
     554 
     555/** 
     556 * Release write lock. 
     557 * 
     558 * @param mutex     The mutex. 
     559 * @return          PJ_SUCCESS on success, or the error code. 
     560 */ 
     561PJ_DECL(pj_status_t) pj_rwmutex_unlock_write(pj_rwmutex_t *mutex); 
     562 
     563/** 
     564 * Destroy reader/writer mutex. 
     565 * 
     566 * @param mutex     The mutex. 
     567 * @return          PJ_SUCCESS on success, or the error code. 
     568 */ 
     569PJ_DECL(pj_status_t) pj_rwmutex_destroy(pj_rwmutex_t *mutex); 
     570 
     571 
     572/** 
     573 * @} 
     574 */ 
     575 
    507576 
    508577/////////////////////////////////////////////////////////////////////////////// 
  • pjproject/trunk/pjlib/include/pj/sock.h

    r66 r106  
    177177 * This structure describes Internet socket address. 
    178178 */ 
    179 typedef struct pj_sockaddr_in 
     179struct pj_sockaddr_in 
    180180{ 
    181181    pj_uint16_t sin_family;     /**< Address family.                */ 
     
    183183    pj_in_addr  sin_addr;       /**< IP address.                    */ 
    184184    char        sin_zero[8];    /**< Padding.                       */ 
    185 } pj_sockaddr_in; 
     185}; 
    186186 
    187187 
  • pjproject/trunk/pjlib/include/pj/types.h

    r66 r106  
    218218/** Generic socket address. */ 
    219219typedef void pj_sockaddr_t; 
     220 
     221/** Forward declaration. */ 
     222typedef struct pj_sockaddr_in pj_sockaddr_in; 
    220223 
    221224/** Color type. */ 
  • pjproject/trunk/pjlib/src/pj/os_core_win32.c

    r70 r106  
    860860 
    861861/////////////////////////////////////////////////////////////////////////////// 
     862 
     863struct pj_rwmutex_t 
     864{ 
     865    pj_mutex_t *read_lock, *write_lock; 
     866    int reader_count; 
     867}; 
     868 
     869/* 
     870 * Create reader/writer mutex. 
     871 * 
     872 */ 
     873PJ_DEF(pj_status_t) pj_rwmutex_create(pj_pool_t *pool, const char *name, 
     874                                      pj_rwmutex_t **p_mutex) 
     875{ 
     876    pj_status_t status; 
     877    pj_rwmutex_t *rwmutex; 
     878 
     879    PJ_ASSERT_RETURN(pool && p_mutex, PJ_EINVAL); 
     880 
     881    *p_mutex = NULL; 
     882    rwmutex = pj_pool_alloc(pool, sizeof(struct pj_rwmutex_t)); 
     883 
     884    status = pj_mutex_create_simple(pool, name, &rwmutex ->read_lock); 
     885    if (status != PJ_SUCCESS) 
     886        return status; 
     887 
     888    status = pj_mutex_create_recursive(pool, name, &rwmutex->write_lock); 
     889    if (status != PJ_SUCCESS) { 
     890        pj_mutex_destroy(rwmutex->read_lock); 
     891        return status; 
     892    } 
     893 
     894    rwmutex->reader_count = 0; 
     895    *p_mutex = rwmutex; 
     896    return PJ_SUCCESS; 
     897} 
     898 
     899/* 
     900 * Lock the mutex for reading. 
     901 * 
     902 */ 
     903PJ_DEF(pj_status_t) pj_rwmutex_lock_read(pj_rwmutex_t *mutex) 
     904{ 
     905    pj_status_t status; 
     906 
     907    PJ_ASSERT_RETURN(mutex, PJ_EINVAL); 
     908 
     909    status = pj_mutex_lock(mutex->read_lock); 
     910    if (status != PJ_SUCCESS) 
     911        return status; 
     912 
     913    mutex->reader_count++; 
     914    if (mutex->reader_count == 1) 
     915        pj_mutex_lock(mutex->write_lock); 
     916 
     917    status = pj_mutex_unlock(mutex->read_lock); 
     918    return status; 
     919} 
     920 
     921/* 
     922 * Lock the mutex for writing. 
     923 * 
     924 */ 
     925PJ_DEF(pj_status_t) pj_rwmutex_lock_write(pj_rwmutex_t *mutex) 
     926{ 
     927    PJ_ASSERT_RETURN(mutex, PJ_EINVAL); 
     928    return pj_mutex_lock(mutex->write_lock); 
     929} 
     930 
     931/* 
     932 * Release read lock. 
     933 * 
     934 */ 
     935PJ_DEF(pj_status_t) pj_rwmutex_unlock_read(pj_rwmutex_t *mutex) 
     936{ 
     937    pj_status_t status; 
     938 
     939    PJ_ASSERT_RETURN(mutex, PJ_EINVAL); 
     940 
     941    status = pj_mutex_lock(mutex->read_lock); 
     942    if (status != PJ_SUCCESS) 
     943        return status; 
     944 
     945    pj_assert(mutex->reader_count >= 1); 
     946 
     947    --mutex->reader_count; 
     948    if (mutex->reader_count == 0) 
     949        pj_mutex_unlock(mutex->write_lock); 
     950 
     951    status = pj_mutex_unlock(mutex->read_lock); 
     952    return status; 
     953} 
     954 
     955/* 
     956 * Release write lock. 
     957 * 
     958 */ 
     959PJ_DEF(pj_status_t) pj_rwmutex_unlock_write(pj_rwmutex_t *mutex) 
     960{ 
     961    PJ_ASSERT_RETURN(mutex, PJ_EINVAL); 
     962    return pj_mutex_unlock(mutex->write_lock); 
     963} 
     964 
     965 
     966/* 
     967 * Destroy reader/writer mutex. 
     968 * 
     969 */ 
     970PJ_DEF(pj_status_t) pj_rwmutex_destroy(pj_rwmutex_t *mutex) 
     971{ 
     972    PJ_ASSERT_RETURN(mutex, PJ_EINVAL); 
     973    pj_mutex_destroy(mutex->read_lock); 
     974    pj_mutex_destroy(mutex->write_lock); 
     975    return PJ_SUCCESS; 
     976} 
     977 
     978/////////////////////////////////////////////////////////////////////////////// 
    862979/* 
    863980 * pj_enter_critical_section() 
  • pjproject/trunk/pjlib/src/pj/sock_bsd.c

    r66 r106  
    188188    PJ_CHECK_STACK(); 
    189189 
    190     PJ_ASSERT_RETURN(str_addr && str_addr->slen < PJ_MAX_HOSTNAME,  
     190    PJ_ASSERT_RETURN(!str_addr || str_addr->slen < PJ_MAX_HOSTNAME,  
    191191                     (addr->sin_addr.s_addr=PJ_INADDR_NONE, PJ_EINVAL)); 
    192192 
     
    225225                                         pj_uint16_t port) 
    226226{ 
    227     PJ_ASSERT_RETURN(addr && str_addr,  
    228                      (addr->sin_addr.s_addr=PJ_INADDR_NONE, PJ_EINVAL)); 
     227    PJ_ASSERT_RETURN(addr, (addr->sin_addr.s_addr=PJ_INADDR_NONE, PJ_EINVAL)); 
    229228 
    230229    addr->sin_family = PJ_AF_INET; 
  • pjproject/trunk/pjsip/build/pjsip_core.dsp

    r82 r106  
    125125 
    126126SOURCE=..\src\pjsip\sip_transaction.c 
     127# PROP Exclude_From_Build 1 
    127128# End Source File 
    128129# Begin Source File 
     
    141142 
    142143SOURCE=..\src\pjsip\sip_util.c 
     144# End Source File 
     145# Begin Source File 
     146 
     147SOURCE=..\src\pjsip\sip_util_statefull.c 
     148# PROP Exclude_From_Build 1 
    143149# End Source File 
    144150# End Group 
  • pjproject/trunk/pjsip/build/test_pjsip.dsp

    r105 r106  
    102102# Begin Source File 
    103103 
     104SOURCE="..\src\test-pjsip\transport_test.c" 
     105# End Source File 
     106# Begin Source File 
     107 
     108SOURCE="..\src\test-pjsip\transport_udp_test.c" 
     109# End Source File 
     110# Begin Source File 
     111 
     112SOURCE="..\src\test-pjsip\txdata_test.c" 
     113# End Source File 
     114# Begin Source File 
     115 
    104116SOURCE="..\src\test-pjsip\uri_test.c" 
    105117# End Source File 
  • pjproject/trunk/pjsip/include/pjsip/sip_endpoint.h

    r105 r106  
    116116                                         const pj_time_val *max_timeout); 
    117117 
     118 
     119/** 
     120 * Schedule timer to endpoint's timer heap. Application must poll the endpoint 
     121 * periodically (by calling #pjsip_endpt_handle_events) to ensure that the 
     122 * timer events are handled in timely manner. When the timeout for the timer 
     123 * has elapsed, the callback specified in the entry argument will be called. 
     124 * This function, like all other endpoint functions, is thread safe. 
     125 * 
     126 * @param endpt     The endpoint. 
     127 * @param entry     The timer entry. 
     128 * @param delay     The relative delay of the timer. 
     129 * @return          PJ_OK (zero) if successfull. 
     130 */ 
     131PJ_DECL(pj_status_t) pjsip_endpt_schedule_timer( pjsip_endpoint *endpt, 
     132                                                 pj_timer_entry *entry, 
     133                                                 const pj_time_val *delay ); 
     134 
     135/** 
     136 * Cancel the previously registered timer. 
     137 * This function, like all other endpoint functions, is thread safe. 
     138 * 
     139 * @param endpt     The endpoint. 
     140 * @param entry     The timer entry previously registered. 
     141 */ 
     142PJ_DECL(void) pjsip_endpt_cancel_timer( pjsip_endpoint *endpt,  
     143                                        pj_timer_entry *entry ); 
     144 
     145 
    118146/** 
    119147 * Dump endpoint status to the log. This will print the status to the log 
     
    126154 */ 
    127155PJ_DECL(void) pjsip_endpt_dump( pjsip_endpoint *endpt, pj_bool_t detail ); 
     156 
     157 
     158/** 
     159 * Register new module to the endpoint. 
     160 * The endpoint will then call the load and start function in the module to  
     161 * properly initialize the module, and assign a unique module ID for the  
     162 * module. 
     163 * 
     164 * @param endpt         The endpoint. 
     165 * @param module        The module to be registered. 
     166 * 
     167 * @return              PJ_SUCCESS on success. 
     168 */ 
     169PJ_DECL(pj_status_t) pjsip_endpt_register_module( pjsip_endpoint *endpt, 
     170                                                  pjsip_module *module ); 
     171 
     172/** 
     173 * Unregister a module from the endpoint. 
     174 * The endpoint will then call the stop and unload function in the module to  
     175 * properly shutdown the module. 
     176 * 
     177 * @param endpt         The endpoint. 
     178 * @param module        The module to be registered. 
     179 * 
     180 * @return              PJ_SUCCESS on success. 
     181 */ 
     182PJ_DECL(pj_status_t) pjsip_endpt_unregister_module( pjsip_endpoint *endpt, 
     183                                                    pjsip_module *module ); 
     184 
    128185 
    129186/** 
     
    157214 
    158215/** 
    159  * Schedule timer to endpoint's timer heap. Application must poll the endpoint 
    160  * periodically (by calling #pjsip_endpt_handle_events) to ensure that the 
    161  * timer events are handled in timely manner. When the timeout for the timer 
    162  * has elapsed, the callback specified in the entry argument will be called. 
    163  * This function, like all other endpoint functions, is thread safe. 
    164  * 
    165  * @param endpt     The endpoint. 
    166  * @param entry     The timer entry. 
    167  * @param delay     The relative delay of the timer. 
    168  * @return          PJ_OK (zero) if successfull. 
    169  */ 
    170 PJ_DECL(pj_status_t) pjsip_endpt_schedule_timer( pjsip_endpoint *endpt, 
    171                                                  pj_timer_entry *entry, 
    172                                                  const pj_time_val *delay ); 
    173  
    174 /** 
    175  * Cancel the previously registered timer. 
    176  * This function, like all other endpoint functions, is thread safe. 
    177  * 
    178  * @param endpt     The endpoint. 
    179  * @param entry     The timer entry previously registered. 
    180  */ 
    181 PJ_DECL(void) pjsip_endpt_cancel_timer( pjsip_endpoint *endpt,  
    182                                         pj_timer_entry *entry ); 
    183  
    184 /** 
    185216 * Create a new transaction. After creating the transaction, application MUST 
    186217 * initialize the transaction as either UAC or UAS (by calling 
     
    279310 * @see pjsip_transport_get 
    280311 */ 
    281 PJ_DECL(pj_status_t) pjsip_endpt_alloc_transport( pjsip_endpoint *endpt, 
    282                                                   pjsip_transport_type_e type, 
    283                                                   const pj_sockaddr *remote, 
    284                                                   int addr_len, 
    285                                                   pjsip_transport **p_transport); 
     312PJ_DECL(pj_status_t)  
     313pjsip_endpt_acquire_transport( pjsip_endpoint *endpt, 
     314                               pjsip_transport_type_e type, 
     315                               const pj_sockaddr_t *remote, 
     316                               int addr_len, 
     317                               pjsip_transport **p_transport); 
    286318 
    287319/** 
  • pjproject/trunk/pjsip/include/pjsip/sip_errno.h

    r65 r106  
    9494/** 
    9595 * @hideinitializer 
    96  * Invalid message (syntax error) 
     96 * General invalid message error (e.g. syntax error) 
    9797 */ 
    9898#define PJSIP_EINVALIDMSG       (PJSIP_ERRNO_START_PJSIP + 20)  /* 171020 */ 
     
    114114/** 
    115115 * @hideinitializer 
     116 * Missing Request-URI. 
     117 */ 
     118#define PJSIP_EMISSINGREQURI    (PJSIP_ERRNO_START_PJSIP + 24)  /* 171024 */ 
     119/** 
     120 * @hideinitializer 
    116121 * Missing required header(s). 
    117122 */ 
    118 #define PJSIP_EMISSINGHDR       (PJSIP_ERRNO_START_PJSIP + 24)  /* 171024 */ 
     123#define PJSIP_EMISSINGHDR       (PJSIP_ERRNO_START_PJSIP + 25)  /* 171025 */ 
     124/** 
     125 * @hideinitializer 
     126 * Missing message body. 
     127 */ 
     128#define PJSIP_EMISSINGBODY      (PJSIP_ERRNO_START_PJSIP + 26)  /* 171026 */ 
    119129/** 
    120130 * @hideinitializer 
    121131 * Invalid Via header in response (sent-by, etc). 
    122132 */ 
    123 #define PJSIP_EINVALIDVIA       (PJSIP_ERRNO_START_PJSIP + 25)  /* 171025 */ 
     133#define PJSIP_EINVALIDVIA       (PJSIP_ERRNO_START_PJSIP + 27)  /* 171027 */ 
    124134/** 
    125135 * @hideinitializer 
    126136 * Multiple Via headers in response. 
    127137 */ 
    128 #define PJSIP_EMULTIPLEVIA      (PJSIP_ERRNO_START_PJSIP + 26)  /* 171026 */ 
     138#define PJSIP_EMULTIPLEVIA      (PJSIP_ERRNO_START_PJSIP + 28)  /* 171028 */ 
     139/** 
     140 * @hideinitializer 
     141 * Invalid request URI. 
     142 */ 
     143#define PJSIP_EINVALIDREQURI    (PJSIP_ERRNO_START_PJSIP + 29)  /* 171029 */ 
     144/** 
     145 * @hideinitializer 
     146 * Expecting request message. 
     147 */ 
     148#define PJSIP_ENOTREQUESTMSG    (PJSIP_ERRNO_START_PJSIP + 30)  /* 171030 */ 
     149/** 
     150 * @hideinitializer 
     151 * Expecting response message. 
     152 */ 
     153#define PJSIP_ENOTRESPONSEMSG   (PJSIP_ERRNO_START_PJSIP + 31)  /* 171031 */ 
     154 
    129155 
    130156/************************************************************ 
     
    145171 * Rx buffer overflow. See also PJSIP_EMSGTOOLONG. 
    146172 */ 
    147 #define PJSIP_ERXOVERFLOW         (PJSIP_ERRNO_START_PJSIP + 42)/* 171042 */ 
     173#define PJSIP_ERXOVERFLOW       (PJSIP_ERRNO_START_PJSIP + 42)  /* 171042 */ 
     174/** 
     175 * @hideinitializer 
     176 * This is not really an error, it just informs application that 
     177 * transmit data has been deleted on return of pjsip_tx_data_dec_ref(). 
     178 */ 
     179#define PJSIP_EBUFDESTROYED     (PJSIP_ERRNO_START_PJSIP + 43)  /* 171043 */ 
    148180 
    149181 
  • pjproject/trunk/pjsip/include/pjsip/sip_module.h

    r65 r106  
    4242struct pjsip_module 
    4343{ 
     44    /** To allow chaining of modules in the endpoint. */ 
     45    PJ_DECL_LIST_MEMBER(struct pjsip_module); 
     46 
    4447    /** 
    4548     * Module name. 
     
    4851 
    4952    /** 
    50      * Flag to indicate the type of interfaces supported by the module. 
     53     * Module ID. 
    5154     */ 
    52     pj_uint32_t flag; 
     55    int id; 
    5356 
    5457    /** 
     
    5760     * initialized later. 
    5861     */ 
    59     pj_uint32_t priority; 
     62    int priority; 
    6063 
    6164    /** 
     
    6366     * the module itself. 
    6467     */ 
    65     void *mod_data; 
     68    void *user_data; 
    6669 
    6770    /** 
     
    7982     * 
    8083     * @param endpt     The endpoint instance. 
    81      * @param mod       The module. 
    82      * @param id        The unique module ID assigned to this module. 
    83      * 
    84      * @return          Module should return zero when initialization succeed. 
     84     * @return          Module should return PJ_SUCCESS to indicate success. 
    8585     */ 
    86     pj_status_t (*init_module)(pjsip_endpoint *endpt, 
    87                                struct pjsip_module *mod, pj_uint32_t id); 
     86    pj_status_t (*load)(pjsip_endpoint *endpt); 
    8887 
    8988    /** 
    9089     * Pointer to function to be called to start the module. 
    9190     * 
    92      * @param mod       The module. 
    93      * 
    9491     * @return          Module should return zero to indicate success. 
    9592     */ 
    96     pj_status_t (*start_module)(struct pjsip_module *mod); 
     93    pj_status_t (*start)(void); 
     94 
     95    /** 
     96     * Pointer to function to be called to deinitialize the module before 
     97     * it is unloaded. 
     98     * 
     99     * @return          Module should return PJ_SUCCESS to indicate success. 
     100     */ 
     101    pj_status_t (*stop)(void); 
    97102 
    98103    /** 
     
    102107     * @param mod       The module. 
    103108     * 
    104      * @return          Module should return zero to indicate success. 
     109     * @return          Module should return PJ_SUCCESS to indicate success. 
    105110     */ 
    106     pj_status_t (*deinit_module)(struct pjsip_module *mod); 
     111    pj_status_t (*unload)(void); 
    107112 
    108113    /** 
    109      * Pointer to function to receive transaction related events. 
    110      * If the module doesn't wish to receive such notification, this member 
    111      * must be set to NULL. 
     114     * Called to process incoming request. 
    112115     * 
    113      * @param mod       The module. 
    114      * @param event     The transaction event. 
     116     * @param rdata     The incoming message. 
     117     * 
     118     * @return          Module should return PJ_TRUE if it handles the request, 
     119     *                  or otherwise it should return PJ_FALSE to allow other 
     120     *                  modules to handle the request. 
    115121     */ 
    116     void (*tsx_handler)(struct pjsip_module *mod, pjsip_event *event); 
     122    pj_bool_t (*on_rx_request)(pjsip_rx_data *rdata); 
     123 
     124    /** 
     125     * Called to processed incoming response. 
     126     * 
     127     * @param rdata     The incoming message. 
     128     * 
     129     * @return          Module should return PJ_TRUE if it handles the  
     130     *                  response, or otherwise it should return PJ_FALSE to  
     131     *                  allow other modules to handle the response. 
     132     */ 
     133    pj_bool_t (*on_rx_response)(pjsip_rx_data *rdata); 
     134 
     135    /** 
     136     * Called when this module is acting as transaction user for the specified 
     137     * transaction, when the transaction's state has changed. 
     138     * 
     139     * @param tsx       The transaction. 
     140     * @param event     The event which has caused the transaction state 
     141     *                  to change. 
     142     */ 
     143    void (*on_tsx_state)(pjsip_transaction *tsx, pjsip_event *event); 
     144 
    117145}; 
    118146 
    119147 
    120148/** 
    121  * Prototype of function to register static modules (eg modules that are 
    122  * linked staticly with the application). This function must be implemented  
    123  * by any applications that use PJSIP library. 
    124  * 
    125  * @param count     [input/output] On input, it contains the maximum number of 
    126  *                  elements in the array. On output, the function fills with  
    127  *                  the number of modules to be registered. 
    128  * @param modules   [output] array of pointer to modules to be registered. 
     149 * Module priority guidelines. 
    129150 */ 
    130 pj_status_t register_static_modules( pj_size_t *count, 
    131                                      pjsip_module **modules ); 
     151enum pjsip_module_priority 
     152{ 
     153    PJSIP_MOD_PRIORITY_TSX_LAYER = 4, 
     154    PJSIP_MOD_PRIORITY_UA_PROXY_LAYER = 16, 
     155    PJSIP_MOD_PRIORITY_APPLICATION = 32, 
     156}; 
     157 
    132158 
    133159/** 
  • pjproject/trunk/pjsip/include/pjsip/sip_msg.h

    r65 r106  
    5353typedef enum pjsip_method_e 
    5454{ 
    55     /** INVITE method, for establishing dialogs. */ 
    56     PJSIP_INVITE_METHOD, 
    57  
    58     /** CANCEL method, for cancelling request. */ 
    59     PJSIP_CANCEL_METHOD, 
    60  
    61     /** ACK method, for acknowledging final response to INVITE. */ 
    62     PJSIP_ACK_METHOD, 
    63  
    64     /** BYE method, for terminating dialog. */ 
    65     PJSIP_BYE_METHOD, 
    66  
    67     /** REGISTER method. */ 
    68     PJSIP_REGISTER_METHOD, 
    69  
    70     /** OPTIONS method, for querying remote capabilities. */ 
    71     PJSIP_OPTIONS_METHOD, 
    72  
    73     /** Other method, which means that the method name itself will be stored 
    74         elsewhere. */ 
    75     PJSIP_OTHER_METHOD, 
     55    PJSIP_INVITE_METHOD,    /**< INVITE method, for establishing dialogs.   */ 
     56    PJSIP_CANCEL_METHOD,    /**< CANCEL method, for cancelling request.     */ 
     57    PJSIP_ACK_METHOD,       /**< ACK method.                                */ 
     58    PJSIP_BYE_METHOD,       /**< BYE method, for terminating dialog.        */ 
     59    PJSIP_REGISTER_METHOD,  /**< REGISTER method.                           */ 
     60    PJSIP_OPTIONS_METHOD,   /**< OPTIONS method.                            */ 
     61 
     62    PJSIP_OTHER_METHOD,     /**< Other method.                              */ 
    7663 
    7764} pjsip_method_e; 
     
    9279                                 method string. */ 
    9380} pjsip_method; 
     81 
     82 
     83/* 
     84 * For convenience, standard method structures are defined in the library. 
     85 */ 
     86extern const pjsip_method pjsip_invite_method;      /**< INVITE structure.  */ 
     87extern const pjsip_method pjsip_cancel_method;      /**< CANCEL structure.  */ 
     88extern const pjsip_method pjsip_ack_method;         /**< ACK structure.     */ 
     89extern const pjsip_method pjsip_bye_method;         /**< BYE structure.     */ 
     90extern const pjsip_method pjsip_register_method;    /**< REGISTER structure.*/ 
     91extern const pjsip_method pjsip_options_method;     /**< OPTIONS structure. */ 
    9492 
    9593 
     
    639637 *                  type is found. 
    640638 */ 
    641 PJ_DECL(void*)  pjsip_msg_find_hdr( pjsip_msg *msg,  
    642                                     pjsip_hdr_e type, void *start); 
     639PJ_DECL(void*)  pjsip_msg_find_hdr( const pjsip_msg *msg,  
     640                                    pjsip_hdr_e type, const void *start); 
    643641 
    644642/**  
     
    655653 *                  type is found. 
    656654 */ 
    657 PJ_DECL(void*)  pjsip_msg_find_hdr_by_name( pjsip_msg *msg,  
    658                                             const pj_str_t *name, void *start); 
     655PJ_DECL(void*)  pjsip_msg_find_hdr_by_name( const pjsip_msg *msg,  
     656                                            const pj_str_t *name,  
     657                                            const void *start); 
    659658 
    660659/**  
     
    703702 *              value if the message is too large for the specified buffer. 
    704703 */ 
    705 PJ_DECL(pj_ssize_t) pjsip_msg_print(pjsip_msg *msg, char *buf, pj_size_t size); 
     704PJ_DECL(pj_ssize_t) pjsip_msg_print(const pjsip_msg *msg,  
     705                                    char *buf, pj_size_t size); 
    706706 
    707707/** 
  • pjproject/trunk/pjsip/include/pjsip/sip_transport.h

    r105 r106  
    368368/** 
    369369 * Decrement reference counter of the transmit buffer. 
    370  * When the transmit buffer is no longer used, it will be destroyed. 
     370 * When the transmit buffer is no longer used, it will be destroyed and 
     371 * caller is informed with PJSIP_EBUFDESTROYED return status. 
    371372 * 
    372373 * @param tdata     The transmit buffer data. 
    373  */ 
    374 PJ_DECL(void) pjsip_tx_data_dec_ref( pjsip_tx_data *tdata ); 
     374 * @return          This function will always succeeded eventhough the return 
     375 *                  status is non-zero. A status PJSIP_EBUFDESTROYED will be 
     376 *                  returned to inform that buffer is destroyed. 
     377 */ 
     378PJ_DECL(pj_status_t) pjsip_tx_data_dec_ref( pjsip_tx_data *tdata ); 
    375379 
    376380/** 
     
    378382 * 
    379383 * @param tdata     The transmit buffer. 
     384 * @return          Non-zero (PJ_TRUE) if buffer contains a valid message. 
    380385 */ 
    381386PJ_DECL(pj_bool_t) pjsip_tx_data_is_valid( pjsip_tx_data *tdata ); 
     
    543548    /** 
    544549     * Create new outbound connection. 
     550     * Note that the factory is responsible for both creating the 
     551     * transport and registering it to the transport manager. 
    545552     */ 
    546553    pj_status_t (*create_transport)(pjsip_tpfactory *factory, 
     
    548555                                    pjsip_endpoint *endpt, 
    549556                                    const pj_sockaddr *rem_addr, 
     557                                    int addr_len, 
    550558                                    pjsip_transport **transport); 
    551559 
     
    622630 * suitable transport is found, a new one will be created. 
    623631 */ 
    624 PJ_DECL(pj_status_t) pjsip_tpmgr_alloc_transport( pjsip_tpmgr *mgr, 
    625                                                   pjsip_transport_type_e type, 
    626                                                   const pj_sockaddr_t *remote, 
    627                                                   int addr_len, 
    628                                                   pjsip_transport **p_transport ); 
     632PJ_DECL(pj_status_t) pjsip_tpmgr_acquire_transport(pjsip_tpmgr *mgr, 
     633                                                   pjsip_transport_type_e type, 
     634                                                   const pj_sockaddr_t *remote, 
     635                                                   int addr_len, 
     636                                                   pjsip_transport **tp); 
    629637 
    630638 
  • pjproject/trunk/pjsip/include/pjsip/sip_transport_udp.h

    r105 r106  
    2222#include <pjsip/sip_transport.h> 
    2323 
    24 PJ_DECL 
     24PJ_BEGIN_DECL 
    2525 
    2626/** 
  • pjproject/trunk/pjsip/include/pjsip/sip_util.h

    r105 r106  
    2121 
    2222#include <pjsip/sip_msg.h> 
     23#include <pjsip/sip_resolve.h> 
    2324 
    2425PJ_BEGIN_DECL 
     
    3435 * request outside a dialog, such as OPTIONS, MESSAGE, etc. To create a request 
    3536 * inside a dialog, application should use #pjsip_dlg_create_request. 
     37 * 
     38 * This function adds the following headers in the request: 
     39 *  - From, To, Call-ID, and CSeq, 
     40 *  - Contact header, if contact is specified. 
     41 *  - A blank Via header. 
     42 *  - Additional request headers (such as Max-Forwards) which are copied 
     43 *    from endpoint configuration. 
     44 * 
     45 * In addition, the function adds a unique tag in the From header. 
    3646 * 
    3747 * Once a transmit data is created, the reference counter is initialized to 1. 
     
    6373/** 
    6474 * Create an independent request message from the specified headers. This 
    65  * function will shallow clone the headers and put them in the request. 
     75 * function will clone the headers and put them in the request. 
     76 * 
     77 * This function adds the following headers in the request: 
     78 *  - From, To, Call-ID, and CSeq, 
     79 *  - Contact header, if contact is specified. 
     80 *  - A blank Via header. 
     81 *  - Additional request headers (such as Max-Forwards) which are copied 
     82 *    from endpoint configuration. 
     83 * 
     84 * In addition, the function adds a unique tag in the From header. 
    6685 * 
    6786 * Once a transmit data is created, the reference counter is initialized to 1. 
     
    93112 
    94113/** 
     114 * Construct a minimal response message for the received request. This function 
     115 * will construct all the Via, Record-Route, Call-ID, From, To, CSeq, and  
     116 * Call-ID headers from the request. 
     117 * 
     118 * Note: the txdata reference counter is set to ZERO!. 
     119 * 
     120 * @param endpt     The endpoint. 
     121 * @param rdata     The request receive data. 
     122 * @param st_code   Status code to be put in the response. 
     123 * @param st_text   Optional status text, or NULL to get the default text. 
     124 * @param p_tdata   Pointer to receive the transmit data. 
     125 * 
     126 * @return          PJ_SUCCESS, or the appropriate error code. 
     127 */ 
     128PJ_DECL(pj_status_t) pjsip_endpt_create_response( pjsip_endpoint *endpt, 
     129                                                  const pjsip_rx_data *rdata, 
     130                                                  int st_code, 
     131                                                  const pj_str_t *st_text, 
     132                                                  pjsip_tx_data **p_tdata); 
     133 
     134/** 
     135 * Construct a full ACK request for the received non-2xx final response. 
     136 * This utility function is normally called by the transaction to construct 
     137 * an ACK request to 3xx-6xx final response. 
     138 * The generation of ACK message for 2xx final response is different than 
     139 * this one. 
     140 *  
     141 * @param endpt     The endpoint. 
     142 * @param tdata     This contains the original INVITE request 
     143 * @param rdata     The final response. 
     144 * @param ack       The ACK request created. 
     145 * 
     146 * @return          PJ_SUCCESS, or the appropriate error code. 
     147 */ 
     148PJ_DECL(pj_status_t) pjsip_endpt_create_ack( pjsip_endpoint *endpt, 
     149                                             const pjsip_tx_data *tdata, 
     150                                             const pjsip_rx_data *rdata, 
     151                                             pjsip_tx_data **ack); 
     152 
     153 
     154/** 
     155 * Construct CANCEL request for the previously sent request. 
     156 * 
     157 * @param endpt     The endpoint. 
     158 * @param tdata     The transmit buffer for the request being cancelled. 
     159 * @param p_tdata   Pointer to receive the transmit data. 
     160 * 
     161 * @return          PJ_SUCCESS, or the appropriate error code. 
     162 */ 
     163PJ_DECL(pj_status_t) pjsip_endpt_create_cancel( pjsip_endpoint *endpt, 
     164                                                const pjsip_tx_data *tdata, 
     165                                                pjsip_tx_data **p_tdata); 
     166 
     167 
     168/** 
     169 * Find which destination to be used to send the request message, based 
     170 * on the request URI and Route headers in the message. The procedure 
     171 * used here follows the guidelines on sending the request in RFC 3261 
     172 * chapter 8.1.2. 
     173 * 
     174 * This function may modify the message (request line and Route headers), 
     175 * if the Route information specifies strict routing and the request 
     176 * URI in the message is different than the calculated target URI. In that 
     177 * case, the target URI will be put as the request URI of the request and 
     178 * current request URI will be put as the last entry of the Route headers. 
     179 * 
     180 * @param tdata     The transmit data containing the request message. 
     181 * @param dest_info On return, it contains information about destination 
     182 *                  host to contact, along with the preferable transport 
     183 *                  type, if any. Caller will then normally proceed with 
     184 *                  resolving this host with server resolution procedure 
     185 *                  described in RFC 3263. 
     186 * 
     187 * @return          PJ_SUCCESS, or the appropriate error code. 
     188 */ 
     189PJ_DECL(pj_status_t) pjsip_get_request_addr( pjsip_tx_data *tdata, 
     190                                             pjsip_host_info *dest_info ); 
     191 
     192 
     193/** 
     194 * This structure holds the state of outgoing stateless request. 
     195 */ 
     196typedef struct pjsip_send_state 
     197{ 
     198    /** Application token, which was specified when the function 
     199     *  #pjsip_endpt_send_request_stateless() is called. 
     200     */ 
     201    void *token; 
     202 
     203    /** Endpoint instance.  
     204     */ 
     205    pjsip_endpoint *endpt; 
     206 
     207    /** Transmit data buffer being sent.  
     208     */ 
     209    pjsip_tx_data *tdata; 
     210 
     211    /** Server addresses resolved.  
     212     */ 
     213    pjsip_server_addresses   addr; 
     214 
     215    /** Current server address being tried.  
     216     */ 
     217    unsigned cur_addr; 
     218 
     219    /** Current transport being used.  
     220     */ 
     221    pjsip_transport *cur_transport; 
     222 
     223    /** The application callback which was specified when the function 
     224     *  #pjsip_endpt_send_request_stateless() was called. 
     225     */ 
     226    void (*app_cb)(struct pjsip_send_state*, 
     227                   pj_ssize_t sent, 
     228                   pj_bool_t *cont); 
     229} pjsip_send_state; 
     230 
     231/** 
     232 * Send outgoing request statelessly The function will take care of which  
     233 * destination and transport to use based on the information in the message, 
     234 * taking care of URI in the request line and Route header. 
     235 * 
     236 * This function is different than #pjsip_transport_send() in that this  
     237 * function adds/modify the Via header as necessary. 
     238 * 
     239 * @param endpt     The endpoint instance. 
     240 * @param tdata     The transmit data to be sent. 
     241 * 
     242 * @return          PJ_SUCCESS, or the appropriate error code. 
     243 */ 
     244PJ_DECL(pj_status_t)  
     245pjsip_endpt_send_request_stateless( pjsip_endpoint *endpt, 
     246                                    pjsip_tx_data *tdata, 
     247                                    void *token, 
     248                                    void (*cb)(pjsip_send_state*, 
     249                                               pj_ssize_t sent, 
     250                                               pj_bool_t *cont)); 
     251 
     252/** 
     253 * This structure describes destination information to send response. 
     254 * It is initialized by calling #pjsip_get_response_addr(). 
     255 * 
     256 * If the response message should be sent using transport from which 
     257 * the request was received, then transport, addr, and addr_len fields 
     258 * are initialized. 
     259 * 
     260 * The dst_host field is also initialized. It should be used when server 
     261 * fails to send the response using the transport from which the request 
     262 * was received, or when the transport is NULL, which means server 
     263 * must send the response to this address (this situation occurs when 
     264 * maddr parameter is set, or when rport param is not set in the request). 
     265 */ 
     266typedef struct pjsip_response_addr 
     267{ 
     268    pjsip_transport *transport; /**< Immediate transport to be used. */ 
     269    pj_sockaddr      addr;      /**< Immediate address to send to.   */ 
     270    int              addr_len;  /**< Address length.                 */ 
     271    pjsip_host_info  dst_host;  /**< Destination host to contact.    */ 
     272} pjsip_response_addr; 
     273 
     274/** 
     275 * Determine which address (and transport) to use to send response message 
     276 * based on the received request. This function follows the specification 
     277 * in section 18.2.2 of RFC 3261 and RFC 3581 for calculating the destination 
     278 * address and transport. 
     279 * 
     280 * The information about destination to send the response will be returned 
     281 * in res_addr argument. Please see #pjsip_response_addr for more info. 
     282 * 
     283 * @param pool      The pool. 
     284 * @param rdata     The incoming request received by the server. 
     285 * @param res_addr  On return, it will be initialized with information about 
     286 *                  destination address and transport to send the response. 
     287 * 
     288 * @return          zero (PJ_OK) if successfull. 
     289 */ 
     290PJ_DECL(pj_status_t) pjsip_get_response_addr(pj_pool_t *pool, 
     291                                             pjsip_rx_data *rdata, 
     292                                             pjsip_response_addr *res_addr); 
     293 
     294/** 
     295 * Send response in tdata statelessly. The function will take care of which  
     296 * response destination and transport to use based on the information in the  
     297 * Via header (such as the presence of rport, symmetric transport, etc.). 
     298 * 
     299 * This function will create a new ephemeral transport if no existing  
     300 * transports can be used to send the message to the destination. The ephemeral 
     301 * transport will be destroyed after some period if it is not used to send any  
     302 * more messages. 
     303 * 
     304 * The behavior of this function complies with section 18.2.2 of RFC 3261 
     305 * and RFC 3581. 
     306 * 
     307 * @param endpt     The endpoint instance. 
     308 * @param res_addr  The information about the address and transport to send 
     309 *                  the response to. Application can get this information 
     310 *                  by calling #pjsip_get_response_addr(). 
     311 * @param tdata     The response message to be sent. 
     312 * @param token     Token to be passed back when the callback is called. 
     313 * @param cb        Optional callback to notify the transmission status 
     314 *                  to application, and to inform whether next address or 
     315 *                  transport will be tried. 
     316 *  
     317 * @return          PJ_SUCCESS if response has been successfully created and 
     318 *                  sent to transport layer, or a non-zero error code.  
     319 *                  However, even when it returns PJ_SUCCESS, there is no  
     320 *                  guarantee that the response has been successfully sent. 
     321 */ 
     322PJ_DECL(pj_status_t) pjsip_endpt_send_response( pjsip_endpoint *endpt, 
     323                                                pjsip_response_addr *res_addr, 
     324                                                pjsip_tx_data *tdata, 
     325                                                void *token, 
     326                                                void (*cb)(pjsip_send_state*, 
     327                                                           pj_ssize_t sent, 
     328                                                           pj_bool_t *cont)); 
     329 
     330/** 
    95331 * Send outgoing request and initiate UAC transaction for the request. 
    96332 * This is an auxiliary function to be used by application to send arbitrary 
     
    117353                                               void (*cb)(void*,pjsip_event*)); 
    118354 
    119 /** 
    120  * Construct a minimal response message for the received request. This function 
    121  * will construct all the Via, Record-Route, Call-ID, From, To, CSeq, and  
    122  * Call-ID headers from the request. 
    123  * 
    124  * Note: the txdata reference counter is set to ZERO!. 
    125  * 
    126  * @param endpt     The endpoint. 
    127  * @param rdata     The request receive data. 
    128  * @param code      Status code to be put in the response. 
    129  * @param p_tdata   Pointer to receive the transmit data. 
    130  * 
    131  * @return          PJ_SUCCESS, or the appropriate error code. 
    132  */ 
    133 PJ_DECL(pj_status_t) pjsip_endpt_create_response( pjsip_endpoint *endpt, 
    134                                                   const pjsip_rx_data *rdata, 
    135                                                   int code, 
    136                                                   pjsip_tx_data **p_tdata); 
    137  
    138 /** 
    139  * Construct a full ACK request for the received non-2xx final response. 
    140  * This utility function is normally called by the transaction to construct 
    141  * an ACK request to 3xx-6xx final response. 
    142  * The generation of ACK message for 2xx final response is different than 
    143  * this one. 
    144  *  
    145  * @param endpt     The endpoint. 
    146  * @param tdata     On input, this contains the original INVITE request, and on 
    147  *                  output, it contains the ACK message. 
    148  * @param rdata     The final response message. 
    149  */ 
    150 PJ_DECL(void) pjsip_endpt_create_ack( pjsip_endpoint *endpt, 
    151                                       pjsip_tx_data *tdata, 
    152                                       const pjsip_rx_data *rdata ); 
    153  
    154  
    155 /** 
    156  * Construct CANCEL request for the previously sent request. 
    157  * 
    158  * @param endpt     The endpoint. 
    159  * @param tdata     The transmit buffer for the request being cancelled. 
    160  * @param p_tdata   Pointer to receive the transmit data. 
    161  * 
    162  * @return          PJ_SUCCESS, or the appropriate error code. 
    163  */ 
    164 PJ_DECL(pj_status_t) pjsip_endpt_create_cancel( pjsip_endpoint *endpt, 
    165                                                 pjsip_tx_data *tdata, 
    166                                                 pjsip_tx_data **p_tdata); 
    167  
    168  
    169 /** 
    170  * Get the address parameters (host, port, flag, TTL, etc) to send the 
    171  * response. 
    172  * 
    173  * @param pool      The pool. 
    174  * @param tr        The transport where the request was received. 
    175  * @param via       The top-most Via header of the request. 
    176  * @param addr      The send address concluded from the calculation. 
    177  * 
    178  * @return          zero (PJ_OK) if successfull. 
    179  */ 
    180 PJ_DECL(pj_status_t) pjsip_get_response_addr(pj_pool_t *pool, 
    181                                              const pjsip_transport *tr, 
    182                                              const pjsip_via_hdr *via, 
    183                                              pjsip_host_info *addr); 
    184355 
    185356/** 
  • pjproject/trunk/pjsip/include/pjsip_core.h

    r82 r106  
    3232#include <pjsip/sip_transaction.h> 
    3333#include <pjsip/sip_transport.h> 
     34#include <pjsip/sip_transport_udp.h> 
    3435#include <pjsip/sip_uri.h> 
    3536#include <pjsip/sip_util.h> 
  • pjproject/trunk/pjsip/src/pjsip/sip_endpoint.c

    r105 r106  
    5757    pj_str_t             name; 
    5858 
    59     /** Transaction table. */ 
    60     pj_hash_table_t     *tsx_table; 
    61  
    62     /** Mutex for transaction table. */ 
    63     pj_mutex_t          *tsx_table_mutex; 
    64  
    6559    /** Timer heap. */ 
    6660    pj_timer_heap_t     *timer_heap; 
     
    7569    pjsip_resolver_t    *resolver; 
    7670 
    77     /** Number of modules registered. */ 
    78     pj_uint32_t          mod_count; 
     71    /** Modules lock. */ 
     72    pj_rwmutex_t        *mod_mutex; 
    7973 
    8074    /** Modules. */ 
    8175    pjsip_module        *modules[PJSIP_MAX_MODULE]; 
     76 
     77    /** Module list, sorted by priority. */ 
     78    pjsip_module         module_list; 
    8279 
    8380    /** Number of supported methods. */ 
     
    128125 
    129126/* 
    130  * Initialize modules. 
    131  */ 
    132 static pj_status_t init_modules( pjsip_endpoint *endpt ) 
     127 * Register new module to the endpoint. 
     128 * The endpoint will then call the load and start function in the module to  
     129 * properly initialize the module, and assign a unique module ID for the  
     130 * module. 
     131 */ 
     132PJ_DEF(pj_status_t) pjsip_endpt_register_module( pjsip_endpoint *endpt, 
     133                                                 pjsip_module *mod ) 
     134{ 
     135    pj_status_t status = PJ_SUCCESS; 
     136    pjsip_module *m; 
     137    int i; 
     138 
     139    pj_rwmutex_lock_write(endpt->mod_mutex); 
     140 
     141    /* Make sure that this module has not been registered. */ 
     142    PJ_ASSERT_ON_FAIL(  pj_list_find_node(&endpt->module_list, mod) == NULL, 
     143                        {status = PJ_EEXISTS; goto on_return;}); 
     144 
     145    /* Find unused ID for this module. */ 
     146    for (i=0; i<PJ_ARRAY_SIZE(endpt->modules); ++i) { 
     147        if (endpt->modules[i] == NULL) 
     148            break; 
     149    } 
     150    if (i == PJ_ARRAY_SIZE(endpt->modules)) { 
     151        pj_assert(!"Too many modules registered!"); 
     152        status = PJ_ETOOMANY; 
     153        goto on_return; 
     154    } 
     155 
     156    /* Assign the ID. */ 
     157    mod->id = i; 
     158 
     159    /* Try to load the module. */ 
     160    if (mod->load) { 
     161        status = (*mod->load)(endpt); 
     162        if (status != PJ_SUCCESS) 
     163            goto on_return; 
     164    } 
     165 
     166    /* Try to start the module. */ 
     167    if (mod->start) { 
     168        status = (*mod->start)(); 
     169        if (status != PJ_SUCCESS) 
     170            goto on_return; 
     171    } 
     172 
     173    /* Save the module. */ 
     174    endpt->modules[i] = mod; 
     175 
     176    /* Put in the module list, sorted by priority. */ 
     177    m = endpt->module_list.next; 
     178    while (m != &endpt->module_list) { 
     179        if (m->priority > mod->priority) 
     180            break; 
     181        m = m->next; 
     182    } 
     183    pj_list_insert_before(m, mod); 
     184 
     185    /* Done. */ 
     186    PJ_TODO(BUILD_ALLOW_HEADER_BASED_ON_MODULES_SUPPORTED_METHODS); 
     187 
     188on_return: 
     189    pj_rwmutex_unlock_write(endpt->mod_mutex); 
     190    return status; 
     191} 
     192 
     193/* 
     194 * Unregister a module from the endpoint. 
     195 * The endpoint will then call the stop and unload function in the module to  
     196 * properly shutdown the module. 
     197 */ 
     198PJ_DEF(pj_status_t) pjsip_endpt_unregister_module( pjsip_endpoint *endpt, 
     199                                                   pjsip_module *mod ) 
    133200{ 
    134201    pj_status_t status; 
    135     unsigned i; 
    136     //pj_str_t str_COMMA = { ", ", 2 }; 
    137     extern pjsip_module aux_tsx_module; 
    138  
    139     PJ_LOG(5, (THIS_FILE, "init_modules()")); 
    140  
    141     /* Load static modules. */ 
    142     endpt->mod_count = PJSIP_MAX_MODULE; 
    143     status = register_static_modules( &endpt->mod_count, endpt->modules ); 
    144     if (status != 0) { 
    145         return status; 
    146     } 
    147  
    148     /* Add mini aux module. */ 
    149     endpt->modules[endpt->mod_count++] = &aux_tsx_module; 
    150  
    151     /* Load dynamic modules. */ 
    152     // Not supported yet! 
    153  
    154     /* Sort modules on the priority. */ 
    155     for (i=endpt->mod_count-1; i>0; --i) { 
    156         pj_uint32_t max = 0; 
    157         unsigned j; 
    158         for (j=1; j<=i; ++j) { 
    159             if (endpt->modules[j]->priority > endpt->modules[max]->priority) 
    160                 max = j; 
    161         } 
    162         if (max != i) { 
    163             pjsip_module *temp = endpt->modules[max]; 
    164             endpt->modules[max] = endpt->modules[i]; 
    165             endpt->modules[i] = temp; 
    166         } 
    167     } 
    168  
    169     /* Initialize each module. */ 
    170     for (i=0; i < endpt->mod_count; ++i) { 
    171         int j; 
    172  
    173         pjsip_module *mod = endpt->modules[i]; 
    174         if (mod->init_module) { 
    175             status = mod->init_module(endpt, mod, i); 
    176             if (status != 0) { 
    177                 return status; 
    178             } 
    179         } 
    180  
    181         /* Collect all supported methods from modules. */ 
    182         for (j=0; j<mod->method_cnt; ++j) { 
    183             unsigned k; 
    184             for (k=0; k<endpt->method_cnt; ++k) { 
    185                 if (pjsip_method_cmp(mod->methods[j], endpt->methods[k]) == 0) 
    186                     break; 
    187             } 
    188             if (k == endpt->method_cnt) { 
    189                 if (endpt->method_cnt < MAX_METHODS) { 
    190                     endpt->methods[endpt->method_cnt++] = mod->methods[j]; 
    191                 } else { 
    192                     PJ_LOG(1,(THIS_FILE, "Too many methods")); 
    193                     return -1; 
    194                 } 
    195             } 
    196         } 
    197     } 
    198  
    199     /* Create Allow header. */ 
    200     endpt->allow_hdr = pjsip_allow_hdr_create( endpt->pool ); 
    201     endpt->allow_hdr->count = endpt->method_cnt; 
    202     for (i=0; i<endpt->method_cnt; ++i) { 
    203         endpt->allow_hdr->values[i] = endpt->methods[i]->name; 
    204     } 
    205  
    206     /* Start each module. */ 
    207     for (i=0; i < endpt->mod_count; ++i) { 
    208         pjsip_module *mod = endpt->modules[i]; 
    209         if (mod->start_module) { 
    210             status = mod->start_module(mod); 
    211             if (status != 0) { 
    212                 return status; 
    213             } 
    214         } 
    215     } 
     202 
     203    pj_rwmutex_lock_write(endpt->mod_mutex); 
     204 
     205    /* Make sure the module exists in the list. */ 
     206    PJ_ASSERT_ON_FAIL(  pj_list_find_node(&endpt->module_list, mod) == mod, 
     207                        {status = PJ_ENOTFOUND;goto on_return;} ); 
     208 
     209    /* Make sure the module exists in the array. */ 
     210    PJ_ASSERT_ON_FAIL(  mod->id>=0 && mod->id<PJ_ARRAY_SIZE(endpt->modules) && 
     211                        endpt->modules[mod->id] == mod, 
     212                        {status = PJ_ENOTFOUND; goto on_return;}); 
     213 
     214    /* Try to stop the module. */ 
     215    if (mod->stop) { 
     216        status = (*mod->stop)(); 
     217        if (status != PJ_SUCCESS) goto on_return; 
     218    } 
     219 
     220    /* Try to unload the module. */ 
     221    if (mod->unload) { 
     222        status = (*mod->unload)(); 
     223        if (status != PJ_SUCCESS) goto on_return; 
     224    } 
     225 
     226    /* Remove module from array. */ 
     227    endpt->modules[mod->id] = NULL; 
     228 
     229    /* Remove module from list. */ 
     230    pj_list_erase(mod); 
    216231 
    217232    /* Done. */ 
    218     return 0; 
    219 } 
    220  
    221 /* 
    222  * Unregister the transaction from the hash table, and destroy the resources 
    223  * from the transaction. 
    224  */ 
    225 PJ_DEF(void) pjsip_endpt_destroy_tsx( pjsip_endpoint *endpt, 
    226                                       pjsip_transaction *tsx) 
    227 { 
    228     PJ_LOG(5, (THIS_FILE, "pjsip_endpt_destroy_tsx(%s)", tsx->obj_name)); 
    229  
    230     pj_assert(tsx->state == PJSIP_TSX_STATE_DESTROYED); 
    231  
    232     /* No need to lock transaction.  
    233      * This function typically is called from the transaction callback, which 
    234      * means that transaction mutex is being held. 
    235      */ 
    236     pj_assert( pj_mutex_is_locked(tsx->mutex) ); 
    237  
    238     /* Lock endpoint. */ 
    239     pj_mutex_lock( endpt->tsx_table_mutex ); 
    240  
    241     /* Unregister from the hash table. */ 
    242     pj_hash_set( NULL, endpt->tsx_table, tsx->transaction_key.ptr,  
    243                  tsx->transaction_key.slen, NULL); 
    244  
    245     /* Unlock endpoint mutex. */ 
    246     pj_mutex_unlock( endpt->tsx_table_mutex ); 
    247  
    248     /* Destroy transaction mutex. */ 
    249     pj_mutex_destroy( tsx->mutex ); 
    250  
    251     /* Release the pool for the transaction. */ 
    252     pj_pool_release(tsx->pool); 
    253  
    254     PJ_LOG(4, (THIS_FILE, "tsx%p destroyed", tsx)); 
    255 } 
    256  
    257  
    258 /* 
    259  * Receive transaction events from transactions and dispatch them to the  
    260  * modules. 
    261  */ 
    262 static void endpt_do_event( pjsip_endpoint *endpt, pjsip_event *evt) 
    263 { 
    264     unsigned i; 
    265  
    266     /* Dispatch event to modules. */ 
    267     for (i=0; i<endpt->mod_count; ++i) { 
    268         pjsip_module *mod = endpt->modules[i]; 
    269         if (mod && mod->tsx_handler) { 
    270             mod->tsx_handler( mod, evt ); 
    271         } 
    272     } 
    273  
    274     /* Destroy transaction if it is terminated. */ 
    275     if (evt->type == PJSIP_EVENT_TSX_STATE &&  
    276         evt->body.tsx_state.tsx->state == PJSIP_TSX_STATE_DESTROYED)  
    277     { 
    278         /* No need to lock mutex. Mutex is locked inside the destroy function */ 
    279         pjsip_endpt_destroy_tsx( endpt, evt->body.tsx_state.tsx ); 
    280     } 
    281 } 
    282  
    283 /* 
    284  * Receive transaction events from transactions and put in the event queue 
    285  * to be processed later. 
    286  */ 
    287 void pjsip_endpt_send_tsx_event( pjsip_endpoint *endpt, pjsip_event *evt ) 
    288 { 
    289     // Need to protect this with try/catch? 
    290     endpt_do_event(endpt, evt); 
     233    status = PJ_SUCCESS; 
     234 
     235    PJ_TODO(REMOVE_METHODS_FROM_ALLOW_HEADER_WHEN_MODULE_IS_UNREGISTERED); 
     236 
     237on_return: 
     238    pj_rwmutex_unlock_write(endpt->mod_mutex); 
     239    return status; 
    291240} 
    292241 
     
    376325 
    377326    /* Create endpoint. */ 
    378     endpt = pj_pool_calloc(pool, 1, sizeof(*endpt)); 
     327    endpt = pj_pool_zalloc(pool, sizeof(*endpt)); 
    379328    endpt->pool = pool; 
    380329    endpt->pf = pf; 
     330 
     331    /* Init modules list. */ 
     332    pj_list_init(&endpt->module_list); 
     333 
     334    /* Create R/W mutex for module manipulation. */ 
     335    status = pj_rwmutex_create(endpt->pool, "ept%p", &endpt->mod_mutex); 
     336    if (status != PJ_SUCCESS) 
     337        goto on_error; 
    381338 
    382339    /* Init parser. */ 
     
    400357    } 
    401358 
    402     /* Create mutex for the transaction table. */ 
    403     status = pj_mutex_create_recursive( endpt->pool, "mtbl%p",  
    404                                         &endpt->tsx_table_mutex); 
    405     if (status != PJ_SUCCESS) { 
    406         goto on_error; 
    407     } 
    408  
    409     /* Create hash table for transaction. */ 
    410     endpt->tsx_table = pj_hash_create( endpt->pool, PJSIP_MAX_TSX_COUNT ); 
    411     if (!endpt->tsx_table) { 
    412         status = PJ_ENOMEM; 
    413         goto on_error; 
    414     } 
    415  
    416359    /* Create timer heap to manage all timers within this endpoint. */ 
    417360    status = pj_timer_heap_create( endpt->pool, PJSIP_MAX_TIMER_COUNT,  
     
    453396    } 
    454397 
    455     /* Initialize TLS ID for transaction lock. */ 
    456     status = pj_thread_local_alloc(&pjsip_tsx_lock_tls_id); 
    457     if (status != PJ_SUCCESS) { 
    458         goto on_error; 
    459     } 
    460     pj_thread_local_set(pjsip_tsx_lock_tls_id, NULL); 
    461  
    462398    /* Initialize request headers. */ 
    463399    pj_list_init(&endpt->req_hdr); 
     
    471407    pj_list_insert_before( &endpt->req_hdr, mf_hdr); 
    472408 
    473     /* Load and init modules. */ 
    474     status = init_modules(endpt); 
    475     if (status != PJ_SUCCESS) { 
    476         PJ_LOG(4, (THIS_FILE, "pjsip_endpt_init(): error in init_modules()")); 
    477         return status; 
    478     } 
    479  
    480409    /* Done. */ 
    481410    *p_endpt = endpt; 
     
    491420        endpt->mutex = NULL; 
    492421    } 
    493     if (endpt->tsx_table_mutex) { 
    494         pj_mutex_destroy(endpt->tsx_table_mutex); 
    495         endpt->tsx_table_mutex = NULL; 
     422    if (endpt->mod_mutex) { 
     423        pj_rwmutex_destroy(endpt->mod_mutex); 
     424        endpt->mod_mutex = NULL; 
    496425    } 
    497426    pj_pool_release( endpt->pool ); 
     
    513442    /* Delete endpoint mutex. */ 
    514443    pj_mutex_destroy(endpt->mutex); 
    515  
    516     /* Delete transaction table mutex. */ 
    517     pj_mutex_destroy(endpt->tsx_table_mutex); 
    518444 
    519445    /* Finally destroy pool. */ 
     
    625551 
    626552/* 
    627  * Create a new transaction. 
    628  * Endpoint must then initialize the new transaction as either UAS or UAC, and 
    629  * register it to the hash table. 
    630  */ 
    631 PJ_DEF(pj_status_t) pjsip_endpt_create_tsx(pjsip_endpoint *endpt, 
    632                                            pjsip_transaction **p_tsx) 
    633 { 
    634     pj_pool_t *pool; 
    635  
    636     PJ_ASSERT_RETURN(endpt && p_tsx, PJ_EINVAL); 
    637  
    638     PJ_LOG(5, (THIS_FILE, "pjsip_endpt_create_tsx()")); 
    639  
    640     /* Request one pool for the transaction. Mutex is locked there. */ 
    641     pool = pjsip_endpt_create_pool(endpt, "ptsx%p",  
    642                                       PJSIP_POOL_LEN_TSX, PJSIP_POOL_INC_TSX); 
    643     if (pool == NULL) { 
    644         return PJ_ENOMEM; 
    645     } 
    646  
    647     /* Create the transaction. */ 
    648     return pjsip_tsx_create(pool, endpt, p_tsx); 
    649 } 
    650  
    651 /* 
    652  * Register the transaction to the endpoint. 
    653  * This will put the transaction to the transaction hash table. Before calling 
    654  * this function, the transaction must be INITIALIZED as either UAS or UAC, so 
    655  * that the transaction key is built. 
    656  */ 
    657 PJ_DEF(void) pjsip_endpt_register_tsx( pjsip_endpoint *endpt, 
    658                                        pjsip_transaction *tsx) 
    659 { 
    660     PJ_LOG(5, (THIS_FILE, "pjsip_endpt_register_tsx(%s)", tsx->obj_name)); 
    661  
    662     pj_assert(tsx->transaction_key.slen != 0); 
    663     //pj_assert(tsx->state != PJSIP_TSX_STATE_NULL); 
    664  
    665     /* Lock hash table mutex. */ 
    666     pj_mutex_lock(endpt->tsx_table_mutex); 
    667  
    668     /* Register the transaction to the hash table. */ 
    669     pj_hash_set( tsx->pool, endpt->tsx_table, tsx->transaction_key.ptr, 
    670                  tsx->transaction_key.slen, tsx); 
    671  
    672     /* Unlock mutex. */ 
    673     pj_mutex_unlock(endpt->tsx_table_mutex); 
    674 } 
    675  
    676 /* 
    677  * Find transaction by the key. 
    678  */ 
    679 PJ_DEF(pjsip_transaction*) pjsip_endpt_find_tsx( pjsip_endpoint *endpt, 
    680                                                   const pj_str_t *key ) 
    681 { 
    682     pjsip_transaction *tsx; 
    683  
    684     PJ_LOG(5, (THIS_FILE, "pjsip_endpt_find_tsx()")); 
    685  
    686     /* Start lock mutex in the endpoint. */ 
    687     pj_mutex_lock(endpt->tsx_table_mutex); 
    688  
    689     /* Find the transaction in the hash table. */ 
    690     tsx = pj_hash_get( endpt->tsx_table, key->ptr, key->slen ); 
    691  
    692     /* Unlock mutex. */ 
    693     pj_mutex_unlock(endpt->tsx_table_mutex); 
    694  
    695     return tsx; 
    696 } 
    697  
    698 /* 
    699  * Create key. 
    700  */ 
    701 static void rdata_create_key( pjsip_rx_data *rdata) 
    702 { 
    703     pjsip_role_e role; 
    704     if (rdata->msg_info.msg->type == PJSIP_REQUEST_MSG) { 
    705         role = PJSIP_ROLE_UAS; 
    706     } else { 
    707         role = PJSIP_ROLE_UAC; 
    708     } 
    709     pjsip_tsx_create_key(rdata->tp_info.pool, &rdata->endpt_info.key, role, 
    710                          &rdata->msg_info.cseq->method, rdata); 
    711 } 
    712  
    713 /* 
    714553 * This is the callback that is called by the transport manager when it  
    715554 * receives a message from the network. 
     
    720559{ 
    721560    pjsip_msg *msg = rdata->msg_info.msg; 
    722     pjsip_transaction *tsx; 
    723     pj_bool_t a_new_transaction_just_been_created = PJ_FALSE; 
    724561 
    725562    PJ_LOG(5, (THIS_FILE, "endpt_transport_callback(rdata=%p)", rdata)); 
    726563 
    727564    if (status != PJ_SUCCESS) { 
    728         const char *src_addr = rdata->pkt_info.src_name; 
    729         int port = rdata->pkt_info.src_port; 
    730565        PJSIP_ENDPT_LOG_ERROR((endpt, "transport", status, 
    731                                "Src.addr=%s:%d, packet:--\n" 
     566                               "Error processing packet from %s:%d, packet:--\n" 
    732567                               "%s\n" 
    733                                "-- end of packet. Error", 
    734                                src_addr, port, rdata->msg_info.msg_buf)); 
     568                               "-- end of packet.", 
     569                               rdata->pkt_info.src_name,  
     570                               rdata->pkt_info.src_port,  
     571                               rdata->msg_info.msg_buf)); 
    735572        return; 
    736573    } 
     
    741578     */ 
    742579    if (msg->type == PJSIP_RESPONSE_MSG) { 
    743         const pj_str_t *addr_addr; 
     580        const pj_str_t *local_addr; 
    744581        int port = rdata->msg_info.via->sent_by.port; 
    745582        pj_bool_t mismatch = PJ_FALSE; 
     
    749586            port = pjsip_transport_get_default_port_for_type(type); 
    750587        } 
    751         addr_addr = &rdata->tp_info.transport->local_name.host; 
    752         if (pj_strcmp(&rdata->msg_info.via->sent_by.host, addr_addr) != 0) 
     588        local_addr = &rdata->tp_info.transport->local_name.host; 
     589        if (pj_strcmp(&rdata->msg_info.via->sent_by.host, local_addr) != 0) 
    753590            mismatch = PJ_TRUE; 
    754591        else if (port != rdata->tp_info.transport->local_name.port) { 
     
    760597             * both the port in sent-by and rport. We try to be lenient here! 
    761598             */ 
    762             if (rdata->msg_info.via->rport_param != rdata->tp_info.transport->local_name.port) 
     599            if (rdata->msg_info.via->rport_param !=  
     600                rdata->tp_info.transport->local_name.port) 
    763601                mismatch = PJ_TRUE; 
    764602            else { 
    765                 PJ_LOG(4,(THIS_FILE, "Response %p has mismatch port in sent-by" 
    766                                     " but the rport parameter is correct", 
    767                                     rdata)); 
     603                PJ_LOG(4,(THIS_FILE, "Response %p from %s has mismatch port in " 
     604                                     "sent-by but the rport parameter is " 
     605                                     "correct", 
     606                                     rdata, rdata->pkt_info.src_name)); 
    768607            } 
    769608        } 
    770609 
    771610        if (mismatch) { 
    772             pjsip_event e; 
    773  
    774             PJSIP_EVENT_INIT_DISCARD_MSG(e, rdata, PJSIP_EINVALIDVIA); 
    775             endpt_do_event( endpt, &e ); 
     611            PJ_TODO(ENDPT_REPORT_WHEN_DROPPING_MESSAGE); 
     612            PJ_LOG(4,(THIS_FILE, "Dropping response from %s:%d because sent-by" 
     613                                 " is mismatch",  
     614                                 rdata->pkt_info.src_name,  
     615                                 rdata->pkt_info.src_port)); 
    776616            return; 
    777617        } 
    778     }  
    779  
    780     /* Create key for transaction lookup. */ 
    781     rdata_create_key( rdata); 
    782  
    783     /* Find the transaction for the received message. */ 
    784     PJ_LOG(5, (THIS_FILE, "finding tsx with key=%.*s",  
    785                          rdata->endpt_info.key.slen, rdata->endpt_info.key.ptr)); 
    786  
    787     /* Start lock mutex in the endpoint. */ 
    788     pj_mutex_lock(endpt->tsx_table_mutex); 
    789  
    790     /* Find the transaction in the hash table. */ 
    791     tsx = pj_hash_get( endpt->tsx_table, rdata->endpt_info.key.ptr, rdata->endpt_info.key.slen ); 
    792  
    793     /* Unlock mutex. */ 
    794     pj_mutex_unlock(endpt->tsx_table_mutex); 
    795  
    796     /* If the transaction is not found... */ 
    797     if (tsx == NULL || tsx->state == PJSIP_TSX_STATE_TERMINATED) { 
    798  
    799         /*  
    800          * For response message, discard the message, except if the response is 
    801          * an 2xx class response to INVITE, which in this case it must be 
    802          * passed to TU to be acked. 
    803          */ 
    804         if (msg->type == PJSIP_RESPONSE_MSG) { 
    805  
    806             /* Inform TU about the 200 message, only if it's INVITE. */ 
    807             if (PJSIP_IS_STATUS_IN_CLASS(msg->line.status.code, 200) && 
    808                 rdata->msg_info.cseq->method.id == PJSIP_INVITE_METHOD)  
    809             { 
    810                 pjsip_event e; 
    811  
    812                 /* Should not happen for UA. Tsx theoritically lives until 
    813                  * all responses are absorbed. 
    814                  */ 
    815                 pj_assert(0); 
    816  
    817                 PJSIP_EVENT_INIT_RX_200_MSG(e, rdata); 
    818                 endpt_do_event( endpt, &e ); 
    819  
    820             } else { 
    821                 /* Just discard the response, inform TU. */ 
    822                 pjsip_event e; 
    823  
    824                 PJSIP_EVENT_INIT_DISCARD_MSG(e, rdata,  
    825                     PJSIP_ERRNO_FROM_SIP_STATUS(PJSIP_SC_CALL_TSX_DOES_NOT_EXIST)); 
    826                 endpt_do_event( endpt, &e ); 
    827             } 
    828  
    829         /* 
    830          * For non-ACK request message, create a new transaction. 
    831          */ 
    832         } else if (rdata->msg_info.msg->line.req.method.id != PJSIP_ACK_METHOD) { 
    833  
    834             pj_status_t status; 
    835  
    836             /* Create transaction, mutex is locked there. */ 
    837             status = pjsip_endpt_create_tsx(endpt, &tsx); 
    838             if (status != PJ_SUCCESS) { 
    839                 PJSIP_ENDPT_LOG_ERROR((endpt, THIS_FILE, status, 
    840                                        "Unable to create transaction")); 
    841                 return; 
    842             } 
    843  
    844             /* Initialize transaction as UAS. */ 
    845             pjsip_tsx_init_uas( tsx, rdata ); 
    846  
    847             /* Register transaction, mutex is locked there. */ 
    848             pjsip_endpt_register_tsx( endpt, tsx ); 
    849  
    850             a_new_transaction_just_been_created = PJ_TRUE; 
     618    } 
     619 
     620 
     621    /* Distribute to modules. */ 
     622    pj_rwmutex_lock_read(endpt->mod_mutex); 
     623 
     624    if (msg->type == PJSIP_REQUEST_MSG) { 
     625        pjsip_module *mod; 
     626        pj_bool_t handled = PJ_FALSE; 
     627 
     628        mod = endpt->module_list.next; 
     629        while (mod != &endpt->module_list) { 
     630            if (mod->on_rx_request) 
     631                handled = (*mod->on_rx_request)(rdata); 
     632            if (handled) 
     633                break; 
     634            mod = mod->next; 
    851635        } 
    852     } 
    853  
    854     /* If transaction is found (or newly created), pass the message. 
    855      * Otherwise if it's an ACK request, pass directly to TU. 
    856      */ 
    857     if (tsx && tsx->state != PJSIP_TSX_STATE_TERMINATED) { 
    858         /* Dispatch message to transaction. */ 
    859         pjsip_tsx_on_rx_msg( tsx, rdata ); 
    860  
    861     } else if (rdata->msg_info.msg->line.req.method.id == PJSIP_ACK_METHOD) { 
    862         /* 
    863          * This is an ACK message, but the INVITE transaction could not 
    864          * be found (possibly because the branch parameter in Via in ACK msg 
    865          * is different than the branch in original INVITE). This happens with 
    866          * SER! 
    867          */ 
    868         pjsip_event event; 
    869  
    870         PJSIP_EVENT_INIT_RX_ACK_MSG(event,rdata); 
    871         endpt_do_event( endpt, &event ); 
    872     } 
    873  
    874     /* 
    875      * If a new request message has just been receieved, but no modules 
    876      * seem to be able to handle the request message, then terminate the 
    877      * transaction. 
    878      * 
    879      * Ideally for cases like "unsupported method", we should be able to 
    880      * answer the request statelessly. But we can not do that since the 
    881      * endpoint shoule be able to be used as both user agent and proxy stack, 
    882      * and a proxy stack should be able to handle arbitrary methods. 
    883      */ 
    884     if (a_new_transaction_just_been_created && tsx->status_code < 100) { 
    885         /* Certainly no modules has sent any response message. 
    886          * Check that any modules has attached a module data. 
    887          */ 
    888         int i; 
    889         for (i=0; i<PJSIP_MAX_MODULE; ++i) { 
    890             if (tsx->module_data[i] != NULL) { 
     636 
     637        /* No module is able to handle the request. */ 
     638        if (!handled) { 
     639            PJ_TODO(ENDPT_RESPOND_UNHANDLED_REQUEST); 
     640            PJ_LOG(4,(THIS_FILE, "Request from %s:%d was dropped/unhandled by" 
     641                                 " any modules")); 
     642        } 
     643 
     644    } else { 
     645        pjsip_module *mod; 
     646        pj_bool_t handled = PJ_FALSE; 
     647 
     648        mod = endpt->module_list.next; 
     649        while (mod != &endpt->module_list) { 
     650            if (mod->on_rx_response) 
     651                handled = (*mod->on_rx_response)(rdata); 
     652            if (handled) 
    891653                break; 
    892             } 
     654            mod = mod->next; 
    893655        } 
    894         if (i == PJSIP_MAX_MODULE) { 
    895             /* No modules have attached itself to the transaction.  
    896              * Terminate the transaction with 501/Not Implemented. 
    897              */ 
    898             pjsip_tx_data *tdata; 
    899             pj_status_t status; 
    900              
    901             if (tsx->method.id == PJSIP_OPTIONS_METHOD) { 
    902                 status = pjsip_endpt_create_response(endpt, rdata, 200,  
    903                                                      &tdata); 
    904             } else { 
    905                 status = pjsip_endpt_create_response(endpt, rdata,  
    906                                                      PJSIP_SC_METHOD_NOT_ALLOWED, 
    907                                                      &tdata); 
    908             } 
    909  
    910             if (status != PJ_SUCCESS) { 
    911                 PJSIP_ENDPT_LOG_ERROR((endpt, THIS_FILE, status, 
    912                                        "Unable to create response")); 
    913                 return; 
    914             } 
    915  
    916             if (endpt->allow_hdr) { 
    917                 pjsip_msg_add_hdr( tdata->msg,  
    918                                    pjsip_hdr_shallow_clone(tdata->pool, endpt->allow_hdr)); 
    919             } 
    920             pjsip_tsx_on_tx_msg( tsx, tdata ); 
    921  
    922         } else { 
    923             /* 
    924              * If a module has registered itself in the transaction but it 
    925              * hasn't responded the request, chances are the module wouldn't 
    926              * respond to the request at all. We terminate the request here 
    927              * with 500/Internal Server Error, to be safe. 
    928              */ 
    929             pjsip_tx_data *tdata; 
    930             pj_status_t status; 
    931  
    932             status = pjsip_endpt_create_response(endpt, rdata, 500, &tdata); 
    933             if (status != PJ_SUCCESS) { 
    934                 PJSIP_ENDPT_LOG_ERROR((endpt, THIS_FILE, status, 
    935                                        "Unable to create response")); 
    936                 return; 
    937             } 
    938  
    939             pjsip_tsx_on_tx_msg(tsx, tdata); 
     656 
     657        if (!handled) { 
     658            PJ_LOG(4,(THIS_FILE, "Response from %s:%d was dropped/unhandled by" 
     659                                 " any modules")); 
    940660        } 
    941661    } 
     662 
     663    pj_rwmutex_unlock_read(endpt->mod_mutex); 
    942664} 
    943665 
     
    984706 * Find/create transport. 
    985707 */ 
    986 PJ_DEF(pj_status_t) pjsip_endpt_alloc_transport( pjsip_endpoint *endpt, 
     708PJ_DEF(pj_status_t) pjsip_endpt_acquire_transport(pjsip_endpoint *endpt, 
    987709                                                  pjsip_transport_type_e type, 
    988                                                   const pj_sockaddr *remote, 
     710                                                  const pj_sockaddr_t *remote, 
    989711                                                  int addr_len, 
    990                                                   pjsip_transport **p_transport) 
    991 { 
    992     PJ_LOG(5, (THIS_FILE, "pjsip_endpt_alloc_transport()")); 
    993     return pjsip_tpmgr_alloc_transport( endpt->transport_mgr, type,  
    994                                         remote, addr_len, p_transport); 
     712                                                  pjsip_transport **transport) 
     713{ 
     714    PJ_LOG(5, (THIS_FILE, "pjsip_endpt_acquire_transport()")); 
     715    return pjsip_tpmgr_acquire_transport(endpt->transport_mgr, type,  
     716                                         remote, addr_len, transport); 
    995717} 
    996718 
     
    1050772{ 
    1051773#if PJ_LOG_MAX_LEVEL >= 3 
    1052     unsigned count; 
    1053  
    1054774    PJ_LOG(5, (THIS_FILE, "pjsip_endpt_dump()")); 
    1055775 
     
    1066786               pj_pool_get_capacity(endpt->pool), 
    1067787               pj_pool_get_used_size(endpt->pool))); 
    1068  
    1069     /* Transaction tables. */ 
    1070     count = pj_hash_count(endpt->tsx_table); 
    1071     PJ_LOG(3, (THIS_FILE, " Number of transactions: %u", count)); 
    1072  
    1073     if (count && detail) { 
    1074         pj_hash_iterator_t it_val; 
    1075         pj_hash_iterator_t *it; 
    1076         pj_time_val now; 
    1077  
    1078         PJ_LOG(3, (THIS_FILE, " Dumping transaction tables:")); 
    1079  
    1080         pj_gettimeofday(&now); 
    1081         it = pj_hash_first(endpt->tsx_table, &it_val); 
    1082  
    1083         while (it != NULL) { 
    1084             int timeout_diff; 
    1085  
    1086             /* Get the transaction. No need to lock transaction's mutex 
    1087              * since we already hold endpoint mutex, so that no transactions 
    1088              * will be deleted. 
    1089              */ 
    1090             pjsip_transaction *tsx = pj_hash_this(endpt->tsx_table, it); 
    1091  
    1092             const char *role = (tsx->role == PJSIP_ROLE_UAS ? "UAS" : "UAC"); 
    1093          
    1094             if (tsx->timeout_timer._timer_id != -1) { 
    1095                 if (tsx->timeout_timer._timer_value.sec > now.sec) { 
    1096                     timeout_diff = tsx->timeout_timer._timer_value.sec - now.sec; 
    1097                 } else { 
    1098                     timeout_diff = now.sec - tsx->timeout_timer._timer_value.sec; 
    1099                     timeout_diff = 0 - timeout_diff; 
    1100                 } 
    1101             } else { 
    1102                 timeout_diff = -1; 
    1103             } 
    1104  
    1105             PJ_LOG(3, (THIS_FILE, "  %s %s %10.*s %.9u %s t=%ds",  
    1106                        tsx->obj_name, role,  
    1107                        tsx->method.name.slen, tsx->method.name.ptr, 
    1108                        tsx->cseq, 
    1109                        pjsip_tsx_state_str(tsx->state), 
    1110                        timeout_diff)); 
    1111  
    1112             it = pj_hash_next(endpt->tsx_table, it); 
    1113         } 
    1114     } 
    1115788 
    1116789    /* Transports.  
  • pjproject/trunk/pjsip/src/pjsip/sip_errno.c

    r65 r106  
    4040    { PJSIP_EMSGTOOLONG,        "Message too long" }, 
    4141    { PJSIP_EPARTIALMSG,        "Partial message" }, 
     42    { PJSIP_EMISSINGREQURI,     "Missing Request-URI" }, 
    4243    { PJSIP_EMISSINGHDR,        "Missing required header(s)" }, 
     44    { PJSIP_EMISSINGBODY,       "Missing message body" }, 
    4345    { PJSIP_EINVALIDVIA,        "Invalid Via header" }, 
    4446    { PJSIP_EMULTIPLEVIA,       "Multiple Via headers in response" }, 
     47    { PJSIP_EINVALIDREQURI,     "Invalid Request URI" }, 
     48    { PJSIP_ENOTREQUESTMSG,     "Expecting request message"}, 
     49    { PJSIP_ENOTRESPONSEMSG,    "Expecting response message"}, 
    4550 
    4651    /* Transport errors */ 
     
    4853    { PJSIP_EPENDINGTX,         "Transmit buffer already pending"}, 
    4954    { PJSIP_ERXOVERFLOW,        "Rx buffer overflow"}, 
     55    { PJSIP_EBUFDESTROYED,      "Buffer destroyed"}, 
    5056 
    5157    /* Transaction errors */ 
  • pjproject/trunk/pjsip/src/pjsip/sip_msg.c

    r82 r106  
    2222#include <pj/string.h> 
    2323#include <pj/pool.h> 
     24#include <pj/assert.h> 
    2425 
    2526/* 
     
    3031#endif 
    3132 
    32 static const pj_str_t method_names[] =  
    33 { 
    34     { "INVITE",     6 }, 
    35     { "CANCEL",     6 }, 
    36     { "ACK",        3 }, 
    37     { "BYE",        3 }, 
    38     { "REGISTER",   8 }, 
    39     { "OPTIONS",    7 }, 
     33const pjsip_method  
     34    pjsip_invite_method     = { PJSIP_INVITE_METHOD,    { "INVITE",6 }  }, 
     35    pjsip_cancel_method     = { PJSIP_CANCEL_METHOD,    { "CANCEL",6 }  }, 
     36    pjsip_ack_method        = { PJSIP_ACK_METHOD,       { "ACK",3}      }, 
     37    pjsip_bye_method        = { PJSIP_BYE_METHOD,       { "BYE",3}      }, 
     38    pjsip_register_method   = { PJSIP_REGISTER_METHOD,  { "REGISTER",8} }, 
     39    pjsip_options_method    = { PJSIP_OPTIONS_METHOD,   { "OPTIONS",7}  }; 
     40 
     41static const pj_str_t *method_names[] =  
     42{ 
     43    &pjsip_invite_method.name, 
     44    &pjsip_cancel_method.name, 
     45    &pjsip_ack_method.name, 
     46    &pjsip_bye_method.name, 
     47    &pjsip_register_method.name, 
     48    &pjsip_options_method.name 
    4049}; 
    4150 
     
    179188PJ_DEF(void) pjsip_method_set( pjsip_method *m, pjsip_method_e me ) 
    180189{ 
     190    pj_assert(me < PJSIP_OTHER_METHOD); 
    181191    m->id = me; 
    182     m->name = method_names[me]; 
     192    m->name = *method_names[me]; 
    183193} 
    184194 
     
    188198    int i; 
    189199    for (i=0; i<PJ_ARRAY_SIZE(method_names); ++i) { 
    190         if (pj_stricmp(str, &method_names[i])==0) { 
     200        if (pj_stricmp(str, method_names[i])==0) { 
    191201            m->id = (pjsip_method_e)i; 
    192             m->name = method_names[i]; 
     202            m->name = *method_names[i]; 
    193203            return; 
    194204        } 
     
    236246} 
    237247 
    238 PJ_DEF(void*)  pjsip_msg_find_hdr( pjsip_msg *msg,  
    239                                    pjsip_hdr_e hdr_type, void *start) 
    240 { 
    241     pjsip_hdr *hdr=start, *end=&msg->hdr; 
     248PJ_DEF(void*)  pjsip_msg_find_hdr( const pjsip_msg *msg,  
     249                                   pjsip_hdr_e hdr_type, const void *start) 
     250{ 
     251    const pjsip_hdr *hdr=start, *end=&msg->hdr; 
    242252 
    243253    if (hdr == NULL) { 
     
    246256    for (; hdr!=end; hdr = hdr->next) { 
    247257        if (hdr->type == hdr_type) 
    248             return hdr; 
     258            return (void*)hdr; 
    249259    } 
    250260    return NULL; 
    251261} 
    252262 
    253 PJ_DEF(void*)  pjsip_msg_find_hdr_by_name( pjsip_msg *msg,  
    254                                            const pj_str_t *name, void *start) 
    255 { 
    256     pjsip_hdr *hdr=start, *end=&msg->hdr; 
     263PJ_DEF(void*)  pjsip_msg_find_hdr_by_name( const pjsip_msg *msg,  
     264                                           const pj_str_t *name,  
     265                                           const void *start) 
     266{ 
     267    const pjsip_hdr *hdr=start, *end=&msg->hdr; 
    257268 
    258269    if (hdr == NULL) { 
     
    262273        if (hdr->type < PJSIP_H_OTHER) { 
    263274            if (pj_stricmp(&pjsip_hdr_names[hdr->type], name) == 0) 
    264                 return hdr; 
     275                return (void*)hdr; 
    265276        } else { 
    266277            if (pj_stricmp(&hdr->name, name) == 0) 
    267                 return hdr; 
     278                return (void*)hdr; 
    268279        } 
    269280    } 
     
    281292} 
    282293 
    283 PJ_DEF(pj_ssize_t) pjsip_msg_print( pjsip_msg *msg, char *buf, pj_size_t size) 
     294PJ_DEF(pj_ssize_t) pjsip_msg_print( const pjsip_msg *msg,  
     295                                    char *buf, pj_size_t size) 
    284296{ 
    285297    char *p=buf, *end=buf+size; 
     
    13501362    pjsip_via_hdr *hdr = pj_pool_calloc(pool, 1, sizeof(*hdr)); 
    13511363    init_hdr(hdr, PJSIP_H_VIA, &via_hdr_vptr); 
    1352     hdr->sent_by.port = 5060; 
     1364    //hdr->sent_by.port = 5060; 
    13531365    hdr->ttl_param = -1; 
    13541366    hdr->rport_param = -1; 
     
    13841396    pj_memcpy(buf, hdr->sent_by.host.ptr, hdr->sent_by.host.slen); 
    13851397    buf += hdr->sent_by.host.slen; 
    1386     *buf++ = ':'; 
    1387     printed = pj_utoa(hdr->sent_by.port, buf); 
    1388     buf += printed; 
     1398    if (hdr->sent_by.port != 0) { 
     1399        *buf++ = ':'; 
     1400        printed = pj_utoa(hdr->sent_by.port, buf); 
     1401        buf += printed; 
     1402    } 
    13891403 
    13901404    if (hdr->ttl_param >= 0) { 
  • pjproject/trunk/pjsip/src/pjsip/sip_parser.c

    r82 r106  
    17831783            pj_scan_get(scanner, &pjsip_DIGIT_SPEC, &digit); 
    17841784            hdr->sent_by.port = pj_strtoul(&digit); 
    1785         } else { 
    1786             hdr->sent_by.port = 5060; 
    17871785        } 
    17881786         
  • pjproject/trunk/pjsip/src/pjsip/sip_transaction.c

    r105 r106  
    3030#include <pj/pool.h> 
    3131#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 */ 
     55PJ_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 */ 
     82PJ_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 */ 
     104PJ_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 */ 
     126static 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 */ 
     143static 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 
    32422 
    33423/* Thread Local Storage ID for transaction lock (initialized by endpoint) */ 
     
    153543    return role_name[role]; 
    154544} 
     545 
     546 
     547 
     548/* 
     549 * Unregister the transaction from the hash table, and destroy the resources 
     550 * from the transaction. 
     551 */ 
     552PJ_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 
    155584 
    156585 
     
    501930                                      pjsip_host_info *send_addr ) 
    502931{ 
    503     const pjsip_uri *new_request_uri, *target_uri; 
    504     const pjsip_name_addr *topmost_route_uri; 
    505     pjsip_route_hdr *first_route_hdr, *last_route_hdr; 
     932    pjsip_route_hdr *route_hdr; 
    506933     
    507934    pj_assert(tdata->msg->type == PJSIP_REQUEST_MSG); 
     
    511938     * headers from the endpoint first. 
    512939     */ 
    513     last_route_hdr = first_route_hdr =  
    514         pjsip_msg_find_hdr(tdata->msg, PJSIP_H_ROUTE, NULL); 
    515     if (first_route_hdr) { 
    516         topmost_route_uri = &first_route_hdr->name_addr; 
    517         while (last_route_hdr->next != (void*)&tdata->msg->hdr) { 
    518             pjsip_route_hdr *hdr; 
    519             hdr = pjsip_msg_find_hdr(tdata->msg, PJSIP_H_ROUTE,  
    520                                      last_route_hdr->next); 
    521             if (!hdr) 
    522                 break; 
    523             last_route_hdr = hdr; 
    524         } 
    525     } else { 
     940    route_hdr = pjsip_msg_find_hdr(tdata->msg, PJSIP_H_ROUTE, NULL); 
     941    if (!route_hdr) { 
    526942        const pjsip_route_hdr *hdr_list; 
    527         hdr_list = (pjsip_route_hdr*)pjsip_endpt_get_routing(tsx->endpt); 
    528         if (hdr_list->next != hdr_list) { 
    529             const pjsip_route_hdr *hdr = (pjsip_route_hdr*)hdr_list->next; 
    530             first_route_hdr = NULL; 
    531             topmost_route_uri = &hdr->name_addr; 
    532             do { 
    533                 last_route_hdr = pjsip_hdr_shallow_clone(tdata->pool, hdr); 
    534                 if (first_route_hdr == NULL) 
    535                     first_route_hdr = last_route_hdr; 
    536                 pjsip_msg_add_hdr(tdata->msg, (pjsip_hdr*)last_route_hdr); 
    537                 hdr = hdr->next; 
    538             } while (hdr != hdr_list); 
    539         } else { 
    540             topmost_route_uri = NULL; 
    541         } 
    542     } 
    543  
    544     /* If Route headers exist, and the first element indicates loose-route, 
    545      * the URI is taken from the Request-URI, and we keep all existing Route 
    546      * headers intact. 
    547      * If Route headers exist, and the first element DOESN'T indicate loose 
    548      * route, the URI is taken from the first Route header, and remove the 
    549      * first Route header from the message. 
    550      * Otherwise if there's no Route headers, the URI is taken from the 
    551      * Request-URI. 
    552      */ 
    553     if (topmost_route_uri) { 
    554         pj_bool_t has_lr_param; 
    555  
    556         if (PJSIP_URI_SCHEME_IS_SIP(topmost_route_uri) || 
    557             PJSIP_URI_SCHEME_IS_SIPS(topmost_route_uri)) 
    558         { 
    559             const pjsip_url *url = pjsip_uri_get_uri((void*)topmost_route_uri); 
    560             has_lr_param = url->lr_param; 
    561         } else { 
    562             has_lr_param = 0; 
    563         } 
    564  
    565         if (has_lr_param) { 
    566             new_request_uri = tdata->msg->line.req.uri; 
    567             /* We shouldn't need to delete topmost Route if it has lr param. 
    568              * But seems like it breaks some proxy implementation, so we 
    569              * delete it anyway. 
    570              */ 
    571             /* 
    572             pj_list_erase(first_route_hdr); 
    573             if (first_route_hdr == last_route_hdr) 
    574                 last_route_hdr = NULL; 
    575             */ 
    576         } else { 
    577             new_request_uri = pjsip_uri_get_uri((void*)topmost_route_uri); 
    578             pj_list_erase(first_route_hdr); 
    579             if (first_route_hdr == last_route_hdr) 
    580                 last_route_hdr = NULL; 
    581         } 
    582  
    583         target_uri = (pjsip_uri*)topmost_route_uri; 
    584  
    585     } else { 
    586         target_uri = new_request_uri = tdata->msg->line.req.uri; 
    587     } 
    588  
    589     /* The target URI must be a SIP/SIPS URL so we can resolve it's address. 
    590      * Otherwise we're in trouble (i.e. there's no host part in tel: URL). 
    591      */ 
    592     pj_memset(send_addr, 0, sizeof(*send_addr)); 
    593  
    594     if (PJSIP_URI_SCHEME_IS_SIPS(target_uri)) { 
    595         pjsip_uri *uri = (pjsip_uri*) target_uri; 
    596         const pjsip_url *url = (const pjsip_url*)pjsip_uri_get_uri(uri); 
    597         send_addr->flag |= (PJSIP_TRANSPORT_SECURE | PJSIP_TRANSPORT_RELIABLE); 
    598         pj_strdup(tdata->pool, &send_addr->addr.host, &url->host); 
    599         send_addr->addr.port = url->port; 
    600         send_addr->type =  
    601             pjsip_transport_get_type_from_name(&url->transport_param); 
    602  
    603     } else if (PJSIP_URI_SCHEME_IS_SIP(target_uri)) { 
    604         pjsip_uri *uri = (pjsip_uri*) target_uri; 
    605         const pjsip_url *url = (const pjsip_url*)pjsip_uri_get_uri(uri); 
    606         pj_strdup(tdata->pool, &send_addr->addr.host, &url->host); 
    607         send_addr->addr.port = url->port; 
    608         send_addr->type =  
    609             pjsip_transport_get_type_from_name(&url->transport_param); 
    610 #if PJ_HAS_TCP 
    611         if (send_addr->type == PJSIP_TRANSPORT_TCP ||  
    612             send_addr->type == PJSIP_TRANSPORT_SCTP)  
    613         { 
    614             send_addr->flag |= PJSIP_TRANSPORT_RELIABLE; 
    615         } 
    616 #endif 
    617     } else { 
    618         pj_assert(!"Unsupported URI scheme!"); 
    619         return PJSIP_EINVALIDSCHEME; 
    620     } 
    621  
    622     /* If target URI is different than request URI, replace  
    623      * request URI add put the original URI in the last Route header. 
    624      */ 
    625     if (new_request_uri && new_request_uri!=tdata->msg->line.req.uri) { 
    626         pjsip_route_hdr *route = pjsip_route_hdr_create(tdata->pool); 
    627         route->name_addr.uri = tdata->msg->line.req.uri; 
    628         if (last_route_hdr) 
    629             pj_list_insert_after(last_route_hdr, route); 
    630         else 
    631             pjsip_msg_add_hdr(tdata->msg, (pjsip_hdr*)route); 
    632         tdata->msg->line.req.uri = (pjsip_uri*)new_request_uri; 
    633     } 
    634  
    635     /* Success. */ 
    636     return PJ_SUCCESS;   
     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);   
    637954} 
    638955 
  • pjproject/trunk/pjsip/src/pjsip/sip_transport.c

    r105 r106  
    4444    pjsip_endpoint  *endpt; 
    4545    pjsip_tpfactory  factory_list; 
     46#if defined(PJ_DEBUG) && PJ_DEBUG!=0 
     47    pj_atomic_t     *tdata_counter; 
     48#endif 
    4649    void           (*msg_cb)(pjsip_endpoint*, pj_status_t, pjsip_rx_data*); 
    4750}; 
     
    205208    pj_ioqueue_op_key_init(&tdata->op_key.key, sizeof(tdata->op_key)); 
    206209 
     210#if defined(PJ_DEBUG) && PJ_DEBUG!=0 
     211    pj_atomic_inc( tdata->mgr->tdata_counter ); 
     212#endif 
     213 
    207214    *p_tdata = tdata; 
    208215    return PJ_SUCCESS; 
     
    222229 * reaches zero. 
    223230 */ 
    224 PJ_DEF(void) pjsip_tx_data_dec_ref( pjsip_tx_data *tdata ) 
     231PJ_DEF(pj_status_t) pjsip_tx_data_dec_ref( pjsip_tx_data *tdata ) 
    225232{ 
    226233    pj_assert( pj_atomic_get(tdata->ref_cnt) > 0); 
    227234    if (pj_atomic_dec_and_get(tdata->ref_cnt) <= 0) { 
    228235        PJ_LOG(5,(tdata->obj_name, "destroying txdata")); 
     236#if defined(PJ_DEBUG) && PJ_DEBUG!=0 
     237        pj_atomic_dec( tdata->mgr->tdata_counter ); 
     238#endif 
    229239        pj_atomic_destroy( tdata->ref_cnt ); 
    230240        pj_lock_destroy( tdata->lock ); 
    231241        pjsip_endpt_destroy_pool( tdata->mgr->endpt, tdata->pool ); 
     242        return PJSIP_EBUFDESTROYED; 
     243    } else { 
     244        return PJ_SUCCESS; 
    232245    } 
    233246} 
     
    453466     * Unregister timer, if any. 
    454467     */ 
    455     pj_assert(tp->idle_timer.id == PJ_FALSE); 
     468    //pj_assert(tp->idle_timer.id == PJ_FALSE); 
    456469    if (tp->idle_timer.id != PJ_FALSE) { 
    457470        pjsip_endpt_cancel_timer(mgr->endpt, &tp->idle_timer); 
     
    567580        return status; 
    568581 
     582#if defined(PJ_DEBUG) && PJ_DEBUG!=0 
     583    status = pj_atomic_create(pool, 0, &mgr->tdata_counter); 
     584    if (status != PJ_SUCCESS) 
     585        return status; 
     586#endif 
     587 
    569588    *p_mgr = mgr; 
    570589    return PJ_SUCCESS; 
     
    582601     
    583602    PJ_LOG(5, (THIS_FILE, "pjsip_tpmgr_destroy()")); 
     603 
     604#if defined(PJ_DEBUG) && PJ_DEBUG!=0 
     605    pj_assert(pj_atomic_get(mgr->tdata_counter) == 0); 
     606#endif 
    584607 
    585608    pj_lock_acquire(mgr->lock); 
     
    601624 
    602625    pj_lock_release(mgr->lock); 
     626    pj_lock_destroy(mgr->lock); 
    603627 
    604628    return PJ_SUCCESS; 
     
    742766 
    743767/* 
    744  * pjsip_tpmgr_alloc_transport() 
     768 * pjsip_tpmgr_acquire_transport() 
    745769 * 
    746770 * Get transport suitable to communicate to remote. Create a new one 
    747771 * if necessary. 
    748772 */ 
    749 PJ_DEF(pj_status_t) pjsip_tpmgr_alloc_transport( pjsip_tpmgr *mgr, 
    750                                                  pjsip_transport_type_e type, 
    751                                                  const pj_sockaddr_t *remote, 
    752                                                  int addr_len, 
    753                                                  pjsip_transport **p_transport) 
     773PJ_DEF(pj_status_t) pjsip_tpmgr_acquire_transport(pjsip_tpmgr *mgr, 
     774                                                  pjsip_transport_type_e type, 
     775                                                  const pj_sockaddr_t *remote, 
     776                                                  int addr_len, 
     777                                                  pjsip_transport **tp) 
    754778{ 
    755779    struct transport_key 
     
    799823        pjsip_transport_add_ref(transport); 
    800824        pj_lock_release(mgr->lock); 
    801         *p_transport = transport; 
     825        *tp = transport; 
    802826        return PJ_SUCCESS; 
    803827    } 
     
    822846    /* Request factory to create transport. */ 
    823847    status = factory->create_transport(factory, mgr, mgr->endpt, 
    824                                        remote, p_transport); 
    825  
     848                                       remote, addr_len, tp); 
     849    if (status == PJ_SUCCESS) { 
     850        PJ_ASSERT_ON_FAIL(tp!=NULL,  
     851            {pj_lock_release(mgr->lock); return PJ_EBUG;}); 
     852        pjsip_transport_add_ref(*tp); 
     853    } 
    826854    pj_lock_release(mgr->lock); 
    827855    return status; 
  • pjproject/trunk/pjsip/src/pjsip/sip_transport_udp.c

    r105 r106  
    2222#include <pj/pool.h> 
    2323#include <pj/sock.h> 
     24#include <pj/addr_resolv.h> 
    2425#include <pj/os.h> 
    2526#include <pj/lock.h> 
     
    268269    pj_status_t status; 
    269270 
     271    PJ_ASSERT_RETURN(endpt && sock!=PJ_INVALID_SOCKET && a_name && async_cnt>0, 
     272                     PJ_EINVAL); 
     273 
    270274    /* Create pool. */ 
    271275    pool = pjsip_endpt_create_pool(endpt, "udp%p", PJSIP_POOL_LEN_TRANSPORT,  
     
    328332                              pj_inet_ntoa(((pj_sockaddr_in*)&tp->base.local_addr)->sin_addr), 
    329333                              pj_ntohs(((pj_sockaddr_in*)&tp->base.local_addr)->sin_port), 
    330                               tp->base.local_name.host, 
     334                              tp->base.local_name.host.ptr, 
    331335                              tp->base.local_name.port); 
    332336 
     
    368372    /* Create rdata and put it in the array. */ 
    369373    tp->rdata_cnt = 0; 
     374    tp->rdata = pj_pool_calloc(tp->base.pool, async_cnt,  
     375                               sizeof(pjsip_rx_data*)); 
    370376    for (i=0; i<async_cnt; ++i) { 
    371377        pj_pool_t *rdata_pool = pjsip_endpt_create_pool(endpt, "rtd%p",  
     
    383389        tp->rdata[i]->tp_info.pool = rdata_pool; 
    384390        tp->rdata[i]->tp_info.transport = &tp->base; 
     391        tp->rdata[i]->tp_info.op_key.rdata = tp->rdata[i]; 
    385392        pj_ioqueue_op_key_init(&tp->rdata[i]->tp_info.op_key.op_key,  
    386393                               sizeof(pj_ioqueue_op_key_t)); 
     
    437444    pjsip_host_port bound_name; 
    438445 
     446    PJ_ASSERT_RETURN(local != NULL, PJ_EINVAL); 
     447 
    439448    status = pj_sock_socket(PJ_AF_INET, PJ_SOCK_DGRAM, 0, &sock); 
    440449    if (status != PJ_SUCCESS) 
     
    448457 
    449458    if (a_name == NULL) { 
     459        /* Address name is not specified.  
     460         * Build a name based on bound address. 
     461         */ 
    450462        a_name = &bound_name; 
    451463        bound_name.host.ptr = addr_buf; 
    452         pj_strcpy2(&bound_name.host, pj_inet_ntoa(local->sin_addr)); 
    453464        bound_name.port = pj_ntohs(local->sin_port); 
     465 
     466        /* If bound address specifies "0.0.0.0", get the IP address 
     467         * of local hostname. 
     468         */ 
     469        if (local->sin_addr.s_addr == PJ_INADDR_ANY) { 
     470            pj_hostent he; 
     471            const pj_str_t *hostname = pj_gethostname(); 
     472            status = pj_gethostbyname(hostname, &he); 
     473            if (status != PJ_SUCCESS) { 
     474                pj_sock_close(sock); 
     475                return status; 
     476            } 
     477            pj_strcpy2(&bound_name.host,  
     478                       pj_inet_ntoa(*(pj_in_addr*)he.h_addr)); 
     479        } else { 
     480            /* Otherwise use bound address. */ 
     481            pj_strcpy2(&bound_name.host, pj_inet_ntoa(local->sin_addr)); 
     482        } 
     483         
    454484    } 
    455485 
  • pjproject/trunk/pjsip/src/pjsip/sip_util.c

    r105 r106  
    2424#include <pjsip/sip_transaction.h> 
    2525#include <pjsip/sip_module.h> 
     26#include <pjsip/sip_errno.h> 
    2627#include <pj/log.h> 
    2728#include <pj/string.h> 
     
    5253static pj_str_t str_TEXT = { "text", 4}, 
    5354                str_PLAIN = { "plain", 5 }; 
    54 static int aux_mod_id; 
    55  
    56 struct aux_tsx_data 
    57 { 
    58     void *token; 
    59     void (*cb)(void*,pjsip_event*); 
    60 }; 
    61  
    62 static pj_status_t aux_tsx_init( pjsip_endpoint *endpt, 
    63                                  struct pjsip_module *mod, pj_uint32_t id ) 
    64 { 
    65     PJ_UNUSED_ARG(endpt); 
    66     PJ_UNUSED_ARG(mod); 
    67  
    68     aux_mod_id = id; 
    69     return 0; 
    70 } 
    71  
    72 static void aux_tsx_handler( struct pjsip_module *mod, pjsip_event *event ) 
    73 { 
    74     pjsip_transaction *tsx; 
    75     struct aux_tsx_data *tsx_data; 
    76  
    77     PJ_UNUSED_ARG(mod); 
    78  
    79     if (event->type != PJSIP_EVENT_TSX_STATE) 
    80         return; 
    81  
    82     pj_assert(event->body.tsx_state.tsx != NULL); 
    83     tsx = event->body.tsx_state.tsx; 
    84     if (tsx == NULL) 
    85         return; 
    86     if (tsx->module_data[aux_mod_id] == NULL) 
    87         return; 
    88     if (tsx->status_code < 200) 
    89         return; 
    90  
    91     /* Call the callback, if any, and prevent the callback to be called again 
    92      * by clearing the transaction's module_data. 
    93      */ 
    94     tsx_data = tsx->module_data[aux_mod_id]; 
    95     tsx->module_data[aux_mod_id] = NULL; 
    96  
    97     if (tsx_data->cb) { 
    98         (*tsx_data->cb)(tsx_data->token, event); 
    99     } 
    100 } 
    101  
    102 pjsip_module aux_tsx_module =  
    103 { 
    104     { "Aux-Tsx", 7},        /* Name.            */ 
    105     0,                      /* Flag             */ 
    106     128,                    /* Priority         */ 
    107     NULL,                   /* Arbitrary data.  */ 
    108     0,                      /* Number of methods supported (none). */ 
    109     { 0 },                  /* Array of methods (none) */ 
    110     &aux_tsx_init,          /* init_module()    */ 
    111     NULL,                   /* start_module()   */ 
    112     NULL,                   /* deinit_module()  */ 
    113     &aux_tsx_handler,       /* tsx_handler()    */ 
    114 }; 
    115  
    116 PJ_DEF(pj_status_t) pjsip_endpt_send_request(  pjsip_endpoint *endpt, 
    117                                                pjsip_tx_data *tdata, 
    118                                                int timeout, 
    119                                                void *token, 
    120                                                void (*cb)(void*,pjsip_event*)) 
    121 { 
    122     pjsip_transaction *tsx; 
    123     struct aux_tsx_data *tsx_data; 
    124     pj_status_t status; 
    125  
    126     status = pjsip_endpt_create_tsx(endpt, &tsx); 
    127     if (!tsx) { 
    128         pjsip_tx_data_dec_ref(tdata); 
    129         return -1; 
    130     } 
    131  
    132     tsx_data = pj_pool_alloc(tsx->pool, sizeof(struct aux_tsx_data)); 
    133     tsx_data->token = token; 
    134     tsx_data->cb = cb; 
    135     tsx->module_data[aux_mod_id] = tsx_data; 
    136  
    137     if (pjsip_tsx_init_uac(tsx, tdata) != 0) { 
    138         pjsip_endpt_destroy_tsx(endpt, tsx); 
    139         pjsip_tx_data_dec_ref(tdata); 
    140         return -1; 
    141     } 
    142  
    143     pjsip_endpt_register_tsx(endpt, tsx); 
    144     pjsip_tx_data_invalidate_msg(tdata); 
    145     pjsip_tsx_on_tx_msg(tsx, tdata); 
    146     pjsip_tx_data_dec_ref(tdata); 
    147     return 0; 
    148 } 
    14955 
    15056/* 
     
    17076    pjsip_msg *msg; 
    17177    pjsip_msg_body *body; 
     78    pjsip_via_hdr *via; 
    17279    const pjsip_hdr *endpt_hdr; 
    17380 
     
    205112    /* Add CSeq header. */ 
    206113    pjsip_msg_add_hdr(msg, (void*)param_cseq); 
     114 
     115    /* Add a blank Via header. */ 
     116    via = pjsip_via_hdr_create(tdata->pool); 
     117    via->rport_param = 0; 
     118    pjsip_msg_insert_first_hdr(msg, (void*)via); 
    207119 
    208120    /* Create message body. */ 
     
    217129        msg->body = body; 
    218130    } 
     131 
     132    PJ_LOG(4,(THIS_FILE, "Request %s (CSeq=%d/%.*s) created.",  
     133                         tdata->obj_name,  
     134                         param_cseq->cseq,  
     135                         param_cseq->method.name.slen, 
     136                         param_cseq->method.name.ptr)); 
     137 
    219138} 
    220139 
     
    329248    PJ_END 
    330249 
    331     PJ_LOG(4,(THIS_FILE, "Request %s (%d %.*s) created.",  
    332                         tdata->obj_name,  
    333                         cseq->cseq,  
    334                         cseq->method.name.slen, 
    335                         cseq->method.name.ptr)); 
    336  
    337250    *p_tdata = tdata; 
    338251    return PJ_SUCCESS; 
     
    367280    PJ_LOG(5,(THIS_FILE, "Entering pjsip_endpt_create_request_from_hdr()")); 
    368281 
     282    /* Check arguments. */ 
     283    PJ_ASSERT_RETURN(endpt && method && param_target && param_from && 
     284                     param_to && p_tdata, PJ_EINVAL); 
     285 
     286    /* Create new transmit data. */ 
    369287    status = pjsip_endpt_create_tdata(endpt, &tdata); 
    370288    if (status != PJ_SUCCESS) 
    371289        return status; 
    372290 
     291    /* Set initial reference counter to 1. */ 
    373292    pjsip_tx_data_add_ref(tdata); 
    374293 
    375294    PJ_TRY { 
     295        /* Duplicate target URI and headers. */ 
    376296        target = pjsip_uri_clone(tdata->pool, param_target); 
    377         from = pjsip_hdr_shallow_clone(tdata->pool, param_from); 
     297        from = pjsip_hdr_clone(tdata->pool, param_from); 
    378298        pjsip_fromto_set_from(from); 
    379         to = pjsip_hdr_shallow_clone(tdata->pool, param_to); 
     299        to = pjsip_hdr_clone(tdata->pool, param_to); 
    380300        pjsip_fromto_set_to(to); 
    381301        if (param_contact) 
    382             contact = pjsip_hdr_shallow_clone(tdata->pool, param_contact); 
     302            contact = pjsip_hdr_clone(tdata->pool, param_contact); 
    383303        else 
    384304            contact = NULL; 
    385         call_id = pjsip_hdr_shallow_clone(tdata->pool, param_call_id); 
     305        call_id = pjsip_hdr_clone(tdata->pool, param_call_id); 
    386306        cseq = pjsip_cseq_hdr_create(tdata->pool); 
    387307        if (param_cseq >= 0) 
     
    391311        pjsip_method_copy(tdata->pool, &cseq->method, method); 
    392312 
     313        /* Copy headers to the request. */ 
    393314        init_request_throw(endpt, tdata, &cseq->method, target, from, to,  
    394315                           contact, call_id, cseq, param_text); 
     
    400321    PJ_END; 
    401322 
    402     PJ_LOG(4,(THIS_FILE, "Request %s (%d %.*s) created.",  
    403                         tdata->obj_name,  
    404                         cseq->cseq,  
    405                         cseq->method.name.slen, 
    406                         cseq->method.name.ptr)); 
    407  
    408323    *p_tdata = tdata; 
    409324    return PJ_SUCCESS; 
     
    419334PJ_DEF(pj_status_t) pjsip_endpt_create_response( pjsip_endpoint *endpt, 
    420335                                                 const pjsip_rx_data *rdata, 
    421                                                  int code, 
     336                                                 int st_code, 
     337                                                 const pj_str_t *st_text, 
    422338                                                 pjsip_tx_data **p_tdata) 
    423339{ 
     
    435351    /* Log this action. */ 
    436352    PJ_LOG(5,(THIS_FILE, "pjsip_endpt_create_response(rdata=%p, code=%d)",  
    437                          rdata, code)); 
     353                         rdata, st_code)); 
    438354 
    439355    /* Create a new transmit buffer. */ 
     
    442358        return status; 
    443359 
     360    /* Set initial reference count to 1. */ 
     361    pjsip_tx_data_add_ref(tdata); 
     362 
    444363    /* Create new response message. */ 
    445364    tdata->msg = msg = pjsip_msg_create(tdata->pool, PJSIP_RESPONSE_MSG); 
    446365 
    447366    /* Set status code and reason text. */ 
    448     msg->line.status.code = code; 
    449     msg->line.status.reason = *pjsip_get_status_text(code); 
     367    msg->line.status.code = st_code; 
     368    if (st_text) 
     369        pj_strdup(tdata->pool, &msg->line.status.reason, st_text); 
     370    else 
     371        msg->line.status.reason = *pjsip_get_status_text(st_code); 
    450372 
    451373    /* Set TX data attributes. */ 
     
    501423 * and one must not use this function to generate such ACK. 
    502424 */ 
    503 PJ_DEF(void) pjsip_endpt_create_ack(pjsip_endpoint *endpt, 
    504                                     pjsip_tx_data *tdata, 
    505                                     const pjsip_rx_data *rdata ) 
    506 { 
    507     pjsip_msg *ack_msg, *invite_msg; 
     425PJ_DEF(pj_status_t) pjsip_endpt_create_ack( pjsip_endpoint *endpt, 
     426                                            const pjsip_tx_data *tdata, 
     427                                            const pjsip_rx_data *rdata, 
     428                                            pjsip_tx_data **ack_tdata) 
     429{ 
     430    pjsip_tx_data *ack = NULL; 
     431    const pjsip_msg *invite_msg; 
     432    const pjsip_from_hdr *from_hdr; 
     433    const pjsip_to_hdr *to_hdr; 
     434    const pjsip_cid_hdr *cid_hdr; 
     435    const pjsip_cseq_hdr *cseq_hdr; 
     436    const pjsip_hdr *hdr; 
    508437    pjsip_to_hdr *to; 
    509     pjsip_from_hdr *from; 
    510     pjsip_cseq_hdr *cseq; 
    511     pjsip_hdr *hdr; 
    512  
    513     /* Make compiler happy. */ 
    514     PJ_UNUSED_ARG(endpt); 
     438    pj_status_t status; 
     439 
     440    /* Log this action. */ 
     441    PJ_LOG(5,(THIS_FILE, "pjsip_endpt_create_ack(rdata=%p)", rdata)); 
    515442 
    516443    /* rdata must be a final response. */ 
     
    518445              rdata->msg_info.msg->line.status.code >= 300); 
    519446 
    520     /* Log this action. */ 
    521     PJ_LOG(5,(THIS_FILE, "pjsip_endpt_create_ack(rdata=%p)", rdata)); 
    522  
    523     /* Create new request message. */ 
    524     ack_msg = pjsip_msg_create(tdata->pool, PJSIP_REQUEST_MSG); 
    525     pjsip_method_set( &ack_msg->line.req.method, PJSIP_ACK_METHOD ); 
     447    /* Initialize return value to NULL. */ 
     448    *ack_tdata = NULL; 
    526449 
    527450    /* The original INVITE message. */ 
    528451    invite_msg = tdata->msg; 
    529452 
    530     /* Copy Request-Uri from the original INVITE. */ 
    531     ack_msg->line.req.uri = invite_msg->line.req.uri; 
    532      
    533     /* Copy Call-ID from the original INVITE */ 
    534     hdr = pjsip_msg_find_remove_hdr( invite_msg, PJSIP_H_CALL_ID, NULL); 
    535     pjsip_msg_add_hdr( ack_msg, hdr ); 
    536  
    537     /* Copy From header from the original INVITE. */ 
    538     from = (pjsip_from_hdr*)pjsip_msg_find_remove_hdr(invite_msg,  
    539                                                       PJSIP_H_FROM, NULL); 
    540     pjsip_msg_add_hdr( ack_msg, (pjsip_hdr*)from ); 
    541  
    542     /* Copy To header from the original INVITE. */ 
    543     to = (pjsip_to_hdr*)pjsip_msg_find_remove_hdr( invite_msg,  
    544                                                    PJSIP_H_TO, NULL); 
    545     pj_strdup(tdata->pool, &to->tag, &rdata->msg_info.to->tag); 
    546     pjsip_msg_add_hdr( ack_msg, (pjsip_hdr*)to ); 
     453    /* Get the headers from original INVITE request. */ 
     454#   define FIND_HDR(m,HNAME) pjsip_msg_find_hdr(m, PJSIP_H_##HNAME, NULL) 
     455 
     456    from_hdr = (const pjsip_from_hdr*) FIND_HDR(invite_msg, FROM); 
     457    PJ_ASSERT_ON_FAIL(from_hdr != NULL, goto on_missing_hdr); 
     458 
     459    to_hdr = (const pjsip_to_hdr*) FIND_HDR(invite_msg, TO); 
     460    PJ_ASSERT_ON_FAIL(to_hdr != NULL, goto on_missing_hdr); 
     461 
     462    cid_hdr = (const pjsip_cid_hdr*) FIND_HDR(invite_msg, CALL_ID); 
     463    PJ_ASSERT_ON_FAIL(to_hdr != NULL, goto on_missing_hdr); 
     464 
     465    cseq_hdr = (const pjsip_cseq_hdr*) FIND_HDR(invite_msg, CSEQ); 
     466    PJ_ASSERT_ON_FAIL(to_hdr != NULL, goto on_missing_hdr); 
     467 
     468#   undef FIND_HDR 
     469 
     470    /* Create new request message from the headers. */ 
     471    status = pjsip_endpt_create_request_from_hdr(endpt,  
     472                                                 &pjsip_ack_method, 
     473                                                 tdata->msg->line.req.uri, 
     474                                                 from_hdr, to_hdr, 
     475                                                 NULL, cid_hdr, 
     476                                                 cseq_hdr->cseq, NULL, 
     477                                                 &ack); 
     478 
     479    if (status != PJ_SUCCESS) 
     480        return status; 
     481 
     482    /* Update tag in To header with the one from the response (if any). */ 
     483    to = (pjsip_to_hdr*) pjsip_msg_find_hdr(ack->msg, PJSIP_H_TO, NULL); 
     484    pj_strdup(ack->pool, &to->tag, &rdata->msg_info.to->tag); 
    547485 
    548486    /* Must contain single Via, just as the original INVITE. */ 
    549     hdr = pjsip_msg_find_remove_hdr( invite_msg, PJSIP_H_VIA, NULL); 
    550     pjsip_msg_insert_first_hdr( ack_msg, hdr ); 
    551  
    552     /* Must have the same CSeq value as the original INVITE, but method  
    553      * changed to ACK  
    554      */ 
    555     cseq = (pjsip_cseq_hdr*) pjsip_msg_find_remove_hdr( invite_msg,  
    556                                                         PJSIP_H_CSEQ, NULL); 
    557     pjsip_method_set( &cseq->method, PJSIP_ACK_METHOD ); 
    558     pjsip_msg_add_hdr( ack_msg, (pjsip_hdr*) cseq ); 
     487    hdr = pjsip_msg_find_hdr( invite_msg, PJSIP_H_VIA, NULL); 
     488    if (hdr) { 
     489        pjsip_msg_insert_first_hdr( ack->msg, pjsip_hdr_clone(ack->pool,hdr) ); 
     490    } 
    559491 
    560492    /* If the original INVITE has Route headers, those header fields MUST  
    561493     * appear in the ACK. 
    562494     */ 
    563     hdr = pjsip_msg_find_remove_hdr( invite_msg, PJSIP_H_ROUTE, NULL); 
     495    hdr = pjsip_msg_find_hdr( invite_msg, PJSIP_H_ROUTE, NULL); 
    564496    while (hdr != NULL) { 
    565         pjsip_msg_add_hdr( ack_msg, hdr ); 
    566         hdr = pjsip_msg_find_remove_hdr( invite_msg, PJSIP_H_ROUTE, NULL); 
    567     } 
    568  
    569     /* Set the message in the "tdata" to point to the ACK message. */ 
    570     tdata->msg = ack_msg; 
    571  
    572     /* Reset transmit packet buffer, to force 're-printing' of message. */ 
    573     tdata->buf.cur = tdata->buf.start; 
     497        pjsip_msg_add_hdr( ack->msg, pjsip_hdr_clone(ack->pool, hdr) ); 
     498        hdr = hdr->next; 
     499        if (hdr == &invite_msg->hdr) 
     500            break; 
     501        hdr = pjsip_msg_find_hdr( invite_msg, PJSIP_H_ROUTE, hdr); 
     502    } 
    574503 
    575504    /* We're done. 
    576505     * "tdata" parameter now contains the ACK message. 
    577506     */ 
     507    *ack_tdata = ack; 
     508    return PJ_SUCCESS; 
     509 
     510on_missing_hdr: 
     511    if (ack) 
     512        pjsip_tx_data_dec_ref(ack); 
     513    return PJSIP_EMISSINGHDR; 
    578514} 
    579515 
     
    584520 */ 
    585521PJ_DEF(pj_status_t) pjsip_endpt_create_cancel( pjsip_endpoint *endpt, 
    586                                                pjsip_tx_data *req_tdata, 
     522                                               const pjsip_tx_data *req_tdata, 
    587523                                               pjsip_tx_data **p_tdata) 
    588524{ 
    589     pjsip_msg *req_msg; /* the original request. */ 
    590     pjsip_tx_data *cancel_tdata; 
    591     pjsip_msg *cancel_msg; 
    592     pjsip_hdr *hdr; 
    593     pjsip_cseq_hdr *req_cseq, *cseq; 
    594     pjsip_uri *req_uri; 
     525    pjsip_tx_data *cancel_tdata = NULL; 
     526    const pjsip_from_hdr *from_hdr; 
     527    const pjsip_to_hdr *to_hdr; 
     528    const pjsip_cid_hdr *cid_hdr; 
     529    const pjsip_cseq_hdr *cseq_hdr; 
     530    const pjsip_hdr *hdr; 
    595531    pj_status_t status; 
    596532 
     
    598534    PJ_LOG(5,(THIS_FILE, "pjsip_endpt_create_cancel(tdata=%p)", req_tdata)); 
    599535 
    600     /* Get the original request. */ 
    601     req_msg = req_tdata->msg; 
    602  
    603536    /* The transmit buffer must INVITE request. */ 
    604     PJ_ASSERT_RETURN(req_msg->type == PJSIP_REQUEST_MSG && 
    605                      req_msg->line.req.method.id == PJSIP_INVITE_METHOD, 
     537    PJ_ASSERT_RETURN(req_tdata->msg->type == PJSIP_REQUEST_MSG && 
     538                     req_tdata->msg->line.req.method.id == PJSIP_INVITE_METHOD, 
    606539                     PJ_EINVAL); 
    607540 
    608     /* Create new transmit buffer. */ 
    609     status = pjsip_endpt_create_tdata( endpt, &cancel_tdata); 
    610     if (status != PJ_SUCCESS) { 
     541    /* Get the headers from original INVITE request. */ 
     542#   define FIND_HDR(m,HNAME) pjsip_msg_find_hdr(m, PJSIP_H_##HNAME, NULL) 
     543 
     544    from_hdr = (const pjsip_from_hdr*) FIND_HDR(req_tdata->msg, FROM); 
     545    PJ_ASSERT_ON_FAIL(from_hdr != NULL, goto on_missing_hdr); 
     546 
     547    to_hdr = (const pjsip_to_hdr*) FIND_HDR(req_tdata->msg, TO); 
     548    PJ_ASSERT_ON_FAIL(to_hdr != NULL, goto on_missing_hdr); 
     549 
     550    cid_hdr = (const pjsip_cid_hdr*) FIND_HDR(req_tdata->msg, CALL_ID); 
     551    PJ_ASSERT_ON_FAIL(to_hdr != NULL, goto on_missing_hdr); 
     552 
     553    cseq_hdr = (const pjsip_cseq_hdr*) FIND_HDR(req_tdata->msg, CSEQ); 
     554    PJ_ASSERT_ON_FAIL(to_hdr != NULL, goto on_missing_hdr); 
     555 
     556#   undef FIND_HDR 
     557 
     558    /* Create new request message from the headers. */ 
     559    status = pjsip_endpt_create_request_from_hdr(endpt,  
     560                                                 &pjsip_cancel_method, 
     561                                                 req_tdata->msg->line.req.uri, 
     562                                                 from_hdr, to_hdr, 
     563                                                 NULL, cid_hdr, 
     564                                                 cseq_hdr->cseq, NULL, 
     565                                                 &cancel_tdata); 
     566 
     567    if (status != PJ_SUCCESS) 
    611568        return status; 
    612     } 
    613  
    614     /* Create CANCEL request message. */ 
    615     cancel_msg = pjsip_msg_create(cancel_tdata->pool, PJSIP_REQUEST_MSG); 
    616     cancel_tdata->msg = cancel_msg; 
    617  
    618     /* Request-URI, Call-ID, From, To, and the numeric part of the CSeq are 
    619      * copied from the original request. 
    620      */ 
    621     /* Set request line. */ 
    622     pjsip_method_set(&cancel_msg->line.req.method, PJSIP_CANCEL_METHOD); 
    623     req_uri = req_msg->line.req.uri; 
    624     cancel_msg->line.req.uri = pjsip_uri_clone(cancel_tdata->pool, req_uri); 
    625  
    626     /* Copy Call-ID */ 
    627     hdr = pjsip_msg_find_hdr(req_msg, PJSIP_H_CALL_ID, NULL); 
    628     pjsip_msg_add_hdr(cancel_msg, pjsip_hdr_clone(cancel_tdata->pool, hdr)); 
    629  
    630     /* Copy From header. */ 
    631     hdr = pjsip_msg_find_hdr(req_msg, PJSIP_H_FROM, NULL); 
    632     pjsip_msg_add_hdr(cancel_msg, pjsip_hdr_clone(cancel_tdata->pool, hdr)); 
    633  
    634     /* Copy To header. */ 
    635     hdr = pjsip_msg_find_hdr(req_msg, PJSIP_H_TO, NULL); 
    636     pjsip_msg_add_hdr(cancel_msg, pjsip_hdr_clone(cancel_tdata->pool, hdr)); 
    637  
    638     /* Create new CSeq with equal number, but method set to CANCEL. */ 
    639     req_cseq = (pjsip_cseq_hdr*) pjsip_msg_find_hdr(req_msg, PJSIP_H_CSEQ, NULL); 
    640     cseq = pjsip_cseq_hdr_create(cancel_tdata->pool); 
    641     cseq->cseq = req_cseq->cseq; 
    642     pjsip_method_set(&cseq->method, PJSIP_CANCEL_METHOD); 
    643     pjsip_msg_add_hdr(cancel_msg, (pjsip_hdr*)cseq); 
    644569 
    645570    /* Must only have single Via which matches the top-most Via in the  
    646571     * request being cancelled.  
    647572     */ 
    648     hdr = pjsip_msg_find_hdr(req_msg, PJSIP_H_VIA, NULL); 
    649     pjsip_msg_insert_first_hdr(cancel_msg,  
    650                                pjsip_hdr_clone(cancel_tdata->pool, hdr)); 
     573    hdr = pjsip_msg_find_hdr(req_tdata->msg, PJSIP_H_VIA, NULL); 
     574    if (hdr) { 
     575        pjsip_msg_insert_first_hdr(cancel_tdata->msg,  
     576                                   pjsip_hdr_clone(cancel_tdata->pool, hdr)); 
     577    } 
    651578 
    652579    /* If the original request has Route header, the CANCEL request must also 
     
    654581     * Copy "Route" header from the request. 
    655582     */ 
    656     hdr = pjsip_msg_find_hdr(req_msg, PJSIP_H_ROUTE, NULL); 
     583    hdr = pjsip_msg_find_hdr(req_tdata->msg, PJSIP_H_ROUTE, NULL); 
    657584    while (hdr != NULL) { 
    658         pjsip_msg_add_hdr(cancel_msg, pjsip_hdr_clone(cancel_tdata->pool, hdr)); 
     585        pjsip_msg_add_hdr(cancel_tdata->msg,  
     586                          pjsip_hdr_clone(cancel_tdata->pool, hdr)); 
    659587        hdr = hdr->next; 
    660         if (hdr != &cancel_msg->hdr) 
    661             hdr = pjsip_msg_find_hdr(req_msg, PJSIP_H_ROUTE, hdr); 
     588        if (hdr != &cancel_tdata->msg->hdr) 
     589            hdr = pjsip_msg_find_hdr(cancel_tdata->msg, PJSIP_H_ROUTE, hdr); 
    662590        else 
    663591            break; 
     
    669597    *p_tdata = cancel_tdata; 
    670598    return PJ_SUCCESS; 
    671 } 
    672  
    673 /* Get the address parameters (host, port, flag, TTL, etc) to send the 
    674  * response. 
    675  */ 
    676 PJ_DEF(pj_status_t) pjsip_get_response_addr(pj_pool_t *pool, 
    677                                             const pjsip_transport *req_transport, 
    678                                             const pjsip_via_hdr *via, 
    679                                             pjsip_host_info *send_addr) 
    680 { 
    681     /* Determine the destination address (section 18.2.2): 
    682      * - for TCP, SCTP, or TLS, send the response using the transport where 
    683      *   the request was received. 
    684      * - if maddr parameter is present, send to this address using the port 
    685      *   in sent-by or 5060. If multicast is used, the TTL in the Via must 
    686      *   be used, or 1 if ttl parameter is not present. 
    687      * - otherwise if received parameter is present, set to this address. 
    688      * - otherwise send to the address in sent-by. 
     599 
     600on_missing_hdr: 
     601    if (cancel_tdata) 
     602        pjsip_tx_data_dec_ref(cancel_tdata); 
     603    return PJSIP_EMISSINGHDR; 
     604} 
     605 
     606 
     607/* 
     608 * Find which destination to be used to send the request message, based 
     609 * on the request URI and Route headers in the message. The procedure 
     610 * used here follows the guidelines on sending the request in RFC 3261 
     611 * chapter 8.1.2. 
     612 */ 
     613PJ_DEF(pj_status_t) pjsip_get_request_addr( pjsip_tx_data *tdata, 
     614                                            pjsip_host_info *dest_info ) 
     615{ 
     616    const pjsip_uri *new_request_uri, *target_uri; 
     617    const pjsip_name_addr *topmost_route_uri; 
     618    pjsip_route_hdr *first_route_hdr, *last_route_hdr; 
     619     
     620    PJ_ASSERT_RETURN(tdata->msg->type == PJSIP_REQUEST_MSG,  
     621                     PJSIP_ENOTREQUESTMSG); 
     622    PJ_ASSERT_RETURN(dest_info != NULL, PJ_EINVAL); 
     623 
     624    /* Get the first "Route" header from the message. If the message doesn't 
     625     * have any "Route" headers but the endpoint has, then copy the "Route" 
     626     * headers from the endpoint first. 
    689627     */ 
    690     send_addr->flag = req_transport->flag; 
    691     send_addr->type = req_transport->key.type; 
    692  
    693     if (PJSIP_TRANSPORT_IS_RELIABLE(req_transport)) { 
    694         pj_strdup( pool, &send_addr->addr.host,  
    695                    &req_transport->remote_name.host); 
    696         send_addr->addr.port = req_transport->remote_name.port; 
    697  
     628    last_route_hdr = first_route_hdr =  
     629        pjsip_msg_find_hdr(tdata->msg, PJSIP_H_ROUTE, NULL); 
     630    if (first_route_hdr) { 
     631        topmost_route_uri = &first_route_hdr->name_addr; 
     632        while (last_route_hdr->next != (void*)&tdata->msg->hdr) { 
     633            pjsip_route_hdr *hdr; 
     634            hdr = pjsip_msg_find_hdr(tdata->msg, PJSIP_H_ROUTE,  
     635                                     last_route_hdr->next); 
     636            if (!hdr) 
     637                break; 
     638            last_route_hdr = hdr; 
     639        } 
    698640    } else { 
    699         /* Set the host part */ 
    700         if (via->maddr_param.slen) { 
    701             pj_strdup(pool, &send_addr->addr.host, &via->maddr_param); 
    702         } else if (via->recvd_param.slen) { 
    703             pj_strdup(pool, &send_addr->addr.host, &via->recvd_param); 
     641        topmost_route_uri = NULL; 
     642    } 
     643 
     644    /* If Route headers exist, and the first element indicates loose-route, 
     645     * the URI is taken from the Request-URI, and we keep all existing Route 
     646     * headers intact. 
     647     * If Route headers exist, and the first element DOESN'T indicate loose 
     648     * route, the URI is taken from the first Route header, and remove the 
     649     * first Route header from the message. 
     650     * Otherwise if there's no Route headers, the URI is taken from the 
     651     * Request-URI. 
     652     */ 
     653    if (topmost_route_uri) { 
     654        pj_bool_t has_lr_param; 
     655 
     656        if (PJSIP_URI_SCHEME_IS_SIP(topmost_route_uri) || 
     657            PJSIP_URI_SCHEME_IS_SIPS(topmost_route_uri)) 
     658        { 
     659            const pjsip_url *url = pjsip_uri_get_uri((void*)topmost_route_uri); 
     660            has_lr_param = url->lr_param; 
    704661        } else { 
    705             pj_strdup(pool, &send_addr->addr.host, &via->sent_by.host); 
    706         } 
    707  
    708         /* Set the port */ 
    709         send_addr->addr.port = via->sent_by.port; 
    710     } 
    711  
     662            has_lr_param = 0; 
     663        } 
     664 
     665        if (has_lr_param) { 
     666            new_request_uri = tdata->msg->line.req.uri; 
     667            /* We shouldn't need to delete topmost Route if it has lr param. 
     668             * But seems like it breaks some proxy implementation, so we 
     669             * delete it anyway. 
     670             */ 
     671            /* 
     672            pj_list_erase(first_route_hdr); 
     673            if (first_route_hdr == last_route_hdr) 
     674                last_route_hdr = NULL; 
     675            */ 
     676        } else { 
     677            new_request_uri = pjsip_uri_get_uri((void*)topmost_route_uri); 
     678            pj_list_erase(first_route_hdr); 
     679            if (first_route_hdr == last_route_hdr) 
     680                last_route_hdr = NULL; 
     681        } 
     682 
     683        target_uri = (pjsip_uri*)topmost_route_uri; 
     684 
     685    } else { 
     686        target_uri = new_request_uri = tdata->msg->line.req.uri; 
     687    } 
     688 
     689    /* The target URI must be a SIP/SIPS URL so we can resolve it's address. 
     690     * Otherwise we're in trouble (i.e. there's no host part in tel: URL). 
     691     */ 
     692    pj_memset(dest_info, 0, sizeof(*dest_info)); 
     693 
     694    if (PJSIP_URI_SCHEME_IS_SIPS(target_uri)) { 
     695        pjsip_uri *uri = (pjsip_uri*) target_uri; 
     696        const pjsip_url *url = (const pjsip_url*)pjsip_uri_get_uri(uri); 
     697        dest_info->flag |= (PJSIP_TRANSPORT_SECURE | PJSIP_TRANSPORT_RELIABLE); 
     698        pj_strdup(tdata->pool, &dest_info->addr.host, &url->host); 
     699        dest_info->addr.port = url->port; 
     700        dest_info->type =  
     701            pjsip_transport_get_type_from_name(&url->transport_param); 
     702 
     703    } else if (PJSIP_URI_SCHEME_IS_SIP(target_uri)) { 
     704        pjsip_uri *uri = (pjsip_uri*) target_uri; 
     705        const pjsip_url *url = (const pjsip_url*)pjsip_uri_get_uri(uri); 
     706        pj_strdup(tdata->pool, &dest_info->addr.host, &url->host); 
     707        dest_info->addr.port = url->port; 
     708        dest_info->type =  
     709            pjsip_transport_get_type_from_name(&url->transport_param); 
     710#if PJ_HAS_TCP 
     711        if (dest_info->type == PJSIP_TRANSPORT_TCP ||  
     712            dest_info->type == PJSIP_TRANSPORT_SCTP)  
     713        { 
     714            dest_info->flag |= PJSIP_TRANSPORT_RELIABLE; 
     715        } 
     716#endif 
     717    } else { 
     718        pj_assert(!"Unsupported URI scheme!"); 
     719        PJ_TODO(SUPPORT_REQUEST_ADDR_RESOLUTION_FOR_TEL_URI); 
     720        return PJSIP_EINVALIDSCHEME; 
     721    } 
     722 
     723    /* If target URI is different than request URI, replace  
     724     * request URI add put the original URI in the last Route header. 
     725     */ 
     726    if (new_request_uri && new_request_uri!=tdata->msg->line.req.uri) { 
     727        pjsip_route_hdr *route = pjsip_route_hdr_create(tdata->pool); 
     728        route->name_addr.uri = tdata->msg->line.req.uri; 
     729        if (last_route_hdr) 
     730            pj_list_insert_after(last_route_hdr, route); 
     731        else 
     732            pjsip_msg_add_hdr(tdata->msg, (pjsip_hdr*)route); 
     733        tdata->msg->line.req.uri = (pjsip_uri*)new_request_uri; 
     734    } 
     735 
     736    /* Success. */ 
     737    return PJ_SUCCESS;   
     738} 
     739 
     740 
     741/* Transport callback for sending stateless request.  
     742 * This is one of the most bizzare function in pjsip, so 
     743 * good luck if you happen to debug this function!! 
     744 */ 
     745static void stateless_send_transport_cb( void *token, 
     746                                         pjsip_tx_data *tdata, 
     747                                         pj_ssize_t sent ) 
     748{ 
     749    pjsip_send_state *stateless_data = token; 
     750 
     751    PJ_UNUSED_ARG(tdata); 
     752    pj_assert(tdata == stateless_data->tdata); 
     753 
     754    for (;;) { 
     755        pj_status_t status; 
     756        pj_bool_t cont; 
     757 
     758        pj_sockaddr_t *cur_addr; 
     759        pjsip_transport_type_e cur_addr_type; 
     760        int cur_addr_len; 
     761 
     762        pjsip_via_hdr *via; 
     763 
     764        if (sent == -PJ_EPENDING) { 
     765            /* This is the initial process. 
     766             * When the process started, this function will be called by 
     767             * stateless_send_resolver_callback() with sent argument set to 
     768             * -PJ_EPENDING. 
     769             */ 
     770            cont = PJ_TRUE; 
     771        } else { 
     772            /* There are two conditions here: 
     773             * (1) Message is sent (i.e. sent > 0), 
     774             * (2) Failure (i.e. sent <= 0) 
     775             */ 
     776            cont = (sent > 0) ? PJ_FALSE : 
     777                   (stateless_data->cur_addr<stateless_data->addr.count-1); 
     778            if (stateless_data->app_cb) { 
     779                (*stateless_data->app_cb)(stateless_data, sent, &cont); 
     780            } else { 
     781                /* Doesn't have application callback. 
     782                 * Terminate the process. 
     783                 */ 
     784                cont = PJ_FALSE; 
     785            } 
     786        } 
     787 
     788        /* Finished with this transport. */ 
     789        if (stateless_data->cur_transport) { 
     790            pjsip_transport_dec_ref(stateless_data->cur_transport); 
     791            stateless_data->cur_transport = NULL; 
     792        } 
     793 
     794        /* Done if application doesn't want to continue. */ 
     795        if (sent > 0 || !cont) { 
     796            pjsip_tx_data_dec_ref(tdata); 
     797            return; 
     798        } 
     799 
     800        /* Try next address, if any, and only when this is not the  
     801         * first invocation.  
     802         */ 
     803        if (sent != -PJ_EPENDING) { 
     804            stateless_data->cur_addr++; 
     805        } 
     806 
     807        /* Have next address? */ 
     808        if (stateless_data->cur_addr >= stateless_data->addr.count) { 
     809            /* This only happens when a rather buggy application has 
     810             * sent 'cont' to PJ_TRUE when the initial value was PJ_FALSE. 
     811             * In this case just stop the processing; we don't need to 
     812             * call the callback again as application has been informed 
     813             * before. 
     814             */ 
     815            pjsip_tx_data_dec_ref(tdata); 
     816            return; 
     817        } 
     818 
     819        /* Keep current server address information handy. */ 
     820        cur_addr = &stateless_data->addr.entry[stateless_data->cur_addr].addr; 
     821        cur_addr_type = stateless_data->addr.entry[stateless_data->cur_addr].type; 
     822        cur_addr_len = stateless_data->addr.entry[stateless_data->cur_addr].addr_len; 
     823 
     824        /* Acquire transport. */ 
     825        status = pjsip_endpt_acquire_transport( stateless_data->endpt, 
     826                                                cur_addr_type, 
     827                                                cur_addr, 
     828                                                cur_addr_len, 
     829                                                &stateless_data->cur_transport); 
     830        if (status != PJ_SUCCESS) { 
     831            sent = -status; 
     832            continue; 
     833        } 
     834 
     835        /* Modify Via header. */ 
     836        via = (pjsip_via_hdr*) pjsip_msg_find_hdr( tdata->msg, 
     837                                                   PJSIP_H_VIA, NULL); 
     838        if (!via) { 
     839            /* Shouldn't happen if request was created with PJSIP API!  
     840             * But we handle the case anyway for robustness. 
     841             */ 
     842            pj_assert(!"Via header not found!"); 
     843            via = pjsip_via_hdr_create(tdata->pool); 
     844            pjsip_msg_insert_first_hdr(tdata->msg, (pjsip_hdr*)via); 
     845        } 
     846 
     847        if (via->branch_param.slen == 0) { 
     848            pj_str_t tmp; 
     849            via->branch_param.ptr = pj_pool_alloc(tdata->pool, 
     850                                                  PJSIP_MAX_BRANCH_LEN); 
     851            via->branch_param.slen = PJSIP_MAX_BRANCH_LEN; 
     852            pj_memcpy(via->branch_param.ptr, PJSIP_RFC3261_BRANCH_ID, 
     853                      PJSIP_RFC3261_BRANCH_LEN); 
     854            tmp.ptr = via->branch_param.ptr + PJSIP_RFC3261_BRANCH_LEN; 
     855            pj_generate_unique_string(&tmp); 
     856        } 
     857 
     858        via->transport = pj_str(stateless_data->cur_transport->type_name); 
     859        via->sent_by = stateless_data->cur_transport->local_name; 
     860        via->rport_param = 0; 
     861 
     862        /* Send message using this transport. */ 
     863        status = pjsip_transport_send( stateless_data->cur_transport, 
     864                                       tdata, 
     865                                       cur_addr, 
     866                                       cur_addr_len, 
     867                                       stateless_data, 
     868                                       &stateless_send_transport_cb); 
     869        if (status == PJ_SUCCESS) { 
     870            /* Recursively call this function. */ 
     871            sent = tdata->buf.cur - tdata->buf.start; 
     872            stateless_send_transport_cb( stateless_data, tdata, sent ); 
     873            return; 
     874        } else if (status == PJ_EPENDING) { 
     875            /* This callback will be called later. */ 
     876            return; 
     877        } else { 
     878            /* Recursively call this function. */ 
     879            sent = -status; 
     880            stateless_send_transport_cb( stateless_data, tdata, sent ); 
     881            return; 
     882        } 
     883    } 
     884 
     885} 
     886 
     887/* Resolver callback for sending stateless request. */ 
     888static void  
     889stateless_send_resolver_callback( pj_status_t status, 
     890                                  void *token, 
     891                                  const struct pjsip_server_addresses *addr) 
     892{ 
     893    pjsip_send_state *stateless_data = token; 
     894 
     895    /* Fail on server resolution. */ 
     896    if (status != PJ_SUCCESS) { 
     897        if (stateless_data->app_cb) { 
     898            pj_bool_t cont = PJ_FALSE; 
     899            (*stateless_data->app_cb)(stateless_data, -status, &cont); 
     900        } 
     901        pjsip_tx_data_dec_ref(stateless_data->tdata); 
     902        return; 
     903    } 
     904 
     905    /* Copy server addresses */ 
     906    pj_memcpy( &stateless_data->addr, addr, sizeof(pjsip_server_addresses)); 
     907 
     908    /* Process the addresses. */ 
     909    stateless_send_transport_cb( stateless_data, stateless_data->tdata, 
     910                                 -PJ_EPENDING); 
     911} 
     912 
     913/* 
     914 * Send stateless request. 
     915 * The sending process consists of several stages: 
     916 *  - determine which host to contact (#pjsip_get_request_addr). 
     917 *  - resolve the host (#pjsip_endpt_resolve) 
     918 *  - establish transport (#pjsip_endpt_acquire_transport) 
     919 *  - send the message (#pjsip_transport_send) 
     920 */ 
     921PJ_DEF(pj_status_t)  
     922pjsip_endpt_send_request_stateless(pjsip_endpoint *endpt,  
     923                                   pjsip_tx_data *tdata, 
     924                                   void *token, 
     925                                   void (*cb)(pjsip_send_state*, 
     926                                              pj_ssize_t sent, 
     927                                              pj_bool_t *cont)) 
     928{ 
     929    pjsip_host_info dest_info; 
     930    pjsip_send_state *stateless_data; 
     931    pj_status_t status; 
     932 
     933    PJ_ASSERT_RETURN(endpt && tdata, PJ_EINVAL); 
     934 
     935    /* Get destination name to contact. */ 
     936    status = pjsip_get_request_addr(tdata, &dest_info); 
     937    if (status != PJ_SUCCESS) 
     938        return status; 
     939 
     940    /* Keep stateless data. */ 
     941    stateless_data = pj_pool_zalloc(tdata->pool, sizeof(pjsip_send_state)); 
     942    stateless_data->token = token; 
     943    stateless_data->endpt = endpt; 
     944    stateless_data->tdata = tdata; 
     945    stateless_data->app_cb = cb; 
     946 
     947    /* Resolve destination host. 
     948     * The processing then resumed when the resolving callback is called. 
     949     */ 
     950    pjsip_endpt_resolve( endpt, tdata->pool, &dest_info, stateless_data, 
     951                         &stateless_send_resolver_callback); 
    712952    return PJ_SUCCESS; 
    713953} 
     954 
     955/* 
     956 * Determine which address (and transport) to use to send response message 
     957 * based on the received request. This function follows the specification 
     958 * in section 18.2.2 of RFC 3261 and RFC 3581 for calculating the destination 
     959 * address and transport. 
     960 */ 
     961PJ_DEF(pj_status_t) pjsip_get_response_addr( pj_pool_t *pool, 
     962                                             pjsip_rx_data *rdata, 
     963                                             pjsip_response_addr *res_addr ) 
     964{ 
     965    pjsip_transport *src_transport = rdata->tp_info.transport; 
     966 
     967    /* Check arguments. */ 
     968    PJ_ASSERT_RETURN(pool && rdata && res_addr, PJ_EINVAL); 
     969 
     970    /* All requests must have "received" parameter. 
     971     * This must always be done in transport layer. 
     972     */ 
     973    pj_assert(rdata->msg_info.via->recvd_param.slen != 0); 
     974 
     975    /* Do the calculation based on RFC 3261 Section 18.2.2 and RFC 3581 */ 
     976 
     977    if (PJSIP_TRANSPORT_IS_RELIABLE(src_transport)) { 
     978        /* For reliable protocol such as TCP or SCTP, or TLS over those, the 
     979         * response MUST be sent using the existing connection to the source 
     980         * of the original request that created the transaction, if that  
     981         * connection is still open.  
     982         * If that connection is no longer open, the server SHOULD open a  
     983         * connection to the IP address in the received parameter, if present, 
     984         * using the port in the sent-by value, or the default port for that  
     985         * transport, if no port is specified.  
     986         * If that connection attempt fails, the server SHOULD use the  
     987         * procedures in [4] for servers in order to determine the IP address 
     988         * and port to open the connection and send the response to. 
     989         */ 
     990        res_addr->transport = rdata->tp_info.transport; 
     991        pj_memcpy(&res_addr->addr, &rdata->pkt_info.src_addr, 
     992                  rdata->pkt_info.src_addr_len); 
     993        res_addr->addr_len = rdata->pkt_info.src_addr_len; 
     994        res_addr->dst_host.type = src_transport->key.type; 
     995        res_addr->dst_host.flag = src_transport->flag; 
     996        pj_strdup( pool, &res_addr->dst_host.addr.host,  
     997                   &rdata->msg_info.via->recvd_param); 
     998        res_addr->dst_host.addr.port = rdata->msg_info.via->sent_by.port; 
     999        if (res_addr->dst_host.addr.port == 0) { 
     1000            res_addr->dst_host.addr.port =  
     1001                pjsip_transport_get_default_port_for_type(res_addr->dst_host.type); 
     1002        } 
     1003 
     1004    } else if (rdata->msg_info.via->maddr_param.slen) { 
     1005        /* Otherwise, if the Via header field value contains a maddr parameter, 
     1006         * the response MUST be forwarded to the address listed there, using  
     1007         * the port indicated in sent-by, or port 5060 if none is present.  
     1008         * If the address is a multicast address, the response SHOULD be sent  
     1009         * using the TTL indicated in the ttl parameter, or with a TTL of 1 if 
     1010         * that parameter is not present.  
     1011         */ 
     1012        res_addr->transport = NULL; 
     1013        res_addr->dst_host.type = src_transport->key.type; 
     1014        res_addr->dst_host.flag = src_transport->flag; 
     1015        pj_strdup( pool, &res_addr->dst_host.addr.host,  
     1016                   &rdata->msg_info.via->maddr_param); 
     1017        res_addr->dst_host.addr.port = rdata->msg_info.via->sent_by.port; 
     1018        if (res_addr->dst_host.addr.port == 0) 
     1019            res_addr->dst_host.addr.port = 5060; 
     1020 
     1021    } else if (rdata->msg_info.via->rport_param >= 0) { 
     1022        /* There is both a "received" parameter and an "rport" parameter,  
     1023         * the response MUST be sent to the IP address listed in the "received" 
     1024         * parameter, and the port in the "rport" parameter.  
     1025         * The response MUST be sent from the same address and port that the  
     1026         * corresponding request was received on. 
     1027         */ 
     1028        res_addr->transport = rdata->tp_info.transport; 
     1029        pj_memcpy(&res_addr->addr, &rdata->pkt_info.src_addr, 
     1030                  rdata->pkt_info.src_addr_len); 
     1031        res_addr->addr_len = rdata->pkt_info.src_addr_len; 
     1032        res_addr->dst_host.type = src_transport->key.type; 
     1033        res_addr->dst_host.flag = src_transport->flag; 
     1034        pj_strdup( pool, &res_addr->dst_host.addr.host,  
     1035                   &rdata->msg_info.via->recvd_param); 
     1036        res_addr->dst_host.addr.port = rdata->msg_info.via->sent_by.port; 
     1037        if (res_addr->dst_host.addr.port == 0) { 
     1038            res_addr->dst_host.addr.port =  
     1039                pjsip_transport_get_default_port_for_type(res_addr->dst_host.type); 
     1040        } 
     1041 
     1042    } else { 
     1043        res_addr->transport = NULL; 
     1044        res_addr->dst_host.type = src_transport->key.type; 
     1045        res_addr->dst_host.flag = src_transport->flag; 
     1046        pj_strdup( pool, &res_addr->dst_host.addr.host,  
     1047                   &rdata->msg_info.via->recvd_param); 
     1048        res_addr->dst_host.addr.port = rdata->msg_info.via->sent_by.port; 
     1049        if (res_addr->dst_host.addr.port == 0) { 
     1050            res_addr->dst_host.addr.port =  
     1051                pjsip_transport_get_default_port_for_type(res_addr->dst_host.type); 
     1052        } 
     1053    } 
     1054 
     1055    return PJ_SUCCESS; 
     1056} 
     1057 
     1058/* 
     1059 * Callback called by transport during send_response. 
     1060 */ 
     1061static void send_response_transport_cb(void *token, pjsip_tx_data *tdata, 
     1062                                       pj_ssize_t sent) 
     1063{ 
     1064    pjsip_send_state *send_state = token; 
     1065    pj_bool_t cont = PJ_FALSE; 
     1066 
     1067    /* Call callback, if any. */ 
     1068    if (send_state->app_cb) 
     1069        (*send_state->app_cb)(send_state, sent, &cont); 
     1070 
     1071    /* Decrement transport reference counter. */ 
     1072    pjsip_transport_dec_ref(send_state->cur_transport); 
     1073 
     1074    /* Decrement transmit data ref counter. */ 
     1075    pjsip_tx_data_dec_ref(tdata); 
     1076} 
     1077 
     1078/* 
     1079 * Resolver calback during send_response. 
     1080 */ 
     1081static void send_response_resolver_cb( pj_status_t status, void *token, 
     1082                                       const pjsip_server_addresses *addr ) 
     1083{ 
     1084    pjsip_send_state *send_state = token; 
     1085 
     1086    if (status != PJ_SUCCESS) { 
     1087        if (send_state->app_cb) { 
     1088            pj_bool_t cont = PJ_FALSE; 
     1089            (*send_state->app_cb)(send_state, -status, &cont); 
     1090        } 
     1091        pjsip_tx_data_dec_ref(send_state->tdata); 
     1092        return; 
     1093    } 
     1094 
     1095    /* Only handle the first address resolved. */ 
     1096 
     1097    /* Acquire transport. */ 
     1098    status = pjsip_endpt_acquire_transport( send_state->endpt,  
     1099                                            addr->entry[0].type, 
     1100                                            &addr->entry[0].addr, 
     1101                                            addr->entry[0].addr_len, 
     1102                                            &send_state->cur_transport); 
     1103    if (status != PJ_SUCCESS) { 
     1104        if (send_state->app_cb) { 
     1105            pj_bool_t cont = PJ_FALSE; 
     1106            (*send_state->app_cb)(send_state, -status, &cont); 
     1107        } 
     1108        pjsip_tx_data_dec_ref(send_state->tdata); 
     1109        return; 
     1110    } 
     1111 
     1112    /* Send response using the transoprt. */ 
     1113    status = pjsip_transport_send( send_state->cur_transport,  
     1114                                   send_state->tdata, 
     1115                                   &addr->entry[0].addr, 
     1116                                   addr->entry[0].addr_len, 
     1117                                   send_state, 
     1118                                   &send_response_transport_cb); 
     1119    if (status == PJ_SUCCESS) { 
     1120        pj_ssize_t sent = send_state->tdata->buf.cur -  
     1121                          send_state->tdata->buf.start; 
     1122        send_response_transport_cb(send_state, send_state->tdata, sent); 
     1123 
     1124    } else if (status == PJ_EPENDING) { 
     1125        /* Transport callback will be called later. */ 
     1126    } else { 
     1127        send_response_transport_cb(send_state, send_state->tdata, -status); 
     1128    } 
     1129} 
     1130 
     1131/* 
     1132 * Send response. 
     1133 */ 
     1134PJ_DEF(pj_status_t) pjsip_endpt_send_response( pjsip_endpoint *endpt, 
     1135                                               pjsip_response_addr *res_addr, 
     1136                                               pjsip_tx_data *tdata, 
     1137                                               void *token, 
     1138                                               void (*cb)(pjsip_send_state*, 
     1139                                                          pj_ssize_t sent, 
     1140                                                          pj_bool_t *cont)) 
     1141{ 
     1142    /* Determine which transports and addresses to send the response, 
     1143     * based on Section 18.2.2 of RFC 3261. 
     1144     */ 
     1145    pjsip_send_state *send_state; 
     1146    pj_status_t status; 
     1147 
     1148    /* Create structure to keep the sending state. */ 
     1149    send_state = pj_pool_zalloc(tdata->pool, sizeof(pjsip_send_state)); 
     1150    send_state->endpt = endpt; 
     1151    send_state->tdata = tdata; 
     1152    send_state->token = token; 
     1153    send_state->app_cb = cb; 
     1154 
     1155    if (res_addr->transport != NULL) { 
     1156        send_state->cur_transport = res_addr->transport; 
     1157        pjsip_transport_add_ref(send_state->cur_transport); 
     1158 
     1159        status = pjsip_transport_send( send_state->cur_transport, tdata,  
     1160                                       &res_addr->addr, 
     1161                                       res_addr->addr_len, 
     1162                                       send_state, 
     1163                                       &send_response_transport_cb ); 
     1164        if (status == PJ_SUCCESS) { 
     1165            pj_ssize_t sent = tdata->buf.cur - tdata->buf.start; 
     1166            send_response_transport_cb(send_state, tdata, sent); 
     1167            return PJ_SUCCESS; 
     1168        } else if (status == PJ_EPENDING) { 
     1169            /* Callback will be called later. */ 
     1170            return PJ_SUCCESS; 
     1171        } else { 
     1172            send_response_transport_cb(send_state, tdata, -status); 
     1173            return status; 
     1174        } 
     1175    } else { 
     1176        pjsip_endpt_resolve(endpt, tdata->pool, &res_addr->dst_host,  
     1177                            send_state, &send_response_resolver_cb); 
     1178        return PJ_SUCCESS; 
     1179    } 
     1180} 
     1181 
    7141182 
    7151183/* 
  • pjproject/trunk/pjsip/src/test-pjsip/main.c

    r77 r106  
    1818 */ 
    1919#include "test.h" 
     20#include <stdio.h> 
    2021 
    21 int main(void) 
     22int main(int argc, char *argv[]) 
    2223{ 
    23     return test_main(); 
     24    int retval = test_main(); 
     25 
     26    if (argc != 1) { 
     27        char s[10]; 
     28        printf("<Press ENTER to quit>\n"); 
     29        fgets(s, sizeof(s), stdin); 
     30    } 
     31 
     32    return retval; 
    2433} 
  • pjproject/trunk/pjsip/src/test-pjsip/msg_test.c

    r105 r106  
    665665/*****************************************************************************/ 
    666666 
    667 pj_status_t msg_test(void) 
     667int msg_test(void) 
    668668{ 
    669669    pj_status_t status; 
  • pjproject/trunk/pjsip/src/test-pjsip/test.c

    r82 r106  
    8484    DO_TEST(uri_test()); 
    8585    DO_TEST(msg_test()); 
     86    DO_TEST(txdata_test()); 
     87    DO_TEST(transport_udp_test()); 
    8688 
    8789on_return: 
  • pjproject/trunk/pjsip/src/test-pjsip/test.h

    r77 r106  
    2424extern pjsip_endpoint *endpt; 
    2525 
    26 pj_status_t uri_test(void); 
    27 pj_status_t msg_test(void); 
     26#define TEST_UDP_PORT   15060 
    2827 
     28/* The tests */ 
     29int uri_test(void); 
     30int msg_test(void); 
     31int txdata_test(void); 
     32int transport_udp_test(void); 
     33 
     34/* Transport test helpers (transport_test.c). */ 
     35int generic_transport_test(pjsip_transport *tp); 
     36int transport_send_recv_test( pjsip_transport_type_e tp_type, 
     37                              pjsip_transport *ref_tp, 
     38                              const pj_sockaddr_in *rem_addr ); 
     39int transport_rt_test( pjsip_transport_type_e tp_type, 
     40                       pjsip_transport *ref_tp, 
     41                       const pj_sockaddr_in *rem_addr ); 
     42 
     43/* Test main entry */ 
    2944int  test_main(void); 
     45 
     46/* Test utilities. */ 
    3047void app_perror(const char *msg, pj_status_t status); 
    3148 
  • pjproject/trunk/pjsip/src/test-pjsip/uri_test.c

    r105 r106  
    784784} 
    785785 
    786 pj_status_t uri_test() 
     786int uri_test() 
    787787{ 
    788788    unsigned i, loop; 
Note: See TracChangeset for help on using the changeset viewer.