- Timestamp:
- May 29, 2009 1:04:03 PM (16 years ago)
- Location:
- pjproject/trunk
- Files:
-
- 34 edited
Legend:
- Unmodified
- Added
- Removed
-
pjproject/trunk/pjlib-util/src/pjlib-util/resolver.c
r2394 r2724 29 29 #include <pj/pool.h> 30 30 #include <pj/pool_buf.h> 31 #include <pj/rand.h> 31 32 #include <pj/string.h> 32 33 #include <pj/sock.h> … … 784 785 785 786 /* Save the ID and key */ 787 /* TODO: dnsext-forgery-resilient: randomize id for security */ 786 788 q->id = resolver->last_id++; 787 789 if (resolver->last_id == 0) -
pjproject/trunk/pjmedia/src/pjmedia-codec/ipp_codecs.c
r2573 r2724 234 234 { 235 235 # if PJMEDIA_HAS_INTEL_IPP_CODEC_AMR 236 /* AMR-NB SID seems to produce noise, so let's just disable its VAD. */ 236 237 {1, "AMR", PJMEDIA_RTP_PT_AMR, &USC_GSMAMR_Fxns, 8000, 1, 160, 237 5900, 12200, 4, 1, 1,238 &predecode_amr, &parse_amr, &pack_amr 239 /*, {1, {{{"octet-align", 11}, {"1", 1}}} } */238 7400, 12200, 2, 0, 1, 239 &predecode_amr, &parse_amr, &pack_amr, 240 {1, {{{"octet-align", 11}, {"1", 1}}} } 240 241 }, 241 242 # endif … … 244 245 {1, "AMR-WB", PJMEDIA_RTP_PT_AMRWB, &USC_AMRWB_Fxns, 16000, 1, 320, 245 246 15850, 23850, 1, 1, 1, 246 &predecode_amr, &parse_amr, &pack_amr 247 &predecode_amr, &parse_amr, &pack_amr, 248 {1, {{{"octet-align", 11}, {"1", 1}}} } 247 249 }, 248 250 # endif … … 561 563 /* Check Change Mode Request. */ 562 564 if ((setting->amr_nb && cmr <= 7) || (!setting->amr_nb && cmr <= 8)) { 565 struct ipp_codec *ippc = &ipp_codec[codec_data->codec_idx]; 566 563 567 s->enc_mode = cmr; 568 codec_data->info->params.modes.bitrate = s->enc_setting.amr_nb? 569 pjmedia_codec_amrnb_bitrates[s->enc_mode] : 570 pjmedia_codec_amrwb_bitrates[s->enc_mode]; 571 ippc->fxns->std.Control(&codec_data->info->params.modes, 572 codec_data->enc); 564 573 } 565 574 … … 1034 1043 1035 1044 /* Not sure if VAD affects decoder, just try to be safe */ 1036 codec_data->info->params.modes.vad = ippc->has_native_vad;1045 //codec_data->info->params.modes.vad = ippc->has_native_vad; 1037 1046 1038 1047 /* Get number of memory blocks needed by the decoder */ … … 1085 1094 amr_settings_t *s; 1086 1095 pj_uint8_t octet_align = 0; 1087 const pj_str_t STR_FMTP_OCTET_ALIGN = {"octet-align", 11}; 1088 1089 /* Check octet-align */ 1096 pj_int8_t enc_mode = -1; 1097 1098 /* Check AMR specific attributes */ 1099 1090 1100 for (i = 0; i < attr->setting.dec_fmtp.cnt; ++i) { 1101 /* octet-align, one of the parameters that must have same value 1102 * in offer & answer (RFC 4867 Section 8.3.1). Just check fmtp 1103 * in the decoder side, since it's value is guaranteed to fulfil 1104 * above requirement (by SDP negotiator). 1105 */ 1106 const pj_str_t STR_FMTP_OCTET_ALIGN = {"octet-align", 11}; 1107 1091 1108 if (pj_stricmp(&attr->setting.dec_fmtp.param[i].name, 1092 1109 &STR_FMTP_OCTET_ALIGN) == 0) 1093 1110 { 1094 1111 octet_align=(pj_uint8_t) 1095 (pj_strtoul(&attr->setting.dec_fmtp.param[i].val));1112 pj_strtoul(&attr->setting.dec_fmtp.param[i].val); 1096 1113 break; 1097 1114 } 1098 1115 } 1099 1116 for (i = 0; i < attr->setting.enc_fmtp.cnt; ++i) { 1117 /* mode-set */ 1118 const pj_str_t STR_FMTP_MODE_SET = {"mode-set", 8}; 1119 1120 if (pj_stricmp(&attr->setting.enc_fmtp.param[i].name, 1121 &STR_FMTP_MODE_SET) == 0) 1122 { 1123 pj_int8_t tmp; 1124 1125 /* Just get the first value. */ 1126 tmp = (pj_int8_t) 1127 pj_strtoul(&attr->setting.enc_fmtp.param[i].val); 1128 1129 if ((ippc->pt == PJMEDIA_RTP_PT_AMR && tmp > 0 && tmp < 8) || 1130 (ippc->pt == PJMEDIA_RTP_PT_AMRWB && tmp > 0 && tmp < 9)) 1131 { 1132 enc_mode = tmp; 1133 PJ_LOG(4,(THIS_FILE, "Remote specifies AMR mode-set attr, " 1134 "selected: %d", enc_mode)); 1135 } 1136 break; 1137 } 1138 } 1139 1140 /* Initialize AMR specific settings */ 1100 1141 s = PJ_POOL_ZALLOC_T(pool, amr_settings_t); 1101 1142 codec_data->codec_setting = s; 1102 1103 s->enc_mode = pjmedia_codec_amr_get_mode(ippc->def_bitrate);1104 if (s->enc_mode < 0)1105 goto on_error;1106 1143 1107 1144 s->enc_setting.amr_nb = (pj_uint8_t)(ippc->pt == PJMEDIA_RTP_PT_AMR); … … 1109 1146 s->enc_setting.reorder = PJ_TRUE; 1110 1147 s->enc_setting.cmr = 15; 1111 1148 1112 1149 s->dec_setting.amr_nb = (pj_uint8_t)(ippc->pt == PJMEDIA_RTP_PT_AMR); 1113 1150 s->dec_setting.octet_aligned = octet_align; 1114 1151 s->dec_setting.reorder = PJ_TRUE; 1152 1153 s->enc_mode = pjmedia_codec_amr_get_mode( 1154 codec_data->info->params.modes.bitrate); 1155 if (s->enc_mode < 0) 1156 goto on_error; 1157 1158 if (enc_mode != -1) { 1159 s->enc_mode = enc_mode; 1160 1161 /* Apply requested encoder bitrate */ 1162 codec_data->info->params.modes.bitrate = s->enc_setting.amr_nb? 1163 pjmedia_codec_amrnb_bitrates[s->enc_mode] : 1164 pjmedia_codec_amrwb_bitrates[s->enc_mode]; 1165 ippc->fxns->std.Control(&codec_data->info->params.modes, 1166 codec_data->enc); 1167 } 1168 1115 1169 } 1116 1170 #endif -
pjproject/trunk/pjmedia/src/pjmedia/conf_switch.c
r2581 r2724 554 554 } 555 555 556 /* Check if sink is listening to other ports */ 556 /* If sink is currently listening to other ports, it needs to be released 557 * first before the new connection made. 558 */ 557 559 if (dst_port->transmitter_cnt > 0) { 558 pj_mutex_unlock(conf->mutex); 559 return PJ_ETOOMANYCONN; 560 unsigned j; 561 pj_bool_t transmitter_found = PJ_FALSE; 562 563 pj_assert(dst_port->transmitter_cnt == 1); 564 for (j=0; j<conf->max_ports && !transmitter_found; ++j) { 565 if (conf->ports[j]) { 566 unsigned k; 567 568 for (k=0; k < conf->ports[j]->listener_cnt; ++k) { 569 if (conf->ports[j]->listener_slots[k] == sink_slot) { 570 PJ_LOG(4,(THIS_FILE, "Connection [%d->%d] is " 571 "disconnected forcedly for the new " 572 "connection [%d->%d]", 573 j, sink_slot, src_slot, sink_slot)); 574 pjmedia_conf_disconnect_port(conf, j, sink_slot); 575 transmitter_found = PJ_TRUE; 576 break; 577 } 578 } 579 } 580 } 581 pj_assert(dst_port->transmitter_cnt == 0); 560 582 } 561 583 -
pjproject/trunk/pjmedia/src/pjmedia/sdp_neg.c
r2643 r2724 866 866 { 867 867 /* Further check for G7221, negotiate bitrate. */ 868 if (pj_str cmp2(&or_.enc_name, "G7221") == 0) {868 if (pj_stricmp2(&or_.enc_name, "G7221") == 0) { 869 869 if (match_g7221(offer, i, answer, j)) 870 870 break; 871 871 } else 872 872 /* Further check for AMR, negotiate fmtp. */ 873 if (pj_strcmp2(&or_.enc_name, "AMR") == 0) { 873 if (pj_stricmp2(&or_.enc_name, "AMR") == 0 || 874 pj_stricmp2(&or_.enc_name, "AMR-WB") == 0) 875 { 874 876 if (match_amr(offer, i, answer, j, PJ_FALSE, 875 877 NULL)) … … 1071 1073 pjmedia_sdp_attr_get_rtpmap(a, &or_); 1072 1074 1073 if (!pj_str cmp2(&or_.enc_name, "telephone-event")) {1075 if (!pj_stricmp2(&or_.enc_name, "telephone-event")) { 1074 1076 master_has_telephone_event = 1; 1075 1077 if (found_matching_telephone_event) … … 1098 1100 if (!pj_stricmp(&or_.enc_name, &lr.enc_name) && 1099 1101 or_.clock_rate == lr.clock_rate && 1100 (pj_str cmp(&or_.param, &lr.param)==0 ||1102 (pj_stricmp(&or_.param, &lr.param)==0 || 1101 1103 (or_.param.slen==1 && *or_.param.ptr=='1'))) 1102 1104 { … … 1104 1106 if (is_codec) { 1105 1107 /* Further check for G7221, negotiate bitrate */ 1106 if (pj_str cmp2(&or_.enc_name, "G7221") == 0 &&1108 if (pj_stricmp2(&or_.enc_name, "G7221") == 0 && 1107 1109 !match_g7221(master, i, slave, j)) 1108 1110 { … … 1110 1112 } else 1111 1113 /* Further check for AMR, negotiate fmtp */ 1112 if (pj_strcmp2(&or_.enc_name, "AMR")==0) { 1114 if (pj_stricmp2(&or_.enc_name, "AMR")==0 || 1115 pj_stricmp2(&or_.enc_name, "AMR-WB")==0) 1116 { 1113 1117 unsigned o_med_idx, a_med_idx; 1114 1118 -
pjproject/trunk/pjmedia/src/pjmedia/tonegen.c
r2394 r2724 385 385 { '1', 697, 1209 }, 386 386 { '2', 697, 1336 }, 387 { '3', 697, 14 47 },387 { '3', 697, 1477 }, 388 388 { '4', 770, 1209 }, 389 389 { '5', 770, 1336 }, 390 { '6', 770, 14 47 },390 { '6', 770, 1477 }, 391 391 { '7', 852, 1209 }, 392 392 { '8', 852, 1336 }, 393 { '9', 852, 14 47 },393 { '9', 852, 1477 }, 394 394 { 'a', 697, 1633 }, 395 395 { 'b', 770, 1633 }, -
pjproject/trunk/pjnath/include/pjnath/config.h
r2642 r2724 260 260 #define PJ_ICE_MAX_COMP (2<<PJ_ICE_COMP_BITS) 261 261 262 /** 263 * Use the priority value according to the ice-draft. 264 */ 265 #ifndef PJNATH_ICE_PRIO_STD 266 # define PJNATH_ICE_PRIO_STD 1 267 #endif 268 262 269 263 270 /** … … 265 272 */ 266 273 #ifndef PJ_ICE_CAND_TYPE_PREF_BITS 267 # define PJ_ICE_CAND_TYPE_PREF_BITS 2 274 # if PJNATH_ICE_PRIO_STD 275 # define PJ_ICE_CAND_TYPE_PREF_BITS 8 276 # else 277 # define PJ_ICE_CAND_TYPE_PREF_BITS 2 278 # endif 268 279 #endif 269 280 … … 325 336 326 337 /** 338 * For a controlled agent, specify how long it wants to wait (in milliseconds) 339 * for the controlling agent to complete sending connectivity check with 340 * nominated flag set to true for all components after the controlled agent 341 * has found that all connectivity checks in its checklist have been completed 342 * and there is at least one successful (but not nominated) check for every 343 * component. 344 * 345 * When selecting the value, bear in mind that the connectivity check from 346 * controlling agent may be delayed because of delay in receiving SDP answer 347 * from the controlled agent. 348 * 349 * Application may set this value to -1 to disable this timer. 350 * 351 * Default: 10000 (milliseconds) 352 */ 353 #ifndef ICE_CONTROLLED_AGENT_WAIT_NOMINATION_TIMEOUT 354 # define ICE_CONTROLLED_AGENT_WAIT_NOMINATION_TIMEOUT 10000 355 #endif 356 357 358 /** 359 * For controlling agent if it uses regular nomination, specify the delay to 360 * perform nominated check (connectivity check with USE-CANDIDATE attribute) 361 * after all components have a valid pair. 362 * 363 * Default: 4*PJ_STUN_RTO_VALUE (milliseconds) 364 */ 365 #ifndef PJ_ICE_NOMINATED_CHECK_DELAY 366 # define PJ_ICE_NOMINATED_CHECK_DELAY (4*PJ_STUN_RTO_VALUE) 367 #endif 368 369 370 /** 327 371 * Minimum interval value to be used for sending STUN keep-alive on the ICE 328 * s tream transport, in seconds. This minimum interval, plus a random value329 * which maximum is PJ_ICE_S T_KEEP_ALIVE_MAX_RAND, specify the actual interval372 * session, in seconds. This minimum interval, plus a random value 373 * which maximum is PJ_ICE_SESS_KEEP_ALIVE_MAX_RAND, specify the actual interval 330 374 * of the STUN keep-alive. 331 375 * 332 * Default: 20 seconds 333 * 334 * @see PJ_ICE_ST_KEEP_ALIVE_MAX_RAND 335 */ 336 #ifndef PJ_ICE_ST_KEEP_ALIVE_MIN 337 # define PJ_ICE_ST_KEEP_ALIVE_MIN 20 338 #endif 339 376 * Default: 15 seconds 377 * 378 * @see PJ_ICE_SESS_KEEP_ALIVE_MAX_RAND 379 */ 380 #ifndef PJ_ICE_SESS_KEEP_ALIVE_MIN 381 # define PJ_ICE_SESS_KEEP_ALIVE_MIN 20 382 #endif 383 384 /* Warn about deprecated macro */ 385 #ifdef PJ_ICE_ST_KEEP_ALIVE_MIN 386 # error PJ_ICE_ST_KEEP_ALIVE_MIN is deprecated 387 #endif 340 388 341 389 /** 342 390 * To prevent STUN keep-alives to be sent simultaneously, application should 343 * add random interval to minimum interval (PJ_ICE_S T_KEEP_ALIVE_MIN). This391 * add random interval to minimum interval (PJ_ICE_SESS_KEEP_ALIVE_MIN). This 344 392 * setting specifies the maximum random value to be added to the minimum 345 393 * interval, in seconds. … … 347 395 * Default: 5 seconds 348 396 * 349 * @see PJ_ICE_ST_KEEP_ALIVE_MIN 350 */ 351 #ifndef PJ_ICE_ST_KEEP_ALIVE_MAX_RAND 352 # define PJ_ICE_ST_KEEP_ALIVE_MAX_RAND 5 397 * @see PJ_ICE_SESS_KEEP_ALIVE_MIN 398 */ 399 #ifndef PJ_ICE_SESS_KEEP_ALIVE_MAX_RAND 400 # define PJ_ICE_SESS_KEEP_ALIVE_MAX_RAND 5 401 #endif 402 403 /* Warn about deprecated macro */ 404 #ifdef PJ_ICE_ST_KEEP_ALIVE_MAX_RAND 405 # error PJ_ICE_ST_KEEP_ALIVE_MAX_RAND is deprecated 353 406 #endif 354 407 -
pjproject/trunk/pjnath/include/pjnath/errno.h
r2642 r2724 197 197 */ 198 198 #define PJNATH_EICENOHOSTCAND (PJNATH_ERRNO_START+92) /* 370092 */ 199 199 /** 200 * @hideinitializer 201 * Controlled agent timed-out in waiting for the controlling agent to 202 * send nominated check after all connectivity checks have completed. 203 */ 204 #define PJNATH_EICENOMTIMEOUT (PJNATH_ERRNO_START+93) /* 370093 */ 200 205 201 206 /************************************************************ -
pjproject/trunk/pjnath/include/pjnath/ice_session.h
r2642 r2724 177 177 { 178 178 /** 179 * The pointer to ICE check which was nominated for this component.180 * The value will be NULL if a nominated check has not been found181 * for this component.179 * Pointer to ICE check with highest priority which connectivity check 180 * has been successful. The value will be NULL if a no successful check 181 * has not been found for this component. 182 182 */ 183 183 pj_ice_sess_check *valid_check; 184 185 /** 186 * Pointer to ICE check with highest priority which connectivity check 187 * has been successful and it has been nominated. The value may be NULL 188 * if there is no such check yet. 189 */ 190 pj_ice_sess_check *nominated_check; 184 191 185 192 /** … … 554 561 555 562 /** 563 * This structure describes various ICE session options. Application 564 * configure the ICE session with these options by calling 565 * #pj_ice_sess_set_options(). 566 */ 567 typedef struct pj_ice_sess_options 568 { 569 /** 570 * Specify whether to use aggressive nomination. 571 */ 572 pj_bool_t aggressive; 573 574 /** 575 * For controlling agent if it uses regular nomination, specify the delay 576 * to perform nominated check (connectivity check with USE-CANDIDATE 577 * attribute) after all components have a valid pair. 578 * 579 * Default value is PJ_ICE_NOMINATED_CHECK_DELAY. 580 */ 581 unsigned nominated_check_delay; 582 583 /** 584 * For a controlled agent, specify how long it wants to wait (in 585 * milliseconds) for the controlling agent to complete sending 586 * connectivity check with nominated flag set to true for all components 587 * after the controlled agent has found that all connectivity checks in 588 * its checklist have been completed and there is at least one successful 589 * (but not nominated) check for every component. 590 * 591 * Default value for this option is 592 * ICE_CONTROLLED_AGENT_WAIT_NOMINATION_TIMEOUT. Specify -1 to disable 593 * this timer. 594 */ 595 int controlled_agent_want_nom_timeout; 596 597 } pj_ice_sess_options; 598 599 600 /** 556 601 * This structure describes the ICE session. For this version of PJNATH, 557 602 * an ICE session corresponds to a single media stream (unlike the ICE … … 570 615 pj_mutex_t *mutex; /**< Mutex. */ 571 616 pj_ice_sess_role role; /**< ICE role. */ 617 pj_ice_sess_options opt; /**< Options */ 572 618 pj_timestamp tie_breaker; /**< Tie breaker value */ 573 619 pj_uint8_t *prefs; /**< Type preference. */ 620 pj_bool_t is_nominating; /**< Nominating stage */ 574 621 pj_bool_t is_complete; /**< Complete? */ 575 622 pj_status_t ice_status; /**< Error status. */ 576 pj_timer_entry completion_timer; /**< To call callback.*/623 pj_timer_entry timer; /**< ICE timer. */ 577 624 pj_ice_sess_cb cb; /**< Callback. */ 578 625 … … 590 637 unsigned comp_cnt; /**< # of components. */ 591 638 pj_ice_sess_comp comp[PJ_ICE_MAX_COMP]; /**< Component array */ 639 unsigned comp_ka; /**< Next comp for KA */ 592 640 593 641 /* Local candidates */ … … 655 703 const pj_sockaddr *base_addr); 656 704 705 /** 706 * Initialize ICE session options with library default values. 707 * 708 * @param opt ICE session options. 709 */ 710 PJ_DECL(void) pj_ice_sess_options_default(pj_ice_sess_options *opt); 657 711 658 712 /** … … 690 744 691 745 /** 746 * Get the value of various options of the ICE session. 747 * 748 * @param ice The ICE session. 749 * @param opt The options to be initialized with the values 750 * from the ICE session. 751 * 752 * @return PJ_SUCCESS on success, or the appropriate error. 753 */ 754 PJ_DECL(pj_status_t) pj_ice_sess_get_options(pj_ice_sess *ice, 755 pj_ice_sess_options *opt); 756 757 /** 758 * Specify various options for this ICE session. Application MUST only 759 * call this function after the ICE session has been created but before 760 * any connectivity check is started. 761 * 762 * Application should call #pj_ice_sess_get_options() to initialize the 763 * options with their default values. 764 * 765 * @param ice The ICE session. 766 * @param opt Options to be applied to the ICE session. 767 * 768 * @return PJ_SUCCESS on success, or the appropriate error. 769 */ 770 PJ_DECL(pj_status_t) pj_ice_sess_set_options(pj_ice_sess *ice, 771 const pj_ice_sess_options *opt); 772 773 /** 692 774 * Destroy ICE session. This will cancel any connectivity checks currently 693 775 * running, if any, and any other events scheduled by this session, as well -
pjproject/trunk/pjnath/include/pjnath/ice_strans.h
r2642 r2724 198 198 199 199 /** 200 * This contains various STUN session options. Once the ICE stream 201 * transport is created, application may also change the options 202 * with #pj_ice_strans_set_options(). 203 */ 204 pj_ice_sess_options opt; 205 206 /** 200 207 * STUN and local transport settings. This specifies the 201 208 * settings for local UDP socket, which will be resolved … … 210 217 211 218 /** 212 * Disable host candidates. When this option is set, no213 * host candidates will be added.214 * 215 * Default: PJ_FALSE216 */ 217 pj_bool_t no_host_cands;219 * Maximum number of host candidates to be added. If the 220 * value is zero, no host candidates will be added. 221 * 222 * Default: 64 223 */ 224 unsigned max_host_cands; 218 225 219 226 /** … … 384 391 */ 385 392 PJ_DECL(void*) pj_ice_strans_get_user_data(pj_ice_strans *ice_st); 393 394 395 /** 396 * Get the value of various options of the ICE stream transport. 397 * 398 * @param ice_st The ICE stream transport. 399 * @param opt The options to be initialized with the values 400 * from the ICE stream transport. 401 * 402 * @return PJ_SUCCESS on success, or the appropriate error. 403 */ 404 PJ_DECL(pj_status_t) pj_ice_strans_get_options(pj_ice_strans *ice_st, 405 pj_ice_sess_options *opt); 406 407 /** 408 * Specify various options for this ICE stream transport. Application 409 * should call #pj_ice_strans_get_options() to initialize the options 410 * with their default values. 411 * 412 * @param ice_st The ICE stream transport. 413 * @param opt Options to be applied to this ICE stream transport. 414 * 415 * @return PJ_SUCCESS on success, or the appropriate error. 416 */ 417 PJ_DECL(pj_status_t) pj_ice_strans_set_options(pj_ice_strans *ice_st, 418 const pj_ice_sess_options *opt); 386 419 387 420 -
pjproject/trunk/pjnath/include/pjnath/stun_msg.h
r2642 r2724 198 198 PJ_STUN_BINDING_ERROR_RESPONSE = 0x0111, 199 199 200 /** 201 * Binding Indication (ICE) 202 */ 203 PJ_STUN_BINDING_INDICATION = 0x0011, 200 204 201 205 /** -
pjproject/trunk/pjnath/include/pjnath/stun_session.h
r2642 r2724 486 486 PJ_DECL(void) pj_stun_session_set_log(pj_stun_session *sess, 487 487 unsigned flags); 488 /** 489 * Configure whether the STUN session should utilize FINGERPRINT in 490 * outgoing messages. 491 * 492 * @param sess The STUN session instance. 493 * @param use Boolean for the setting. 494 * 495 * @return The previous configured value of FINGERPRINT 496 * utilization of the sessoin. 497 */ 498 PJ_DECL(pj_bool_t) pj_stun_session_use_fingerprint(pj_stun_session *sess, 499 pj_bool_t use); 488 500 489 501 /** -
pjproject/trunk/pjnath/src/pjnath-test/ice_test.c
r2394 r2724 65 65 66 66 struct test_result expected;/* Expected result */ 67 68 pj_bool_t nom_regular; /* Use regular nomination? */ 67 69 }; 68 70 … … 142 144 143 145 if (ept->cfg.enable_host == 0) { 144 ice_cfg.stun. no_host_cands = PJ_TRUE;146 ice_cfg.stun.max_host_cands = 0; 145 147 } else { 146 ice_cfg.stun.no_host_cands = PJ_FALSE;148 //ice_cfg.stun.no_host_cands = PJ_FALSE; 147 149 ice_cfg.stun.loop_addr = PJ_TRUE; 148 150 } -
pjproject/trunk/pjnath/src/pjnath/errno.c
r2580 r2724 68 68 PJ_BUILD_ERR( PJNATH_EICEINCANDSDP, "Invalid SDP \"candidate\" attribute"), 69 69 PJ_BUILD_ERR( PJNATH_EICENOHOSTCAND, "No host candidate associated with srflx"), 70 PJ_BUILD_ERR( PJNATH_EICENOMTIMEOUT, "Controlled agent timed out waiting for nomination"), 70 71 71 72 /* TURN related errors */ -
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 -
pjproject/trunk/pjnath/src/pjnath/ice_strans.c
r2599 r2724 51 51 * specify preference among candidates with the same type. Since 52 52 * we don't have the facility to specify that, we'll just set it 53 * all to zero. 54 */ 55 #define SRFLX_PREF 0 56 #define HOST_PREF 0 57 #define RELAY_PREF 0 53 * all to the same value. 54 */ 55 #if PJNATH_ICE_PRIO_STD 56 # define SRFLX_PREF 65535 57 # define HOST_PREF 65535 58 # define RELAY_PREF 65535 59 #else 60 # define SRFLX_PREF 0 61 # define HOST_PREF 0 62 # define RELAY_PREF 0 63 #endif 64 58 65 59 66 /* The candidate type preference when STUN candidate is used */ 60 67 static pj_uint8_t srflx_pref_table[4] = 61 68 { 69 #if PJNATH_ICE_PRIO_STD 70 100, /**< PJ_ICE_HOST_PREF */ 71 126, /**< PJ_ICE_SRFLX_PREF */ 72 110, /**< PJ_ICE_PRFLX_PREF */ 73 0 /**< PJ_ICE_RELAYED_PREF */ 74 #else 62 75 /* Keep it to 2 bits */ 63 76 1, /**< PJ_ICE_HOST_PREF */ … … 65 78 3, /**< PJ_ICE_PRFLX_PREF */ 66 79 0 /**< PJ_ICE_RELAYED_PREF */ 80 #endif 67 81 }; 68 82 … … 198 212 pj_turn_alloc_param_default(&cfg->turn.alloc_param); 199 213 214 pj_ice_sess_options_default(&cfg->opt); 215 200 216 cfg->af = pj_AF_INET(); 201 217 cfg->stun.port = PJ_STUN_PORT; 202 218 cfg->turn.conn_type = PJ_TURN_TP_UDP; 219 220 cfg->stun.max_host_cands = 64; 203 221 } 204 222 … … 246 264 247 265 /* Create STUN transport if configured */ 248 if (ice_st->cfg.stun.server.slen || !ice_st->cfg.stun.no_host_cands) {266 if (ice_st->cfg.stun.server.slen || ice_st->cfg.stun.max_host_cands) { 249 267 pj_stun_sock_cb stun_sock_cb; 250 268 pj_ice_sess_cand *cand; … … 310 328 } 311 329 312 /* Add local addresses to host candidates, unless no_host_cands313 * flag is set.330 /* Add local addresses to host candidates, unless max_host_cands 331 * is set to zero. 314 332 */ 315 if (ice_st->cfg.stun. no_host_cands == PJ_FALSE) {333 if (ice_st->cfg.stun.max_host_cands) { 316 334 pj_stun_sock_info stun_sock_info; 317 335 unsigned i; … … 322 340 return status; 323 341 324 for (i=0; i<stun_sock_info.alias_cnt; ++i) { 342 for (i=0; i<stun_sock_info.alias_cnt && 343 i<ice_st->cfg.stun.max_host_cands; ++i) 344 { 325 345 char addrinfo[PJ_INET6_ADDRSTRLEN+10]; 326 346 const pj_sockaddr *addr = &stun_sock_info.aliases[i]; … … 648 668 649 669 /* 670 * Get the value of various options of the ICE stream transport. 671 */ 672 PJ_DEF(pj_status_t) pj_ice_strans_get_options( pj_ice_strans *ice_st, 673 pj_ice_sess_options *opt) 674 { 675 PJ_ASSERT_RETURN(ice_st && opt, PJ_EINVAL); 676 pj_memcpy(opt, &ice_st->cfg.opt, sizeof(*opt)); 677 return PJ_SUCCESS; 678 } 679 680 /* 681 * Specify various options for this ICE stream transport. 682 */ 683 PJ_DEF(pj_status_t) pj_ice_strans_set_options(pj_ice_strans *ice_st, 684 const pj_ice_sess_options *opt) 685 { 686 PJ_ASSERT_RETURN(ice_st && opt, PJ_EINVAL); 687 pj_memcpy(&ice_st->cfg.opt, opt, sizeof(*opt)); 688 if (ice_st->ice) 689 pj_ice_sess_set_options(ice_st->ice, &ice_st->cfg.opt); 690 return PJ_SUCCESS; 691 } 692 693 /* 650 694 * Create ICE! 651 695 */ … … 682 726 /* Associate user data */ 683 727 ice_st->ice->user_data = (void*)ice_st; 728 729 /* Set options */ 730 pj_ice_sess_set_options(ice_st->ice, &ice_st->cfg.opt); 684 731 685 732 /* If default candidate for components are SRFLX one, upload a custom -
pjproject/trunk/pjnath/src/pjnath/stun_auth.c
r2394 r2724 529 529 case PJ_STUN_SC_BAD_REQUEST: /* 400 (Bad Request) */ 530 530 case PJ_STUN_SC_UNAUTHORIZED: /* 401 (Unauthorized) */ 531 case PJ_STUN_SC_STALE_NONCE: /* 438 (Stale Nonce) */ 531 532 532 533 /* Due to the way this response is generated here, we can't really -
pjproject/trunk/pjnath/src/pjnath/stun_msg_dump.c
r2589 r2724 58 58 { 59 59 char *p = buffer, *end = buffer + length; 60 const char *attr_name = pj_stun_get_attr_name(ahdr->type); 61 char attr_buf[32]; 60 62 int len; 63 64 if (*attr_name == '?') { 65 pj_ansi_snprintf(attr_buf, sizeof(attr_buf), "Attr 0x%x", 66 ahdr->type); 67 attr_name = attr_buf; 68 } 61 69 62 70 len = pj_ansi_snprintf(p, end-p, 63 71 " %s: length=%d", 64 pj_stun_get_attr_name(ahdr->type),72 attr_name, 65 73 (int)ahdr->length); 66 74 APPLY(); -
pjproject/trunk/pjnath/src/pjnath/stun_session.c
r2589 r2724 220 220 /* If the agent is sending a request, it SHOULD add a SOFTWARE attribute 221 221 * to the request. The server SHOULD include a SOFTWARE attribute in all 222 * responses 222 * responses. 223 * 224 * If magic value is not PJ_STUN_MAGIC, only apply the attribute for 225 * responses. 223 226 */ 224 if (sess->srv_name.slen && !PJ_STUN_IS_INDICATION(msg->hdr.type) && 225 pj_stun_msg_find_attr(msg, PJ_STUN_ATTR_SOFTWARE, 0)==NULL) 227 if (sess->srv_name.slen && 228 pj_stun_msg_find_attr(msg, PJ_STUN_ATTR_SOFTWARE, 0)==NULL && 229 (PJ_STUN_IS_RESPONSE(msg->hdr.type) || 230 PJ_STUN_IS_REQUEST(msg->hdr.type) && msg->hdr.magic==PJ_STUN_MAGIC)) 226 231 { 227 232 pj_stun_msg_add_string_attr(pool, msg, PJ_STUN_ATTR_SOFTWARE, … … 629 634 PJ_ASSERT_ON_FAIL(sess, return); 630 635 sess->log_flag = flags; 636 } 637 638 PJ_DEF(pj_bool_t) pj_stun_session_use_fingerprint(pj_stun_session *sess, 639 pj_bool_t use) 640 { 641 pj_bool_t old_use; 642 643 PJ_ASSERT_RETURN(sess, PJ_FALSE); 644 645 old_use = sess->use_fingerprint; 646 sess->use_fingerprint = use; 647 return old_use; 631 648 } 632 649 -
pjproject/trunk/pjsip-apps/src/pjsua/pjsua_app.c
r2650 r2724 265 265 puts ("Media Transport Options:"); 266 266 puts (" --use-ice Enable ICE (default:no)"); 267 puts (" --ice-no-host Disable ICE host candidates (default: no)"); 267 puts (" --ice-regular Use ICE regular nomination (default: aggressive)"); 268 puts (" --ice-max-hosts=N Set maximum number of ICE host candidates"); 268 269 puts (" --ice-no-rtcp Disable RTCP component in ICE (default: no)"); 269 270 puts (" --rtp-port=N Base port to try for RTP (default=4000)"); … … 477 478 OPT_AUTO_ANSWER, OPT_AUTO_PLAY, OPT_AUTO_PLAY_HANGUP, OPT_AUTO_LOOP, 478 479 OPT_AUTO_CONF, OPT_CLOCK_RATE, OPT_SND_CLOCK_RATE, OPT_STEREO, 479 OPT_USE_ICE, OPT_ USE_SRTP, OPT_SRTP_SECURE,480 OPT_USE_TURN, OPT_ICE_ NO_HOST, OPT_ICE_NO_RTCP, OPT_TURN_SRV,480 OPT_USE_ICE, OPT_ICE_REGULAR, OPT_USE_SRTP, OPT_SRTP_SECURE, 481 OPT_USE_TURN, OPT_ICE_MAX_HOSTS, OPT_ICE_NO_RTCP, OPT_TURN_SRV, 481 482 OPT_TURN_TCP, OPT_TURN_USER, OPT_TURN_PASSWD, 482 483 OPT_PLAY_FILE, OPT_PLAY_TONE, OPT_RTP_PORT, OPT_ADD_CODEC, … … 554 555 555 556 { "use-ice", 0, 0, OPT_USE_ICE}, 557 { "ice-regular",0, 0, OPT_ICE_REGULAR}, 556 558 { "use-turn", 0, 0, OPT_USE_TURN}, 557 { "ice- no-host",0, 0, OPT_ICE_NO_HOST},559 { "ice-max-hosts",1, 0, OPT_ICE_MAX_HOSTS}, 558 560 { "ice-no-rtcp",0, 0, OPT_ICE_NO_RTCP}, 559 561 { "turn-srv", 1, 0, OPT_TURN_SRV}, … … 993 995 break; 994 996 997 case OPT_ICE_REGULAR: 998 cfg->media_cfg.ice_opt.aggressive = PJ_FALSE; 999 break; 1000 995 1001 case OPT_USE_TURN: 996 1002 cfg->media_cfg.enable_turn = PJ_TRUE; 997 1003 break; 998 1004 999 case OPT_ICE_ NO_HOST:1000 cfg->media_cfg.ice_ no_host_cands = PJ_TRUE;1005 case OPT_ICE_MAX_HOSTS: 1006 cfg->media_cfg.ice_max_host_cands = my_atoi(pj_optarg); 1001 1007 break; 1002 1008 … … 1645 1651 pj_strcat2(&cfg, "--use-ice\n"); 1646 1652 1653 if (config->media_cfg.ice_opt.aggressive == PJ_FALSE) 1654 pj_strcat2(&cfg, "--ice-regular\n"); 1655 1647 1656 if (config->media_cfg.enable_turn) 1648 1657 pj_strcat2(&cfg, "--use-turn\n"); 1649 1658 1650 if (config->media_cfg.ice_no_host_cands) 1651 pj_strcat2(&cfg, "--ice-no-host\n"); 1659 if (config->media_cfg.ice_max_host_cands >= 0) { 1660 pj_ansi_sprintf(line, "--ice_max_host_cands %d\n", 1661 config->media_cfg.ice_max_host_cands); 1662 pj_strcat2(&cfg, line); 1663 } 1652 1664 1653 1665 if (config->media_cfg.ice_no_rtcp) … … 1886 1898 } 1887 1899 1888 if ( config->cfg.force_lr) {1900 if (!config->cfg.force_lr) { 1889 1901 pj_strcat2(&cfg, "--no-force-lr\n"); 1890 1902 } … … 3688 3700 } 3689 3701 3690 pjsua_call_xfer_replaces(call, dst_call, 0, &msg_data); 3702 pjsua_call_xfer_replaces(call, dst_call, 3703 PJSUA_XFER_NO_REQUIRE_REPLACES, 3704 &msg_data); 3691 3705 } 3692 3706 break; … … 4719 4733 for (i=0; i<app_config.cfg.max_calls; ++i) { 4720 4734 enum { MAX_RETRY = 10 }; 4735 pj_sock_t sock[2]; 4736 pjmedia_sock_info si; 4721 4737 unsigned j; 4722 4738 … … 4725 4741 4726 4742 for (j=0; j<MAX_RETRY; ++j) { 4727 status = pjmedia_transport_udp_create3(pjsua_get_pjmedia_endpt(), 4728 pj_AF_INET6(), 4729 NULL, 4730 &app_config.rtp_cfg.bound_addr, 4731 port, 4732 0, &tp[i].transport); 4733 4743 unsigned k; 4744 4745 for (k=0; k<2; ++k) { 4746 pj_sockaddr bound_addr; 4747 4748 status = pj_sock_socket(pj_AF_INET6(), pj_SOCK_DGRAM(), 0, &sock[k]); 4749 if (status != PJ_SUCCESS) 4750 break; 4751 4752 status = pj_sockaddr_init(pj_AF_INET6(), &bound_addr, 4753 &app_config.rtp_cfg.bound_addr, 4754 (unsigned short)(port+k)); 4755 if (status != PJ_SUCCESS) 4756 break; 4757 4758 status = pj_sock_bind(sock[k], &bound_addr, 4759 pj_sockaddr_get_len(&bound_addr)); 4760 if (status != PJ_SUCCESS) 4761 break; 4762 } 4763 if (status != PJ_SUCCESS) { 4764 if (k==1) 4765 pj_sock_close(sock[0]); 4766 4767 if (port != 0) 4768 port += 10; 4769 else 4770 break; 4771 4772 continue; 4773 } 4774 4775 pj_bzero(&si, sizeof(si)); 4776 si.rtp_sock = sock[0]; 4777 si.rtcp_sock = sock[1]; 4778 4779 pj_sockaddr_init(pj_AF_INET6(), &si.rtp_addr_name, 4780 &app_config.rtp_cfg.public_addr, 4781 (unsigned short)(port)); 4782 pj_sockaddr_init(pj_AF_INET6(), &si.rtcp_addr_name, 4783 &app_config.rtp_cfg.public_addr, 4784 (unsigned short)(port+1)); 4785 4786 status = pjmedia_transport_udp_attach(pjsua_get_pjmedia_endpt(), 4787 NULL, 4788 &si, 4789 0, 4790 &tp[i].transport); 4734 4791 if (port != 0) 4735 4792 port += 10; -
pjproject/trunk/pjsip-apps/src/samples/debug.c
r2506 r2724 29 29 * #include "playfile.c" 30 30 */ 31 #include " auddemo.c"31 #include "icedemo.c" 32 32 -
pjproject/trunk/pjsip-apps/src/samples/icedemo.c
r2600 r2724 40 40 unsigned comp_cnt; 41 41 pj_str_t ns; 42 pj_bool_t no_host; 42 int max_host; 43 pj_bool_t regular; 43 44 pj_str_t stun_srv; 44 45 pj_str_t turn_srv; … … 307 308 /* -= Start initializing ICE stream transport config =- */ 308 309 309 /* Disable host candidates? */ 310 icedemo.ice_cfg.stun.no_host_cands = icedemo.opt.no_host; 310 /* Maximum number of host candidates */ 311 if (icedemo.opt.max_host != -1) 312 icedemo.ice_cfg.stun.max_host_cands = icedemo.opt.max_host; 313 314 /* Nomination strategy */ 315 if (icedemo.opt.regular) 316 icedemo.ice_cfg.opt.aggressive = PJ_FALSE; 317 else 318 icedemo.ice_cfg.opt.aggressive = PJ_TRUE; 311 319 312 320 /* Configure STUN/srflx candidate resolution */ … … 961 969 */ 962 970 963 if (comp_id >pj_ice_strans_get_running_comp_cnt(icedemo.icest)) {971 if (comp_id<1||comp_id>pj_ice_strans_get_running_comp_cnt(icedemo.icest)) { 964 972 PJ_LOG(1,(THIS_FILE, "Error: invalid component ID")); 965 973 return; … … 1138 1146 puts(" --nameserver, -n IP Configure nameserver to activate DNS SRV"); 1139 1147 puts(" resolution"); 1140 puts(" --no-host, -H Disable host candidates"); 1148 puts(" --max-host, -H N Set max number of host candidates to N"); 1149 puts(" --regular, -R Use regular nomination (default aggressive)"); 1141 1150 puts(" --help, -h Display this screen."); 1142 1151 puts(""); … … 1166 1175 { "comp-cnt", 1, 0, 'c'}, 1167 1176 { "nameserver", 1, 0, 'n'}, 1168 { " no-host", 0, 0, 'H'},1177 { "max-host", 1, 0, 'H'}, 1169 1178 { "help", 0, 0, 'h'}, 1170 1179 { "stun-srv", 1, 0, 's'}, … … 1173 1182 { "turn-username", 1, 0, 'u'}, 1174 1183 { "turn-password", 1, 0, 'p'}, 1175 { "turn-fingerprint", 0, 0, 'F'} 1184 { "turn-fingerprint", 0, 0, 'F'}, 1185 { "regular", 0, 0, 'R'} 1176 1186 }; 1177 1187 int c, opt_id; … … 1179 1189 1180 1190 icedemo.opt.comp_cnt = 1; 1181 1182 while((c=pj_getopt_long(argc,argv, "n:s:t:u:p:HhTF", long_options, &opt_id))!=-1) { 1191 icedemo.opt.max_host = -1; 1192 1193 while((c=pj_getopt_long(argc,argv, "c:n:s:t:u:p:H:hTFR", long_options, &opt_id))!=-1) { 1183 1194 switch (c) { 1184 1195 case 'c': … … 1193 1204 break; 1194 1205 case 'H': 1195 icedemo.opt. no_host = PJ_TRUE;1206 icedemo.opt.max_host = atoi(pj_optarg); 1196 1207 break; 1197 1208 case 'h': … … 1216 1227 icedemo.opt.turn_fingerprint = PJ_TRUE; 1217 1228 break; 1229 case 'R': 1230 icedemo.opt.regular = PJ_TRUE; 1231 break; 1218 1232 default: 1219 1233 printf("Argument \"%s\" is not valid. Use -h to see help", -
pjproject/trunk/pjsip-apps/src/samples/siprtp_report.c
r2394 r2724 78 78 /* Call identification */ 79 79 len = pjsip_hdr_print_on(dlg->remote.info, userinfo, sizeof(userinfo)); 80 if (len < 1)80 if (len < 0) 81 81 pj_ansi_strcpy(userinfo, "<--uri too long-->"); 82 82 else -
pjproject/trunk/pjsip/include/pjsip/sip_config.h
r2394 r2724 228 228 229 229 /** 230 * RFC 3261 section 18.1.1: 231 * If a request is within 200 bytes of the path MTU, or if it is larger 232 * than 1300 bytes and the path MTU is unknown, the request MUST be sent 233 * using an RFC 2914 [43] congestion controlled transport protocol, such 234 * as TCP. 235 * 236 * This setting controls the threshold of the UDP packet, which if it's 237 * larger than this value the request will be sent with TCP. Default is 238 * 1300 bytes. 239 */ 240 #ifndef PJSIP_UDP_SIZE_THRESHOLD 241 # define PJSIP_UDP_SIZE_THRESHOLD 1300 242 #endif 243 244 /** 230 245 * Encode SIP headers in their short forms to reduce size. By default, 231 246 * SIP headers in outgoing messages will be encoded in their full names. -
pjproject/trunk/pjsip/include/pjsip/sip_transport.h
r2394 r2724 579 579 */ 580 580 PJ_DECL(pj_status_t) pjsip_tx_data_dec_ref( pjsip_tx_data *tdata ); 581 582 /** 583 * Print the SIP message to transmit data buffer's internal buffer. This 584 * may allocate memory for the buffer, if the buffer has not been allocated 585 * yet, and encode the SIP message to that buffer. 586 * 587 * @param tdata The transmit buffer. 588 * 589 * @return PJ_SUCCESS on success of the appropriate error code. 590 */ 591 PJ_DECL(pj_status_t) pjsip_tx_data_encode(pjsip_tx_data *tdata); 581 592 582 593 /** -
pjproject/trunk/pjsip/include/pjsua-lib/pjsua.h
r2686 r2724 4261 4261 4262 4262 /** 4263 * Disable ICE host candidates. 4264 */ 4265 pj_bool_t ice_no_host_cands; 4263 * Set the maximum number of host candidates. 4264 * 4265 * Default: -1 (maximum not set) 4266 */ 4267 int ice_max_host_cands; 4268 4269 /** 4270 * ICE session options. 4271 */ 4272 pj_ice_sess_options ice_opt; 4266 4273 4267 4274 /** -
pjproject/trunk/pjsip/src/pjsip/sip_msg.c
r2394 r2724 457 457 /* Print each of the headers. */ 458 458 for (hdr=msg->hdr.next; hdr!=&msg->hdr; hdr=hdr->next) { 459 len = (*hdr->vptr->print_on)(hdr, p, end-p);460 if (len < 1)459 len = pjsip_hdr_print_on(hdr, p, end-p); 460 if (len < 0) 461 461 return -1; 462 p += len; 463 464 if (p+3 >= end) 465 return -1; 466 467 *p++ = '\r'; 468 *p++ = '\n'; 462 463 if (len > 0) { 464 p += len; 465 if (p+3 >= end) 466 return -1; 467 468 *p++ = '\r'; 469 *p++ = '\n'; 470 } 469 471 } 470 472 … … 1602 1604 char *endbuf = buf + size; 1603 1605 const pjsip_parser_const_t *pc = pjsip_parser_const(); 1606 pjsip_sip_uri *sip_uri; 1607 pjsip_param *p; 1608 1609 /* Check the proprietary param 'hide', don't print this header 1610 * if it exists in the route URI. 1611 */ 1612 sip_uri = (pjsip_sip_uri*) pjsip_uri_get_uri(hdr->name_addr.uri); 1613 p = sip_uri->other_param.next; 1614 while (p != &sip_uri->other_param) { 1615 const pj_str_t st_hide = {"hide", 4}; 1616 1617 if (pj_stricmp(&p->name, &st_hide) == 0) { 1618 /* Check if param 'hide' is specified without 'lr'. */ 1619 pj_assert(sip_uri->lr_param != 0); 1620 return 0; 1621 } 1622 p = p->next; 1623 } 1624 1604 1625 /* Route and Record-Route don't compact forms */ 1605 1626 -
pjproject/trunk/pjsip/src/pjsip/sip_transaction.c
r2646 r2724 1726 1726 pjsip_tx_data_get_info(send_state->tdata), -sent, 1727 1727 pj_strerror(-sent, errmsg, sizeof(errmsg)).ptr)); 1728 1729 /* Reset retransmission count */ 1730 tsx->retransmit_count = 0; 1731 1732 /* And reset timeout timer */ 1733 if (tsx->timeout_timer.id) { 1734 pjsip_endpt_cancel_timer(tsx->endpt, &tsx->timeout_timer); 1735 tsx->timeout_timer.id = TIMER_INACTIVE; 1736 1737 tsx->timeout_timer.id = TIMER_ACTIVE; 1738 pjsip_endpt_schedule_timer( tsx->endpt, &tsx->timeout_timer, 1739 &timeout_timer_val); 1740 } 1728 1741 } 1729 1742 } -
pjproject/trunk/pjsip/src/pjsip/sip_transport.c
r2394 r2724 435 435 } 436 436 437 /* 438 * Print the SIP message to transmit data buffer's internal buffer. 439 */ 440 PJ_DEF(pj_status_t) pjsip_tx_data_encode(pjsip_tx_data *tdata) 441 { 442 /* Allocate buffer if necessary. */ 443 if (tdata->buf.start == NULL) { 444 PJ_USE_EXCEPTION; 445 446 PJ_TRY { 447 tdata->buf.start = (char*) 448 pj_pool_alloc(tdata->pool, PJSIP_MAX_PKT_LEN); 449 } 450 PJ_CATCH_ANY { 451 return PJ_ENOMEM; 452 } 453 PJ_END 454 455 tdata->buf.cur = tdata->buf.start; 456 tdata->buf.end = tdata->buf.start + PJSIP_MAX_PKT_LEN; 457 } 458 459 /* Do we need to reprint? */ 460 if (!pjsip_tx_data_is_valid(tdata)) { 461 pj_ssize_t size; 462 463 size = pjsip_msg_print( tdata->msg, tdata->buf.start, 464 tdata->buf.end - tdata->buf.start); 465 if (size < 0) { 466 return PJSIP_EMSGTOOLONG; 467 } 468 pj_assert(size != 0); 469 tdata->buf.cur[size] = '\0'; 470 tdata->buf.cur += size; 471 } 472 473 return PJ_SUCCESS; 474 } 475 437 476 PJ_DEF(pj_bool_t) pjsip_tx_data_is_valid( pjsip_tx_data *tdata ) 438 477 { … … 568 607 static pj_status_t mod_on_tx_msg(pjsip_tx_data *tdata) 569 608 { 570 /* Allocate buffer if necessary. */ 571 if (tdata->buf.start == NULL) { 572 PJ_USE_EXCEPTION; 573 574 PJ_TRY { 575 tdata->buf.start = (char*) 576 pj_pool_alloc(tdata->pool, PJSIP_MAX_PKT_LEN); 577 } 578 PJ_CATCH_ANY { 579 return PJ_ENOMEM; 580 } 581 PJ_END 582 583 tdata->buf.cur = tdata->buf.start; 584 tdata->buf.end = tdata->buf.start + PJSIP_MAX_PKT_LEN; 585 } 586 587 /* Do we need to reprint? */ 588 if (!pjsip_tx_data_is_valid(tdata)) { 589 pj_ssize_t size; 590 591 size = pjsip_msg_print( tdata->msg, tdata->buf.start, 592 tdata->buf.end - tdata->buf.start); 593 if (size < 0) { 594 return PJSIP_EMSGTOOLONG; 595 } 596 pj_assert(size != 0); 597 tdata->buf.cur[size] = '\0'; 598 tdata->buf.cur += size; 599 } 600 601 return PJ_SUCCESS; 609 return pjsip_tx_data_encode(tdata); 602 610 } 603 611 -
pjproject/trunk/pjsip/src/pjsip/sip_ua_layer.c
r2394 r2724 908 908 909 909 len = pjsip_hdr_print_on(dlg->remote.info, userinfo, sizeof(userinfo)); 910 if (len < 1)910 if (len < 0) 911 911 pj_ansi_strcpy(userinfo, "<--uri too long-->"); 912 912 else -
pjproject/trunk/pjsip/src/pjsip/sip_util.c
r2435 r2724 1136 1136 via->rport_param = 0; 1137 1137 1138 pjsip_tx_data_invalidate_msg(tdata); 1139 1138 1140 /* Send message using this transport. */ 1139 1141 status = pjsip_transport_send( stateless_data->cur_transport, … … 1181 1183 /* Copy server addresses */ 1182 1184 pj_memcpy( &stateless_data->addr, addr, sizeof(pjsip_server_addresses)); 1185 1186 /* RFC 3261 section 18.1.1: 1187 * If a request is within 200 bytes of the path MTU, or if it is larger 1188 * than 1300 bytes and the path MTU is unknown, the request MUST be sent 1189 * using an RFC 2914 [43] congestion controlled transport protocol, such 1190 * as TCP. 1191 */ 1192 if (stateless_data->tdata->msg->type == PJSIP_REQUEST_MSG && 1193 addr->count > 0 && 1194 addr->entry[0].type == PJSIP_TRANSPORT_UDP) 1195 { 1196 int len; 1197 1198 /* Encode the request */ 1199 status = pjsip_tx_data_encode(stateless_data->tdata); 1200 if (status != PJ_SUCCESS) { 1201 if (stateless_data->app_cb) { 1202 pj_bool_t cont = PJ_FALSE; 1203 (*stateless_data->app_cb)(stateless_data, -status, &cont); 1204 } 1205 pjsip_tx_data_dec_ref(stateless_data->tdata); 1206 return; 1207 } 1208 1209 /* Check if request message is larger than 1300 bytes. */ 1210 len = stateless_data->tdata->buf.cur - 1211 stateless_data->tdata->buf.start; 1212 if (len >= PJSIP_UDP_SIZE_THRESHOLD) { 1213 int i; 1214 int count = stateless_data->addr.count; 1215 1216 /* Insert "TCP version" of resolved UDP addresses at the 1217 * beginning. 1218 */ 1219 if (count * 2 > PJSIP_MAX_RESOLVED_ADDRESSES) 1220 count = PJSIP_MAX_RESOLVED_ADDRESSES / 2; 1221 for (i = 0; i < count; ++i) { 1222 pj_memcpy(&stateless_data->addr.entry[i+count], 1223 &stateless_data->addr.entry[i], 1224 sizeof(stateless_data->addr.entry[0])); 1225 stateless_data->addr.entry[i].type = PJSIP_TRANSPORT_TCP; 1226 } 1227 stateless_data->addr.count = count * 2; 1228 } 1229 } 1183 1230 1184 1231 /* Process the addresses. */ -
pjproject/trunk/pjsip/src/pjsua-lib/pjsua_call.c
r2695 r2724 2695 2695 2696 2696 len = pjsip_hdr_print_on(dlg->remote.info, userinfo, sizeof(userinfo)); 2697 if (len < 1)2697 if (len < 0) 2698 2698 pj_ansi_strcpy(userinfo, "<--uri too long-->"); 2699 2699 else -
pjproject/trunk/pjsip/src/pjsua-lib/pjsua_core.c
r2686 r2724 183 183 cfg->snd_auto_close_time = 1; 184 184 185 cfg->ice_max_host_cands = -1; 186 pj_ice_sess_options_default(&cfg->ice_opt); 187 185 188 cfg->turn_conn_type = PJ_TURN_TP_UDP; 186 189 } … … 648 651 if (log_cfg) { 649 652 status = pjsua_reconfigure_logging(log_cfg); 650 PJ_ASSERT_RETURN(status == PJ_SUCCESS, status); 653 if (status != PJ_SUCCESS) 654 return status; 651 655 } 652 656 -
pjproject/trunk/pjsip/src/pjsua-lib/pjsua_media.c
r2679 r2724 805 805 ice_cfg.resolver = pjsua_var.resolver; 806 806 807 ice_cfg.opt = pjsua_var.media_cfg.ice_opt; 808 807 809 /* Configure STUN settings */ 808 810 if (pj_sockaddr_has_addr(&pjsua_var.stun_srv)) { … … 811 813 ice_cfg.stun.port = pj_sockaddr_get_port(&pjsua_var.stun_srv); 812 814 } 813 ice_cfg.stun.no_host_cands = pjsua_var.media_cfg.ice_no_host_cands; 815 if (pjsua_var.media_cfg.ice_max_host_cands >= 0) 816 ice_cfg.stun.max_host_cands = pjsua_var.media_cfg.ice_max_host_cands; 814 817 815 818 /* Configure TURN settings */ -
pjproject/trunk/pjsip/src/test/msg_test.c
r2695 r2724 366 366 367 367 while (hdr1 != &parsed_msg->hdr && hdr2 != &ref_msg->hdr) { 368 len = hdr1->vptr->print_on(hdr1, str1.ptr, BUFLEN);369 if (len < 1) {368 len = pjsip_hdr_print_on(hdr1, str1.ptr, BUFLEN); 369 if (len < 0) { 370 370 status = -40; 371 371 goto on_return; … … 374 374 str1.slen = len; 375 375 376 len = hdr2->vptr->print_on(hdr2, str2.ptr, BUFLEN);377 if (len < 1) {376 len = pjsip_hdr_print_on(hdr2, str2.ptr, BUFLEN); 377 if (len < 0) { 378 378 status = -50; 379 379 goto on_return; … … 1945 1945 output = (char*) pj_pool_alloc(pool, 1024); 1946 1946 len = pjsip_hdr_print_on(parsed_hdr1, output, 1024); 1947 if (len < 1|| len >= 1024) {1947 if (len < 0 || len >= 1024) { 1948 1948 PJ_LOG(3,(THIS_FILE, " header too long: %s: %s", test->hname, test->hcontent)); 1949 1949 return -530;
Note: See TracChangeset
for help on using the changeset viewer.