Changeset 6002 for pjproject/trunk/pjsip/src/pjsip/sip_transport.c
- Timestamp:
- May 23, 2019 5:21:59 PM (5 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
pjproject/trunk/pjsip/src/pjsip/sip_transport.c
r5984 r6002 55 55 #endif 56 56 57 /* Specify the initial size of the transport manager's pool. */ 58 #ifndef TPMGR_POOL_INIT_SIZE 59 # define TPMGR_POOL_INIT_SIZE 64 60 #endif 61 62 /* Specify the increment size of the transport manager's pool. */ 63 #ifndef TPMGR_POOL_INC_SIZE 64 #define TPMGR_POOL_INC_SIZE 64 65 #endif 66 67 /* Specify transport entry allocation count. When registering a new transport, 68 * a new entry will be picked from a free list. This setting will determine 69 * the size of the free list size. If all entry is used, then the same number 70 * of entry will be allocated. 71 */ 72 #ifndef PJSIP_TRANSPORT_ENTRY_ALLOC_CNT 73 # define PJSIP_TRANSPORT_ENTRY_ALLOC_CNT 16 74 #endif 75 57 76 /* Prototype. */ 58 77 static pj_status_t mod_on_tx_msg(pjsip_tx_data *tdata); … … 82 101 { 83 102 PJ_DECL_LIST_MEMBER(struct transport); 103 pj_hash_entry_buf tp_buf; 84 104 pjsip_transport *tp; 85 105 } transport; … … 94 114 pjsip_endpoint *endpt; 95 115 pjsip_tpfactory factory_list; 116 pj_pool_t *pool; 96 117 #if defined(PJ_DEBUG) && PJ_DEBUG!=0 97 118 pj_atomic_t *tdata_counter; … … 106 127 */ 107 128 pjsip_tx_data tdata_list; 108 109 /* List of transports which are NOT stored in the hash table, so 110 * that it can be properly cleaned up when transport manager 111 * is destroyed. 112 */ 113 transport tp_list; 129 130 /* List of free transport entry. */ 131 transport tp_entry_freelist; 114 132 }; 115 133 … … 1025 1043 int key_len) 1026 1044 { 1027 transport *tp_ iter;1028 1029 if (pj_hash_get(tpmgr->table, key, key_len, NULL) == (void*)tp) {1030 return PJ_TRUE;1031 } 1032 1033 tp_iter = tpmgr->tp_list.next; 1034 while (tp_iter != &tpmgr->tp_list) {1035 if (tp_iter->tp == tp) { 1036 return PJ_TRUE; 1037 } 1038 tp_iter = tp_iter->next;1045 transport *tp_entry; 1046 1047 tp_entry = (transport *)pj_hash_get(tpmgr->table, key, key_len, NULL); 1048 if (tp_entry != NULL) { 1049 1050 transport *tp_iter = tp_entry; 1051 do { 1052 if (tp_iter->tp == tp) { 1053 return PJ_TRUE; 1054 } 1055 tp_iter = tp_iter->next; 1056 } while (tp_iter != tp_entry); 1039 1057 } 1040 1058 … … 1136 1154 1137 1155 /* Dec ref transport group lock, if any */ 1138 if (tp->grp_lock) 1156 if (tp->grp_lock) { 1139 1157 pj_grp_lock_dec_ref(tp->grp_lock); 1158 } 1140 1159 1141 1160 return PJ_SUCCESS; … … 1151 1170 int key_len; 1152 1171 pj_uint32_t hval; 1153 void *entry; 1172 transport *tp_ref = NULL; 1173 transport *tp_add = NULL; 1154 1174 1155 1175 /* Init. */ … … 1159 1179 tp->idle_timer.cb = &transport_idle_callback; 1160 1180 1161 /* 1181 /* 1162 1182 * Register to hash table (see Trac ticket #42). 1163 1183 */ … … 1165 1185 pj_lock_acquire(mgr->lock); 1166 1186 1167 /* If entry already occupied, unregister previous entry */1168 1187 hval = 0; 1169 entry = pj_hash_get(mgr->table, &tp->key, key_len, &hval); 1170 if (entry != NULL) { 1171 transport *tp_ref; 1172 1173 tp_ref = PJ_POOL_ZALLOC_T(((pjsip_transport *)entry)->pool, transport); 1174 1175 /* 1176 * Add transport to the list before removing it from the hash table. 1177 * See ticket #1774 for more details. 1178 */ 1179 tp_ref->tp = (pjsip_transport *)entry; 1180 pj_list_push_back(&mgr->tp_list, tp_ref); 1181 pj_hash_set(NULL, mgr->table, &tp->key, key_len, hval, NULL); 1182 } 1183 1184 /* Register new entry */ 1185 pj_hash_set(tp->pool, mgr->table, &tp->key, key_len, hval, tp); 1188 tp_ref = (transport *)pj_hash_get(mgr->table, &tp->key, key_len, &hval); 1189 1190 /* Get an empty entry from the freelist. */ 1191 if (pj_list_empty(&mgr->tp_entry_freelist)) { 1192 unsigned i = 0; 1193 1194 TRACE_((THIS_FILE, "Transport list is full, allocate new entry")); 1195 /* Allocate new entry for the freelist. */ 1196 for (; i < PJSIP_TRANSPORT_ENTRY_ALLOC_CNT; ++i) { 1197 tp_add = PJ_POOL_ZALLOC_T(mgr->pool, transport); 1198 if (!tp_add) 1199 return PJ_ENOMEM; 1200 pj_list_init(tp_add); 1201 pj_list_push_back(&mgr->tp_entry_freelist, tp_add); 1202 } 1203 } 1204 tp_add = mgr->tp_entry_freelist.next; 1205 tp_add->tp = tp; 1206 pj_list_erase(tp_add); 1207 1208 if (tp_ref) { 1209 /* There'a already a transport list from the hash table. Add the 1210 * new transport to the list. 1211 */ 1212 pj_list_push_back(tp_ref, tp_add); 1213 } else { 1214 /* Transport list not found, add it to the hash table. */ 1215 pj_hash_set_np(mgr->table, &tp->key, key_len, hval, tp_add->tp_buf, 1216 tp_add); 1217 } 1186 1218 1187 1219 /* Add ref transport group lock, if any */ … … 1230 1262 hval = 0; 1231 1263 entry = pj_hash_get(mgr->table, &tp->key, key_len, &hval); 1232 if (entry == (void*)tp) { 1233 pj_hash_set(NULL, mgr->table, &tp->key, key_len, hval, NULL); 1234 } else { 1235 /* If not found in hash table, remove from the tranport list. */ 1236 transport *tp_iter = mgr->tp_list.next; 1237 while (tp_iter != &mgr->tp_list) { 1238 if (tp_iter->tp == tp) { 1239 pj_list_erase(tp_iter); 1240 break; 1241 } 1242 tp_iter = tp_iter->next; 1243 } 1264 if (entry) { 1265 transport *tp_ref = (transport *)entry; 1266 transport *tp_iter = tp_ref; 1267 /* Search the matching entry from the transport list. */ 1268 do { 1269 if (tp_iter->tp == tp) { 1270 transport *tp_next = tp_iter->next; 1271 1272 /* Update hash table : 1273 * - transport list only contain single element, or 1274 * - the entry is the first element of the transport list. 1275 */ 1276 if (tp_iter == tp_ref) { 1277 pj_hash_set(NULL, mgr->table, &tp->key, key_len, hval, 1278 NULL); 1279 1280 if (tp_ref->next != tp_ref) { 1281 /* The transport list has multiple entry. */ 1282 pj_hash_set_np(mgr->table, &tp_next->tp->key, key_len, 1283 hval, tp_next->tp_buf, tp_next); 1284 } 1285 } 1286 1287 pj_list_erase(tp_iter); 1288 /* Put back to the transport freelist. */ 1289 pj_list_push_back(&mgr->tp_entry_freelist, tp_iter); 1290 1291 break; 1292 } 1293 tp_iter = tp_iter->next; 1294 } while (tp_iter != tp_ref); 1244 1295 } 1245 1296 … … 1248 1299 1249 1300 /* Dec ref transport group lock, if any */ 1250 if (tp->grp_lock) 1301 if (tp->grp_lock) { 1251 1302 pj_grp_lock_dec_ref(tp->grp_lock); 1303 } 1252 1304 1253 1305 /* Destroy. */ … … 1363 1415 pj_lock_acquire(mgr->lock); 1364 1416 1365 /* Check that no factory with the same typehas been registered. */1417 /* Check that no same factory has been registered. */ 1366 1418 status = PJ_SUCCESS; 1367 1419 for (p=mgr->factory_list.next; p!=&mgr->factory_list; p=p->next) { 1368 if (p->type == tpf->type) {1369 status = PJSIP_ETYPEEXISTS;1370 break;1371 }1372 1420 if (p == tpf) { 1373 1421 status = PJ_EEXISTS; … … 1444 1492 pjsip_tpmgr *mgr; 1445 1493 pj_status_t status; 1494 unsigned i = 0; 1495 pj_pool_t *mgr_pool; 1446 1496 1447 1497 PJ_ASSERT_RETURN(pool && endpt && rx_cb && p_mgr, PJ_EINVAL); … … 1453 1503 1454 1504 /* Create and initialize transport manager. */ 1455 mgr = PJ_POOL_ZALLOC_T(pool, pjsip_tpmgr); 1505 mgr_pool = pjsip_endpt_create_pool(endpt, "tpmgr", 1506 TPMGR_POOL_INIT_SIZE, 1507 TPMGR_POOL_INC_SIZE); 1508 mgr = PJ_POOL_ZALLOC_T(mgr_pool, pjsip_tpmgr); 1456 1509 mgr->endpt = endpt; 1457 1510 mgr->on_rx_msg = rx_cb; 1458 1511 mgr->on_tx_msg = tx_cb; 1512 mgr->pool = mgr_pool; 1513 1514 if (!mgr->pool) 1515 return PJ_ENOMEM; 1516 1459 1517 pj_list_init(&mgr->factory_list); 1460 1518 pj_list_init(&mgr->tdata_list); 1461 pj_list_init(&mgr->tp_ list);1462 1463 mgr->table = pj_hash_create( pool, PJSIP_TPMGR_HTABLE_SIZE);1519 pj_list_init(&mgr->tp_entry_freelist); 1520 1521 mgr->table = pj_hash_create(mgr->pool, PJSIP_TPMGR_HTABLE_SIZE); 1464 1522 if (!mgr->table) 1465 1523 return PJ_ENOMEM; 1466 1524 1467 status = pj_lock_create_recursive_mutex( pool, "tmgr%p", &mgr->lock);1525 status = pj_lock_create_recursive_mutex(mgr->pool, "tmgr%p", &mgr->lock); 1468 1526 if (status != PJ_SUCCESS) 1469 1527 return status; 1470 1528 1529 for (; i < PJSIP_TRANSPORT_ENTRY_ALLOC_CNT; ++i) { 1530 transport *tp_add = NULL; 1531 1532 tp_add = PJ_POOL_ZALLOC_T(mgr->pool, transport); 1533 if (!tp_add) 1534 return PJ_ENOMEM; 1535 pj_list_init(tp_add); 1536 pj_list_push_back(&mgr->tp_entry_freelist, tp_add); 1537 } 1538 1471 1539 #if defined(PJ_DEBUG) && PJ_DEBUG!=0 1472 status = pj_atomic_create( pool, 0, &mgr->tdata_counter);1540 status = pj_atomic_create(mgr->pool, 0, &mgr->tdata_counter); 1473 1541 if (status != PJ_SUCCESS) { 1474 1542 pj_lock_destroy(mgr->lock); … … 1698 1766 pj_hash_iterator_t *itr; 1699 1767 int nr_of_transports = 0; 1700 1768 1701 1769 pj_lock_acquire(mgr->lock); 1702 1770 1703 1771 itr = pj_hash_first(mgr->table, &itr_val); 1704 1772 while (itr) { 1705 nr_of_transports++; 1773 transport *tp_entry = (transport *)pj_hash_this(mgr->table, itr); 1774 nr_of_transports += pj_list_size(tp_entry); 1706 1775 itr = pj_hash_next(mgr->table, itr); 1707 1776 } 1708 1777 1709 1778 pj_lock_release(mgr->lock); 1710 1779 … … 1723 1792 pjsip_tpfactory *factory; 1724 1793 pjsip_endpoint *endpt = mgr->endpt; 1725 1794 1726 1795 PJ_LOG(5, (THIS_FILE, "Destroying transport manager")); 1727 1796 … … 1731 1800 * Destroy all transports in the hash table. 1732 1801 */ 1733 itr = pj_hash_first(mgr->table, &itr_val); 1734 while (itr != NULL) { 1735 pj_hash_iterator_t *next; 1736 pjsip_transport *transport; 1737 1738 transport = (pjsip_transport*) pj_hash_this(mgr->table, itr); 1739 1740 next = pj_hash_next(mgr->table, itr); 1741 1742 destroy_transport(mgr, transport); 1743 1744 itr = next; 1745 } 1746 1747 /* 1748 * Destroy transports in the list. 1749 */ 1750 if (!pj_list_empty(&mgr->tp_list)) { 1751 transport *tp_iter = mgr->tp_list.next; 1752 while (tp_iter != &mgr->tp_list) { 1753 transport *next = tp_iter->next; 1754 destroy_transport(mgr, tp_iter->tp); 1755 tp_iter = next; 1756 } 1757 } 1758 1802 for (itr = pj_hash_first(mgr->table, &itr_val); itr; 1803 itr = pj_hash_first(mgr->table, &itr_val)) 1804 { 1805 transport *tp_ref; 1806 tp_ref = pj_hash_this(mgr->table, itr); 1807 destroy_transport(mgr, tp_ref->tp); 1808 } 1809 1759 1810 /* 1760 1811 * Destroy all factories/listeners. … … 1763 1814 while (factory != &mgr->factory_list) { 1764 1815 pjsip_tpfactory *next = factory->next; 1765 1816 1766 1817 factory->destroy(factory); 1767 1818 … … 1805 1856 if (mod_msg_print.id != -1) { 1806 1857 pjsip_endpt_unregister_module(endpt, &mod_msg_print); 1858 } 1859 1860 if (mgr->pool) { 1861 pjsip_endpt_release_pool( mgr->endpt, mgr->pool ); 1807 1862 } 1808 1863 … … 2167 2222 pjsip_transport_key key; 2168 2223 int key_len; 2169 pjsip_transport *transport = NULL; 2224 pjsip_transport *tp_ref = NULL; 2225 transport *tp_entry = NULL; 2226 2170 2227 2171 2228 /* If listener is specified, verify that the listener type matches … … 2188 2245 pj_memcpy(&key.rem_addr, remote, addr_len); 2189 2246 2190 transport = (pjsip_transport*) 2191 pj_hash_get(mgr->table, &key, key_len, NULL); 2192 } 2193 2194 if (transport == NULL && 2247 tp_entry = (transport *)pj_hash_get(mgr->table, &key, key_len, 2248 NULL); 2249 if (tp_entry) { 2250 if (sel && sel->type == PJSIP_TPSELECTOR_LISTENER) { 2251 transport *tp_iter = tp_entry; 2252 do { 2253 if (sel && sel->type == PJSIP_TPSELECTOR_LISTENER && 2254 sel->u.listener && 2255 tp_iter->tp->factory == sel->u.listener) 2256 { 2257 tp_ref = tp_iter->tp; 2258 break; 2259 } 2260 tp_iter = tp_iter->next; 2261 } while (tp_iter != tp_entry); 2262 } else { 2263 tp_ref = tp_entry->tp; 2264 } 2265 } 2266 } 2267 2268 if (tp_ref == NULL && 2195 2269 (!sel || sel->disable_connection_reuse == PJ_FALSE)) 2196 2270 { … … 2207 2281 pj_bzero(addr, addr_len); 2208 2282 key_len = sizeof(key.type) + addr_len; 2209 transport = (pjsip_transport*) 2210 pj_hash_get(mgr->table, &key, key_len, NULL); 2283 tp_entry = (transport *) pj_hash_get(mgr->table, &key, 2284 key_len, NULL); 2285 if (tp_entry) { 2286 tp_ref = tp_entry->tp; 2287 } 2211 2288 } 2212 2289 /* For datagram transports, try lookup with zero address. … … 2220 2297 2221 2298 key_len = sizeof(key.type) + addr_len; 2222 transport = (pjsip_transport*) 2223 pj_hash_get(mgr->table, &key, key_len, NULL); 2299 tp_entry = (transport *) pj_hash_get(mgr->table, &key, 2300 key_len, NULL); 2301 if (tp_entry) { 2302 tp_ref = tp_entry->tp; 2303 } 2224 2304 } 2225 2305 } … … 2227 2307 /* If transport is found and listener is specified, verify listener */ 2228 2308 else if (sel && sel->type == PJSIP_TPSELECTOR_LISTENER && 2229 sel->u.listener && t ransport->factory != sel->u.listener)2309 sel->u.listener && tp_ref->factory != sel->u.listener) 2230 2310 { 2231 t ransport= NULL;2311 tp_ref = NULL; 2232 2312 /* This will cause a new transport to be created which will be a 2233 2313 * 'duplicate' of the existing transport (same type & remote addr, … … 2236 2316 } 2237 2317 2238 if (t ransport!=NULL && !transport->is_shutdown) {2318 if (tp_ref!=NULL && !tp_ref->is_shutdown) { 2239 2319 /* 2240 2320 * Transport found! 2241 2321 */ 2242 pjsip_transport_add_ref(t ransport);2322 pjsip_transport_add_ref(tp_ref); 2243 2323 pj_lock_release(mgr->lock); 2244 *tp = t ransport;2245 2246 TRACE_((THIS_FILE, "Transport %s acquired", t ransport->obj_name));2324 *tp = tp_ref; 2325 2326 TRACE_((THIS_FILE, "Transport %s acquired", tp_ref->obj_name)); 2247 2327 return PJ_SUCCESS; 2248 2328 } … … 2306 2386 if (factory->create_transport2) { 2307 2387 status = factory->create_transport2(factory, mgr, mgr->endpt, 2308 (const pj_sockaddr*) remote, 2388 (const pj_sockaddr*) remote, 2309 2389 addr_len, tdata, tp); 2310 2390 } else { 2311 2391 status = factory->create_transport(factory, mgr, mgr->endpt, 2312 (const pj_sockaddr*) remote, 2392 (const pj_sockaddr*) remote, 2313 2393 addr_len, tp); 2314 2394 } 2315 2395 if (status == PJ_SUCCESS) { 2316 PJ_ASSERT_ON_FAIL(tp!=NULL, 2396 PJ_ASSERT_ON_FAIL(tp!=NULL, 2317 2397 {pj_lock_release(mgr->lock); return PJ_EBUG;}); 2318 2398 pjsip_transport_add_ref(*tp); … … 2357 2437 2358 2438 do { 2359 pjsip_transport *t = (pjsip_transport*) 2360 pj_hash_this(mgr->table, itr); 2361 2362 PJ_LOG(3, (THIS_FILE, " %s %s (refcnt=%d%s)", 2363 t->obj_name, 2364 t->info, 2365 pj_atomic_get(t->ref_cnt), 2366 (t->idle_timer.id ? " [idle]" : ""))); 2367 2439 transport *tp_entry = (transport *) pj_hash_this(mgr->table, itr); 2440 if (tp_entry) { 2441 transport *tp_iter = tp_entry; 2442 2443 do { 2444 pjsip_transport *tp_ref = tp_iter->tp; 2445 2446 PJ_LOG(3, (THIS_FILE, " %s %s%s%s%s(refcnt=%d%s)", 2447 tp_ref->obj_name, 2448 tp_ref->info, 2449 (tp_ref->factory)?" listener[":"", 2450 (tp_ref->factory)?tp_ref->factory->obj_name:"", 2451 (tp_ref->factory)?"]":"", 2452 pj_atomic_get(tp_ref->ref_cnt), 2453 (tp_ref->idle_timer.id ? " [idle]" : ""))); 2454 2455 tp_iter = tp_iter->next; 2456 } while (tp_iter != tp_entry); 2457 } 2368 2458 itr = pj_hash_next(mgr->table, itr); 2369 2459 } while (itr);
Note: See TracChangeset
for help on using the changeset viewer.