Ignore:
Timestamp:
Dec 28, 2016 3:40:07 AM (7 years ago)
Author:
nanang
Message:

Re #1900: More merged from trunk (r5512 mistakenly contains merged changes in third-party dir only).

Location:
pjproject/branches/projects/uwp
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • pjproject/branches/projects/uwp

  • pjproject/branches/projects/uwp/pjnath/src/pjnath/ice_strans.c

    r5151 r5513  
    4949}; 
    5050 
     51 
     52#define CREATE_TP_ID(type, idx)     (pj_uint8_t)((type << 6) | idx) 
     53#define GET_TP_TYPE(transport_id)   ((transport_id & 0xC0) >> 6) 
     54#define GET_TP_IDX(transport_id)    (transport_id & 0x3F) 
     55 
     56 
    5157/* Candidate's local preference values. This is mostly used to 
    5258 * specify preference among candidates with the same type. Since 
     
    149155    unsigned             comp_id;       /**< Component ID.              */ 
    150156 
    151     pj_stun_sock        *stun_sock;     /**< STUN transport.            */ 
    152     pj_turn_sock        *turn_sock;     /**< TURN relay transport.      */ 
    153     pj_bool_t            turn_log_off;  /**< TURN loggin off?           */ 
    154     unsigned             turn_err_cnt;  /**< TURN disconnected count.   */ 
    155  
     157    struct { 
     158        pj_stun_sock    *sock;          /**< STUN transport.            */ 
     159    } stun[PJ_ICE_MAX_STUN]; 
     160 
     161    struct { 
     162        pj_turn_sock    *sock;          /**< TURN relay transport.      */ 
     163        pj_bool_t        log_off;       /**< TURN loggin off?           */ 
     164        unsigned         err_cnt;       /**< TURN disconnected count.   */ 
     165    } turn[PJ_ICE_MAX_TURN]; 
     166 
     167    pj_bool_t            creating;      /**< Is creating the candidates?*/ 
    156168    unsigned             cand_cnt;      /**< # of candidates/aliaes.    */ 
    157169    pj_ice_sess_cand     cand_list[PJ_ICE_ST_MAX_CAND]; /**< Cand array */ 
     
    188200 
    189201 
     202/** 
     203 * This structure describe user data for STUN/TURN sockets of the 
     204 * ICE stream transport. 
     205 */ 
     206typedef struct sock_user_data 
     207{ 
     208    pj_ice_strans_comp      *comp; 
     209    pj_uint8_t               transport_id; 
     210 
     211} sock_user_data; 
     212 
     213 
    190214/* Validate configuration */ 
    191215static pj_status_t pj_ice_strans_cfg_check_valid(const pj_ice_strans_cfg *cfg) 
     
    209233 
    210234    pj_stun_config_init(&cfg->stun_cfg, NULL, 0, NULL, NULL); 
    211     pj_stun_sock_cfg_default(&cfg->stun.cfg); 
    212     pj_turn_alloc_param_default(&cfg->turn.alloc_param); 
    213     pj_turn_sock_cfg_default(&cfg->turn.cfg); 
    214  
     235    pj_ice_strans_stun_cfg_default(&cfg->stun); 
     236    pj_ice_strans_turn_cfg_default(&cfg->turn); 
    215237    pj_ice_sess_options_default(&cfg->opt); 
     238} 
     239 
     240 
     241/* 
     242 * Initialize ICE STUN transport configuration with default values. 
     243 */ 
     244PJ_DEF(void) pj_ice_strans_stun_cfg_default(pj_ice_strans_stun_cfg *cfg) 
     245{ 
     246    pj_bzero(cfg, sizeof(*cfg)); 
    216247 
    217248    cfg->af = pj_AF_INET(); 
    218     cfg->stun.port = PJ_STUN_PORT; 
    219     cfg->turn.conn_type = PJ_TURN_TP_UDP; 
    220  
    221     cfg->stun.max_host_cands = 64; 
    222     cfg->stun.ignore_stun_error = PJ_FALSE; 
     249    cfg->port = PJ_STUN_PORT; 
     250    cfg->max_host_cands = 64; 
     251    cfg->ignore_stun_error = PJ_FALSE; 
     252    pj_stun_sock_cfg_default(&cfg->cfg); 
     253} 
     254 
     255 
     256/* 
     257 * Initialize ICE TURN transport configuration with default values. 
     258 */ 
     259PJ_DEF(void) pj_ice_strans_turn_cfg_default(pj_ice_strans_turn_cfg *cfg) 
     260{ 
     261    pj_bzero(cfg, sizeof(*cfg)); 
     262 
     263    cfg->af = pj_AF_INET(); 
     264    cfg->conn_type = PJ_TURN_TP_UDP; 
     265    pj_turn_alloc_param_default(&cfg->alloc_param); 
     266    pj_turn_sock_cfg_default(&cfg->cfg); 
    223267} 
    224268 
     
    231275                                     const pj_ice_strans_cfg *src) 
    232276{ 
     277    unsigned i; 
     278 
    233279    pj_memcpy(dst, src, sizeof(*src)); 
    234280 
    235281    if (src->stun.server.slen) 
    236282        pj_strdup(pool, &dst->stun.server, &src->stun.server); 
     283 
     284    for (i = 0; i < src->stun_tp_cnt; ++i) { 
     285        if (src->stun_tp[i].server.slen) 
     286            pj_strdup(pool, &dst->stun_tp[i].server, 
     287                      &src->stun_tp[i].server); 
     288    } 
     289 
    237290    if (src->turn.server.slen) 
    238291        pj_strdup(pool, &dst->turn.server, &src->turn.server); 
    239     pj_stun_auth_cred_dup(pool, &dst->turn.auth_cred, 
    240                           &src->turn.auth_cred); 
     292    pj_stun_auth_cred_dup(pool, &dst->turn.auth_cred, &src->turn.auth_cred); 
     293 
     294    for (i = 0; i < src->turn_tp_cnt; ++i) { 
     295        if (src->turn_tp[i].server.slen) 
     296            pj_strdup(pool, &dst->turn_tp[i].server, 
     297                      &src->turn_tp[i].server); 
     298        pj_stun_auth_cred_dup(pool, &dst->turn_tp[i].auth_cred, 
     299                              &src->turn_tp[i].auth_cred); 
     300    } 
    241301} 
    242302 
     
    246306 */ 
    247307static pj_status_t add_update_turn(pj_ice_strans *ice_st, 
    248                                    pj_ice_strans_comp *comp) 
    249 { 
     308                                   pj_ice_strans_comp *comp, 
     309                                   unsigned idx) 
     310{ 
     311    pj_ice_sess_cand *cand = NULL; 
     312    pj_ice_strans_turn_cfg *turn_cfg = &ice_st->cfg.turn_tp[idx]; 
     313    pj_turn_sock_cfg *sock_cfg  = &turn_cfg->cfg; 
     314    unsigned comp_idx = comp->comp_id - 1; 
    250315    pj_turn_sock_cb turn_sock_cb; 
    251     pj_ice_sess_cand *cand = NULL; 
     316    sock_user_data *data; 
    252317    unsigned i; 
     318    pj_uint8_t tp_id; 
    253319    pj_status_t status; 
    254320 
     321    /* Check if TURN transport is configured */ 
     322    if (turn_cfg->server.slen == 0) 
     323        return PJ_SUCCESS; 
     324 
    255325    /* Find relayed candidate in the component */ 
     326    tp_id = CREATE_TP_ID(TP_TURN, idx); 
    256327    for (i=0; i<comp->cand_cnt; ++i) { 
    257         if (comp->cand_list[i].type == PJ_ICE_CAND_TYPE_RELAYED) { 
     328        if (comp->cand_list[i].transport_id == tp_id) { 
    258329            cand = &comp->cand_list[i]; 
    259330            break; 
     
    287358 
    288359    /* Override with component specific QoS settings, if any */ 
    289     if (ice_st->cfg.comp[comp->comp_id-1].qos_type) { 
    290         ice_st->cfg.turn.cfg.qos_type = 
    291             ice_st->cfg.comp[comp->comp_id-1].qos_type; 
    292     } 
    293     if (ice_st->cfg.comp[comp->comp_id-1].qos_params.flags) { 
    294         pj_memcpy(&ice_st->cfg.turn.cfg.qos_params, 
    295                   &ice_st->cfg.comp[comp->comp_id-1].qos_params, 
    296                   sizeof(ice_st->cfg.turn.cfg.qos_params)); 
    297     } 
     360    if (ice_st->cfg.comp[comp_idx].qos_type) 
     361        sock_cfg->qos_type = ice_st->cfg.comp[comp_idx].qos_type; 
     362    if (ice_st->cfg.comp[comp_idx].qos_params.flags) 
     363        pj_memcpy(&sock_cfg->qos_params, 
     364                  &ice_st->cfg.comp[comp_idx].qos_params, 
     365                  sizeof(sock_cfg->qos_params)); 
    298366 
    299367    /* Override with component specific socket buffer size settings, if any */ 
    300     if (ice_st->cfg.comp[comp->comp_id-1].so_rcvbuf_size > 0) { 
    301         ice_st->cfg.turn.cfg.so_rcvbuf_size = 
    302             ice_st->cfg.comp[comp->comp_id-1].so_rcvbuf_size; 
    303     } 
    304     if (ice_st->cfg.comp[comp->comp_id-1].so_sndbuf_size > 0) { 
    305         ice_st->cfg.turn.cfg.so_sndbuf_size = 
    306             ice_st->cfg.comp[comp->comp_id-1].so_sndbuf_size; 
    307     } 
     368    if (ice_st->cfg.comp[comp_idx].so_rcvbuf_size > 0) 
     369        sock_cfg->so_rcvbuf_size = ice_st->cfg.comp[comp_idx].so_rcvbuf_size; 
     370    if (ice_st->cfg.comp[comp_idx].so_sndbuf_size > 0) 
     371        sock_cfg->so_sndbuf_size = ice_st->cfg.comp[comp_idx].so_sndbuf_size; 
     372 
     373    /* Add relayed candidate with pending status if there's no existing one */ 
     374    if (cand == NULL) { 
     375        cand = &comp->cand_list[comp->cand_cnt]; 
     376        cand->type = PJ_ICE_CAND_TYPE_RELAYED; 
     377        cand->status = PJ_EPENDING; 
     378        cand->local_pref = RELAY_PREF; 
     379        cand->transport_id = CREATE_TP_ID(TP_TURN, idx); 
     380        cand->comp_id = (pj_uint8_t) comp->comp_id; 
     381    } 
     382 
     383    /* Allocate and initialize TURN socket data */ 
     384    data = PJ_POOL_ZALLOC_T(ice_st->pool, sock_user_data); 
     385    data->comp = comp; 
     386    data->transport_id = cand->transport_id; 
    308387 
    309388    /* Create the TURN transport */ 
    310     status = pj_turn_sock_create(&ice_st->cfg.stun_cfg, ice_st->cfg.af, 
    311                                  ice_st->cfg.turn.conn_type, 
    312                                  &turn_sock_cb, &ice_st->cfg.turn.cfg, 
    313                                  comp, &comp->turn_sock); 
     389    status = pj_turn_sock_create(&ice_st->cfg.stun_cfg, turn_cfg->af, 
     390                                 turn_cfg->conn_type, 
     391                                 &turn_sock_cb, sock_cfg, 
     392                                 data, &comp->turn[idx].sock); 
    314393    if (status != PJ_SUCCESS) { 
    315394        return status; 
     
    320399 
    321400    /* Start allocation */ 
    322     status=pj_turn_sock_alloc(comp->turn_sock, 
    323                               &ice_st->cfg.turn.server, 
    324                               ice_st->cfg.turn.port, 
     401    status=pj_turn_sock_alloc(comp->turn[idx].sock, 
     402                              &turn_cfg->server, 
     403                              turn_cfg->port, 
    325404                              ice_st->cfg.resolver, 
    326                               &ice_st->cfg.turn.auth_cred, 
    327                               &ice_st->cfg.turn.alloc_param); 
     405                              &turn_cfg->auth_cred, 
     406                              &turn_cfg->alloc_param); 
    328407    if (status != PJ_SUCCESS) { 
    329408        ///sess_dec_ref(ice_st); 
     
    331410    } 
    332411 
    333     /* Add relayed candidate with pending status if there's no existing one */ 
    334     if (cand == NULL) { 
    335         cand = &comp->cand_list[comp->cand_cnt++]; 
    336         cand->type = PJ_ICE_CAND_TYPE_RELAYED; 
    337         cand->status = PJ_EPENDING; 
    338         cand->local_pref = RELAY_PREF; 
    339         cand->transport_id = TP_TURN; 
    340         cand->comp_id = (pj_uint8_t) comp->comp_id; 
    341     } 
     412    /* Commit the relayed candidate. */ 
     413    comp->cand_cnt++; 
    342414 
    343415    PJ_LOG(4,(ice_st->obj_name, 
     
    348420} 
    349421 
     422static pj_bool_t ice_cand_equals(pj_ice_sess_cand *lcand,  
     423                                 pj_ice_sess_cand *rcand) 
     424{ 
     425    if (lcand == NULL && rcand == NULL){ 
     426        return PJ_TRUE; 
     427    } 
     428    if (lcand == NULL || rcand == NULL){ 
     429        return PJ_FALSE; 
     430    } 
     431     
     432    if (lcand->type != rcand->type 
     433        || lcand->status != rcand->status 
     434        || lcand->comp_id != rcand->comp_id 
     435        || lcand->transport_id != rcand->transport_id 
     436        || lcand->local_pref != rcand->local_pref 
     437        || lcand->prio != rcand->prio 
     438        || pj_sockaddr_cmp(&lcand->addr, &rcand->addr) != 0 
     439        || pj_sockaddr_cmp(&lcand->base_addr, &rcand->base_addr) != 0) 
     440    { 
     441        return PJ_FALSE; 
     442    } 
     443     
     444    return PJ_TRUE; 
     445} 
     446 
     447 
     448static pj_status_t add_stun_and_host(pj_ice_strans *ice_st, 
     449                                     pj_ice_strans_comp *comp, 
     450                                     unsigned idx) 
     451{ 
     452    pj_ice_sess_cand *cand; 
     453    pj_ice_strans_stun_cfg *stun_cfg = &ice_st->cfg.stun_tp[idx]; 
     454    pj_stun_sock_cfg *sock_cfg  = &stun_cfg->cfg; 
     455    unsigned comp_idx = comp->comp_id - 1; 
     456    pj_stun_sock_cb stun_sock_cb; 
     457    sock_user_data *data; 
     458    pj_status_t status; 
     459 
     460    /* Check if STUN transport or host candidate is configured */ 
     461    if (stun_cfg->server.slen == 0 && stun_cfg->max_host_cands == 0) 
     462        return PJ_SUCCESS; 
     463 
     464    /* Initialize STUN socket callback */ 
     465    pj_bzero(&stun_sock_cb, sizeof(stun_sock_cb)); 
     466    stun_sock_cb.on_rx_data = &stun_on_rx_data; 
     467    stun_sock_cb.on_status = &stun_on_status; 
     468    stun_sock_cb.on_data_sent = &stun_on_data_sent; 
     469 
     470    /* Override component specific QoS settings, if any */ 
     471    if (ice_st->cfg.comp[comp_idx].qos_type) { 
     472        sock_cfg->qos_type = ice_st->cfg.comp[comp_idx].qos_type; 
     473    } 
     474    if (ice_st->cfg.comp[comp_idx].qos_params.flags) { 
     475        pj_memcpy(&sock_cfg->qos_params, 
     476                  &ice_st->cfg.comp[comp_idx].qos_params, 
     477                  sizeof(sock_cfg->qos_params)); 
     478    } 
     479 
     480    /* Override component specific socket buffer size settings, if any */ 
     481    if (ice_st->cfg.comp[comp_idx].so_rcvbuf_size > 0) { 
     482        sock_cfg->so_rcvbuf_size = ice_st->cfg.comp[comp_idx].so_rcvbuf_size; 
     483    } 
     484    if (ice_st->cfg.comp[comp_idx].so_sndbuf_size > 0) { 
     485        sock_cfg->so_sndbuf_size = ice_st->cfg.comp[comp_idx].so_sndbuf_size; 
     486    } 
     487 
     488    /* Prepare srflx candidate with pending status. */ 
     489    cand = &comp->cand_list[comp->cand_cnt]; 
     490    cand->type = PJ_ICE_CAND_TYPE_SRFLX; 
     491    cand->status = PJ_EPENDING; 
     492    cand->local_pref = SRFLX_PREF; 
     493    cand->transport_id = CREATE_TP_ID(TP_STUN, idx); 
     494    cand->comp_id = (pj_uint8_t) comp->comp_id; 
     495 
     496    /* Allocate and initialize STUN socket data */ 
     497    data = PJ_POOL_ZALLOC_T(ice_st->pool, sock_user_data); 
     498    data->comp = comp; 
     499    data->transport_id = cand->transport_id; 
     500 
     501    /* Create the STUN transport */ 
     502    status = pj_stun_sock_create(&ice_st->cfg.stun_cfg, NULL, 
     503                                 stun_cfg->af, &stun_sock_cb, 
     504                                 sock_cfg, data, &comp->stun[idx].sock); 
     505    if (status != PJ_SUCCESS) 
     506        return status; 
     507 
     508    /* Start STUN Binding resolution and add srflx candidate 
     509     * only if server is set 
     510     */ 
     511    if (stun_cfg->server.slen) { 
     512        pj_stun_sock_info stun_sock_info; 
     513 
     514        /* Add pending job */ 
     515        ///sess_add_ref(ice_st); 
     516 
     517        PJ_LOG(4,(ice_st->obj_name, 
     518                  "Comp %d: srflx candidate starts Binding discovery", 
     519                  comp->comp_id)); 
     520 
     521        pj_log_push_indent(); 
     522 
     523        /* Start Binding resolution */ 
     524        status = pj_stun_sock_start(comp->stun[idx].sock, &stun_cfg->server, 
     525                                    stun_cfg->port, ice_st->cfg.resolver); 
     526        if (status != PJ_SUCCESS) { 
     527            ///sess_dec_ref(ice_st); 
     528            pj_log_pop_indent(); 
     529            return status; 
     530        } 
     531 
     532        /* Enumerate addresses */ 
     533        status = pj_stun_sock_get_info(comp->stun[idx].sock, &stun_sock_info); 
     534        if (status != PJ_SUCCESS) { 
     535            ///sess_dec_ref(ice_st); 
     536            pj_log_pop_indent(); 
     537            return status; 
     538        } 
     539 
     540        /* Update and commit the srflx candidate. */ 
     541        pj_sockaddr_cp(&cand->base_addr, &stun_sock_info.aliases[0]); 
     542        pj_sockaddr_cp(&cand->rel_addr, &cand->base_addr); 
     543        pj_ice_calc_foundation(ice_st->pool, &cand->foundation, 
     544                               cand->type, &cand->base_addr); 
     545        comp->cand_cnt++; 
     546 
     547        /* Set default candidate to srflx */ 
     548        comp->default_cand = (unsigned)(cand - comp->cand_list); 
     549 
     550        pj_log_pop_indent(); 
     551    } 
     552 
     553    /* Add local addresses to host candidates, unless max_host_cands 
     554     * is set to zero. 
     555     */ 
     556    if (stun_cfg->max_host_cands) { 
     557        pj_stun_sock_info stun_sock_info; 
     558        unsigned i; 
     559 
     560        /* Enumerate addresses */ 
     561        status = pj_stun_sock_get_info(comp->stun[idx].sock, &stun_sock_info); 
     562        if (status != PJ_SUCCESS) 
     563            return status; 
     564 
     565        for (i=0; i<stun_sock_info.alias_cnt && 
     566                  i<stun_cfg->max_host_cands; ++i) 
     567        { 
     568            unsigned j; 
     569            pj_bool_t cand_duplicate = PJ_FALSE; 
     570            char addrinfo[PJ_INET6_ADDRSTRLEN+10]; 
     571            const pj_sockaddr *addr = &stun_sock_info.aliases[i]; 
     572 
     573            /* Leave one candidate for relay */ 
     574            if (comp->cand_cnt >= PJ_ICE_ST_MAX_CAND-1) { 
     575                PJ_LOG(4,(ice_st->obj_name, "Too many host candidates")); 
     576                break; 
     577            } 
     578 
     579            /* Ignore loopback addresses if cfg->stun.loop_addr is unset */ 
     580            if (stun_cfg->loop_addr==PJ_FALSE) { 
     581                if (stun_cfg->af == pj_AF_INET() &&  
     582                    (pj_ntohl(addr->ipv4.sin_addr.s_addr)>>24)==127) 
     583                { 
     584                    continue; 
     585                } 
     586                else if (stun_cfg->af == pj_AF_INET6()) { 
     587                    pj_in6_addr in6addr = {{0}}; 
     588                    in6addr.s6_addr[15] = 1; 
     589                    if (pj_memcmp(&in6addr, &addr->ipv6.sin6_addr, 
     590                                  sizeof(in6addr))==0) 
     591                    { 
     592                        continue; 
     593                    } 
     594                } 
     595            } 
     596 
     597            /* Ignore IPv6 link-local address */ 
     598            if (stun_cfg->af == pj_AF_INET6()) { 
     599                const pj_in6_addr *a = &addr->ipv6.sin6_addr; 
     600                if (a->s6_addr[0] == 0xFE && (a->s6_addr[1] & 0xC0) == 0x80) 
     601                    continue; 
     602            } 
     603 
     604            cand = &comp->cand_list[comp->cand_cnt]; 
     605 
     606            cand->type = PJ_ICE_CAND_TYPE_HOST; 
     607            cand->status = PJ_SUCCESS; 
     608            cand->local_pref = HOST_PREF; 
     609            cand->transport_id = CREATE_TP_ID(TP_STUN, idx); 
     610            cand->comp_id = (pj_uint8_t) comp->comp_id; 
     611            pj_sockaddr_cp(&cand->addr, addr); 
     612            pj_sockaddr_cp(&cand->base_addr, addr); 
     613            pj_bzero(&cand->rel_addr, sizeof(cand->rel_addr)); 
     614             
     615            /* Check if not already in list */ 
     616            for (j=0; j<comp->cand_cnt; j++) { 
     617                if (ice_cand_equals(cand, &comp->cand_list[j])) { 
     618                    cand_duplicate = PJ_TRUE; 
     619                    break; 
     620                } 
     621            } 
     622 
     623            if (cand_duplicate) { 
     624                PJ_LOG(4, (ice_st->obj_name, 
     625                       "Comp %d: host candidate %s is a duplicate", 
     626                       comp->comp_id, pj_sockaddr_print(&cand->addr, addrinfo, 
     627                       sizeof(addrinfo), 3))); 
     628 
     629                pj_bzero(&cand->addr, sizeof(cand->addr)); 
     630                pj_bzero(&cand->base_addr, sizeof(cand->base_addr)); 
     631                continue; 
     632            } else { 
     633                comp->cand_cnt+=1; 
     634            } 
     635             
     636            pj_ice_calc_foundation(ice_st->pool, &cand->foundation, 
     637                                   cand->type, &cand->base_addr); 
     638 
     639            PJ_LOG(4,(ice_st->obj_name, 
     640                      "Comp %d: host candidate %s added", 
     641                      comp->comp_id, pj_sockaddr_print(&cand->addr, addrinfo, 
     642                                                      sizeof(addrinfo), 3))); 
     643        } 
     644    } 
     645 
     646    return PJ_SUCCESS; 
     647} 
     648 
    350649 
    351650/* 
     
    355654{ 
    356655    pj_ice_strans_comp *comp = NULL; 
     656    unsigned i; 
    357657    pj_status_t status; 
    358658 
     
    367667    comp->ice_st = ice_st; 
    368668    comp->comp_id = comp_id; 
     669    comp->creating = PJ_TRUE; 
    369670 
    370671    ice_st->comp[comp_id-1] = comp; 
     
    374675 
    375676    /* Create STUN transport if configured */ 
    376     if (ice_st->cfg.stun.server.slen || ice_st->cfg.stun.max_host_cands) { 
    377         pj_stun_sock_cb stun_sock_cb; 
    378         pj_ice_sess_cand *cand; 
    379  
    380         pj_bzero(&stun_sock_cb, sizeof(stun_sock_cb)); 
    381         stun_sock_cb.on_rx_data = &stun_on_rx_data; 
    382         stun_sock_cb.on_status = &stun_on_status; 
    383         stun_sock_cb.on_data_sent = &stun_on_data_sent; 
    384  
    385         /* Override component specific QoS settings, if any */ 
    386         if (ice_st->cfg.comp[comp_id-1].qos_type) { 
    387             ice_st->cfg.stun.cfg.qos_type = 
    388                 ice_st->cfg.comp[comp_id-1].qos_type; 
    389         } 
    390         if (ice_st->cfg.comp[comp_id-1].qos_params.flags) { 
    391             pj_memcpy(&ice_st->cfg.stun.cfg.qos_params, 
    392                       &ice_st->cfg.comp[comp_id-1].qos_params, 
    393                       sizeof(ice_st->cfg.stun.cfg.qos_params)); 
    394         } 
    395  
    396         /* Override component specific socket buffer size settings, if any */ 
    397         if (ice_st->cfg.comp[comp_id-1].so_rcvbuf_size > 0) { 
    398             ice_st->cfg.stun.cfg.so_rcvbuf_size = 
    399                 ice_st->cfg.comp[comp_id-1].so_rcvbuf_size; 
    400         } 
    401         if (ice_st->cfg.comp[comp_id-1].so_sndbuf_size > 0) { 
    402             ice_st->cfg.stun.cfg.so_sndbuf_size = 
    403                 ice_st->cfg.comp[comp_id-1].so_sndbuf_size; 
    404         } 
    405  
    406         /* Create the STUN transport */ 
    407         status = pj_stun_sock_create(&ice_st->cfg.stun_cfg, NULL, 
    408                                      ice_st->cfg.af, &stun_sock_cb, 
    409                                      &ice_st->cfg.stun.cfg, 
    410                                      comp, &comp->stun_sock); 
    411         if (status != PJ_SUCCESS) 
    412             return status; 
    413  
    414         /* Start STUN Binding resolution and add srflx candidate 
    415          * only if server is set 
    416          */ 
    417         if (ice_st->cfg.stun.server.slen) { 
    418             pj_stun_sock_info stun_sock_info; 
    419  
    420             /* Add pending job */ 
    421             ///sess_add_ref(ice_st); 
    422  
    423             PJ_LOG(4,(ice_st->obj_name, 
    424                       "Comp %d: srflx candidate starts Binding discovery", 
    425                       comp_id)); 
    426  
    427             pj_log_push_indent(); 
    428  
    429             /* Start Binding resolution */ 
    430             status = pj_stun_sock_start(comp->stun_sock, 
    431                                         &ice_st->cfg.stun.server, 
    432                                         ice_st->cfg.stun.port, 
    433                                         ice_st->cfg.resolver); 
    434             if (status != PJ_SUCCESS) { 
    435                 ///sess_dec_ref(ice_st); 
    436                 pj_log_pop_indent(); 
    437                 return status; 
    438             } 
    439  
    440             /* Enumerate addresses */ 
    441             status = pj_stun_sock_get_info(comp->stun_sock, &stun_sock_info); 
    442             if (status != PJ_SUCCESS) { 
    443                 ///sess_dec_ref(ice_st); 
    444                 pj_log_pop_indent(); 
    445                 return status; 
    446             } 
    447  
    448             /* Add srflx candidate with pending status. */ 
    449             cand = &comp->cand_list[comp->cand_cnt++]; 
    450             cand->type = PJ_ICE_CAND_TYPE_SRFLX; 
    451             cand->status = PJ_EPENDING; 
    452             cand->local_pref = SRFLX_PREF; 
    453             cand->transport_id = TP_STUN; 
    454             cand->comp_id = (pj_uint8_t) comp_id; 
    455             pj_sockaddr_cp(&cand->base_addr, &stun_sock_info.aliases[0]); 
    456             pj_sockaddr_cp(&cand->rel_addr, &cand->base_addr); 
    457             pj_ice_calc_foundation(ice_st->pool, &cand->foundation, 
    458                                    cand->type, &cand->base_addr); 
    459  
    460             /* Set default candidate to srflx */ 
    461             comp->default_cand = (unsigned)(cand - comp->cand_list); 
    462  
    463             pj_log_pop_indent(); 
    464         } 
    465  
    466         /* Add local addresses to host candidates, unless max_host_cands 
    467          * is set to zero. 
    468          */ 
    469         if (ice_st->cfg.stun.max_host_cands) { 
    470             pj_stun_sock_info stun_sock_info; 
    471             unsigned i; 
    472  
    473             /* Enumerate addresses */ 
    474             status = pj_stun_sock_get_info(comp->stun_sock, &stun_sock_info); 
    475             if (status != PJ_SUCCESS) 
    476                 return status; 
    477  
    478             for (i=0; i<stun_sock_info.alias_cnt && 
    479                       i<ice_st->cfg.stun.max_host_cands; ++i) 
    480             { 
    481                 char addrinfo[PJ_INET6_ADDRSTRLEN+10]; 
    482                 const pj_sockaddr *addr = &stun_sock_info.aliases[i]; 
    483  
    484                 /* Leave one candidate for relay */ 
    485                 if (comp->cand_cnt >= PJ_ICE_ST_MAX_CAND-1) { 
    486                     PJ_LOG(4,(ice_st->obj_name, "Too many host candidates")); 
    487                     break; 
    488                 } 
    489  
    490                 /* Ignore loopback addresses unless cfg->stun.loop_addr 
    491                  * is set 
    492                  */ 
    493                 if ((pj_ntohl(addr->ipv4.sin_addr.s_addr)>>24)==127) { 
    494                     if (ice_st->cfg.stun.loop_addr==PJ_FALSE) 
    495                         continue; 
    496                 } 
    497  
    498                 cand = &comp->cand_list[comp->cand_cnt++]; 
    499  
    500                 cand->type = PJ_ICE_CAND_TYPE_HOST; 
    501                 cand->status = PJ_SUCCESS; 
    502                 cand->local_pref = HOST_PREF; 
    503                 cand->transport_id = TP_STUN; 
    504                 cand->comp_id = (pj_uint8_t) comp_id; 
    505                 pj_sockaddr_cp(&cand->addr, addr); 
    506                 pj_sockaddr_cp(&cand->base_addr, addr); 
    507                 pj_bzero(&cand->rel_addr, sizeof(cand->rel_addr)); 
    508                 pj_ice_calc_foundation(ice_st->pool, &cand->foundation, 
    509                                        cand->type, &cand->base_addr); 
    510  
    511                 PJ_LOG(4,(ice_st->obj_name, 
    512                           "Comp %d: host candidate %s added", 
    513                           comp_id, pj_sockaddr_print(&cand->addr, addrinfo, 
    514                                                      sizeof(addrinfo), 3))); 
    515             } 
     677    for (i=0; i<ice_st->cfg.stun_tp_cnt; ++i) { 
     678        status = add_stun_and_host(ice_st, comp, i); 
     679        if (status != PJ_SUCCESS) { 
     680            PJ_PERROR(3,(ice_st->obj_name, status, 
     681                         "Failed creating STUN transport #%d for comp %d", 
     682                         i, comp->comp_id)); 
     683            //return status; 
    516684        } 
    517685    } 
    518686 
    519687    /* Create TURN relay if configured. */ 
    520     if (ice_st->cfg.turn.server.slen) { 
    521         add_update_turn(ice_st, comp); 
    522     } 
     688    for (i=0; i<ice_st->cfg.turn_tp_cnt; ++i) { 
     689        status = add_update_turn(ice_st, comp, i); 
     690        if (status != PJ_SUCCESS) { 
     691            PJ_PERROR(3,(ice_st->obj_name, status, 
     692                         "Failed creating TURN transport #%d for comp %d", 
     693                         i, comp->comp_id)); 
     694            //return status; 
     695        } 
     696    } 
     697 
     698    /* Done creating all the candidates */ 
     699    comp->creating = PJ_FALSE; 
    523700 
    524701    /* It's possible that we end up without any candidates */ 
     
    582759 
    583760    pj_ice_strans_cfg_copy(pool, &ice_st->cfg, cfg); 
    584     ice_st->cfg.stun.cfg.grp_lock = ice_st->grp_lock; 
    585     ice_st->cfg.turn.cfg.grp_lock = ice_st->grp_lock; 
     761 
     762    /* To maintain backward compatibility, check if old/deprecated setting is set 
     763     * and the new setting is not, copy the value to the new setting. 
     764     */ 
     765    if (cfg->stun_tp_cnt == 0 &&  
     766        (cfg->stun.server.slen || cfg->stun.max_host_cands)) 
     767    { 
     768        ice_st->cfg.stun_tp_cnt = 1; 
     769        ice_st->cfg.stun_tp[0] = ice_st->cfg.stun; 
     770    } 
     771    if (cfg->turn_tp_cnt == 0 && cfg->turn.server.slen) { 
     772        ice_st->cfg.turn_tp_cnt = 1; 
     773        ice_st->cfg.turn_tp[0] = ice_st->cfg.turn; 
     774    } 
     775 
     776    for (i=0; i<ice_st->cfg.stun_tp_cnt; ++i) 
     777        ice_st->cfg.stun_tp[i].cfg.grp_lock = ice_st->grp_lock; 
     778    for (i=0; i<ice_st->cfg.turn_tp_cnt; ++i) 
     779        ice_st->cfg.turn_tp[i].cfg.grp_lock = ice_st->grp_lock; 
    586780    pj_memcpy(&ice_st->cb, cb, sizeof(*cb)); 
    587781 
     
    661855    for (i=0; i<ice_st->comp_cnt; ++i) { 
    662856        if (ice_st->comp[i]) { 
    663             if (ice_st->comp[i]->stun_sock) { 
    664                 pj_stun_sock_destroy(ice_st->comp[i]->stun_sock); 
    665                 ice_st->comp[i]->stun_sock = NULL; 
    666             } 
    667             if (ice_st->comp[i]->turn_sock) { 
    668                 pj_turn_sock_destroy(ice_st->comp[i]->turn_sock); 
    669                 ice_st->comp[i]->turn_sock = NULL; 
     857            pj_ice_strans_comp *comp = ice_st->comp[i]; 
     858            unsigned j; 
     859            for (j = 0; j < ice_st->cfg.stun_tp_cnt; ++j) { 
     860                if (comp->stun[j].sock) { 
     861                    pj_stun_sock_destroy(comp->stun[j].sock); 
     862                    comp->stun[j].sock = NULL; 
     863                } 
     864            } 
     865            for (j = 0; j < ice_st->cfg.turn_tp_cnt; ++j) { 
     866                if (comp->turn[j].sock) { 
     867                    pj_turn_sock_destroy(comp->turn[j].sock); 
     868                    comp->turn[j].sock = NULL; 
     869                } 
    670870            } 
    671871        } 
     
    738938        pj_ice_strans_comp *comp = ice_st->comp[i]; 
    739939 
     940        /* This function can be called when all components or candidates 
     941         * have not been created. 
     942         */ 
     943        if (!comp || comp->creating) return; 
     944 
    740945        for (j=0; j<comp->cand_cnt; ++j) { 
    741946            pj_ice_sess_cand *cand = &comp->cand_list[j]; 
     
    8641069 
    8651070        /* Re-enable logging for Send/Data indications */ 
    866         if (comp->turn_sock) { 
     1071        if (ice_st->cfg.turn_tp_cnt) { 
    8671072            PJ_LOG(5,(ice_st->obj_name, 
    868                       "Disabling STUN Indication logging for " 
     1073                      "Enabling STUN Indication logging for " 
    8691074                      "component %d", i+1)); 
    870             pj_turn_sock_set_log(comp->turn_sock, 0xFFFF); 
    871             comp->turn_log_off = PJ_FALSE; 
     1075        } 
     1076        for (j = 0; j < ice_st->cfg.turn_tp_cnt; ++j) { 
     1077            if (comp->turn[j].sock) { 
     1078                pj_turn_sock_set_log(comp->turn[j].sock, 0xFFFF); 
     1079                comp->turn[j].log_off = PJ_FALSE; 
     1080            } 
    8721081        } 
    8731082 
     
    10751284                                             const pj_ice_sess_cand rem_cand[]) 
    10761285{ 
     1286    unsigned n; 
    10771287    pj_status_t status; 
    10781288 
     
    10901300 
    10911301    /* If we have TURN candidate, now is the time to create the permissions */ 
    1092     if (ice_st->comp[0]->turn_sock) { 
     1302    for (n = 0; n < ice_st->cfg.turn_tp_cnt; ++n) { 
    10931303        unsigned i; 
    10941304 
     
    11001310            /* Gather remote addresses for this component */ 
    11011311            for (j=0; j<rem_cand_cnt && count<PJ_ARRAY_SIZE(addrs); ++j) { 
    1102                 if (rem_cand[j].comp_id==i+1) { 
    1103                     pj_memcpy(&addrs[count++], &rem_cand[j].addr, 
    1104                               pj_sockaddr_get_len(&rem_cand[j].addr)); 
     1312                if (rem_cand[j].comp_id==i+1 && 
     1313                    rem_cand[j].addr.addr.sa_family== 
     1314                    ice_st->cfg.turn_tp[n].af) 
     1315                { 
     1316                    pj_sockaddr_cp(&addrs[count++], &rem_cand[j].addr); 
    11051317                } 
    11061318            } 
    11071319 
    1108             if (count) { 
    1109                 status = pj_turn_sock_set_perm(comp->turn_sock, count, 
     1320            if (count && !comp->turn[n].err_cnt && comp->turn[n].sock) { 
     1321                status = pj_turn_sock_set_perm(comp->turn[n].sock, count, 
    11101322                                               addrs, 0); 
    11111323                if (status != PJ_SUCCESS) { 
     
    11801392{ 
    11811393    pj_ice_strans_comp *comp; 
    1182     unsigned def_cand; 
     1394    pj_ice_sess_cand *def_cand; 
    11831395    pj_status_t status; 
    11841396 
     
    11891401 
    11901402    /* Check that default candidate for the component exists */ 
    1191     def_cand = comp->default_cand; 
    1192     if (def_cand >= comp->cand_cnt) 
     1403    if (comp->default_cand >= comp->cand_cnt) 
    11931404        return PJ_EINVALIDOP; 
    11941405 
     
    12141425     
    12151426    pj_grp_lock_release(ice_st->grp_lock); 
     1427 
     1428    def_cand = &comp->cand_list[comp->default_cand]; 
    12161429     
    1217     if (comp->cand_list[def_cand].status == PJ_SUCCESS) { 
    1218  
    1219         if (comp->cand_list[def_cand].type == PJ_ICE_CAND_TYPE_RELAYED) { 
     1430    if (def_cand->status == PJ_SUCCESS) { 
     1431        unsigned tp_idx = GET_TP_IDX(def_cand->transport_id); 
     1432 
     1433        if (def_cand->type == PJ_ICE_CAND_TYPE_RELAYED) { 
    12201434 
    12211435            enum { 
     
    12261440 
    12271441            /* https://trac.pjsip.org/repos/ticket/1316 */ 
    1228             if (comp->turn_sock == NULL) { 
     1442            if (comp->turn[tp_idx].sock == NULL) { 
    12291443                /* TURN socket error */ 
    12301444                return PJ_EINVALIDOP; 
    12311445            } 
    12321446 
    1233             if (!comp->turn_log_off) { 
     1447            if (!comp->turn[tp_idx].log_off) { 
    12341448                /* Disable logging for Send/Data indications */ 
    12351449                PJ_LOG(5,(ice_st->obj_name, 
    12361450                          "Disabling STUN Indication logging for " 
    12371451                          "component %d", comp->comp_id)); 
    1238                 pj_turn_sock_set_log(comp->turn_sock, msg_disable_ind); 
    1239                 comp->turn_log_off = PJ_TRUE; 
    1240             } 
    1241  
    1242             status = pj_turn_sock_sendto(comp->turn_sock, 
     1452                pj_turn_sock_set_log(comp->turn[tp_idx].sock, 
     1453                                     msg_disable_ind); 
     1454                comp->turn[tp_idx].log_off = PJ_TRUE; 
     1455            } 
     1456 
     1457            status = pj_turn_sock_sendto(comp->turn[tp_idx].sock, 
    12431458                                         (const pj_uint8_t*)data, 
    12441459                                         (unsigned)data_len, 
     
    12471462                    PJ_SUCCESS : status; 
    12481463        } else { 
    1249             status = pj_stun_sock_sendto(comp->stun_sock, NULL, data, 
     1464            status = pj_stun_sock_sendto(comp->stun[tp_idx].sock, NULL, data, 
    12501465                                         (unsigned)data_len, 0, dst_addr, 
    12511466                                         dst_addr_len); 
     
    12951510            for (i=0; i<ice_st->comp_cnt; ++i) { 
    12961511                const pj_ice_sess_check *check; 
     1512                pj_ice_strans_comp *comp = ice_st->comp[i]; 
    12971513 
    12981514                check = pj_ice_strans_get_valid_pair(ice_st, i+1); 
     
    13001516                    char lip[PJ_INET6_ADDRSTRLEN+10]; 
    13011517                    char rip[PJ_INET6_ADDRSTRLEN+10]; 
     1518                    unsigned tp_idx = GET_TP_IDX(check->lcand->transport_id); 
     1519                    unsigned tp_typ = GET_TP_TYPE(check->lcand->transport_id); 
    13021520 
    13031521                    pj_sockaddr_print(&check->lcand->addr, lip, 
     
    13061524                                      sizeof(rip), 3); 
    13071525 
    1308                     if (check->lcand->transport_id == TP_TURN) { 
     1526                    if (tp_typ == TP_TURN) { 
    13091527                        /* Activate channel binding for the remote address 
    13101528                         * for more efficient data transfer using TURN. 
    13111529                         */ 
    13121530                        status = pj_turn_sock_bind_channel( 
    1313                                         ice_st->comp[i]->turn_sock, 
     1531                                        comp->turn[tp_idx].sock, 
    13141532                                        &check->rcand->addr, 
    13151533                                        sizeof(check->rcand->addr)); 
     
    13191537                                  "Disabling STUN Indication logging for " 
    13201538                                  "component %d", i+1)); 
    1321                         pj_turn_sock_set_log(ice_st->comp[i]->turn_sock, 
     1539                        pj_turn_sock_set_log(comp->turn[tp_idx].sock, 
    13221540                                             msg_disable_ind); 
    1323                         ice_st->comp[i]->turn_log_off = PJ_TRUE; 
     1541                        comp->turn[tp_idx].log_off = PJ_TRUE; 
    13241542                    } 
    13251543 
     
    13691587    char daddr[PJ_INET6_ADDRSTRLEN]; 
    13701588#endif 
     1589    unsigned tp_idx = GET_TP_IDX(transport_id); 
     1590    unsigned tp_typ = GET_TP_TYPE(transport_id); 
    13711591 
    13721592    PJ_ASSERT_RETURN(comp_id && comp_id <= ice_st->comp_cnt, PJ_EINVAL); 
     
    13791599               pj_sockaddr_print(dst_addr, daddr, sizeof(addr), 0), 
    13801600               pj_sockaddr_get_port(dst_addr), 
    1381                transport_id)); 
    1382  
    1383     if (transport_id == TP_TURN) { 
    1384         if (comp->turn_sock) { 
    1385             status = pj_turn_sock_sendto(comp->turn_sock, 
     1601               tp_typ)); 
     1602 
     1603    if (tp_typ == TP_TURN) { 
     1604        if (comp->turn[tp_idx].sock) { 
     1605            status = pj_turn_sock_sendto(comp->turn[tp_idx].sock, 
    13861606                                         (const pj_uint8_t*)pkt, 
    13871607                                         (unsigned)size, 
     
    13901610            status = PJ_EINVALIDOP; 
    13911611        } 
    1392     } else if (transport_id == TP_STUN) { 
    1393         status = pj_stun_sock_sendto(comp->stun_sock, NULL, 
     1612    } else if (tp_typ == TP_STUN) { 
     1613        status = pj_stun_sock_sendto(comp->stun[tp_idx].sock, NULL, 
    13941614                                     pkt, (unsigned)size, 0, 
    13951615                                     dst_addr, dst_addr_len); 
     
    14311651                                 unsigned addr_len) 
    14321652{ 
     1653    sock_user_data *data; 
    14331654    pj_ice_strans_comp *comp; 
    14341655    pj_ice_strans *ice_st; 
    14351656    pj_status_t status; 
    14361657 
    1437     comp = (pj_ice_strans_comp*) pj_stun_sock_get_user_data(stun_sock); 
    1438     if (comp == NULL) { 
     1658    data = (sock_user_data*) pj_stun_sock_get_user_data(stun_sock); 
     1659    if (data == NULL) { 
    14391660        /* We have disassociated ourselves from the STUN socket */ 
    14401661        return PJ_FALSE; 
    14411662    } 
    14421663 
     1664    comp = data->comp; 
    14431665    ice_st = comp->ice_st; 
    14441666 
     
    14591681        /* Hand over the packet to ICE session */ 
    14601682        status = pj_ice_sess_on_rx_pkt(comp->ice_st->ice, comp->comp_id, 
    1461                                        TP_STUN, pkt, pkt_len, 
     1683                                       data->transport_id, 
     1684                                       pkt, pkt_len, 
    14621685                                       src_addr, addr_len); 
    14631686 
     
    14891712                                pj_status_t status) 
    14901713{ 
     1714    sock_user_data *data; 
    14911715    pj_ice_strans_comp *comp; 
    14921716    pj_ice_strans *ice_st; 
    14931717    pj_ice_sess_cand *cand = NULL; 
    14941718    unsigned i; 
     1719    int tp_idx; 
    14951720 
    14961721    pj_assert(status != PJ_EPENDING); 
    14971722 
    1498     comp = (pj_ice_strans_comp*) pj_stun_sock_get_user_data(stun_sock); 
     1723    data = (sock_user_data*) pj_stun_sock_get_user_data(stun_sock); 
     1724    comp = data->comp; 
    14991725    ice_st = comp->ice_st; 
    15001726 
     
    15061732    /* Find the srflx cancidate */ 
    15071733    for (i=0; i<comp->cand_cnt; ++i) { 
    1508         if (comp->cand_list[i].type == PJ_ICE_CAND_TYPE_SRFLX) { 
     1734        if (comp->cand_list[i].type == PJ_ICE_CAND_TYPE_SRFLX && 
     1735            comp->cand_list[i].transport_id == data->transport_id) 
     1736        { 
    15091737            cand = &comp->cand_list[i]; 
    15101738            break; 
     
    15221750    } 
    15231751 
     1752    tp_idx = GET_TP_IDX(data->transport_id); 
     1753 
    15241754    switch (op) { 
    15251755    case PJ_STUN_SOCK_DNS_OP: 
     
    15281758            if (cand) 
    15291759                cand->status = status; 
    1530             if (!ice_st->cfg.stun.ignore_stun_error) { 
     1760            if (!ice_st->cfg.stun_tp[tp_idx].ignore_stun_error) { 
    15311761                sess_fail(ice_st, PJ_ICE_STRANS_OP_INIT, 
    15321762                          "DNS resolution failed", status); 
     
    15931823 
    15941824                sess_init_update(ice_st); 
     1825                 
     1826                if (op == PJ_STUN_SOCK_MAPPED_ADDR_CHANGE && 
     1827                    ice_st->cb.on_ice_complete) 
     1828                { 
     1829                    (*ice_st->cb.on_ice_complete)(ice_st,  
     1830                                                  PJ_ICE_STRANS_OP_ADDR_CHANGE, 
     1831                                                  status); 
     1832                } 
    15951833            } 
    15961834        } 
     
    16001838            if (cand) 
    16011839                cand->status = status; 
    1602             if (!ice_st->cfg.stun.ignore_stun_error || comp->cand_cnt==1) { 
     1840            if (!ice_st->cfg.stun_tp[tp_idx].ignore_stun_error || 
     1841                comp->cand_cnt==1) 
     1842            { 
    16031843                sess_fail(ice_st, PJ_ICE_STRANS_OP_INIT, 
    16041844                          "STUN binding request failed", status); 
     
    16251865            pj_assert(cand != NULL); 
    16261866            cand->status = status; 
    1627             if (!ice_st->cfg.stun.ignore_stun_error) { 
     1867            if (!ice_st->cfg.stun_tp[tp_idx].ignore_stun_error) { 
    16281868                sess_fail(ice_st, PJ_ICE_STRANS_OP_INIT, 
    16291869                          "STUN keep-alive failed", status); 
     
    16461886{ 
    16471887    pj_ice_strans_comp *comp; 
     1888    sock_user_data *data; 
    16481889    pj_status_t status; 
    16491890 
    1650     comp = (pj_ice_strans_comp*) pj_turn_sock_get_user_data(turn_sock); 
    1651     if (comp == NULL) { 
     1891    data = (sock_user_data*) pj_turn_sock_get_user_data(turn_sock); 
     1892    if (data == NULL) { 
    16521893        /* We have disassociated ourselves from the TURN socket */ 
    16531894        return; 
    16541895    } 
     1896 
     1897    comp = data->comp; 
    16551898 
    16561899    pj_grp_lock_add_ref(comp->ice_st->grp_lock); 
     
    16711914        /* Hand over the packet to ICE */ 
    16721915        status = pj_ice_sess_on_rx_pkt(comp->ice_st->ice, comp->comp_id, 
    1673                                        TP_TURN, pkt, pkt_len, 
     1916                                       data->transport_id, pkt, pkt_len, 
    16741917                                       peer_addr, addr_len); 
    16751918 
     
    16901933{ 
    16911934    pj_ice_strans_comp *comp; 
    1692  
    1693     comp = (pj_ice_strans_comp*) pj_turn_sock_get_user_data(turn_sock); 
    1694     if (comp == NULL) { 
     1935    sock_user_data *data; 
     1936    int tp_idx; 
     1937 
     1938    data = (sock_user_data*) pj_turn_sock_get_user_data(turn_sock); 
     1939    if (data == NULL) { 
    16951940        /* Not interested in further state notification once the relay is 
    16961941         * disconnecting. 
     
    16981943        return; 
    16991944    } 
     1945 
     1946    comp = data->comp; 
     1947    tp_idx = GET_TP_IDX(data->transport_id); 
    17001948 
    17011949    PJ_LOG(5,(comp->ice_st->obj_name, "TURN client state changed %s --> %s", 
     
    17111959        unsigned i; 
    17121960 
    1713         comp->turn_err_cnt = 0; 
     1961        comp->turn[tp_idx].err_cnt = 0; 
    17141962 
    17151963        /* Get allocation info */ 
     
    17211969        /* Find relayed candidate in the component */ 
    17221970        for (i=0; i<comp->cand_cnt; ++i) { 
    1723             if (comp->cand_list[i].type == PJ_ICE_CAND_TYPE_RELAYED) { 
     1971            if (comp->cand_list[i].type == PJ_ICE_CAND_TYPE_RELAYED && 
     1972                comp->cand_list[i].transport_id == data->transport_id) 
     1973            { 
    17241974                cand = &comp->cand_list[i]; 
    17251975                break; 
     
    17421992        comp->default_cand = (unsigned)(cand - comp->cand_list); 
    17431993 
     1994        /* Prefer IPv4 relay as default candidate for better connectivity 
     1995         * with IPv4 endpoints. 
     1996         */ 
     1997        if (cand->addr.addr.sa_family != pj_AF_INET()) { 
     1998            for (i=0; i<comp->cand_cnt; ++i) { 
     1999                if (comp->cand_list[i].type == PJ_ICE_CAND_TYPE_RELAYED && 
     2000                    comp->cand_list[i].addr.addr.sa_family == pj_AF_INET() && 
     2001                    comp->cand_list[i].status == PJ_SUCCESS) 
     2002                { 
     2003                    comp->default_cand = i; 
     2004                    break; 
     2005                } 
     2006            } 
     2007        } 
     2008 
    17442009        PJ_LOG(4,(comp->ice_st->obj_name, 
    17452010                  "Comp %d: TURN allocation complete, relay address is %s", 
     
    17502015        sess_init_update(comp->ice_st); 
    17512016 
     2017    } else if ((old_state == PJ_TURN_STATE_RESOLVING || 
     2018                old_state == PJ_TURN_STATE_RESOLVED) && 
     2019               new_state == PJ_TURN_STATE_DESTROYING) 
     2020    { 
     2021        pj_ice_sess_cand *cand = NULL; 
     2022        unsigned i; 
     2023 
     2024        /* DNS resolution or TURN transport creation/allocation 
     2025         * has failed. 
     2026         */ 
     2027        ++comp->turn[tp_idx].err_cnt; 
     2028 
     2029        /* Unregister ourself from the TURN relay */ 
     2030        pj_turn_sock_set_user_data(turn_sock, NULL); 
     2031        comp->turn[tp_idx].sock = NULL; 
     2032 
     2033        /* Wait until initialization completes */ 
     2034        pj_grp_lock_acquire(comp->ice_st->grp_lock); 
     2035 
     2036        /* Find relayed candidate in the component */ 
     2037        for (i=0; i<comp->cand_cnt; ++i) { 
     2038            if (comp->cand_list[i].type == PJ_ICE_CAND_TYPE_RELAYED && 
     2039                comp->cand_list[i].transport_id == data->transport_id) 
     2040            { 
     2041                cand = &comp->cand_list[i]; 
     2042                break; 
     2043            } 
     2044        } 
     2045 
     2046        pj_grp_lock_release(comp->ice_st->grp_lock); 
     2047 
     2048        /* If the error happens during pj_turn_sock_create() or 
     2049         * pj_turn_sock_alloc(), the candidate hasn't been added 
     2050         * to the list. 
     2051         */ 
     2052        if (cand) cand->status = PJ_ERESOLVE; 
     2053 
     2054        sess_init_update(comp->ice_st); 
     2055 
    17522056    } else if (new_state >= PJ_TURN_STATE_DEALLOCATING) { 
    17532057        pj_turn_session_info info; 
    17542058 
    1755         ++comp->turn_err_cnt; 
     2059        ++comp->turn[tp_idx].err_cnt; 
    17562060 
    17572061        pj_turn_sock_get_info(turn_sock, &info); 
     
    17592063        /* Unregister ourself from the TURN relay */ 
    17602064        pj_turn_sock_set_user_data(turn_sock, NULL); 
    1761         comp->turn_sock = NULL; 
     2065        comp->turn[tp_idx].sock = NULL; 
    17622066 
    17632067        /* Set session to fail on error. last_status PJ_SUCCESS means normal 
     
    17692073                sess_fail(comp->ice_st, PJ_ICE_STRANS_OP_INIT, 
    17702074                          "TURN allocation failed", info.last_status); 
    1771             } else if (comp->turn_err_cnt > 1) { 
     2075            } else if (comp->turn[tp_idx].err_cnt > 1) { 
    17722076                sess_fail(comp->ice_st, PJ_ICE_STRANS_OP_KEEP_ALIVE, 
    17732077                          "TURN refresh failed", info.last_status); 
     
    17762080                          "Comp %d: TURN allocation failed, retrying", 
    17772081                          comp->comp_id)); 
    1778                 add_update_turn(comp->ice_st, comp); 
     2082                add_update_turn(comp->ice_st, comp, tp_idx); 
    17792083            } 
    17802084        } 
Note: See TracChangeset for help on using the changeset viewer.