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

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

File:
1 edited

Legend:

Unmodified
Added
Removed
  • 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. */ 
Note: See TracChangeset for help on using the changeset viewer.