Changeset 2724 for pjproject/trunk


Ignore:
Timestamp:
May 29, 2009 1:04:03 PM (16 years ago)
Author:
bennylp
Message:

Integration of Sipit24 branch, many tickets involved:

  • #793: AMR encoder should regard 'mode-set' param specified by remote decoder.
  • #831: Automatically switch to TCP transport when sending large request
  • #832: Support for outbound proxy setting without using Route header
  • #849: Modify conference audio switch behavior in connecting ports.
  • #850: Remove 'Require=replaces' param in 'Refer-To' header (in call transfer with replaces).
  • #851: Support for regular nomination in ICE
  • #852: --ip-addr support for IPv6 for media transport in pjsua
  • #854: Adding SOFTWARE attribute in all outgoing requests may cause compatibility problem with older STUN server (thanks Alexei Kuznetsov for the report)
  • #855: Bug in digit map frequencies for DTMF digits (thanks FCCH for the report)
  • #856: Put back the ICE candidate priority values according to the default values in the draft-mmusic-ice
  • #857: Support for ICE keep-alive with Binding indication
  • #858: Do not authenticate STUN 438 response
  • #859: AMR-WB format param in the SDP is not negotiated correctly.
  • #867: Return error instead of asserting when PJSUA-LIB fails to open log file
Location:
pjproject/trunk
Files:
34 edited

Legend:

