Changeset 2724 for pjproject/trunk/pjnath/src/pjnath/ice_session.c
- Timestamp:
- May 29, 2009 1:04:03 PM (14 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
pjproject/trunk/pjnath/src/pjnath/ice_session.c
r2419 r2724 30 30 #include <pj/string.h> 31 31 32 33 32 /* String names for candidate types */ 34 33 static const char *cand_type_names[] = … … 65 64 "Controlled", 66 65 "Controlling" 66 }; 67 68 enum timer_type 69 { 70 TIMER_NONE, /**< Timer not active */ 71 TIMER_COMPLETION_CALLBACK, /**< Call on_ice_complete() callback */ 72 TIMER_CONTROLLED_WAIT_NOM, /**< Controlled agent is waiting for 73 controlling agent to send connectivity 74 check with nominated flag after it has 75 valid check for every components. */ 76 TIMER_START_NOMINATED_CHECK,/**< Controlling agent start connectivity 77 checks with USE-CANDIDATE flag. */ 78 TIMER_KEEP_ALIVE /**< ICE keep-alive timer. */ 79 67 80 }; 68 81 … … 119 132 120 133 /* Forward declarations */ 134 static void on_timer(pj_timer_heap_t *th, pj_timer_entry *te); 135 static void on_ice_complete(pj_ice_sess *ice, pj_status_t status); 136 static void ice_keep_alive(pj_ice_sess *ice, pj_bool_t send_now); 121 137 static void destroy_ice(pj_ice_sess *ice, 122 138 pj_status_t reason); 123 139 static pj_status_t start_periodic_check(pj_timer_heap_t *th, 124 140 pj_timer_entry *te); 141 static void start_nominated_check(pj_ice_sess *ice); 125 142 static void periodic_timer(pj_timer_heap_t *th, 126 143 pj_timer_entry *te); … … 226 243 const pj_sockaddr *base_addr) 227 244 { 228 #if 0245 #if PJNATH_ICE_PRIO_STD 229 246 char buf[64]; 230 247 pj_uint32_t val; … … 296 313 } 297 314 315 316 /* Init options with default values */ 317 PJ_DEF(void) pj_ice_sess_options_default(pj_ice_sess_options *opt) 318 { 319 opt->aggressive = PJ_TRUE; 320 opt->nominated_check_delay = PJ_ICE_NOMINATED_CHECK_DELAY; 321 opt->controlled_agent_want_nom_timeout = 322 ICE_CONTROLLED_AGENT_WAIT_NOMINATION_TIMEOUT; 323 } 298 324 299 325 /* … … 327 353 ice->tie_breaker.u32.lo = pj_rand(); 328 354 ice->prefs = cand_type_prefs; 355 pj_ice_sess_options_default(&ice->opt); 356 357 pj_timer_entry_init(&ice->timer, TIMER_NONE, (void*)ice, &on_timer); 329 358 330 359 pj_ansi_snprintf(ice->obj_name, sizeof(ice->obj_name), … … 346 375 comp = &ice->comp[i]; 347 376 comp->valid_check = NULL; 377 comp->nominated_check = NULL; 348 378 349 379 status = init_comp(ice, i+1, comp); … … 390 420 391 421 /* 422 * Get the value of various options of the ICE session. 423 */ 424 PJ_DEF(pj_status_t) pj_ice_sess_get_options(pj_ice_sess *ice, 425 pj_ice_sess_options *opt) 426 { 427 PJ_ASSERT_RETURN(ice, PJ_EINVAL); 428 pj_memcpy(opt, &ice->opt, sizeof(*opt)); 429 return PJ_SUCCESS; 430 } 431 432 /* 433 * Specify various options for this ICE session. 434 */ 435 PJ_DEF(pj_status_t) pj_ice_sess_set_options(pj_ice_sess *ice, 436 const pj_ice_sess_options *opt) 437 { 438 PJ_ASSERT_RETURN(ice && opt, PJ_EINVAL); 439 pj_memcpy(&ice->opt, opt, sizeof(*opt)); 440 LOG5((ice->obj_name, "ICE nomination type set to %s", 441 (ice->opt.aggressive ? "aggressive" : "regular"))); 442 return PJ_SUCCESS; 443 } 444 445 446 /* 392 447 * Destroy 393 448 */ … … 407 462 } 408 463 409 if (ice-> completion_timer.id) {464 if (ice->timer.id) { 410 465 pj_timer_heap_cancel(ice->stun_cfg.timer_heap, 411 &ice-> completion_timer);412 ice-> completion_timer.id = PJ_FALSE;466 &ice->timer); 467 ice->timer.id = PJ_FALSE; 413 468 } 414 469 … … 604 659 pj_uint32_t comp_id) 605 660 { 606 #if 0661 #if PJNATH_ICE_PRIO_STD 607 662 return ((ice->prefs[type] & 0xFF) << 24) + 608 663 ((local_pref & 0xFFFF) << 8) + … … 1040 1095 } 1041 1096 1042 /* Timer callback to call on_ice_complete() callback */ 1043 static void on_completion_timer(pj_timer_heap_t *th, 1044 pj_timer_entry *te) 1097 /* Timer callback */ 1098 static void on_timer(pj_timer_heap_t *th, pj_timer_entry *te) 1045 1099 { 1046 1100 pj_ice_sess *ice = (pj_ice_sess*) te->user_data; 1101 enum timer_type type = (enum timer_type)te->id; 1047 1102 1048 1103 PJ_UNUSED_ARG(th); 1049 1104 1050 te->id = PJ_FALSE; 1051 1052 if (ice->cb.on_ice_complete) 1053 (*ice->cb.on_ice_complete)(ice, ice->ice_status); 1105 pj_mutex_lock(ice->mutex); 1106 1107 te->id = TIMER_NONE; 1108 1109 switch (type) { 1110 case TIMER_CONTROLLED_WAIT_NOM: 1111 LOG4((ice->obj_name, 1112 "Controlled agent timed-out in waiting for the controlling " 1113 "agent to send nominated check. Setting state to fail now..")); 1114 on_ice_complete(ice, PJNATH_EICENOMTIMEOUT); 1115 break; 1116 case TIMER_COMPLETION_CALLBACK: 1117 /* Start keep-alive timer but don't send any packets yet. 1118 * Need to do it here just in case app destroy the session 1119 * in the callback. 1120 */ 1121 if (ice->ice_status == PJ_SUCCESS) 1122 ice_keep_alive(ice, PJ_FALSE); 1123 1124 /* Notify app about ICE completion*/ 1125 if (ice->cb.on_ice_complete) 1126 (*ice->cb.on_ice_complete)(ice, ice->ice_status); 1127 break; 1128 case TIMER_START_NOMINATED_CHECK: 1129 start_nominated_check(ice); 1130 break; 1131 case TIMER_KEEP_ALIVE: 1132 ice_keep_alive(ice, PJ_TRUE); 1133 break; 1134 case TIMER_NONE: 1135 /* Nothing to do, just to get rid of gcc warning */ 1136 break; 1137 } 1138 1139 pj_mutex_unlock(ice->mutex); 1140 } 1141 1142 /* Send keep-alive */ 1143 static void ice_keep_alive(pj_ice_sess *ice, pj_bool_t send_now) 1144 { 1145 if (send_now) { 1146 /* Send Binding Indication for the component */ 1147 pj_ice_sess_comp *comp = &ice->comp[ice->comp_ka]; 1148 pj_stun_tx_data *tdata; 1149 pj_ice_sess_check *the_check; 1150 pj_ice_msg_data *msg_data; 1151 int addr_len; 1152 pj_bool_t saved; 1153 pj_status_t status; 1154 1155 /* Must have nominated check by now */ 1156 pj_assert(comp->nominated_check != NULL); 1157 the_check = comp->nominated_check; 1158 1159 /* Create the Binding Indication */ 1160 status = pj_stun_session_create_ind(comp->stun_sess, 1161 PJ_STUN_BINDING_INDICATION, 1162 &tdata); 1163 if (status != PJ_SUCCESS) 1164 goto done; 1165 1166 /* Need the transport_id */ 1167 msg_data = PJ_POOL_ZALLOC_T(tdata->pool, pj_ice_msg_data); 1168 msg_data->transport_id = the_check->lcand->transport_id; 1169 1170 /* Temporarily disable FINGERPRINT. The Binding Indication 1171 * SHOULD NOT contain any attributes. 1172 */ 1173 saved = pj_stun_session_use_fingerprint(comp->stun_sess, PJ_FALSE); 1174 1175 /* Send to session */ 1176 addr_len = pj_sockaddr_get_len(&the_check->rcand->addr); 1177 status = pj_stun_session_send_msg(comp->stun_sess, msg_data, 1178 PJ_FALSE, PJ_FALSE, 1179 &the_check->rcand->addr, 1180 addr_len, tdata); 1181 1182 /* Restore FINGERPRINT usage */ 1183 pj_stun_session_use_fingerprint(comp->stun_sess, saved); 1184 1185 done: 1186 ice->comp_ka = (ice->comp_ka + 1) % ice->comp_cnt; 1187 } 1188 1189 if (ice->timer.id == TIMER_NONE) { 1190 pj_time_val delay = { 0, 0 }; 1191 1192 delay.msec = (PJ_ICE_SESS_KEEP_ALIVE_MIN + 1193 (pj_rand() % PJ_ICE_SESS_KEEP_ALIVE_MAX_RAND)) * 1000 / 1194 ice->comp_cnt; 1195 pj_time_val_normalize(&delay); 1196 1197 ice->timer.id = TIMER_KEEP_ALIVE; 1198 pj_timer_heap_schedule(ice->stun_cfg.timer_heap, &ice->timer, &delay); 1199 1200 } else { 1201 pj_assert(!"Not expected any timer active"); 1202 } 1054 1203 } 1055 1204 … … 1061 1210 ice->ice_status = status; 1062 1211 1212 if (ice->timer.id != TIMER_NONE) { 1213 pj_timer_heap_cancel(ice->stun_cfg.timer_heap, &ice->timer); 1214 ice->timer.id = TIMER_NONE; 1215 } 1216 1063 1217 /* Log message */ 1064 1218 LOG4((ice->obj_name, "ICE process complete, status=%s", … … 1072 1226 pj_time_val delay = {0, 0}; 1073 1227 1074 ice->completion_timer.cb = &on_completion_timer; 1075 ice->completion_timer.user_data = (void*) ice; 1076 ice->completion_timer.id = PJ_TRUE; 1077 1228 ice->timer.id = TIMER_COMPLETION_CALLBACK; 1078 1229 pj_timer_heap_schedule(ice->stun_cfg.timer_heap, 1079 &ice->completion_timer, 1080 &delay); 1081 } 1082 } 1083 } 1084 1230 &ice->timer, &delay); 1231 } 1232 } 1233 } 1234 1235 /* Update valid check and nominated check for the candidate */ 1236 static void update_comp_check(pj_ice_sess *ice, unsigned comp_id, 1237 pj_ice_sess_check *check) 1238 { 1239 pj_ice_sess_comp *comp; 1240 1241 comp = find_comp(ice, comp_id); 1242 if (comp->valid_check == NULL) { 1243 comp->valid_check = check; 1244 } else { 1245 if (CMP_CHECK_PRIO(comp->valid_check, check) < 0) 1246 comp->valid_check = check; 1247 } 1248 1249 if (check->nominated) { 1250 /* Update the nominated check for the component */ 1251 if (comp->nominated_check == NULL) { 1252 comp->nominated_check = check; 1253 } else { 1254 if (CMP_CHECK_PRIO(comp->nominated_check, check) < 0) 1255 comp->nominated_check = check; 1256 } 1257 } 1258 } 1085 1259 1086 1260 /* This function is called when one check completes */ … … 1088 1262 pj_ice_sess_check *check) 1089 1263 { 1264 pj_ice_sess_comp *comp; 1090 1265 unsigned i; 1091 1266 1092 1267 pj_assert(check->state >= PJ_ICE_SESS_CHECK_STATE_SUCCEEDED); 1268 1269 comp = find_comp(ice, check->lcand->comp_id); 1093 1270 1094 1271 /* 7.1.2.2.2. Updating Pair States … … 1105 1282 */ 1106 1283 if (check->err_code==PJ_SUCCESS) { 1284 1107 1285 for (i=0; i<ice->clist.count; ++i) { 1108 1286 pj_ice_sess_check *c = &ice->clist.checks[i]; … … 1113 1291 } 1114 1292 } 1293 1294 LOG5((ice->obj_name, "Check %d is successful%s", 1295 GET_CHECK_ID(&ice->clist, check), 1296 (check->nominated ? " and nominated" : ""))); 1297 1115 1298 } 1116 1299 … … 1137 1320 */ 1138 1321 if (check->err_code==PJ_SUCCESS && check->nominated) { 1139 pj_ice_sess_comp *comp;1140 1141 LOG5((ice->obj_name, "Check %d is successful and nominated",1142 GET_CHECK_ID(&ice->clist, check)));1143 1144 comp = find_comp(ice, check->lcand->comp_id);1145 1322 1146 1323 for (i=0; i<ice->clist.count; ++i) { … … 1179 1356 } 1180 1357 } 1181 }1182 1183 /* Update the nominated check for the component */1184 if (comp->valid_check == NULL) {1185 comp->valid_check = check;1186 } else {1187 if (CMP_CHECK_PRIO(comp->valid_check, check) < 0)1188 comp->valid_check = check;1189 1358 } 1190 1359 } … … 1212 1381 */ 1213 1382 for (i=0; i<ice->comp_cnt; ++i) { 1214 if (ice->comp[i]. valid_check == NULL)1383 if (ice->comp[i].nominated_check == NULL) 1215 1384 break; 1216 1385 } … … 1259 1428 * If agent's role is controlled, check if all components have 1260 1429 * valid pair. If it does, this means the controlled agent has 1261 * finished the check list earlyand it's waiting for controlling1262 * agent to send a checkwith USE-CANDIDATE flag set.1430 * finished the check list and it's waiting for controlling 1431 * agent to send checks with USE-CANDIDATE flag set. 1263 1432 */ 1264 1433 if (ice->role == PJ_ICE_SESS_ROLE_CONTROLLED) { 1265 unsigned comp_id; 1266 for (comp_id=1; comp_id <= ice->comp_cnt; ++comp_id) { 1267 unsigned j; 1268 for (j=0; j<ice->valid_list.count; ++j) { 1269 pj_ice_sess_check *vc = &ice->valid_list.checks[j]; 1270 if (vc->lcand->comp_id == comp_id) 1271 break; 1272 } 1273 if (j == ice->valid_list.count) 1434 for (i=0; i < ice->comp_cnt; ++i) { 1435 if (ice->comp[i].valid_check == NULL) 1274 1436 break; 1275 1437 } 1276 1438 1277 if ( comp_id <=ice->comp_cnt) {1439 if (i < ice->comp_cnt) { 1278 1440 /* This component ID doesn't have valid pair. 1279 1441 * Mark ICE as failed. … … 1285 1447 * We should wait until we receive nominated checks. 1286 1448 */ 1449 if (ice->timer.id == TIMER_NONE && 1450 ice->opt.controlled_agent_want_nom_timeout >= 0) 1451 { 1452 pj_time_val delay; 1453 1454 delay.sec = 0; 1455 delay.msec = ice->opt.controlled_agent_want_nom_timeout; 1456 pj_time_val_normalize(&delay); 1457 1458 ice->timer.id = TIMER_CONTROLLED_WAIT_NOM; 1459 pj_timer_heap_schedule(ice->stun_cfg.timer_heap, 1460 &ice->timer, 1461 &delay); 1462 1463 LOG5((ice->obj_name, 1464 "All checks have completed. Controlled agent now " 1465 "waits for nomination from controlling agent " 1466 "(timeout=%d msec)", 1467 ice->opt.controlled_agent_want_nom_timeout)); 1468 } 1287 1469 return PJ_FALSE; 1288 1470 } 1289 } 1290 1291 on_ice_complete(ice, PJNATH_EICEFAILED); 1292 return PJ_TRUE; 1471 1472 /* Unreached */ 1473 1474 } else if (ice->is_nominating) { 1475 /* We are controlling agent and all checks have completed but 1476 * there's at least one component without nominated pair (or 1477 * more likely we don't have any nominated pairs at all). 1478 */ 1479 on_ice_complete(ice, PJNATH_EICEFAILED); 1480 return PJ_TRUE; 1481 1482 } else { 1483 /* We are controlling agent and all checks have completed. If 1484 * we have valid list for every component, then move on to 1485 * sending nominated check, otherwise we have failed. 1486 */ 1487 for (i=0; i<ice->comp_cnt; ++i) { 1488 if (ice->comp[i].valid_check == NULL) 1489 break; 1490 } 1491 1492 if (i < ice->comp_cnt) { 1493 /* At least one component doesn't have a valid check. Mark 1494 * ICE as failed. 1495 */ 1496 on_ice_complete(ice, PJNATH_EICEFAILED); 1497 return PJ_TRUE; 1498 } 1499 1500 /* Now it's time to send connectivity check with nomination 1501 * flag set. 1502 */ 1503 LOG4((ice->obj_name, 1504 "All checks have completed, starting nominated checks now")); 1505 start_nominated_check(ice); 1506 return PJ_FALSE; 1507 } 1508 } 1509 1510 /* If this connectivity check has been successful, scan all components 1511 * and see if they have a valid pair, if we are controlling and we haven't 1512 * started our nominated check yet. 1513 */ 1514 if (check->err_code == PJ_SUCCESS && 1515 ice->role==PJ_ICE_SESS_ROLE_CONTROLLING && 1516 !ice->is_nominating && 1517 ice->timer.id == TIMER_NONE) 1518 { 1519 pj_time_val delay; 1520 1521 for (i=0; i<ice->comp_cnt; ++i) { 1522 if (ice->comp[i].valid_check == NULL) 1523 break; 1524 } 1525 1526 if (i < ice->comp_cnt) { 1527 /* Some components still don't have valid pair, continue 1528 * processing. 1529 */ 1530 return PJ_FALSE; 1531 } 1532 1533 LOG4((ice->obj_name, 1534 "Scheduling nominated check in %d ms", 1535 ice->opt.nominated_check_delay)); 1536 1537 if (ice->timer.id != TIMER_NONE) { 1538 pj_timer_heap_cancel(ice->stun_cfg.timer_heap, &ice->timer); 1539 ice->timer.id = TIMER_NONE; 1540 } 1541 1542 /* All components have valid pair. Let connectivity checks run for 1543 * a little bit more time, then start our nominated check. 1544 */ 1545 delay.sec = 0; 1546 delay.msec = ice->opt.nominated_check_delay; 1547 pj_time_val_normalize(&delay); 1548 1549 ice->timer.id = TIMER_START_NOMINATED_CHECK; 1550 pj_timer_heap_schedule(ice->stun_cfg.timer_heap, &ice->timer, &delay); 1551 return PJ_FALSE; 1293 1552 } 1294 1553 … … 1296 1555 return PJ_FALSE; 1297 1556 } 1298 1299 1557 1300 1558 … … 1431 1689 } 1432 1690 1433 /* Perform check on the specified candidate pair */1691 /* Perform check on the specified candidate pair. */ 1434 1692 static pj_status_t perform_check(pj_ice_sess *ice, 1435 1693 pj_ice_sess_checklist *clist, 1436 unsigned check_id) 1694 unsigned check_id, 1695 pj_bool_t nominate) 1437 1696 { 1438 1697 pj_ice_sess_comp *comp; … … 1473 1732 1474 1733 /* Add PRIORITY */ 1734 #if PJNATH_ICE_PRIO_STD 1735 prio = CALC_CAND_PRIO(ice, PJ_ICE_CAND_TYPE_PRFLX, 65535, 1736 lcand->comp_id); 1737 #else 1475 1738 prio = CALC_CAND_PRIO(ice, PJ_ICE_CAND_TYPE_PRFLX, 0, 1476 1739 lcand->comp_id); 1740 #endif 1477 1741 pj_stun_msg_add_uint_attr(check->tdata->pool, check->tdata->msg, 1478 1742 PJ_STUN_ATTR_PRIORITY, prio); … … 1482 1746 */ 1483 1747 if (ice->role == PJ_ICE_SESS_ROLE_CONTROLLING) { 1484 pj_stun_msg_add_empty_attr(check->tdata->pool, check->tdata->msg, 1485 PJ_STUN_ATTR_USE_CANDIDATE); 1486 check->nominated = PJ_TRUE; 1748 if (nominate) { 1749 pj_stun_msg_add_empty_attr(check->tdata->pool, check->tdata->msg, 1750 PJ_STUN_ATTR_USE_CANDIDATE); 1751 check->nominated = PJ_TRUE; 1752 } 1487 1753 1488 1754 pj_stun_msg_add_uint64_attr(check->tdata->pool, check->tdata->msg, … … 1550 1816 1551 1817 if (check->state == PJ_ICE_SESS_CHECK_STATE_WAITING) { 1552 status = perform_check(ice, clist, i );1818 status = perform_check(ice, clist, i, ice->is_nominating); 1553 1819 if (status != PJ_SUCCESS) { 1554 1820 pj_mutex_unlock(ice->mutex); … … 1569 1835 1570 1836 if (check->state == PJ_ICE_SESS_CHECK_STATE_FROZEN) { 1571 status = perform_check(ice, clist, i );1837 status = perform_check(ice, clist, i, ice->is_nominating); 1572 1838 if (status != PJ_SUCCESS) { 1573 1839 pj_mutex_unlock(ice->mutex); … … 1596 1862 } 1597 1863 1864 1865 /* Start sending connectivity check with USE-CANDIDATE */ 1866 static void start_nominated_check(pj_ice_sess *ice) 1867 { 1868 pj_time_val delay; 1869 unsigned i; 1870 pj_status_t status; 1871 1872 LOG4((ice->obj_name, "Starting nominated check..")); 1873 1874 pj_assert(ice->is_nominating == PJ_FALSE); 1875 1876 /* Stop our timer if it's active */ 1877 if (ice->timer.id == TIMER_START_NOMINATED_CHECK) { 1878 pj_timer_heap_cancel(ice->stun_cfg.timer_heap, &ice->timer); 1879 ice->timer.id = TIMER_NONE; 1880 } 1881 1882 /* For each component, set the check state of valid check with 1883 * highest priority to Waiting (it should have Success state now). 1884 */ 1885 for (i=0; i<ice->comp_cnt; ++i) { 1886 unsigned j; 1887 const pj_ice_sess_check *vc = ice->comp[i].valid_check; 1888 1889 pj_assert(ice->comp[i].nominated_check == NULL); 1890 pj_assert(vc->err_code == PJ_SUCCESS); 1891 1892 for (j=0; j<ice->clist.count; ++j) { 1893 pj_ice_sess_check *c = &ice->clist.checks[j]; 1894 if (c->lcand->transport_id == vc->lcand->transport_id && 1895 c->rcand == vc->rcand) 1896 { 1897 pj_assert(c->err_code == PJ_SUCCESS); 1898 c->state = PJ_ICE_SESS_CHECK_STATE_FROZEN; 1899 check_set_state(ice, c, PJ_ICE_SESS_CHECK_STATE_WAITING, 1900 PJ_SUCCESS); 1901 break; 1902 } 1903 } 1904 } 1905 1906 /* And (re)start the periodic check */ 1907 if (!ice->clist.timer.id) { 1908 pj_timer_heap_cancel(ice->stun_cfg.timer_heap, &ice->clist.timer); 1909 ice->clist.timer.id = PJ_FALSE; 1910 } 1911 1912 ice->clist.timer.id = PJ_TRUE; 1913 delay.sec = delay.msec = 0; 1914 status = pj_timer_heap_schedule(ice->stun_cfg.timer_heap, 1915 &ice->clist.timer, &delay); 1916 if (status != PJ_SUCCESS) { 1917 ice->clist.timer.id = PJ_FALSE; 1918 } else { 1919 LOG5((ice->obj_name, "Periodic timer rescheduled..")); 1920 } 1921 1922 ice->is_nominating = PJ_TRUE; 1923 } 1598 1924 1599 1925 /* Timer callback to perform periodic check */ … … 1642 1968 1643 1969 LOG4((ice->obj_name, "Starting ICE check..")); 1970 1971 /* If we are using aggressive nomination, set the is_nominating state */ 1972 if (ice->opt.aggressive) 1973 ice->is_nominating = PJ_TRUE; 1644 1974 1645 1975 /* The agent examines the check list for the first media stream (a … … 1827 2157 LOG4((ice->obj_name, "Resending check because of role conflict")); 1828 2158 check_set_state(ice, check, PJ_ICE_SESS_CHECK_STATE_WAITING, 0); 1829 perform_check(ice, clist, msg_data->data.req.ckid); 2159 perform_check(ice, clist, msg_data->data.req.ckid, 2160 check->nominated || ice->is_nominating); 1830 2161 pj_mutex_unlock(ice->mutex); 1831 2162 return; … … 1960 2291 */ 1961 2292 1962 /* Add pair to valid list */ 1963 pj_assert(ice->valid_list.count < PJ_ICE_MAX_CHECKS); 1964 new_check = &ice->valid_list.checks[ice->valid_list.count++]; 1965 new_check->lcand = lcand; 1966 new_check->rcand = check->rcand; 1967 new_check->prio = CALC_CHECK_PRIO(ice, lcand, check->rcand); 1968 new_check->state = PJ_ICE_SESS_CHECK_STATE_SUCCEEDED; 1969 new_check->nominated = check->nominated; 1970 new_check->err_code = PJ_SUCCESS; 2293 /* Add pair to valid list, if it's not there, otherwise just update 2294 * nominated flag 2295 */ 2296 for (i=0; i<ice->valid_list.count; ++i) { 2297 if (ice->valid_list.checks[i].lcand == lcand && 2298 ice->valid_list.checks[i].rcand == check->rcand) 2299 break; 2300 } 2301 2302 if (i==ice->valid_list.count) { 2303 pj_assert(ice->valid_list.count < PJ_ICE_MAX_CHECKS); 2304 new_check = &ice->valid_list.checks[ice->valid_list.count++]; 2305 new_check->lcand = lcand; 2306 new_check->rcand = check->rcand; 2307 new_check->prio = CALC_CHECK_PRIO(ice, lcand, check->rcand); 2308 new_check->state = PJ_ICE_SESS_CHECK_STATE_SUCCEEDED; 2309 new_check->nominated = check->nominated; 2310 new_check->err_code = PJ_SUCCESS; 2311 } else { 2312 new_check = &ice->valid_list.checks[i]; 2313 ice->valid_list.checks[i].nominated = check->nominated; 2314 } 1971 2315 1972 2316 /* Sort valid_list */ 1973 2317 sort_checklist(&ice->valid_list); 1974 2318 2319 /* Update valid check and nominated check for the component */ 2320 update_comp_check(ice, new_check->lcand->comp_id, new_check); 1975 2321 1976 2322 /* 7.1.2.2.2. Updating Pair States … … 2313 2659 c->state == PJ_ICE_SESS_CHECK_STATE_WAITING) 2314 2660 { 2661 /* See if we shall nominate this check */ 2662 pj_bool_t nominate = (c->nominated || ice->is_nominating); 2663 2315 2664 LOG5((ice->obj_name, "Performing triggered check for check %d",i)); 2316 perform_check(ice, &ice->clist, i );2665 perform_check(ice, &ice->clist, i, nominate); 2317 2666 2318 2667 } else if (c->state == PJ_ICE_SESS_CHECK_STATE_IN_PROGRESS) { … … 2337 2686 for (j=0; j<ice->valid_list.count; ++j) { 2338 2687 pj_ice_sess_check *vc = &ice->valid_list.checks[j]; 2339 if (vc->lcand == c->lcand && vc->rcand == c->rcand) { 2688 if (vc->lcand->transport_id == c->lcand->transport_id && 2689 vc->rcand == c->rcand) 2690 { 2691 /* Set nominated flag */ 2340 2692 vc->nominated = PJ_TRUE; 2693 2694 /* Update valid check and nominated check for the component */ 2695 update_comp_check(ice, vc->lcand->comp_id, vc); 2696 2697 dump_check(ice->tmp.txt, sizeof(ice->tmp.txt), &ice->valid_list, vc); 2698 LOG5((ice->obj_name, "Valid check %s is nominated", ice->tmp.txt)); 2341 2699 } 2342 2700 } … … 2362 2720 2363 2721 pj_ice_sess_check *c = &ice->clist.checks[ice->clist.count]; 2722 pj_bool_t nominate; 2364 2723 2365 2724 c->lcand = lcand; … … 2370 2729 c->err_code = PJ_SUCCESS; 2371 2730 2731 nominate = (c->nominated || ice->is_nominating); 2732 2372 2733 LOG4((ice->obj_name, "New triggered check added: %d", 2373 2734 ice->clist.count)); 2374 perform_check(ice, &ice->clist, ice->clist.count++ );2735 perform_check(ice, &ice->clist, ice->clist.count++, nominate); 2375 2736 2376 2737 } else { … … 2389 2750 unsigned src_addr_len) 2390 2751 { 2752 struct stun_data *sd; 2753 2391 2754 PJ_UNUSED_ARG(sess); 2392 2755 PJ_UNUSED_ARG(pkt); … … 2397 2760 PJ_UNUSED_ARG(src_addr_len); 2398 2761 2399 PJ_TODO(SUPPORT_RX_BIND_REQUEST_AS_INDICATION); 2400 2401 return PJ_ENOTSUP; 2762 sd = (struct stun_data*) pj_stun_session_get_user_data(sess); 2763 2764 if (msg->hdr.type == PJ_STUN_BINDING_INDICATION) { 2765 LOG5((sd->ice->obj_name, "Received Binding Indication keep-alive " 2766 "for component %d", sd->comp_id)); 2767 } else { 2768 LOG4((sd->ice->obj_name, "Received unexpected %s indication " 2769 "for component %d", pj_stun_get_method_name(msg->hdr.type), 2770 sd->comp_id)); 2771 } 2772 2773 return PJ_SUCCESS; 2402 2774 } 2403 2775
Note: See TracChangeset
for help on using the changeset viewer.