Changeset 4360 for pjproject/trunk/pjnath/src/pjnath/ice_session.c
- Timestamp:
- Feb 21, 2013 11:26:35 AM (11 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
pjproject/trunk/pjnath/src/pjnath/ice_session.c
r4357 r4360 98 98 }; 99 99 100 #define THIS_FILE "ice_session.c" 100 101 #define CHECK_NAME_LEN 128 101 102 #define LOG4(expr) PJ_LOG(4,expr) … … 135 136 static void on_ice_complete(pj_ice_sess *ice, pj_status_t status); 136 137 static void ice_keep_alive(pj_ice_sess *ice, pj_bool_t send_now); 138 static void ice_on_destroy(void *obj); 137 139 static void destroy_ice(pj_ice_sess *ice, 138 140 pj_status_t reason); … … 289 291 status = pj_stun_session_create(&ice->stun_cfg, NULL, 290 292 &sess_cb, PJ_TRUE, 293 ice->grp_lock, 291 294 &comp->stun_sess); 292 295 if (status != PJ_SUCCESS) … … 333 336 const pj_str_t *local_ufrag, 334 337 const pj_str_t *local_passwd, 338 pj_grp_lock_t *grp_lock, 335 339 pj_ice_sess **p_ice) 336 340 { … … 360 364 name, ice); 361 365 362 status = pj_mutex_create_recursive(pool, ice->obj_name, 363 &ice->mutex); 364 if (status != PJ_SUCCESS) { 365 destroy_ice(ice, status); 366 return status; 367 } 366 if (grp_lock) { 367 ice->grp_lock = grp_lock; 368 } else { 369 status = pj_grp_lock_create(pool, NULL, &ice->grp_lock); 370 if (status != PJ_SUCCESS) { 371 pj_pool_release(pool); 372 return status; 373 } 374 } 375 376 pj_grp_lock_add_ref(ice->grp_lock); 377 pj_grp_lock_add_handler(ice->grp_lock, pool, ice, 378 &ice_on_destroy); 368 379 369 380 pj_memcpy(&ice->cb, cb, sizeof(*cb)); … … 445 456 446 457 /* 458 * Callback to really destroy the session 459 */ 460 static void ice_on_destroy(void *obj) 461 { 462 pj_ice_sess *ice = (pj_ice_sess*) obj; 463 464 if (ice->pool) { 465 pj_pool_t *pool = ice->pool; 466 ice->pool = NULL; 467 pj_pool_release(pool); 468 } 469 LOG4((THIS_FILE, "ICE session %p destroyed", ice)); 470 } 471 472 /* 447 473 * Destroy 448 474 */ … … 453 479 454 480 if (reason == PJ_SUCCESS) { 455 LOG4((ice->obj_name, "Destroying ICE session")); 481 LOG4((ice->obj_name, "Destroying ICE session %p", ice)); 482 } 483 484 pj_grp_lock_acquire(ice->grp_lock); 485 486 if (ice->is_destroying) { 487 pj_grp_lock_release(ice->grp_lock); 488 return; 456 489 } 457 490 458 491 ice->is_destroying = PJ_TRUE; 459 492 460 /* Let other callbacks finish */ 461 if (ice->mutex) { 462 pj_mutex_lock(ice->mutex); 463 pj_mutex_unlock(ice->mutex); 464 } 465 466 if (ice->timer.id) { 467 pj_timer_heap_cancel(ice->stun_cfg.timer_heap, 468 &ice->timer); 469 ice->timer.id = PJ_FALSE; 470 } 493 pj_timer_heap_cancel_if_active(ice->stun_cfg.timer_heap, 494 &ice->timer, PJ_FALSE); 471 495 472 496 for (i=0; i<ice->comp_cnt; ++i) { … … 477 501 } 478 502 479 if (ice->clist.timer.id) { 480 pj_timer_heap_cancel(ice->stun_cfg.timer_heap, &ice->clist.timer); 481 ice->clist.timer.id = PJ_FALSE; 482 } 483 484 if (ice->mutex) { 485 pj_mutex_destroy(ice->mutex); 486 ice->mutex = NULL; 487 } 488 489 if (ice->pool) { 490 pj_pool_t *pool = ice->pool; 491 ice->pool = NULL; 492 pj_pool_release(pool); 493 } 503 pj_timer_heap_cancel_if_active(ice->stun_cfg.timer_heap, 504 &ice->clist.timer, 505 PJ_FALSE); 506 507 pj_grp_lock_dec_ref(ice->grp_lock); 508 pj_grp_lock_release(ice->grp_lock); 494 509 } 495 510 … … 710 725 PJ_ASSERT_RETURN(comp_id <= ice->comp_cnt, PJ_EINVAL); 711 726 712 pj_ mutex_lock(ice->mutex);727 pj_grp_lock_acquire(ice->grp_lock); 713 728 714 729 if (ice->lcand_cnt >= PJ_ARRAY_SIZE(ice->lcand)) { … … 750 765 751 766 on_error: 752 pj_ mutex_unlock(ice->mutex);767 pj_grp_lock_release(ice->grp_lock); 753 768 return status; 754 769 } … … 767 782 *cand_id = -1; 768 783 769 pj_ mutex_lock(ice->mutex);784 pj_grp_lock_acquire(ice->grp_lock); 770 785 771 786 /* First find in valid list if we have nominated pair */ … … 775 790 if (check->lcand->comp_id == comp_id) { 776 791 *cand_id = GET_LCAND_ID(check->lcand); 777 pj_ mutex_unlock(ice->mutex);792 pj_grp_lock_release(ice->grp_lock); 778 793 return PJ_SUCCESS; 779 794 } … … 787 802 { 788 803 *cand_id = GET_LCAND_ID(lcand); 789 pj_ mutex_unlock(ice->mutex);804 pj_grp_lock_release(ice->grp_lock); 790 805 return PJ_SUCCESS; 791 806 } … … 800 815 { 801 816 *cand_id = GET_LCAND_ID(lcand); 802 pj_ mutex_unlock(ice->mutex);817 pj_grp_lock_release(ice->grp_lock); 803 818 return PJ_SUCCESS; 804 819 } … … 812 827 { 813 828 *cand_id = GET_LCAND_ID(lcand); 814 pj_ mutex_unlock(ice->mutex);829 pj_grp_lock_release(ice->grp_lock); 815 830 return PJ_SUCCESS; 816 831 } … … 818 833 819 834 /* Still no candidate is found! :( */ 820 pj_ mutex_unlock(ice->mutex);835 pj_grp_lock_release(ice->grp_lock); 821 836 822 837 pj_assert(!"Should have a candidate by now"); … … 1128 1143 pj_ice_sess *ice = (pj_ice_sess*) te->user_data; 1129 1144 enum timer_type type = (enum timer_type)te->id; 1130 pj_bool_t has_mutex = PJ_TRUE;1131 1145 1132 1146 PJ_UNUSED_ARG(th); 1133 1147 1134 pj_ mutex_lock(ice->mutex);1148 pj_grp_lock_acquire(ice->grp_lock); 1135 1149 1136 1150 te->id = TIMER_NONE; 1151 1152 if (ice->is_destroying) { 1153 /* Stray timer, could happen when destroy is invoked while callback 1154 * is pending. */ 1155 pj_grp_lock_release(ice->grp_lock); 1156 return; 1157 } 1137 1158 1138 1159 switch (type) { … … 1158 1179 ice_status = ice->ice_status; 1159 1180 on_ice_complete = ice->cb.on_ice_complete; 1160 has_mutex = PJ_FALSE;1161 pj_mutex_unlock(ice->mutex);1162 1181 1163 1182 /* Notify app about ICE completion*/ … … 1177 1196 } 1178 1197 1179 if (has_mutex) 1180 pj_mutex_unlock(ice->mutex); 1198 pj_grp_lock_release(ice->grp_lock); 1181 1199 } 1182 1200 … … 1236 1254 pj_time_val_normalize(&delay); 1237 1255 1238 ice->timer.id = TIMER_KEEP_ALIVE; 1239 pj_timer_heap_schedule(ice->stun_cfg.timer_heap, &ice->timer, &delay); 1256 pj_timer_heap_schedule_w_grp_lock(ice->stun_cfg.timer_heap, 1257 &ice->timer, &delay, 1258 TIMER_KEEP_ALIVE, 1259 ice->grp_lock); 1240 1260 1241 1261 } else { … … 1251 1271 ice->ice_status = status; 1252 1272 1253 if (ice->timer.id != TIMER_NONE) { 1254 pj_timer_heap_cancel(ice->stun_cfg.timer_heap, &ice->timer); 1255 ice->timer.id = TIMER_NONE; 1256 } 1273 pj_timer_heap_cancel_if_active(ice->stun_cfg.timer_heap, &ice->timer, 1274 TIMER_NONE); 1257 1275 1258 1276 /* Log message */ … … 1267 1285 pj_time_val delay = {0, 0}; 1268 1286 1269 ice->timer.id = TIMER_COMPLETION_CALLBACK; 1270 pj_timer_heap_schedule(ice->stun_cfg.timer_heap, 1271 &ice->timer, &delay); 1287 pj_timer_heap_schedule_w_grp_lock(ice->stun_cfg.timer_heap, 1288 &ice->timer, &delay, 1289 TIMER_COMPLETION_CALLBACK, 1290 ice->grp_lock); 1272 1291 } 1273 1292 } … … 1497 1516 pj_time_val_normalize(&delay); 1498 1517 1499 ice->timer.id = TIMER_CONTROLLED_WAIT_NOM; 1500 pj_timer_heap_schedule(ice->stun_cfg.timer_heap, 1501 &ice->timer, 1502 &delay); 1518 pj_timer_heap_schedule_w_grp_lock( 1519 ice->stun_cfg.timer_heap, 1520 &ice->timer, &delay, 1521 TIMER_CONTROLLED_WAIT_NOM, 1522 ice->grp_lock); 1503 1523 1504 1524 LOG5((ice->obj_name, … … 1576 1596 ice->opt.nominated_check_delay)); 1577 1597 1578 if (ice->timer.id != TIMER_NONE) { 1579 pj_timer_heap_cancel(ice->stun_cfg.timer_heap, &ice->timer); 1580 ice->timer.id = TIMER_NONE; 1581 } 1598 pj_timer_heap_cancel_if_active(ice->stun_cfg.timer_heap, &ice->timer, 1599 TIMER_NONE); 1582 1600 1583 1601 /* All components have valid pair. Let connectivity checks run for … … 1588 1606 pj_time_val_normalize(&delay); 1589 1607 1590 ice->timer.id = TIMER_START_NOMINATED_CHECK; 1591 pj_timer_heap_schedule(ice->stun_cfg.timer_heap, &ice->timer, &delay); 1608 pj_timer_heap_schedule_w_grp_lock(ice->stun_cfg.timer_heap, 1609 &ice->timer, &delay, 1610 TIMER_START_NOMINATED_CHECK, 1611 ice->grp_lock); 1592 1612 return PJ_FALSE; 1593 1613 } … … 1619 1639 PJ_ETOOMANY); 1620 1640 1621 pj_ mutex_lock(ice->mutex);1641 pj_grp_lock_acquire(ice->grp_lock); 1622 1642 1623 1643 /* Save credentials */ … … 1667 1687 1668 1688 if (clist->count >= PJ_ICE_MAX_CHECKS) { 1669 pj_ mutex_unlock(ice->mutex);1689 pj_grp_lock_release(ice->grp_lock); 1670 1690 return PJ_ETOOMANY; 1671 1691 } … … 1695 1715 if (clist->count == 0) { 1696 1716 LOG4((ice->obj_name, "Error: no checklist can be created")); 1697 pj_ mutex_unlock(ice->mutex);1717 pj_grp_lock_release(ice->grp_lock); 1698 1718 return PJ_ENOTFOUND; 1699 1719 } … … 1705 1725 status = prune_checklist(ice, clist); 1706 1726 if (status != PJ_SUCCESS) { 1707 pj_ mutex_unlock(ice->mutex);1727 pj_grp_lock_release(ice->grp_lock); 1708 1728 return status; 1709 1729 } … … 1732 1752 dump_checklist("Checklist created:", ice, clist); 1733 1753 1734 pj_ mutex_unlock(ice->mutex);1754 pj_grp_lock_release(ice->grp_lock); 1735 1755 1736 1756 return PJ_SUCCESS; … … 1851 1871 clist = td->clist; 1852 1872 1853 if (ice->is_destroying) 1854 return PJ_SUCCESS; 1855 1856 pj_mutex_lock(ice->mutex); 1873 pj_grp_lock_acquire(ice->grp_lock); 1857 1874 1858 1875 if (ice->is_destroying) { 1859 pj_ mutex_unlock(ice->mutex);1876 pj_grp_lock_release(ice->grp_lock); 1860 1877 return PJ_SUCCESS; 1861 1878 } … … 1879 1896 status = perform_check(ice, clist, i, ice->is_nominating); 1880 1897 if (status != PJ_SUCCESS) { 1881 pj_ mutex_unlock(ice->mutex);1898 pj_grp_lock_release(ice->grp_lock); 1882 1899 pj_log_pop_indent(); 1883 1900 return status; … … 1899 1916 status = perform_check(ice, clist, i, ice->is_nominating); 1900 1917 if (status != PJ_SUCCESS) { 1901 pj_ mutex_unlock(ice->mutex);1918 pj_grp_lock_release(ice->grp_lock); 1902 1919 pj_log_pop_indent(); 1903 1920 return status; … … 1916 1933 pj_time_val timeout = {0, PJ_ICE_TA_VAL}; 1917 1934 1918 te->id = PJ_TRUE;1919 1935 pj_time_val_normalize(&timeout); 1920 pj_timer_heap_schedule(th, te, &timeout); 1921 } 1922 1923 pj_mutex_unlock(ice->mutex); 1936 pj_timer_heap_schedule_w_grp_lock(th, te, &timeout, PJ_TRUE, 1937 ice->grp_lock); 1938 } 1939 1940 pj_grp_lock_release(ice->grp_lock); 1924 1941 pj_log_pop_indent(); 1925 1942 return PJ_SUCCESS; … … 1941 1958 /* Stop our timer if it's active */ 1942 1959 if (ice->timer.id == TIMER_START_NOMINATED_CHECK) { 1943 pj_timer_heap_cancel (ice->stun_cfg.timer_heap, &ice->timer);1944 ice->timer.id = TIMER_NONE;1960 pj_timer_heap_cancel_if_active(ice->stun_cfg.timer_heap, &ice->timer, 1961 TIMER_NONE); 1945 1962 } 1946 1963 … … 1970 1987 1971 1988 /* And (re)start the periodic check */ 1972 if (ice->clist.timer.id) { 1973 pj_timer_heap_cancel(ice->stun_cfg.timer_heap, &ice->clist.timer); 1974 ice->clist.timer.id = PJ_FALSE; 1975 } 1976 1977 ice->clist.timer.id = PJ_TRUE; 1989 pj_timer_heap_cancel_if_active(ice->stun_cfg.timer_heap, 1990 &ice->clist.timer, PJ_FALSE); 1991 1978 1992 delay.sec = delay.msec = 0; 1979 status = pj_timer_heap_schedule (ice->stun_cfg.timer_heap,1980 &ice->clist.timer, &delay); 1981 if (status != PJ_SUCCESS) {1982 ice->clist.timer.id = PJ_FALSE;1983 } else{1993 status = pj_timer_heap_schedule_w_grp_lock(ice->stun_cfg.timer_heap, 1994 &ice->clist.timer, &delay, 1995 PJ_TRUE, 1996 ice->grp_lock); 1997 if (status == PJ_SUCCESS) { 1984 1998 LOG5((ice->obj_name, "Periodic timer rescheduled..")); 1985 1999 } … … 2031 2045 2032 2046 /* Lock session */ 2033 pj_ mutex_lock(ice->mutex);2047 pj_grp_lock_acquire(ice->grp_lock); 2034 2048 2035 2049 LOG4((ice->obj_name, "Starting ICE check..")); … … 2061 2075 if (i == clist->count) { 2062 2076 pj_assert(!"Unable to find checklist for component 1"); 2063 pj_ mutex_unlock(ice->mutex);2077 pj_grp_lock_release(ice->grp_lock); 2064 2078 pj_log_pop_indent(); 2065 2079 return PJNATH_EICEINCOMPID; … … 2115 2129 * return start_periodic_check(ice->stun_cfg.timer_heap, &clist->timer); 2116 2130 */ 2117 clist->timer.id = PJ_TRUE;2118 2131 delay.sec = delay.msec = 0; 2119 status = pj_timer_heap_schedule(ice->stun_cfg.timer_heap, 2120 &clist->timer, &delay); 2132 status = pj_timer_heap_schedule_w_grp_lock(ice->stun_cfg.timer_heap, 2133 &clist->timer, &delay, 2134 PJ_TRUE, ice->grp_lock); 2121 2135 if (status != PJ_SUCCESS) { 2122 2136 clist->timer.id = PJ_FALSE; 2123 2137 } 2124 2138 2125 pj_ mutex_unlock(ice->mutex);2139 pj_grp_lock_release(ice->grp_lock); 2126 2140 pj_log_pop_indent(); 2127 2141 return status; … … 2144 2158 pj_ice_sess *ice = sd->ice; 2145 2159 pj_ice_msg_data *msg_data = (pj_ice_msg_data*) token; 2160 pj_status_t status; 2146 2161 2147 return (*ice->cb.on_tx_pkt)(ice, sd->comp_id, msg_data->transport_id, 2148 pkt, pkt_size, dst_addr, addr_len); 2162 pj_grp_lock_acquire(ice->grp_lock); 2163 2164 if (ice->is_destroying) { 2165 /* Stray retransmit timer that could happen while 2166 * we're being destroyed */ 2167 pj_grp_lock_release(ice->grp_lock); 2168 return PJ_EINVALIDOP; 2169 } 2170 2171 status = (*ice->cb.on_tx_pkt)(ice, sd->comp_id, msg_data->transport_id, 2172 pkt, pkt_size, dst_addr, addr_len); 2173 2174 pj_grp_lock_release(ice->grp_lock); 2175 return status; 2149 2176 } 2150 2177 … … 2181 2208 check->tdata = NULL; 2182 2209 2183 pj_mutex_lock(ice->mutex); 2210 pj_grp_lock_acquire(ice->grp_lock); 2211 2212 if (ice->is_destroying) { 2213 /* Not sure if this is possible but just in case */ 2214 pj_grp_lock_release(ice->grp_lock); 2215 return; 2216 } 2184 2217 2185 2218 /* Init lcand to NULL. lcand will be found from the mapped address … … 2232 2265 check->nominated || ice->is_nominating); 2233 2266 pj_log_pop_indent(); 2234 pj_ mutex_unlock(ice->mutex);2267 pj_grp_lock_release(ice->grp_lock); 2235 2268 return; 2236 2269 } … … 2247 2280 on_check_complete(ice, check); 2248 2281 pj_log_pop_indent(); 2249 pj_ mutex_unlock(ice->mutex);2282 pj_grp_lock_release(ice->grp_lock); 2250 2283 return; 2251 2284 } … … 2271 2304 on_check_complete(ice, check); 2272 2305 pj_log_pop_indent(); 2273 pj_ mutex_unlock(ice->mutex);2306 pj_grp_lock_release(ice->grp_lock); 2274 2307 return; 2275 2308 } … … 2304 2337 PJNATH_ESTUNNOMAPPEDADDR); 2305 2338 on_check_complete(ice, check); 2306 pj_ mutex_unlock(ice->mutex);2339 pj_grp_lock_release(ice->grp_lock); 2307 2340 return; 2308 2341 } … … 2352 2385 status); 2353 2386 on_check_complete(ice, check); 2354 pj_ mutex_unlock(ice->mutex);2387 pj_grp_lock_release(ice->grp_lock); 2355 2388 return; 2356 2389 } … … 2412 2445 if (on_check_complete(ice, check)) { 2413 2446 /* ICE complete! */ 2414 pj_ mutex_unlock(ice->mutex);2447 pj_grp_lock_release(ice->grp_lock); 2415 2448 return; 2416 2449 } 2417 2450 2418 pj_ mutex_unlock(ice->mutex);2451 pj_grp_lock_release(ice->grp_lock); 2419 2452 } 2420 2453 … … 2457 2490 ice = sd->ice; 2458 2491 2459 pj_mutex_lock(ice->mutex); 2492 pj_grp_lock_acquire(ice->grp_lock); 2493 2494 if (ice->is_destroying) { 2495 pj_grp_lock_release(ice->grp_lock); 2496 return PJ_EINVALIDOP; 2497 } 2460 2498 2461 2499 /* … … 2472 2510 if (prio_attr == NULL) { 2473 2511 LOG5((ice->obj_name, "Received Binding request with no PRIORITY")); 2474 pj_ mutex_unlock(ice->mutex);2512 pj_grp_lock_release(ice->grp_lock); 2475 2513 return PJ_SUCCESS; 2476 2514 } … … 2517 2555 NULL, token, PJ_TRUE, 2518 2556 src_addr, src_addr_len); 2519 pj_ mutex_unlock(ice->mutex);2557 pj_grp_lock_release(ice->grp_lock); 2520 2558 return PJ_SUCCESS; 2521 2559 } … … 2529 2567 NULL, token, PJ_TRUE, 2530 2568 src_addr, src_addr_len); 2531 pj_ mutex_unlock(ice->mutex);2569 pj_grp_lock_release(ice->grp_lock); 2532 2570 return PJ_SUCCESS; 2533 2571 } else { … … 2544 2582 status = pj_stun_session_create_res(sess, rdata, 0, NULL, &tdata); 2545 2583 if (status != PJ_SUCCESS) { 2546 pj_ mutex_unlock(ice->mutex);2584 pj_grp_lock_release(ice->grp_lock); 2547 2585 return status; 2548 2586 } … … 2596 2634 } 2597 2635 2598 pj_ mutex_unlock(ice->mutex);2636 pj_grp_lock_release(ice->grp_lock); 2599 2637 return PJ_SUCCESS; 2600 2638 } … … 2885 2923 } 2886 2924 2887 pj_mutex_lock(ice->mutex); 2925 pj_grp_lock_acquire(ice->grp_lock); 2926 2927 if (ice->is_destroying) { 2928 pj_grp_lock_release(ice->grp_lock); 2929 return PJ_EINVALIDOP; 2930 } 2888 2931 2889 2932 comp = find_comp(ice, comp_id); 2890 2933 if (comp == NULL) { 2891 2934 status = PJNATH_EICEINCOMPID; 2892 pj_ mutex_unlock(ice->mutex);2935 pj_grp_lock_release(ice->grp_lock); 2893 2936 goto on_return; 2894 2937 } … … 2896 2939 if (comp->valid_check == NULL) { 2897 2940 status = PJNATH_EICEINPROGRESS; 2898 pj_ mutex_unlock(ice->mutex);2941 pj_grp_lock_release(ice->grp_lock); 2899 2942 goto on_return; 2900 2943 } … … 2905 2948 2906 2949 /* Release the mutex now to avoid deadlock (see ticket #1451). */ 2907 pj_mutex_unlock(ice->mutex); 2950 pj_grp_lock_release(ice->grp_lock); 2951 2952 PJ_RACE_ME(5); 2908 2953 2909 2954 status = (*ice->cb.on_tx_pkt)(ice, comp_id, transport_id, … … 2932 2977 PJ_ASSERT_RETURN(ice, PJ_EINVAL); 2933 2978 2934 pj_mutex_lock(ice->mutex); 2979 pj_grp_lock_acquire(ice->grp_lock); 2980 2981 if (ice->is_destroying) { 2982 pj_grp_lock_release(ice->grp_lock); 2983 return PJ_EINVALIDOP; 2984 } 2935 2985 2936 2986 comp = find_comp(ice, comp_id); 2937 2987 if (comp == NULL) { 2938 pj_ mutex_unlock(ice->mutex);2988 pj_grp_lock_release(ice->grp_lock); 2939 2989 return PJNATH_EICEINCOMPID; 2940 2990 } … … 2949 2999 if (msg_data == NULL) { 2950 3000 pj_assert(!"Invalid transport ID"); 2951 pj_ mutex_unlock(ice->mutex);3001 pj_grp_lock_release(ice->grp_lock); 2952 3002 return PJ_EINVAL; 2953 3003 } … … 2969 3019 ice->tmp.errmsg)); 2970 3020 } 2971 pj_ mutex_unlock(ice->mutex);3021 pj_grp_lock_release(ice->grp_lock); 2972 3022 } else { 2973 3023 /* Not a STUN packet. Call application's callback instead, but release 2974 3024 * the mutex now or otherwise we may get deadlock. 2975 3025 */ 2976 pj_mutex_unlock(ice->mutex); 3026 pj_grp_lock_release(ice->grp_lock); 3027 3028 PJ_RACE_ME(5); 2977 3029 2978 3030 (*ice->cb.on_rx_data)(ice, comp_id, transport_id, pkt, pkt_size,
Note: See TracChangeset
for help on using the changeset viewer.