Unmodified
Added
Removed
  • pjproject/trunk/pjlib-util/src/pjlib-util/resolver.c

    r2394 r2724  
    2929#include <pj/pool.h> 
    3030#include <pj/pool_buf.h> 
     31#include <pj/rand.h> 
    3132#include <pj/string.h> 
    3233#include <pj/sock.h> 
     
    784785 
    785786    /* Save the ID and key */ 
     787    /* TODO: dnsext-forgery-resilient: randomize id for security */ 
    786788    q->id = resolver->last_id++; 
    787789    if (resolver->last_id == 0) 
  • pjproject/trunk/pjmedia/src/pjmedia-codec/ipp_codecs.c

    r2573 r2724  
    234234{ 
    235235#   if PJMEDIA_HAS_INTEL_IPP_CODEC_AMR 
     236    /* AMR-NB SID seems to produce noise, so let's just disable its VAD. */ 
    236237    {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}}} } 
    240241    }, 
    241242#   endif 
     
    244245    {1, "AMR-WB",   PJMEDIA_RTP_PT_AMRWB,     &USC_AMRWB_Fxns,  16000, 1, 320, 
    245246                    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}}} } 
    247249    }, 
    248250#   endif 
     
    561563    /* Check Change Mode Request. */ 
    562564    if ((setting->amr_nb && cmr <= 7) || (!setting->amr_nb && cmr <= 8)) { 
     565        struct ipp_codec *ippc = &ipp_codec[codec_data->codec_idx]; 
     566 
    563567        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); 
    564573    } 
    565574 
     
    10341043 
    10351044    /* 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; 
    10371046 
    10381047    /* Get number of memory blocks needed by the decoder */ 
     
    10851094        amr_settings_t *s; 
    10861095        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 
    10901100        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             
    10911108            if (pj_stricmp(&attr->setting.dec_fmtp.param[i].name,  
    10921109                           &STR_FMTP_OCTET_ALIGN) == 0) 
    10931110            { 
    10941111                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); 
    10961113                break; 
    10971114            } 
    10981115        } 
    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 */ 
    11001141        s = PJ_POOL_ZALLOC_T(pool, amr_settings_t); 
    11011142        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; 
    11061143 
    11071144        s->enc_setting.amr_nb = (pj_uint8_t)(ippc->pt == PJMEDIA_RTP_PT_AMR); 
     
    11091146        s->enc_setting.reorder = PJ_TRUE; 
    11101147        s->enc_setting.cmr = 15; 
    1111          
     1148 
    11121149        s->dec_setting.amr_nb = (pj_uint8_t)(ippc->pt == PJMEDIA_RTP_PT_AMR); 
    11131150        s->dec_setting.octet_aligned = octet_align; 
    11141151        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 
    11151169    } 
    11161170#endif 
  • pjproject/trunk/pjmedia/src/pjmedia/conf_switch.c

    r2581 r2724  
    554554    } 
    555555     
    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     */  
    557559    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); 
    560582    } 
    561583 
  • pjproject/trunk/pjmedia/src/pjmedia/sdp_neg.c

    r2643 r2724  
    866866                        { 
    867867                            /* Further check for G7221, negotiate bitrate. */ 
    868                             if (pj_strcmp2(&or_.enc_name, "G7221") == 0) { 
     868                            if (pj_stricmp2(&or_.enc_name, "G7221") == 0) { 
    869869                                if (match_g7221(offer, i, answer, j)) 
    870870                                    break; 
    871871                            } else 
    872872                            /* 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                            { 
    874876                                if (match_amr(offer, i, answer, j, PJ_FALSE,  
    875877                                              NULL)) 
     
    10711073                pjmedia_sdp_attr_get_rtpmap(a, &or_); 
    10721074 
    1073                 if (!pj_strcmp2(&or_.enc_name, "telephone-event")) { 
     1075                if (!pj_stricmp2(&or_.enc_name, "telephone-event")) { 
    10741076                    master_has_telephone_event = 1; 
    10751077                    if (found_matching_telephone_event) 
     
    10981100                        if (!pj_stricmp(&or_.enc_name, &lr.enc_name) && 
    10991101                            or_.clock_rate == lr.clock_rate && 
    1100                             (pj_strcmp(&or_.param, &lr.param)==0 || 
     1102                            (pj_stricmp(&or_.param, &lr.param)==0 || 
    11011103                             (or_.param.slen==1 && *or_.param.ptr=='1')))  
    11021104                        { 
     
    11041106                            if (is_codec) { 
    11051107                                /* Further check for G7221, negotiate bitrate */ 
    1106                                 if (pj_strcmp2(&or_.enc_name, "G7221") == 0 && 
     1108                                if (pj_stricmp2(&or_.enc_name, "G7221") == 0 && 
    11071109                                    !match_g7221(master, i, slave, j)) 
    11081110                                { 
     
    11101112                                } else  
    11111113                                /* 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                                { 
    11131117                                    unsigned o_med_idx, a_med_idx; 
    11141118 
  • pjproject/trunk/pjmedia/src/pjmedia/tonegen.c

    r2394 r2724  
    385385        { '1', 697,  1209 }, 
    386386        { '2', 697,  1336 }, 
    387         { '3', 697,  1447 }, 
     387        { '3', 697,  1477 }, 
    388388        { '4', 770,  1209 }, 
    389389        { '5', 770,  1336 }, 
    390         { '6', 770,  1447 }, 
     390        { '6', 770,  1477 }, 
    391391        { '7', 852,  1209 }, 
    392392        { '8', 852,  1336 }, 
    393         { '9', 852,  1447 }, 
     393        { '9', 852,  1477 }, 
    394394        { 'a', 697,  1633 }, 
    395395        { 'b', 770,  1633 }, 
  • pjproject/trunk/pjnath/include/pjnath/config.h

    r2642 r2724  
    260260#define PJ_ICE_MAX_COMP             (2<<PJ_ICE_COMP_BITS) 
    261261 
     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 
    262269 
    263270/** 
     
    265272 */ 
    266273#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 
    268279#endif 
    269280 
     
    325336 
    326337/** 
     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/** 
    327371 * Minimum interval value to be used for sending STUN keep-alive on the ICE 
    328  * stream transport, in seconds. This minimum interval, plus a random value 
    329  * which maximum is PJ_ICE_ST_KEEP_ALIVE_MAX_RAND, specify the actual interval 
     372 * 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 
    330374 * of the STUN keep-alive. 
    331375 * 
    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 
    340388 
    341389/** 
    342390 * To prevent STUN keep-alives to be sent simultaneously, application should 
    343  * add random interval to minimum interval (PJ_ICE_ST_KEEP_ALIVE_MIN). This 
     391 * add random interval to minimum interval (PJ_ICE_SESS_KEEP_ALIVE_MIN). This 
    344392 * setting specifies the maximum random value to be added to the minimum 
    345393 * interval, in seconds. 
     
    347395 * Default: 5 seconds 
    348396 * 
    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 
    353406#endif 
    354407 
  • pjproject/trunk/pjnath/include/pjnath/errno.h

    r2642 r2724  
    197197 */ 
    198198#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 */ 
    200205 
    201206/************************************************************ 
  • pjproject/trunk/pjnath/include/pjnath/ice_session.h

    r2642 r2724  
    177177{ 
    178178    /** 
    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 found 
    181      * 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. 
    182182     */ 
    183183    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; 
    184191 
    185192    /** 
     
    554561 
    555562/** 
     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 */ 
     567typedef 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/** 
    556601 * This structure describes the ICE session. For this version of PJNATH, 
    557602 * an ICE session corresponds to a single media stream (unlike the ICE 
     
    570615    pj_mutex_t          *mutex;                     /**< Mutex.             */ 
    571616    pj_ice_sess_role     role;                      /**< ICE role.          */ 
     617    pj_ice_sess_options  opt;                       /**< Options            */ 
    572618    pj_timestamp         tie_breaker;               /**< Tie breaker value  */ 
    573619    pj_uint8_t          *prefs;                     /**< Type preference.   */ 
     620    pj_bool_t            is_nominating;             /**< Nominating stage   */ 
    574621    pj_bool_t            is_complete;               /**< Complete?          */ 
    575622    pj_status_t          ice_status;                /**< Error status.      */ 
    576     pj_timer_entry       completion_timer;          /**< To call callback.  */ 
     623    pj_timer_entry       timer;                     /**< ICE timer.         */ 
    577624    pj_ice_sess_cb       cb;                        /**< Callback.          */ 
    578625 
     
    590637    unsigned             comp_cnt;                  /**< # of components.   */ 
    591638    pj_ice_sess_comp     comp[PJ_ICE_MAX_COMP];     /**< Component array    */ 
     639    unsigned             comp_ka;                   /**< Next comp for KA   */ 
    592640 
    593641    /* Local candidates */ 
     
    655703                                     const pj_sockaddr *base_addr); 
    656704 
     705/** 
     706 * Initialize ICE session options with library default values. 
     707 * 
     708 * @param opt           ICE session options. 
     709 */ 
     710PJ_DECL(void) pj_ice_sess_options_default(pj_ice_sess_options *opt); 
    657711 
    658712/** 
     
    690744 
    691745/** 
     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 */ 
     754PJ_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 */ 
     770PJ_DECL(pj_status_t) pj_ice_sess_set_options(pj_ice_sess *ice, 
     771                                             const pj_ice_sess_options *opt); 
     772 
     773/** 
    692774 * Destroy ICE session. This will cancel any connectivity checks currently 
    693775 * running, if any, and any other events scheduled by this session, as well 
  • pjproject/trunk/pjnath/include/pjnath/ice_strans.h

    r2642 r2724  
    198198 
    199199    /** 
     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    /** 
    200207     * STUN and local transport settings. This specifies the  
    201208     * settings for local UDP socket, which will be resolved 
     
    210217 
    211218        /** 
    212          * Disable host candidates. When this option is set, no 
    213          * host candidates will be added. 
    214          * 
    215          * Default: PJ_FALSE 
    216          */ 
    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; 
    218225 
    219226        /** 
     
    384391 */ 
    385392PJ_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 */ 
     404PJ_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 */ 
     417PJ_DECL(pj_status_t) pj_ice_strans_set_options(pj_ice_strans *ice_st, 
     418                                               const pj_ice_sess_options *opt); 
    386419 
    387420 
  • pjproject/trunk/pjnath/include/pjnath/stun_msg.h

    r2642 r2724  
    198198    PJ_STUN_BINDING_ERROR_RESPONSE          = 0x0111, 
    199199 
     200    /** 
     201     * Binding Indication (ICE) 
     202     */ 
     203    PJ_STUN_BINDING_INDICATION              = 0x0011, 
    200204 
    201205    /** 
  • pjproject/trunk/pjnath/include/pjnath/stun_session.h

    r2642 r2724  
    486486PJ_DECL(void) pj_stun_session_set_log(pj_stun_session *sess, 
    487487                                      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 */ 
     498PJ_DECL(pj_bool_t) pj_stun_session_use_fingerprint(pj_stun_session *sess, 
     499                                                   pj_bool_t use); 
    488500 
    489501/** 
  • pjproject/trunk/pjnath/src/pjnath-test/ice_test.c

    r2394 r2724  
    6565 
    6666    struct test_result expected;/* Expected result              */ 
     67 
     68    pj_bool_t   nom_regular;    /* Use regular nomination?      */ 
    6769}; 
    6870 
     
    142144 
    143145    if (ept->cfg.enable_host == 0) { 
    144         ice_cfg.stun.no_host_cands = PJ_TRUE; 
     146        ice_cfg.stun.max_host_cands = 0; 
    145147    } else { 
    146         ice_cfg.stun.no_host_cands = PJ_FALSE; 
     148        //ice_cfg.stun.no_host_cands = PJ_FALSE; 
    147149        ice_cfg.stun.loop_addr = PJ_TRUE; 
    148150    } 
  • pjproject/trunk/pjnath/src/pjnath/errno.c

    r2580 r2724  
    6868    PJ_BUILD_ERR( PJNATH_EICEINCANDSDP,     "Invalid SDP \"candidate\" attribute"), 
    6969    PJ_BUILD_ERR( PJNATH_EICENOHOSTCAND,    "No host candidate associated with srflx"), 
     70    PJ_BUILD_ERR( PJNATH_EICENOMTIMEOUT,    "Controlled agent timed out waiting for nomination"), 
    7071 
    7172    /* TURN related errors */ 
  • pjproject/trunk/pjnath/src/pjnath/ice_session.c

    r2419 r2724  
    3030#include <pj/string.h> 
    3131 
    32  
    3332/* String names for candidate types */ 
    3433static const char *cand_type_names[] = 
     
    6564    "Controlled", 
    6665    "Controlling" 
     66}; 
     67 
     68enum 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 
    6780}; 
    6881 
     
    119132 
    120133/* Forward declarations */ 
     134static void on_timer(pj_timer_heap_t *th, pj_timer_entry *te); 
     135static void on_ice_complete(pj_ice_sess *ice, pj_status_t status); 
     136static void ice_keep_alive(pj_ice_sess *ice, pj_bool_t send_now); 
    121137static void destroy_ice(pj_ice_sess *ice, 
    122138                        pj_status_t reason); 
    123139static pj_status_t start_periodic_check(pj_timer_heap_t *th,  
    124140                                        pj_timer_entry *te); 
     141static void start_nominated_check(pj_ice_sess *ice); 
    125142static void periodic_timer(pj_timer_heap_t *th,  
    126143                          pj_timer_entry *te); 
     
    226243                                    const pj_sockaddr *base_addr) 
    227244{ 
    228 #if 0 
     245#if PJNATH_ICE_PRIO_STD 
    229246    char buf[64]; 
    230247    pj_uint32_t val; 
     
    296313} 
    297314 
     315 
     316/* Init options with default values */ 
     317PJ_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} 
    298324 
    299325/* 
     
    327353    ice->tie_breaker.u32.lo = pj_rand(); 
    328354    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); 
    329358 
    330359    pj_ansi_snprintf(ice->obj_name, sizeof(ice->obj_name), 
     
    346375        comp = &ice->comp[i]; 
    347376        comp->valid_check = NULL; 
     377        comp->nominated_check = NULL; 
    348378 
    349379        status = init_comp(ice, i+1, comp); 
     
    390420 
    391421/* 
     422 * Get the value of various options of the ICE session. 
     423 */ 
     424PJ_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 */ 
     435PJ_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/* 
    392447 * Destroy 
    393448 */ 
     
    407462    } 
    408463 
    409     if (ice->completion_timer.id) { 
     464    if (ice->timer.id) { 
    410465        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; 
    413468    } 
    414469 
     
    604659                                  pj_uint32_t comp_id) 
    605660{ 
    606 #if 0 
     661#if PJNATH_ICE_PRIO_STD 
    607662    return ((ice->prefs[type] & 0xFF) << 24) +  
    608663           ((local_pref & 0xFFFF)    << 8) + 
     
    10401095} 
    10411096 
    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 */ 
     1098static void on_timer(pj_timer_heap_t *th, pj_timer_entry *te) 
    10451099{ 
    10461100    pj_ice_sess *ice = (pj_ice_sess*) te->user_data; 
     1101    enum timer_type type = (enum timer_type)te->id; 
    10471102 
    10481103    PJ_UNUSED_ARG(th); 
    10491104 
    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 */ 
     1143static 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 
     1185done: 
     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    } 
    10541203} 
    10551204 
     
    10611210        ice->ice_status = status; 
    10621211     
     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 
    10631217        /* Log message */ 
    10641218        LOG4((ice->obj_name, "ICE process complete, status=%s",  
     
    10721226            pj_time_val delay = {0, 0}; 
    10731227 
    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; 
    10781229            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 */ 
     1236static 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} 
    10851259 
    10861260/* This function is called when one check completes */ 
     
    10881262                                   pj_ice_sess_check *check) 
    10891263{ 
     1264    pj_ice_sess_comp *comp; 
    10901265    unsigned i; 
    10911266 
    10921267    pj_assert(check->state >= PJ_ICE_SESS_CHECK_STATE_SUCCEEDED); 
     1268 
     1269    comp = find_comp(ice, check->lcand->comp_id); 
    10931270 
    10941271    /* 7.1.2.2.2.  Updating Pair States 
     
    11051282     */ 
    11061283    if (check->err_code==PJ_SUCCESS) { 
     1284 
    11071285        for (i=0; i<ice->clist.count; ++i) { 
    11081286            pj_ice_sess_check *c = &ice->clist.checks[i]; 
     
    11131291            } 
    11141292        } 
     1293 
     1294        LOG5((ice->obj_name, "Check %d is successful%s", 
     1295             GET_CHECK_ID(&ice->clist, check), 
     1296             (check->nominated ? "  and nominated" : ""))); 
     1297 
    11151298    } 
    11161299 
     
    11371320     */ 
    11381321    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); 
    11451322 
    11461323        for (i=0; i<ice->clist.count; ++i) { 
     
    11791356                } 
    11801357            } 
    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; 
    11891358        } 
    11901359    } 
     
    12121381     */ 
    12131382    for (i=0; i<ice->comp_cnt; ++i) { 
    1214         if (ice->comp[i].valid_check == NULL) 
     1383        if (ice->comp[i].nominated_check == NULL) 
    12151384            break; 
    12161385    } 
     
    12591428         * If agent's role is controlled, check if all components have 
    12601429         * valid pair. If it does, this means the controlled agent has 
    1261          * finished the check list early and it's waiting for controlling 
    1262          * agent to send a check with 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. 
    12631432         */ 
    12641433        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) 
    12741436                    break; 
    12751437            } 
    12761438 
    1277             if (comp_id <= ice->comp_cnt) { 
     1439            if (i < ice->comp_cnt) { 
    12781440                /* This component ID doesn't have valid pair. 
    12791441                 * Mark ICE as failed.  
     
    12851447                 * We should wait until we receive nominated checks. 
    12861448                 */ 
     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                } 
    12871469                return PJ_FALSE; 
    12881470            } 
    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; 
    12931552    } 
    12941553 
     
    12961555    return PJ_FALSE; 
    12971556} 
    1298  
    12991557 
    13001558 
     
    14311689} 
    14321690 
    1433 /* Perform check on the specified candidate pair */ 
     1691/* Perform check on the specified candidate pair. */ 
    14341692static pj_status_t perform_check(pj_ice_sess *ice,  
    14351693                                 pj_ice_sess_checklist *clist, 
    1436                                  unsigned check_id) 
     1694                                 unsigned check_id, 
     1695                                 pj_bool_t nominate) 
    14371696{ 
    14381697    pj_ice_sess_comp *comp; 
     
    14731732 
    14741733    /* 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 
    14751738    prio = CALC_CAND_PRIO(ice, PJ_ICE_CAND_TYPE_PRFLX, 0,  
    14761739                          lcand->comp_id); 
     1740#endif 
    14771741    pj_stun_msg_add_uint_attr(check->tdata->pool, check->tdata->msg,  
    14781742                              PJ_STUN_ATTR_PRIORITY, prio); 
     
    14821746     */ 
    14831747    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        } 
    14871753 
    14881754        pj_stun_msg_add_uint64_attr(check->tdata->pool, check->tdata->msg,  
     
    15501816 
    15511817        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); 
    15531819            if (status != PJ_SUCCESS) { 
    15541820                pj_mutex_unlock(ice->mutex); 
     
    15691835 
    15701836            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); 
    15721838                if (status != PJ_SUCCESS) { 
    15731839                    pj_mutex_unlock(ice->mutex); 
     
    15961862} 
    15971863 
     1864 
     1865/* Start sending connectivity check with USE-CANDIDATE */ 
     1866static 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} 
    15981924 
    15991925/* Timer callback to perform periodic check */ 
     
    16421968 
    16431969    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; 
    16441974 
    16451975    /* The agent examines the check list for the first media stream (a 
     
    18272157            LOG4((ice->obj_name, "Resending check because of role conflict")); 
    18282158            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); 
    18302161            pj_mutex_unlock(ice->mutex); 
    18312162            return; 
     
    19602291     */ 
    19612292 
    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    } 
    19712315 
    19722316    /* Sort valid_list */ 
    19732317    sort_checklist(&ice->valid_list); 
    19742318 
     2319    /* Update valid check and nominated check for the component */ 
     2320    update_comp_check(ice, new_check->lcand->comp_id, new_check); 
    19752321 
    19762322    /* 7.1.2.2.2.  Updating Pair States 
     
    23132659            c->state == PJ_ICE_SESS_CHECK_STATE_WAITING) 
    23142660        { 
     2661            /* See if we shall nominate this check */ 
     2662            pj_bool_t nominate = (c->nominated || ice->is_nominating); 
     2663 
    23152664            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); 
    23172666 
    23182667        } else if (c->state == PJ_ICE_SESS_CHECK_STATE_IN_PROGRESS) { 
     
    23372686                for (j=0; j<ice->valid_list.count; ++j) { 
    23382687                    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 */ 
    23402692                        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)); 
    23412699                    } 
    23422700                } 
     
    23622720 
    23632721        pj_ice_sess_check *c = &ice->clist.checks[ice->clist.count]; 
     2722        pj_bool_t nominate; 
    23642723 
    23652724        c->lcand = lcand; 
     
    23702729        c->err_code = PJ_SUCCESS; 
    23712730 
     2731        nominate = (c->nominated || ice->is_nominating); 
     2732 
    23722733        LOG4((ice->obj_name, "New triggered check added: %d",  
    23732734             ice->clist.count)); 
    2374         perform_check(ice, &ice->clist, ice->clist.count++); 
     2735        perform_check(ice, &ice->clist, ice->clist.count++, nominate); 
    23752736 
    23762737    } else { 
     
    23892750                                         unsigned src_addr_len) 
    23902751{ 
     2752    struct stun_data *sd; 
     2753 
    23912754    PJ_UNUSED_ARG(sess); 
    23922755    PJ_UNUSED_ARG(pkt); 
     
    23972760    PJ_UNUSED_ARG(src_addr_len); 
    23982761 
    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; 
    24022774} 
    24032775 
  • pjproject/trunk/pjnath/src/pjnath/ice_strans.c

    r2599 r2724  
    5151 * specify preference among candidates with the same type. Since 
    5252 * 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 
    5865 
    5966/* The candidate type preference when STUN candidate is used */ 
    6067static pj_uint8_t srflx_pref_table[4] =  
    6168{ 
     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 
    6275    /* Keep it to 2 bits */ 
    6376    1,  /**< PJ_ICE_HOST_PREF       */ 
     
    6578    3,  /**< PJ_ICE_PRFLX_PREF      */ 
    6679    0   /**< PJ_ICE_RELAYED_PREF    */ 
     80#endif 
    6781}; 
    6882 
     
    198212    pj_turn_alloc_param_default(&cfg->turn.alloc_param); 
    199213 
     214    pj_ice_sess_options_default(&cfg->opt); 
     215 
    200216    cfg->af = pj_AF_INET(); 
    201217    cfg->stun.port = PJ_STUN_PORT; 
    202218    cfg->turn.conn_type = PJ_TURN_TP_UDP; 
     219 
     220    cfg->stun.max_host_cands = 64; 
    203221} 
    204222 
     
    246264 
    247265    /* 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) { 
    249267        pj_stun_sock_cb stun_sock_cb; 
    250268        pj_ice_sess_cand *cand; 
     
    310328        } 
    311329 
    312         /* Add local addresses to host candidates, unless no_host_cands 
    313          * flag is set. 
     330        /* Add local addresses to host candidates, unless max_host_cands 
     331         * is set to zero. 
    314332         */ 
    315         if (ice_st->cfg.stun.no_host_cands == PJ_FALSE) { 
     333        if (ice_st->cfg.stun.max_host_cands) { 
    316334            pj_stun_sock_info stun_sock_info; 
    317335            unsigned i; 
     
    322340                return status; 
    323341 
    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            { 
    325345                char addrinfo[PJ_INET6_ADDRSTRLEN+10]; 
    326346                const pj_sockaddr *addr = &stun_sock_info.aliases[i]; 
     
    648668 
    649669/* 
     670 * Get the value of various options of the ICE stream transport. 
     671 */ 
     672PJ_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 */ 
     683PJ_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/* 
    650694 * Create ICE! 
    651695 */ 
     
    682726    /* Associate user data */ 
    683727    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); 
    684731 
    685732    /* If default candidate for components are SRFLX one, upload a custom 
  • pjproject/trunk/pjnath/src/pjnath/stun_auth.c

    r2394 r2724  
    529529    case PJ_STUN_SC_BAD_REQUEST:            /* 400 (Bad Request)            */ 
    530530    case PJ_STUN_SC_UNAUTHORIZED:           /* 401 (Unauthorized)           */ 
     531    case PJ_STUN_SC_STALE_NONCE:            /* 438 (Stale Nonce)            */ 
    531532 
    532533    /* Due to the way this response is generated here, we can't really 
  • pjproject/trunk/pjnath/src/pjnath/stun_msg_dump.c

    r2589 r2724  
    5858{ 
    5959    char *p = buffer, *end = buffer + length; 
     60    const char *attr_name = pj_stun_get_attr_name(ahdr->type); 
     61    char attr_buf[32]; 
    6062    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    } 
    6169 
    6270    len = pj_ansi_snprintf(p, end-p, 
    6371                           "  %s: length=%d", 
    64                            pj_stun_get_attr_name(ahdr->type), 
     72                           attr_name, 
    6573                           (int)ahdr->length); 
    6674    APPLY(); 
  • pjproject/trunk/pjnath/src/pjnath/stun_session.c

    r2589 r2724  
    220220    /* If the agent is sending a request, it SHOULD add a SOFTWARE attribute 
    221221     * 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. 
    223226     */ 
    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))  
    226231    { 
    227232        pj_stun_msg_add_string_attr(pool, msg, PJ_STUN_ATTR_SOFTWARE, 
     
    629634    PJ_ASSERT_ON_FAIL(sess, return); 
    630635    sess->log_flag = flags; 
     636} 
     637 
     638PJ_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; 
    631648} 
    632649 
  • pjproject/trunk/pjsip-apps/src/pjsua/pjsua_app.c

    r2650 r2724  
    265265    puts  ("Media Transport Options:"); 
    266266    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"); 
    268269    puts  ("  --ice-no-rtcp       Disable RTCP component in ICE (default: no)"); 
    269270    puts  ("  --rtp-port=N        Base port to try for RTP (default=4000)"); 
     
    477478           OPT_AUTO_ANSWER, OPT_AUTO_PLAY, OPT_AUTO_PLAY_HANGUP, OPT_AUTO_LOOP, 
    478479           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,  
    481482           OPT_TURN_TCP, OPT_TURN_USER, OPT_TURN_PASSWD, 
    482483           OPT_PLAY_FILE, OPT_PLAY_TONE, OPT_RTP_PORT, OPT_ADD_CODEC,  
     
    554555 
    555556        { "use-ice",    0, 0, OPT_USE_ICE}, 
     557        { "ice-regular",0, 0, OPT_ICE_REGULAR}, 
    556558        { "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}, 
    558560        { "ice-no-rtcp",0, 0, OPT_ICE_NO_RTCP}, 
    559561        { "turn-srv",   1, 0, OPT_TURN_SRV}, 
     
    993995            break; 
    994996 
     997        case OPT_ICE_REGULAR: 
     998            cfg->media_cfg.ice_opt.aggressive = PJ_FALSE; 
     999            break; 
     1000 
    9951001        case OPT_USE_TURN: 
    9961002            cfg->media_cfg.enable_turn = PJ_TRUE; 
    9971003            break; 
    9981004 
    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); 
    10011007            break; 
    10021008 
     
    16451651        pj_strcat2(&cfg, "--use-ice\n"); 
    16461652 
     1653    if (config->media_cfg.ice_opt.aggressive == PJ_FALSE) 
     1654        pj_strcat2(&cfg, "--ice-regular\n"); 
     1655 
    16471656    if (config->media_cfg.enable_turn) 
    16481657        pj_strcat2(&cfg, "--use-turn\n"); 
    16491658 
    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    } 
    16521664 
    16531665    if (config->media_cfg.ice_no_rtcp) 
     
    18861898    } 
    18871899 
    1888     if (config->cfg.force_lr) { 
     1900    if (!config->cfg.force_lr) { 
    18891901        pj_strcat2(&cfg, "--no-force-lr\n"); 
    18901902    } 
     
    36883700                } 
    36893701 
    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); 
    36913705            } 
    36923706            break; 
     
    47194733    for (i=0; i<app_config.cfg.max_calls; ++i) { 
    47204734        enum { MAX_RETRY = 10 }; 
     4735        pj_sock_t sock[2]; 
     4736        pjmedia_sock_info si; 
    47214737        unsigned j; 
    47224738 
     
    47254741 
    47264742        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); 
    47344791            if (port != 0) 
    47354792                port += 10; 
  • pjproject/trunk/pjsip-apps/src/samples/debug.c

    r2506 r2724  
    2929 *  #include "playfile.c" 
    3030 */ 
    31 #include "auddemo.c" 
     31#include "icedemo.c" 
    3232 
  • pjproject/trunk/pjsip-apps/src/samples/icedemo.c

    r2600 r2724  
    4040        unsigned    comp_cnt; 
    4141        pj_str_t    ns; 
    42         pj_bool_t   no_host; 
     42        int         max_host; 
     43        pj_bool_t   regular; 
    4344        pj_str_t    stun_srv; 
    4445        pj_str_t    turn_srv; 
     
    307308    /* -= Start initializing ICE stream transport config =- */ 
    308309 
    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; 
    311319 
    312320    /* Configure STUN/srflx candidate resolution */ 
     
    961969    */ 
    962970 
    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)) { 
    964972        PJ_LOG(1,(THIS_FILE, "Error: invalid component ID")); 
    965973        return; 
     
    11381146    puts(" --nameserver, -n IP       Configure nameserver to activate DNS SRV"); 
    11391147    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)"); 
    11411150    puts(" --help, -h                Display this screen."); 
    11421151    puts(""); 
     
    11661175        { "comp-cnt",           1, 0, 'c'}, 
    11671176        { "nameserver",         1, 0, 'n'}, 
    1168         { "no-host",            0, 0, 'H'}, 
     1177        { "max-host",           1, 0, 'H'}, 
    11691178        { "help",               0, 0, 'h'}, 
    11701179        { "stun-srv",           1, 0, 's'}, 
     
    11731182        { "turn-username",      1, 0, 'u'}, 
    11741183        { "turn-password",      1, 0, 'p'}, 
    1175         { "turn-fingerprint",   0, 0, 'F'} 
     1184        { "turn-fingerprint",   0, 0, 'F'}, 
     1185        { "regular",            0, 0, 'R'} 
    11761186    }; 
    11771187    int c, opt_id; 
     
    11791189 
    11801190    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) { 
    11831194        switch (c) { 
    11841195        case 'c': 
     
    11931204            break; 
    11941205        case 'H': 
    1195             icedemo.opt.no_host = PJ_TRUE; 
     1206            icedemo.opt.max_host = atoi(pj_optarg); 
    11961207            break; 
    11971208        case 'h': 
     
    12161227            icedemo.opt.turn_fingerprint = PJ_TRUE; 
    12171228            break; 
     1229        case 'R': 
     1230            icedemo.opt.regular = PJ_TRUE; 
     1231            break; 
    12181232        default: 
    12191233            printf("Argument \"%s\" is not valid. Use -h to see help", 
  • pjproject/trunk/pjsip-apps/src/samples/siprtp_report.c

    r2394 r2724  
    7878    /* Call identification */ 
    7979    len = pjsip_hdr_print_on(dlg->remote.info, userinfo, sizeof(userinfo)); 
    80     if (len < 1) 
     80    if (len < 0) 
    8181        pj_ansi_strcpy(userinfo, "<--uri too long-->"); 
    8282    else 
  • pjproject/trunk/pjsip/include/pjsip/sip_config.h

    r2394 r2724  
    228228 
    229229/** 
     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/** 
    230245 * Encode SIP headers in their short forms to reduce size. By default, 
    231246 * SIP headers in outgoing messages will be encoded in their full names.  
  • pjproject/trunk/pjsip/include/pjsip/sip_transport.h

    r2394 r2724  
    579579 */ 
    580580PJ_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 */ 
     591PJ_DECL(pj_status_t) pjsip_tx_data_encode(pjsip_tx_data *tdata); 
    581592 
    582593/** 
  • pjproject/trunk/pjsip/include/pjsua-lib/pjsua.h

    r2686 r2724  
    42614261 
    42624262    /** 
    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; 
    42664273 
    42674274    /** 
  • pjproject/trunk/pjsip/src/pjsip/sip_msg.c

    r2394 r2724  
    457457    /* Print each of the headers. */ 
    458458    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) 
    461461            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        } 
    469471    } 
    470472 
     
    16021604    char *endbuf = buf + size; 
    16031605    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 
    16041625    /* Route and Record-Route don't compact forms */ 
    16051626 
  • pjproject/trunk/pjsip/src/pjsip/sip_transaction.c

    r2646 r2724  
    17261726                      pjsip_tx_data_get_info(send_state->tdata), -sent, 
    17271727                      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            } 
    17281741        } 
    17291742    } 
  • pjproject/trunk/pjsip/src/pjsip/sip_transport.c

    r2394 r2724  
    435435} 
    436436 
     437/* 
     438 * Print the SIP message to transmit data buffer's internal buffer. 
     439 */ 
     440PJ_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 
    437476PJ_DEF(pj_bool_t) pjsip_tx_data_is_valid( pjsip_tx_data *tdata ) 
    438477{ 
     
    568607static pj_status_t mod_on_tx_msg(pjsip_tx_data *tdata) 
    569608{ 
    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); 
    602610} 
    603611 
  • pjproject/trunk/pjsip/src/pjsip/sip_ua_layer.c

    r2394 r2724  
    908908 
    909909    len = pjsip_hdr_print_on(dlg->remote.info, userinfo, sizeof(userinfo)); 
    910     if (len < 1) 
     910    if (len < 0) 
    911911        pj_ansi_strcpy(userinfo, "<--uri too long-->"); 
    912912    else 
  • pjproject/trunk/pjsip/src/pjsip/sip_util.c

    r2435 r2724  
    11361136        via->rport_param = 0; 
    11371137 
     1138        pjsip_tx_data_invalidate_msg(tdata); 
     1139 
    11381140        /* Send message using this transport. */ 
    11391141        status = pjsip_transport_send( stateless_data->cur_transport, 
     
    11811183    /* Copy server addresses */ 
    11821184    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    } 
    11831230 
    11841231    /* Process the addresses. */ 
  • pjproject/trunk/pjsip/src/pjsua-lib/pjsua_call.c

    r2695 r2724  
    26952695 
    26962696    len = pjsip_hdr_print_on(dlg->remote.info, userinfo, sizeof(userinfo)); 
    2697     if (len < 1) 
     2697    if (len < 0) 
    26982698        pj_ansi_strcpy(userinfo, "<--uri too long-->"); 
    26992699    else 
  • pjproject/trunk/pjsip/src/pjsua-lib/pjsua_core.c

    r2686 r2724  
    183183    cfg->snd_auto_close_time = 1; 
    184184 
     185    cfg->ice_max_host_cands = -1; 
     186    pj_ice_sess_options_default(&cfg->ice_opt); 
     187 
    185188    cfg->turn_conn_type = PJ_TURN_TP_UDP; 
    186189} 
     
    648651    if (log_cfg) { 
    649652        status = pjsua_reconfigure_logging(log_cfg); 
    650         PJ_ASSERT_RETURN(status == PJ_SUCCESS, status); 
     653        if (status != PJ_SUCCESS) 
     654            return status; 
    651655    } 
    652656 
  • pjproject/trunk/pjsip/src/pjsua-lib/pjsua_media.c

    r2679 r2724  
    805805    ice_cfg.resolver = pjsua_var.resolver; 
    806806     
     807    ice_cfg.opt = pjsua_var.media_cfg.ice_opt; 
     808 
    807809    /* Configure STUN settings */ 
    808810    if (pj_sockaddr_has_addr(&pjsua_var.stun_srv)) { 
     
    811813        ice_cfg.stun.port = pj_sockaddr_get_port(&pjsua_var.stun_srv); 
    812814    } 
    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; 
    814817 
    815818    /* Configure TURN settings */ 
  • pjproject/trunk/pjsip/src/test/msg_test.c

    r2695 r2724  
    366366 
    367367    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) { 
    370370            status = -40; 
    371371            goto on_return; 
     
    374374        str1.slen = len; 
    375375 
    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) { 
    378378            status = -50; 
    379379            goto on_return; 
     
    19451945        output = (char*) pj_pool_alloc(pool, 1024); 
    19461946        len = pjsip_hdr_print_on(parsed_hdr1, output, 1024); 
    1947         if (len < 1 || len >= 1024) { 
     1947        if (len < 0 || len >= 1024) { 
    19481948            PJ_LOG(3,(THIS_FILE, "    header too long: %s: %s", test->hname, test->hcontent)); 
    19491949            return -530; 
Note: See TracChangeset for help on using the changeset viewer.