Changeset 879 for pjproject/trunk


Ignore:
Timestamp:
Jan 12, 2007 6:37:35 AM (18 years ago)
Author:
bennylp
Message:

Workaround for ticket #50: added API to lock/bind transaction, dialog, and regc to a specific transport/listener

Location:
pjproject/trunk/pjsip
Files:
12 edited

Legend:

Unmodified
Added
Removed
  • pjproject/trunk/pjsip/include/pjsip-ua/sip_regc.h

    r843 r879  
    2727#include <pjsip/sip_types.h> 
    2828#include <pjsip/sip_auth.h> 
     29#include <pjsip/sip_transport.h> 
    2930 
    3031 
     
    199200                                              const pjsip_route_hdr*route_set); 
    200201 
     202 
     203/** 
     204 * Lock/bind client registration to a specific transport/listener.  
     205 * This is optional, as normally transport will be selected automatically 
     206 * based on the destination of requests upon resolver completion.  
     207 * When the client registration is explicitly bound to the specific  
     208 * transport/listener, all UAC transactions originated by the client 
     209 * registration will use the specified transport/listener when sending  
     210 * outgoing requests. 
     211 * 
     212 * Note that this doesn't affect the Contact header set for this client 
     213 * registration. Application must manually update the Contact header if 
     214 * necessary, to adjust the address according to the transport being 
     215 * selected. 
     216 * 
     217 * @param regc      The client registration instance. 
     218 * @param sel       Transport selector containing the specification of 
     219 *                  transport or listener to be used by this session 
     220 *                  to send requests. 
     221 * 
     222 * @return          PJ_SUCCESS on success, or the appropriate error code. 
     223 */ 
     224PJ_DECL(pj_status_t) pjsip_regc_set_transport(pjsip_regc *regc, 
     225                                              const pjsip_tpselector *sel); 
     226 
     227 
    201228/** 
    202229 * Add headers to be added to outgoing REGISTER requests. 
  • pjproject/trunk/pjsip/include/pjsip/sip_dialog.h

    r729 r879  
    2929#include <pjsip/sip_auth.h> 
    3030#include <pjsip/sip_errno.h> 
     31#include <pjsip/sip_transport.h> 
    3132#include <pj/sock.h> 
    3233#include <pj/assert.h> 
     
    135136    int                 tsx_count;  /**< Number of pending transactions.    */ 
    136137 
     138    /** Transport selector. */ 
     139    pjsip_tpselector    tp_sel; 
     140 
    137141    /* Dialog usages. */ 
    138142    unsigned            usage_cnt;  /**< Number of registered usages.       */ 
     
    225229 
    226230/** 
     231 * Lock/bind dialog to a specific transport/listener. This is optional, 
     232 * as normally transport will be selected automatically based on the  
     233 * destination of requests upon resolver completion. When the dialog is  
     234 * explicitly bound to the specific transport/listener, all UAC transactions 
     235 * originated by this dialog will use the specified transport/listener 
     236 * when sending outgoing requests. 
     237 * 
     238 * Note that this doesn't affect the Contact header generated by this 
     239 * dialog. Application must manually update the Contact header if 
     240 * necessary, to adjust the address according to the transport being 
     241 * selected. 
     242 * 
     243 * @param dlg       The dialog instance. 
     244 * @param sel       Transport selector containing the specification of 
     245 *                  transport or listener to be used by this dialog 
     246 *                  to send requests. 
     247 * 
     248 * @return          PJ_SUCCESS on success, or the appropriate error code. 
     249 */ 
     250PJ_DECL(pj_status_t) pjsip_dlg_set_transport(pjsip_dialog *dlg, 
     251                                             const pjsip_tpselector *sel); 
     252 
     253 
     254/** 
    227255 * Create a new (forked) dialog on receipt on forked response in rdata.  
    228256 * The new dialog will be created from original_dlg, except that it will have 
  • pjproject/trunk/pjsip/include/pjsip/sip_endpoint.h

    r797 r879  
    353353/** 
    354354 * Find a SIP transport suitable for sending SIP message to the specified 
    355  * address. This function will complete asynchronously when the transport is 
    356  * ready (for example, when TCP socket is connected), and when it completes, 
    357  * the callback will be called with the status of the operation. 
    358  * 
    359  * @see pjsip_transport_get 
     355 * address. If transport selector ("sel") is set, then the function will 
     356 * check if the transport selected is suitable to send requests to the 
     357 * specified address. 
     358 * 
     359 * @see pjsip_tpmgr_acquire_transport 
     360 * 
     361 * @param endpt     The SIP endpoint instance. 
     362 * @param type      The type of transport to be acquired. 
     363 * @param remote    The remote address to send message to. 
     364 * @param addr_len  Length of the remote address. 
     365 * @param sel       Optional pointer to transport selector instance which is 
     366 *                  used to find explicit transport, if required. 
     367 * @param p_tp      Pointer to receive the transport instance, if one is found. 
     368 * 
     369 * @return          PJ_SUCCESS on success, or the appropriate error code. 
    360370 */ 
    361371PJ_DECL(pj_status_t)  
     
    364374                               const pj_sockaddr_t *remote, 
    365375                               int addr_len, 
    366                                pjsip_transport **p_transport); 
     376                               const pjsip_tpselector *sel, 
     377                               pjsip_transport **p_tp); 
    367378 
    368379 
  • pjproject/trunk/pjsip/include/pjsip/sip_errno.h

    r871 r879  
    215215 */ 
    216216#define PJSIP_EBUFDESTROYED     (PJSIP_ERRNO_START_PJSIP + 63)  /* 171063 */ 
     217/** 
     218 * @hideinitializer 
     219 * Unsuitable transport selected. This error occurs when application 
     220 * has explicitly requested to use a particular transport/listener, 
     221 * but the selected transport is not suitable to send request to 
     222 * the specified destination. 
     223 */ 
     224#define PJSIP_ETPNOTSUITABLE    (PJSIP_ERRNO_START_PJSIP + 64)  /* 171064 */ 
    217225 
    218226 
  • pjproject/trunk/pjsip/include/pjsip/sip_transaction.h

    r622 r879  
    2727#include <pjsip/sip_msg.h> 
    2828#include <pjsip/sip_util.h> 
     29#include <pjsip/sip_transport.h> 
    2930#include <pj/timer.h> 
    3031 
     
    9798    pj_uint32_t                 hashed_key;     /**< Key's hashed value.    */ 
    9899    pj_str_t                    branch;         /**< The branch Id.         */ 
     100    pjsip_tpselector            tp_sel;         /**< Transport selector.    */ 
    99101 
    100102    /* 
     
    215217 
    216218/** 
     219 * Lock/bind transaction to a specific transport/listener. This is optional, 
     220 * as normally transport will be selected automatically based on the  
     221 * destination of the request upon resolver completion. Also it's only valid 
     222 * for UAC transaction (to send outgoing request), since for UAS the 
     223 * transport will be selected according to rules about handling incoming 
     224 * request (most likely it will use the transport where the request is 
     225 * coming from if ";rport" parameter is present in Via header). 
     226 * 
     227 * @param tsx       The UAC transaction. 
     228 * @param sel       Transport selector containing the specification of 
     229 *                  transport or listener to be used by this transaction 
     230 *                  to send requests. 
     231 * 
     232 * @return          PJ_SUCCESS on success, or the appropriate error code. 
     233 */ 
     234PJ_DECL(pj_status_t) pjsip_tsx_set_transport(pjsip_transaction *tsx, 
     235                                             const pjsip_tpselector *sel); 
     236 
     237 
     238/** 
    217239 * Call this function to manually feed a message to the transaction. 
    218240 * For UAS transaction, application MUST call this function after 
  • pjproject/trunk/pjsip/include/pjsip/sip_transport.h

    r742 r879  
    5555 * 
    5656 *****************************************************************************/ 
     57 
     58/* 
     59 * Forward declaration for transport factory (since it is referenced by 
     60 * the transport factory itself). 
     61 */ 
     62typedef struct pjsip_tpfactory pjsip_tpfactory; 
     63 
    5764 
    5865/** 
     
    157164 
    158165 
     166 
     167/***************************************************************************** 
     168 * 
     169 * TRANSPORT SELECTOR. 
     170 * 
     171 *****************************************************************************/ 
     172 
     173/** 
     174 * This structure describes the type of data in pjsip_tpselector. 
     175 */ 
     176typedef enum pjsip_tpselector_type 
     177{ 
     178    /** Transport is not specified. */ 
     179    PJSIP_TPSELECTOR_NONE, 
     180 
     181    /** Use the specific transport to send request. */ 
     182    PJSIP_TPSELECTOR_TRANSPORT, 
     183 
     184    /** Use the specific listener to send request. */ 
     185    PJSIP_TPSELECTOR_LISTENER, 
     186 
     187} pjsip_tpselector_type; 
     188 
     189 
     190/** 
     191 * This structure describes the transport/listener preference to be used 
     192 * when sending outgoing requests. 
     193 * 
     194 * Normally transport will be selected automatically according to rules about 
     195 * sending requests. But some applications (such as proxies or B2BUAs) may  
     196 * want to explicitly use specific transport to send requests, for example 
     197 * when they want to make sure that outgoing request should go from a specific 
     198 * network interface. 
     199 * 
     200 * The pjsip_tpselector structure is used for that purpose, i.e. to allow 
     201 * application specificly request that a particular transport/listener 
     202 * should be used to send request. This structure is used when calling 
     203 * pjsip_tsx_set_transport() and pjsip_dlg_set_transport(). 
     204 */ 
     205typedef struct pjsip_tpselector 
     206{ 
     207    /** The type of data in the union */ 
     208    pjsip_tpselector_type   type; 
     209 
     210    /** Union representing the transport/listener criteria to be used. */ 
     211    union { 
     212        pjsip_transport *transport; 
     213        pjsip_tpfactory *listener; 
     214    } u; 
     215 
     216} pjsip_tpselector; 
     217 
     218 
     219/** 
     220 * Add transport/listener reference in the selector to prevent the specified 
     221 * transport/listener from being destroyed while application still has 
     222 * reference to it. 
     223 * 
     224 * @param sel   The transport selector. 
     225 */ 
     226PJ_DECL(void) pjsip_tpselector_add_ref(pjsip_tpselector *sel); 
     227 
     228 
     229/** 
     230 * Decrement transport/listener reference in the selector. 
     231 * @param sel   The transport selector 
     232 */ 
     233PJ_DECL(void) pjsip_tpselector_dec_ref(pjsip_tpselector *sel); 
     234 
     235 
    159236/***************************************************************************** 
    160237 * 
     
    432509        int                  dst_port;      /**< Destination port.      */ 
    433510    } tp_info; 
     511 
     512    /**  
     513     * Transport selector, to specify which transport to be used.  
     514     * The value here must be set with pjsip_tx_data_set_transport(), 
     515     * to allow reference counter to be set properly. 
     516     */ 
     517    pjsip_tpselector        tp_sel; 
     518 
    434519}; 
    435520 
     
    499584 */ 
    500585PJ_DECL(char*) pjsip_tx_data_get_info( pjsip_tx_data *tdata ); 
     586 
     587/** 
     588 * Set the explicit transport to be used when sending this transmit data. 
     589 * Application should not need to call this function, but rather use 
     590 * pjsip_tsx_set_transport() and pjsip_dlg_set_transport() instead (which 
     591 * will call this function). 
     592 * 
     593 * @param tdata     The transmit buffer. 
     594 * @param sel       Transport selector. 
     595 * 
     596 * @return          PJ_SUCCESS on success. 
     597 */ 
     598PJ_DECL(pj_status_t) pjsip_tx_data_set_transport(pjsip_tx_data *tdata, 
     599                                                 const pjsip_tpselector *sel); 
    501600 
    502601 
     
    707806 *****************************************************************************/ 
    708807 
    709 /* 
    710  * Forward declaration for transport factory (since it is referenced by 
    711  * the transport factory itself). 
    712  */ 
    713 typedef struct pjsip_tpfactory pjsip_tpfactory; 
    714  
    715808 
    716809/** 
     
    860953 * Find transport to be used to send message to remote destination. If no 
    861954 * suitable transport is found, a new one will be created. 
     955 * 
     956 * This is an internal function since normally application doesn't have access 
     957 * to transport manager. Application should use pjsip_endpt_acquire_transport() 
     958 * instead. 
     959 * 
     960 * @param mgr       The transport manager instance. 
     961 * @param type      The type of transport to be acquired. 
     962 * @param remote    The remote address to send message to. 
     963 * @param addr_len  Length of the remote address. 
     964 * @param sel       Optional pointer to transport selector instance which is 
     965 *                  used to find explicit transport, if required. 
     966 * @param tp        Pointer to receive the transport instance, if one is found. 
     967 * 
     968 * @return          PJ_SUCCESS on success, or the appropriate error code. 
    862969 */ 
    863970PJ_DECL(pj_status_t) pjsip_tpmgr_acquire_transport(pjsip_tpmgr *mgr, 
     
    865972                                                   const pj_sockaddr_t *remote, 
    866973                                                   int addr_len, 
     974                                                   const pjsip_tpselector *sel, 
    867975                                                   pjsip_transport **tp); 
    868976 
  • pjproject/trunk/pjsip/src/pjsip-ua/sip_reg.c

    r843 r879  
    7777    pj_time_val                  next_reg; 
    7878    pj_timer_entry               timer; 
     79 
     80    /* Transport selector */ 
     81    pjsip_tpselector             tp_sel; 
    7982}; 
    8083 
     
    125128        regc->cb = NULL; 
    126129    } else { 
     130        pjsip_tpselector_dec_ref(&regc->tp_sel); 
    127131        pjsip_endpt_release_pool(regc->endpt, regc->pool); 
    128132    } 
     
    310314    return PJ_SUCCESS; 
    311315} 
     316 
     317 
     318/* 
     319 * Bind client registration to a specific transport/listener.  
     320 */ 
     321PJ_DEF(pj_status_t) pjsip_regc_set_transport( pjsip_regc *regc, 
     322                                              const pjsip_tpselector *sel) 
     323{ 
     324    PJ_ASSERT_RETURN(regc && sel, PJ_EINVAL); 
     325 
     326    pjsip_tpselector_dec_ref(&regc->tp_sel); 
     327    pj_memcpy(&regc->tp_sel, sel, sizeof(*sel)); 
     328    pjsip_tpselector_add_ref(&regc->tp_sel); 
     329 
     330    return PJ_SUCCESS; 
     331} 
     332 
    312333 
    313334PJ_DEF(pj_status_t) pjsip_regc_add_headers( pjsip_regc *regc, 
  • pjproject/trunk/pjsip/src/pjsip/sip_dialog.c

    r797 r879  
    507507 
    508508/* 
     509 * Bind dialog to a specific transport/listener. 
     510 */ 
     511PJ_DEF(pj_status_t) pjsip_dlg_set_transport( pjsip_dialog *dlg, 
     512                                             const pjsip_tpselector *sel) 
     513{ 
     514    /* Validate */ 
     515    PJ_ASSERT_RETURN(dlg && sel, PJ_EINVAL); 
     516 
     517    /* Start locking the dialog. */ 
     518    pjsip_dlg_inc_lock(dlg); 
     519 
     520    /* Decrement reference counter of previous transport selector */ 
     521    pjsip_tpselector_dec_ref(&dlg->tp_sel); 
     522 
     523    /* Copy transport selector structure .*/ 
     524    pj_memcpy(&dlg->tp_sel, sel, sizeof(*sel)); 
     525 
     526    /* Increment reference counter */ 
     527    pjsip_tpselector_add_ref(&dlg->tp_sel); 
     528 
     529    /* Unlock dialog. */ 
     530    pjsip_dlg_dec_lock(dlg); 
     531 
     532    return PJ_SUCCESS; 
     533} 
     534 
     535 
     536/* 
    509537 * Create forked dialog from a response. 
    510538 */ 
     
    10661094            goto on_error; 
    10671095 
     1096        /* Set transport selector */ 
     1097        status = pjsip_tsx_set_transport(tsx, &dlg->tp_sel); 
     1098        pj_assert(status == PJ_SUCCESS); 
     1099 
    10681100        /* Attach this dialog to the transaction, so that user agent 
    10691101         * will dispatch events to this dialog. 
     
    10871119 
    10881120    } else { 
     1121        /* Set transport selector */ 
     1122        pjsip_tx_data_set_transport(tdata, &dlg->tp_sel); 
     1123 
     1124        /* Send request */ 
    10891125        status = pjsip_endpt_send_request_stateless(dlg->endpt, tdata,  
    10901126                                                    NULL, NULL); 
  • pjproject/trunk/pjsip/src/pjsip/sip_endpoint.c

    r839 r879  
    10441044                                                  const pj_sockaddr_t *remote, 
    10451045                                                  int addr_len, 
     1046                                                  const pjsip_tpselector *sel, 
    10461047                                                  pjsip_transport **transport) 
    10471048{ 
    10481049    return pjsip_tpmgr_acquire_transport(endpt->transport_mgr, type,  
    1049                                          remote, addr_len, transport); 
     1050                                         remote, addr_len, sel, transport); 
    10501051} 
    10511052 
  • pjproject/trunk/pjsip/src/pjsip/sip_transaction.c

    r839 r879  
    932932        tsx->transport = NULL; 
    933933    } 
     934    /* Decrement reference counter in transport selector */ 
     935    pjsip_tpselector_dec_ref(&tsx->tp_sel); 
     936 
    934937    /* Free last transmitted message. */ 
    935938    if (tsx->last_tx) { 
     
    13641367 
    13651368/* 
     1369 * Bind transaction to a specific transport/listener.  
     1370 */ 
     1371PJ_DEF(pj_status_t) pjsip_tsx_set_transport(pjsip_transaction *tsx, 
     1372                                            const pjsip_tpselector *sel) 
     1373{ 
     1374    struct tsx_lock_data lck; 
     1375 
     1376    /* Must be UAC transaction */ 
     1377    PJ_ASSERT_RETURN(tsx && sel && tsx->role == PJSIP_ROLE_UAC, PJ_EINVAL); 
     1378 
     1379    /* Start locking the transaction. */ 
     1380    lock_tsx(tsx, &lck); 
     1381 
     1382    /* Decrement reference counter of previous transport selector */ 
     1383    pjsip_tpselector_dec_ref(&tsx->tp_sel); 
     1384 
     1385    /* Copy transport selector structure .*/ 
     1386    pj_memcpy(&tsx->tp_sel, sel, sizeof(*sel)); 
     1387 
     1388    /* Increment reference counter */ 
     1389    pjsip_tpselector_add_ref(&tsx->tp_sel); 
     1390 
     1391    /* Unlock transaction. */ 
     1392    unlock_tsx(tsx, &lck); 
     1393 
     1394    return PJ_SUCCESS; 
     1395} 
     1396 
     1397 
     1398/* 
    13661399 * Set transaction status code and reason. 
    13671400 */ 
     
    14241457    /* Dispatch to transaction. */ 
    14251458    lock_tsx(tsx, &lck); 
     1459 
     1460    /* Set transport selector to tdata */ 
     1461    pjsip_tx_data_set_transport(tdata, &tsx->tp_sel); 
     1462 
     1463    /* Dispatch to state handler */ 
    14261464    status = (*tsx->state_handler)(tsx, &event); 
     1465 
    14271466    unlock_tsx(tsx, &lck); 
    14281467 
    1429     /* Will always decrement tdata reference counter 
    1430      * (consistent with other send functions. 
     1468    /* Only decrement reference counter when it returns success. 
     1469     * (This is the specification from the .PDF design document). 
    14311470     */ 
    14321471    if (status == PJ_SUCCESS) { 
  • pjproject/trunk/pjsip/src/pjsip/sip_transport.c

    r866 r879  
    260260} 
    261261 
     262 
     263/***************************************************************************** 
     264 * 
     265 * TRANSPORT SELECTOR 
     266 * 
     267 *****************************************************************************/ 
     268 
     269/* 
     270 * Add transport/listener reference in the selector. 
     271 */ 
     272PJ_DEF(void) pjsip_tpselector_add_ref(pjsip_tpselector *sel) 
     273{ 
     274    if (sel->type == PJSIP_TPSELECTOR_TRANSPORT && sel->u.transport != NULL) 
     275        pjsip_transport_add_ref(sel->u.transport); 
     276    else if (sel->type == PJSIP_TPSELECTOR_LISTENER && sel->u.listener != NULL) 
     277        ; /* Hmm.. looks like we don't have reference counter for listener */ 
     278} 
     279 
     280 
     281/* 
     282 * Decrement transport/listener reference in the selector. 
     283 */ 
     284PJ_DEF(void) pjsip_tpselector_dec_ref(pjsip_tpselector *sel) 
     285{ 
     286    if (sel->type == PJSIP_TPSELECTOR_TRANSPORT && sel->u.transport != NULL) 
     287        pjsip_transport_dec_ref(sel->u.transport); 
     288    else if (sel->type == PJSIP_TPSELECTOR_LISTENER && sel->u.listener != NULL) 
     289        ; /* Hmm.. looks like we don't have reference counter for listener */ 
     290} 
     291 
     292 
    262293/***************************************************************************** 
    263294 * 
     
    331362        PJ_LOG(5,(tdata->obj_name, "Destroying txdata %s", 
    332363                  pjsip_tx_data_get_info(tdata))); 
     364        pjsip_tpselector_dec_ref(&tdata->tp_sel); 
    333365#if defined(PJ_DEBUG) && PJ_DEBUG!=0 
    334366        pj_atomic_dec( tdata->mgr->tdata_counter ); 
     
    408440    return tdata->info; 
    409441} 
     442 
     443PJ_DEF(pj_status_t) pjsip_tx_data_set_transport(pjsip_tx_data *tdata, 
     444                                                const pjsip_tpselector *sel) 
     445{ 
     446    PJ_ASSERT_RETURN(tdata && sel, PJ_EINVAL); 
     447 
     448    pj_lock_acquire(tdata->lock); 
     449 
     450    pjsip_tpselector_dec_ref(&tdata->tp_sel); 
     451 
     452    pj_memcpy(&tdata->tp_sel, sel, sizeof(*sel)); 
     453    pjsip_tpselector_add_ref(&tdata->tp_sel); 
     454 
     455    pj_lock_release(tdata->lock); 
     456 
     457    return PJ_SUCCESS; 
     458} 
     459 
    410460 
    411461PJ_DEF(char*) pjsip_rx_data_get_info(pjsip_rx_data *rdata) 
     
    912962        pj_sockaddr_in_init(&remote, NULL, 0); 
    913963        status = pjsip_tpmgr_acquire_transport(tpmgr, type, &remote, 
    914                                                sizeof(remote), &tp); 
     964                                               sizeof(remote), NULL, &tp); 
    915965 
    916966        if (status == PJ_SUCCESS) { 
     
    12011251                                                  const pj_sockaddr_t *remote, 
    12021252                                                  int addr_len, 
     1253                                                  const pjsip_tpselector *sel, 
    12031254                                                  pjsip_transport **tp) 
    12041255{ 
    1205     struct transport_key key; 
    1206     int key_len; 
    1207     pjsip_transport *transport; 
    12081256    pjsip_tpfactory *factory; 
    12091257    pj_status_t status; 
     
    12161264    pj_lock_acquire(mgr->lock); 
    12171265 
    1218     key_len = sizeof(key.type) + addr_len; 
    1219  
    1220     /* First try to get exact destination. */ 
    1221     key.type = type; 
    1222     pj_memcpy(&key.addr, remote, addr_len); 
    1223  
    1224     transport = pj_hash_get(mgr->table, &key, key_len, NULL); 
    1225     if (transport == NULL) { 
    1226         unsigned flag = pjsip_transport_get_flag_from_type(type); 
    1227         const pj_sockaddr *remote_addr = (const pj_sockaddr*)remote; 
    1228  
    1229         /* Ignore address for loop transports. */ 
    1230         if (type == PJSIP_TRANSPORT_LOOP || 
    1231                  type == PJSIP_TRANSPORT_LOOP_DGRAM) 
    1232         { 
    1233             pj_sockaddr_in *addr = (pj_sockaddr_in*)&key.addr; 
    1234  
    1235             pj_bzero(addr, sizeof(pj_sockaddr_in)); 
    1236             key_len = sizeof(key.type) + sizeof(pj_sockaddr_in); 
    1237             transport = pj_hash_get(mgr->table, &key, key_len, NULL); 
    1238         } 
    1239         /* For datagram INET transports, try lookup with zero address. 
     1266    /* If transport is specified, then just use it if it is suitable 
     1267     * for the destination. 
     1268     */ 
     1269    if (sel && sel->type == PJSIP_TPSELECTOR_TRANSPORT && 
     1270        sel->u.transport)  
     1271    { 
     1272        pjsip_transport *seltp = sel->u.transport; 
     1273 
     1274        /* See if the transport is (not) suitable */ 
     1275        if (seltp->key.type != type) { 
     1276            pj_lock_release(mgr->lock); 
     1277            return PJSIP_ETPNOTSUITABLE; 
     1278        } 
     1279 
     1280        /* We could also verify that the destination address is reachable 
     1281         * from this transport (i.e. both are equal), but if application 
     1282         * has requested a specific transport to be used, assume that 
     1283         * it knows what to do. 
     1284         * 
     1285         * In other words, I don't think destination verification is a good 
     1286         * idea for now. 
    12401287         */ 
    1241         else if ((flag & PJSIP_TRANSPORT_DATAGRAM) &&  
    1242                  (remote_addr->sa_family == PJ_AF_INET))  
    1243         { 
    1244             pj_sockaddr_in *addr = (pj_sockaddr_in*)&key.addr; 
    1245  
    1246             pj_bzero(addr, sizeof(pj_sockaddr_in)); 
    1247             addr->sin_family = PJ_AF_INET; 
    1248  
    1249             key_len = sizeof(key.type) + sizeof(pj_sockaddr_in); 
    1250             transport = pj_hash_get(mgr->table, &key, key_len, NULL); 
    1251         } 
    1252     } 
     1288 
     1289        /* Transport looks to be suitable to use, so just use it. */ 
     1290        pjsip_transport_add_ref(seltp); 
     1291        pj_lock_release(mgr->lock); 
     1292        *tp = seltp; 
     1293 
     1294        TRACE_((THIS_FILE, "Transport %s acquired", seltp->obj_name)); 
     1295        return PJ_SUCCESS; 
     1296 
     1297 
     1298    } else if (sel && sel->type == PJSIP_TPSELECTOR_LISTENER && 
     1299               sel->u.listener) 
     1300    { 
     1301        /* Application has requested that a specific listener is to 
     1302         * be used. In this case, skip transport hash table lookup. 
     1303         */ 
     1304 
     1305        /* Verify that the listener type matches the destination type */ 
     1306        if (sel->u.listener->type != type) { 
     1307            pj_lock_release(mgr->lock); 
     1308            return PJSIP_ETPNOTSUITABLE; 
     1309        } 
     1310 
     1311        /* We'll use this listener to create transport */ 
     1312        factory = sel->u.listener; 
     1313 
     1314    } else { 
     1315 
     1316        /* 
     1317         * This is the "normal" flow, where application doesn't specify 
     1318         * specific transport/listener to be used to send message to. 
     1319         * In this case, lookup the transport from the hash table. 
     1320         */ 
     1321        struct transport_key key; 
     1322        int key_len; 
     1323        pjsip_transport *transport; 
     1324 
     1325        key_len = sizeof(key.type) + addr_len; 
     1326 
     1327        /* First try to get exact destination. */ 
     1328        key.type = type; 
     1329        pj_memcpy(&key.addr, remote, addr_len); 
     1330 
     1331        transport = pj_hash_get(mgr->table, &key, key_len, NULL); 
     1332        if (transport == NULL) { 
     1333            unsigned flag = pjsip_transport_get_flag_from_type(type); 
     1334            const pj_sockaddr *remote_addr = (const pj_sockaddr*)remote; 
     1335 
     1336            /* Ignore address for loop transports. */ 
     1337            if (type == PJSIP_TRANSPORT_LOOP || 
     1338                     type == PJSIP_TRANSPORT_LOOP_DGRAM) 
     1339            { 
     1340                pj_sockaddr_in *addr = (pj_sockaddr_in*)&key.addr; 
     1341 
     1342                pj_bzero(addr, sizeof(pj_sockaddr_in)); 
     1343                key_len = sizeof(key.type) + sizeof(pj_sockaddr_in); 
     1344                transport = pj_hash_get(mgr->table, &key, key_len, NULL); 
     1345            } 
     1346            /* For datagram INET transports, try lookup with zero address. 
     1347             */ 
     1348            else if ((flag & PJSIP_TRANSPORT_DATAGRAM) &&  
     1349                     (remote_addr->sa_family == PJ_AF_INET))  
     1350            { 
     1351                pj_sockaddr_in *addr = (pj_sockaddr_in*)&key.addr; 
     1352 
     1353                pj_bzero(addr, sizeof(pj_sockaddr_in)); 
     1354                addr->sin_family = PJ_AF_INET; 
     1355 
     1356                key_len = sizeof(key.type) + sizeof(pj_sockaddr_in); 
     1357                transport = pj_hash_get(mgr->table, &key, key_len, NULL); 
     1358            } 
     1359        } 
     1360 
     1361        if (transport!=NULL && !transport->is_shutdown) { 
     1362            /* 
     1363             * Transport found! 
     1364             */ 
     1365            pjsip_transport_add_ref(transport); 
     1366            pj_lock_release(mgr->lock); 
     1367            *tp = transport; 
     1368 
     1369            TRACE_((THIS_FILE, "Transport %s acquired", transport->obj_name)); 
     1370            return PJ_SUCCESS; 
     1371        } 
     1372 
     1373        /* 
     1374         * Transport not found! 
     1375         * Find factory that can create such transport. 
     1376         */ 
     1377        factory = mgr->factory_list.next; 
     1378        while (factory != &mgr->factory_list) { 
     1379            if (factory->type == type) 
     1380                break; 
     1381            factory = factory->next; 
     1382        } 
     1383 
     1384        if (factory == &mgr->factory_list) { 
     1385            /* No factory can create the transport! */ 
     1386            pj_lock_release(mgr->lock); 
     1387            TRACE_((THIS_FILE, "No suitable factory was found either")); 
     1388            return PJSIP_EUNSUPTRANSPORT; 
     1389        } 
     1390 
     1391    } 
     1392 
    12531393     
    1254     if (transport!=NULL && !transport->is_shutdown) { 
    1255         /* 
    1256          * Transport found! 
    1257          */ 
    1258         pjsip_transport_add_ref(transport); 
    1259         pj_lock_release(mgr->lock); 
    1260         *tp = transport; 
    1261  
    1262         TRACE_((THIS_FILE, "Transport %s acquired", transport->obj_name)); 
    1263         return PJ_SUCCESS; 
    1264     } 
    1265  
    1266     /* 
    1267      * Transport not found! 
    1268      * Find factory that can create such transport. 
    1269      */ 
    1270     factory = mgr->factory_list.next; 
    1271     while (factory != &mgr->factory_list) { 
    1272         if (factory->type == type) 
    1273             break; 
    1274         factory = factory->next; 
    1275     } 
    1276  
    1277     if (factory == &mgr->factory_list) { 
    1278         /* No factory can create the transport! */ 
    1279         pj_lock_release(mgr->lock); 
    1280         TRACE_((THIS_FILE, "No suitable factory was found either")); 
    1281         return PJSIP_EUNSUPTRANSPORT; 
    1282     } 
    1283  
    1284     TRACE_((THIS_FILE, "%s, creating new one from factory", 
    1285            (transport?"Transport is shutdown":"No transport found"))); 
     1394    TRACE_((THIS_FILE, "Creating new transport from factory")); 
    12861395 
    12871396    /* Request factory to create transport. */ 
  • pjproject/trunk/pjsip/src/pjsip/sip_util.c

    r797 r879  
    838838                                                cur_addr, 
    839839                                                cur_addr_len, 
     840                                                &tdata->tp_sel, 
    840841                                                &stateless_data->cur_transport); 
    841842        if (status != PJ_SUCCESS) { 
     
    11121113                                            &addr->entry[0].addr, 
    11131114                                            addr->entry[0].addr_len, 
     1115                                            &send_state->tdata->tp_sel, 
    11141116                                            &send_state->cur_transport); 
    11151117    if (status != PJ_SUCCESS) { 
Note: See TracChangeset for help on using the changeset viewer.