Changeset 1140 for pjproject


Ignore:
Timestamp:
Apr 3, 2007 6:01:27 PM (18 years ago)
Author:
bennylp
Message:

Fixed misc bugs with ICE: (1) moved STUN session from candidate to component since it causes STUN response to wrong session, and (2) keep-alive transaction timed-out when ICE is active

Location:
pjproject/trunk
Files:
10 edited

Legend:

Unmodified
Added
Removed
  • pjproject/trunk/pjmedia/src/pjmedia/transport_ice.c

    r1126 r1140  
    435435    pj_bool_t remote_is_lite = PJ_FALSE; 
    436436    pj_bool_t ice_mismatch = PJ_FALSE; 
     437    pjmedia_sdp_conn *conn = NULL; 
     438    pj_sockaddr conn_addr; 
     439    pj_bool_t conn_found_in_candidate = PJ_FALSE; 
    437440    const pj_str_t STR_CANDIDATE = {"candidate", 9}; 
    438441    const pj_str_t STR_ICE_LITE = {"ice-lite", 8}; 
     
    445448 
    446449    sdp_med = rem_sdp->media[media_index]; 
     450 
     451    /* Get the SDP connection for the media stream. 
     452     * We'll verify later if the SDP connection address is specified  
     453     * as one of the candidate. 
     454     */ 
     455    conn = sdp_med->conn; 
     456    if (conn == NULL) 
     457        conn = rem_sdp->conn; 
     458 
     459    if (conn == NULL) { 
     460        /* Unable to find SDP connection */ 
     461        return PJMEDIA_SDP_EMISSINGCONN; 
     462    } 
     463 
     464    pj_sockaddr_in_init(&conn_addr.ipv4, &conn->addr,  
     465                        (pj_uint16_t)sdp_med->desc.port); 
    447466 
    448467    /* Find ice-ufrag attribute in session descriptor */ 
     
    481500        attr = sdp_med->attr[i]; 
    482501 
     502        /* Detect if remote is ICE lite */ 
    483503        if (pj_strcmp(&attr->name, &STR_ICE_LITE)==0) { 
    484504            remote_is_lite = PJ_TRUE; 
     
    486506        } 
    487507 
     508        /* Detect if remote has reported ICE mismatch */ 
    488509        if (pj_strcmp(&attr->name, &STR_ICE_MISMATCH)==0) { 
    489510            ice_mismatch = PJ_TRUE; 
     
    494515            continue; 
    495516 
     517        /* Parse candidate */ 
    496518        status = parse_cand(pool, &attr->value, &cand[cand_cnt]); 
    497519        if (status != PJ_SUCCESS) 
    498520            return status; 
    499521 
     522        /* Check if this candidate is equal to the connection line */ 
     523        if (!conn_found_in_candidate && 
     524            pj_memcmp(&conn_addr.ipv4, &cand[cand_cnt].addr.ipv4, 
     525                      sizeof(pj_sockaddr_in))==0) 
     526        { 
     527            conn_found_in_candidate = PJ_TRUE; 
     528        } 
     529 
    500530        cand_cnt++; 
    501531    } 
     
    503533    /* Handle ice-mismatch case */ 
    504534    if (ice_mismatch) { 
    505         set_no_ice(tp_ice, "ice-mismatch detected"); 
     535        set_no_ice(tp_ice, "remote reported ice-mismatch"); 
     536        return PJ_SUCCESS; 
     537    } 
     538 
     539    /* Handle case where SDP connection address is not specified as 
     540     * one of the candidate. 
     541     */ 
     542    if (!conn_found_in_candidate) { 
     543        set_no_ice(tp_ice, "local reported ice-mismatch"); 
    506544        return PJ_SUCCESS; 
    507545    } 
     
    658696    char dst_addr[32]; 
    659697 
     698    pj_gettimeofday(&end_ice); 
     699    PJ_TIME_VAL_SUB(end_ice, tp_ice->start_ice); 
     700 
    660701    if (status != PJ_SUCCESS) { 
    661702        char errmsg[PJ_ERR_MSG_SIZE]; 
    662703        pj_strerror(status, errmsg, sizeof(errmsg)); 
    663         PJ_LOG(1,(ice_st->obj_name, "ICE negotiation failed: %s", errmsg)); 
     704        PJ_LOG(1,(ice_st->obj_name,  
     705                  "ICE negotiation failed after %d:%03ds: %s",  
     706                  (int)end_ice.sec, (int)end_ice.msec, 
     707                  errmsg)); 
    664708        return; 
    665709    } 
    666  
    667     pj_gettimeofday(&end_ice); 
    668     PJ_TIME_VAL_SUB(end_ice, tp_ice->start_ice); 
    669710 
    670711    check = &ice_st->ice->valid_list.checks[0]; 
  • pjproject/trunk/pjnath/include/pjnath/config.h

    r1126 r1140  
    165165 
    166166 
     167/** 
     168 * Minimum interval value to be used for sending STUN keep-alive on the ICE 
     169 * stream transport, in seconds. This minimum interval, plus a random value 
     170 * which maximum is PJ_ICE_ST_KEEP_ALIVE_MAX_RAND, specify the actual interval 
     171 * of the STUN keep-alive. 
     172 * 
     173 * Default: 20 seconds 
     174 * 
     175 * @see PJ_ICE_ST_KEEP_ALIVE_MAX_RAND 
     176 */ 
     177#ifndef PJ_ICE_ST_KEEP_ALIVE_MIN 
     178#   define PJ_ICE_ST_KEEP_ALIVE_MIN                 20 
     179#endif 
     180 
     181 
     182/** 
     183 * To prevent STUN keep-alives to be sent simultaneously, application should 
     184 * add random interval to minimum interval (PJ_ICE_ST_KEEP_ALIVE_MIN). This 
     185 * setting specifies the maximum random value to be added to the minimum 
     186 * interval, in seconds. 
     187 * 
     188 * Default: 5 seconds 
     189 * 
     190 * @see PJ_ICE_ST_KEEP_ALIVE_MIN 
     191 */ 
     192#ifndef PJ_ICE_ST_KEEP_ALIVE_MAX_RAND 
     193#   define PJ_ICE_ST_KEEP_ALIVE_MAX_RAND            5 
     194#endif 
     195 
     196 
     197 
    167198 
    168199/** 
  • pjproject/trunk/pjnath/include/pjnath/ice_session.h

    r1129 r1140  
    120120     */ 
    121121    pj_ice_sess_check   *valid_check; 
     122 
     123    /** 
     124     * The STUN session to be used to send and receive STUN messages for this 
     125     * component. 
     126     */ 
     127    pj_stun_session     *stun_sess; 
    122128 
    123129} pj_ice_sess_comp; 
     
    188194    pj_sockaddr          rel_addr; 
    189195 
    190     /** 
    191      * The STUN session to be used to send and receive STUN messages for this 
    192      * candidate. 
    193      */ 
    194     pj_stun_session     *stun_sess; 
    195  
    196196} pj_ice_sess_cand; 
    197197 
     
    367367     * @param ice           The ICE session. 
    368368     * @param comp_id       ICE component ID. 
    369      * @param cand_id       ICE candidate ID. 
    370369     * @param pkt           The STUN packet. 
    371370     * @param size          The size of the packet. 
     
    374373     */ 
    375374    pj_status_t (*on_tx_pkt)(pj_ice_sess *ice, unsigned comp_id,  
    376                              unsigned cand_id, 
    377375                             const void *pkt, pj_size_t size, 
    378376                             const pj_sockaddr_t *dst_addr, 
     
    696694 * @param ice           The ICE session. 
    697695 * @param comp_id       Component ID. 
    698  * @param cand_id       Candidate ID. 
    699696 * @param pkt           Incoming packet. 
    700697 * @param pkt_size      Size of incoming packet. 
     
    706703PJ_DECL(pj_status_t) pj_ice_sess_on_rx_pkt(pj_ice_sess *ice, 
    707704                                           unsigned comp_id, 
    708                                            unsigned cand_id, 
    709705                                           void *pkt, 
    710706                                           pj_size_t pkt_size, 
  • pjproject/trunk/pjnath/include/pjnath/ice_strans.h

    r1114 r1140  
    275275 
    276276    pj_stun_session     *stun_sess;     /**< STUN session.              */ 
     277    pj_uint8_t           ka_tsx_id[12]; /**< ID for keep STUN alives    */ 
    277278 
    278279    pj_sockaddr          local_addr;    /**< Local/base address.        */ 
  • pjproject/trunk/pjnath/include/pjnath/stun_session.h

    r1110 r1140  
    246246 * @param msg_type  The STUN request message type, from pj_stun_method_e or 
    247247 *                  from pj_stun_msg_type. 
     248 * @param tsx_id    Optional transaction ID. 
    248249 * @param p_tdata   Pointer to receive STUN transmit data instance containing 
    249250 *                  the request. 
     
    253254PJ_DECL(pj_status_t) pj_stun_session_create_req(pj_stun_session *sess, 
    254255                                                int msg_type, 
     256                                                const pj_uint8_t tsx_id[12], 
    255257                                                pj_stun_tx_data **p_tdata); 
    256258 
  • pjproject/trunk/pjnath/include/pjnath/stun_transaction.h

    r1110 r1140  
    9191                               pj_size_t pkt_size); 
    9292 
     93    /** 
     94     * This callback is called after the timer that was scheduled by 
     95     * #pj_stun_client_tsx_schedule_destroy() has elapsed. Application 
     96     * should call #pj_stun_client_tsx_destroy() upon receiving this 
     97     * callback. 
     98     * 
     99     * This callback is optional if application will not call  
     100     * #pj_stun_client_tsx_schedule_destroy(). 
     101     * 
     102     * @param tsx           The STUN transaction instance. 
     103     */ 
     104    void (*on_destroy)(pj_stun_client_tsx *tsx); 
     105 
    93106} pj_stun_tsx_cb; 
    94107 
     
    117130 
    118131/** 
    119  * Destroy a STUN client transaction. 
     132 * Schedule timer to destroy the transaction after the transaction is  
     133 * complete. Application normally calls this function in the on_complete() 
     134 * callback. When this timer elapsed, the on_destroy() callback will be  
     135 * called. 
     136 * 
     137 * This is convenient to let the STUN transaction absorbs any response  
     138 * for the previous request retransmissions. If application doesn't want 
     139 * this, it can destroy the transaction immediately by calling  
     140 * #pj_stun_client_tsx_destroy(). 
     141 * 
     142 * @param tsx           The STUN transaction. 
     143 * @param delay         The delay interval before on_destroy() callback 
     144 *                      is called. 
     145 * 
     146 * @return              PJ_SUCCESS on success, or the appropriate error code. 
     147 */ 
     148PJ_DECL(pj_status_t)  
     149pj_stun_client_tsx_schedule_destroy(pj_stun_client_tsx *tsx, 
     150                                    const pj_time_val *delay); 
     151 
     152 
     153/** 
     154 * Destroy a STUN client transaction immediately. This function can be  
     155 * called at any time to stop the transaction and destroy it. 
    120156 * 
    121157 * @param tsx           The STUN transaction. 
  • pjproject/trunk/pjnath/src/pjnath/ice_session.c

    r1129 r1140  
    8484{ 
    8585    pj_ice_sess         *ice; 
    86     pj_ice_sess_cand    *lcand; 
     86    unsigned             comp_id; 
     87    pj_ice_sess_comp    *comp; 
    8788} stun_data; 
    8889 
     
    180181 
    181182 
     183/* Init component */ 
     184static pj_status_t init_comp(pj_ice_sess *ice, 
     185                             unsigned comp_id, 
     186                             pj_ice_sess_comp *comp) 
     187{ 
     188    pj_stun_session_cb sess_cb; 
     189    pj_stun_auth_cred auth_cred; 
     190    stun_data *sd; 
     191    pj_status_t status; 
     192 
     193    /* Init STUN callbacks */ 
     194    pj_bzero(&sess_cb, sizeof(sess_cb)); 
     195    sess_cb.on_request_complete = &on_stun_request_complete; 
     196    sess_cb.on_rx_indication = &on_stun_rx_indication; 
     197    sess_cb.on_rx_request = &on_stun_rx_request; 
     198    sess_cb.on_send_msg = &on_stun_send_msg; 
     199 
     200    /* Create STUN session for this candidate */ 
     201    status = pj_stun_session_create(&ice->stun_cfg, NULL,  
     202                                    &sess_cb, PJ_FALSE, 
     203                                    &comp->stun_sess); 
     204    if (status != PJ_SUCCESS) 
     205        return status; 
     206 
     207    /* Associate data with this STUN session */ 
     208    sd = PJ_POOL_ZALLOC_T(ice->pool, struct stun_data); 
     209    sd->ice = ice; 
     210    sd->comp_id = comp_id; 
     211    sd->comp = comp; 
     212    pj_stun_session_set_user_data(comp->stun_sess, sd); 
     213 
     214    /* Init STUN authentication credential */ 
     215    pj_bzero(&auth_cred, sizeof(auth_cred)); 
     216    auth_cred.type = PJ_STUN_AUTH_CRED_DYNAMIC; 
     217    auth_cred.data.dyn_cred.get_auth = &stun_auth_get_auth; 
     218    auth_cred.data.dyn_cred.get_cred = &stun_auth_get_cred; 
     219    auth_cred.data.dyn_cred.get_password = &stun_auth_get_password; 
     220    auth_cred.data.dyn_cred.user_data = comp->stun_sess; 
     221    pj_stun_session_set_credential(comp->stun_sess, &auth_cred); 
     222 
     223    return PJ_SUCCESS; 
     224} 
     225 
     226 
    182227/* 
    183228 * Create ICE session. 
     
    228273        comp = &ice->comp[i]; 
    229274        comp->valid_check = NULL; 
     275 
     276        status = init_comp(ice, i+1, comp); 
     277        if (status != PJ_SUCCESS) { 
     278            destroy_ice(ice, status); 
     279            return status; 
     280        } 
    230281    } 
    231282 
     
    233284        ice->rx_ufrag.ptr = pj_pool_alloc(ice->pool, 16); 
    234285        pj_create_random_string(ice->rx_ufrag.ptr, 16); 
     286        ice->rx_ufrag.slen = 16; 
    235287    } else { 
    236288        pj_strdup(ice->pool, &ice->rx_ufrag, local_ufrag); 
     
    240292        ice->rx_pass.ptr = pj_pool_alloc(ice->pool, 16); 
    241293        pj_create_random_string(ice->rx_pass.ptr, 16); 
     294        ice->rx_pass.slen = 16; 
    242295    } else { 
    243296        pj_strdup(ice->pool, &ice->rx_pass, local_passwd); 
     
    268321    } 
    269322 
    270     for (i=0; i<ice->lcand_cnt; ++i) { 
    271         if (ice->lcand[i].stun_sess) { 
    272             pj_stun_session_destroy(ice->lcand[i].stun_sess); 
    273             ice->lcand[i].stun_sess = NULL; 
     323    for (i=0; i<ice->comp_cnt; ++i) { 
     324        if (ice->comp[i].stun_sess) { 
     325            pj_stun_session_destroy(ice->comp[i].stun_sess); 
     326            ice->comp[i].stun_sess = NULL; 
    274327        } 
    275328    } 
     
    466519{ 
    467520    pj_ice_sess_cand *lcand; 
    468     pj_stun_session_cb sess_cb; 
    469     pj_stun_auth_cred auth_cred; 
    470     stun_data *sd; 
    471521    pj_status_t status = PJ_SUCCESS; 
    472522    char tmp[128]; 
     
    495545    else 
    496546        pj_bzero(&lcand->rel_addr, sizeof(lcand->rel_addr)); 
    497  
    498  
    499     /* Init STUN callbacks */ 
    500     pj_bzero(&sess_cb, sizeof(sess_cb)); 
    501     sess_cb.on_request_complete = &on_stun_request_complete; 
    502     sess_cb.on_rx_indication = &on_stun_rx_indication; 
    503     sess_cb.on_rx_request = &on_stun_rx_request; 
    504     sess_cb.on_send_msg = &on_stun_send_msg; 
    505  
    506     /* Create STUN session for this candidate */ 
    507     status = pj_stun_session_create(&ice->stun_cfg, ice->obj_name,  
    508                                     &sess_cb, PJ_FALSE, 
    509                                     &lcand->stun_sess); 
    510     if (status != PJ_SUCCESS) { 
    511         pj_mutex_unlock(ice->mutex); 
    512         return status; 
    513     } 
    514  
    515     /* Associate data with this STUN session */ 
    516     sd = PJ_POOL_ZALLOC_T(ice->pool, struct stun_data); 
    517     sd->ice = ice; 
    518     sd->lcand = lcand; 
    519     pj_stun_session_set_user_data(lcand->stun_sess, sd); 
    520  
    521     /* Init STUN authentication credential */ 
    522     pj_bzero(&auth_cred, sizeof(auth_cred)); 
    523     auth_cred.type = PJ_STUN_AUTH_CRED_DYNAMIC; 
    524     auth_cred.data.dyn_cred.get_auth = &stun_auth_get_auth; 
    525     auth_cred.data.dyn_cred.get_cred = &stun_auth_get_cred; 
    526     auth_cred.data.dyn_cred.get_password = &stun_auth_get_password; 
    527     auth_cred.data.dyn_cred.user_data = lcand->stun_sess; 
    528     pj_stun_session_set_credential(lcand->stun_sess, &auth_cred); 
    529547 
    530548 
     
    909927             GET_CHECK_ID(&ice->clist, check))); 
    910928 
     929        comp = find_comp(ice, check->lcand->comp_id); 
     930 
    911931        for (i=0; i<ice->clist.count; ++i) { 
    912932            pj_ice_sess_check *c = &ice->clist.checks[i]; 
     
    927947                             "Cancelling check %s (In Progress)", 
    928948                             dump_check(buf, sizeof(buf), &ice->clist, c))); 
    929                         pj_stun_session_cancel_req(c->lcand->stun_sess,  
     949                        pj_stun_session_cancel_req(comp->stun_sess,  
    930950                                                   c->tdata, PJ_FALSE, 0); 
    931951                        c->tdata = NULL; 
     
    938958 
    939959        /* Update the nominated check for the component */ 
    940         comp = find_comp(ice, check->lcand->comp_id); 
    941960        if (comp->valid_check == NULL) { 
    942961            comp->valid_check = check; 
     
    11651184 
    11661185    /* Create request */ 
    1167     status = pj_stun_session_create_req(lcand->stun_sess,  
     1186    status = pj_stun_session_create_req(comp->stun_sess,  
    11681187                                        PJ_STUN_BINDING_REQUEST,  
    1169                                         &check->tdata); 
     1188                                        NULL, &check->tdata); 
    11701189    if (status != PJ_SUCCESS) { 
    11711190        pjnath_perror(ice->obj_name, "Error creating STUN request", status); 
     
    12001219 
    12011220    /* Initiate STUN transaction to send the request */ 
    1202     status = pj_stun_session_send_msg(lcand->stun_sess, PJ_FALSE,  
     1221    status = pj_stun_session_send_msg(comp->stun_sess, PJ_FALSE,  
    12031222                                      &rcand->addr,  
    12041223                                      sizeof(pj_sockaddr_in), check->tdata); 
     
    14001419    stun_data *sd = (stun_data*) pj_stun_session_get_user_data(sess); 
    14011420    pj_ice_sess *ice = sd->ice; 
    1402     return (*sd->ice->cb.on_tx_pkt)(sd->ice, sd->lcand->comp_id,  
    1403                                     GET_LCAND_ID(sd->lcand), 
    1404                                     pkt, pkt_size,  
    1405                                     dst_addr, addr_len); 
     1421    return (*ice->cb.on_tx_pkt)(ice, sd->comp_id,  
     1422                                pkt, pkt_size,  
     1423                                dst_addr, addr_len); 
    14061424} 
    14071425 
     
    16001618    pj_stun_use_candidate_attr *uc; 
    16011619    pj_ice_sess_comp *comp; 
    1602     pj_ice_sess_cand *lcand; 
     1620    pj_ice_sess_cand *lcand = NULL; 
    16031621    pj_ice_sess_cand *rcand; 
    16041622    unsigned i; 
     
    16251643    sd = (stun_data*) pj_stun_session_get_user_data(sess); 
    16261644    ice = sd->ice; 
    1627     lcand = sd->lcand; 
    1628     comp = find_comp(ice, lcand->comp_id); 
     1645    comp = sd->comp; 
    16291646 
    16301647    pj_mutex_lock(ice->mutex); 
     
    16831700    if (i == ice->rcand_cnt) { 
    16841701        rcand = &ice->rcand[ice->rcand_cnt++]; 
    1685         rcand->comp_id = lcand->comp_id; 
     1702        rcand->comp_id = sd->comp_id; 
    16861703        rcand->type = PJ_ICE_CAND_TYPE_PRFLX; 
    16871704        rcand->prio = ap->value; 
     
    17031720        rcand = &ice->rcand[i]; 
    17041721    } 
     1722 
     1723#if 0 
     1724    /* Find again the local candidate by matching the base address 
     1725     * with the local candidates in the checklist. Checks may have 
     1726     * been pruned before, so it's possible that if we use the lcand 
     1727     * as it is, we wouldn't be able to find the check in the checklist 
     1728     * and we will end up creating a new check unnecessarily. 
     1729     */ 
     1730    for (i=0; i<ice->clist.count; ++i) { 
     1731        pj_ice_sess_check *c = &ice->clist.checks[i]; 
     1732        if (/*c->lcand == lcand ||*/ 
     1733            sockaddr_cmp(&c->lcand->base_addr, &lcand->base_addr)==0) 
     1734        { 
     1735            lcand = c->lcand; 
     1736            break; 
     1737        } 
     1738    } 
     1739#else 
     1740    /* Just get candidate with the highest priority for the specified  
     1741     * component ID in the checklist. 
     1742     */ 
     1743    for (i=0; i<ice->clist.count; ++i) { 
     1744        pj_ice_sess_check *c = &ice->clist.checks[i]; 
     1745        if (c->lcand->comp_id == sd->comp_id) { 
     1746            lcand = c->lcand; 
     1747            break; 
     1748        } 
     1749    } 
     1750    pj_assert(lcand != NULL); 
     1751#endif 
    17051752 
    17061753    /*  
     
    18231870 
    18241871 
    1825 PJ_DEF(pj_status_t) pj_ice_sess_send_data( pj_ice_sess *ice, 
    1826                                       unsigned comp_id, 
    1827                                       const void *data, 
    1828                                       pj_size_t data_len) 
     1872PJ_DEF(pj_status_t) pj_ice_sess_send_data(pj_ice_sess *ice, 
     1873                                          unsigned comp_id, 
     1874                                          const void *data, 
     1875                                          pj_size_t data_len) 
    18291876{ 
    18301877    pj_status_t status = PJ_SUCCESS; 
    18311878    pj_ice_sess_comp *comp; 
    1832     unsigned cand_id; 
    18331879 
    18341880    PJ_ASSERT_RETURN(ice && comp_id && comp_id <= ice->comp_cnt, PJ_EINVAL); 
     
    18471893    } 
    18481894 
    1849     cand_id = GET_LCAND_ID(comp->valid_check->lcand); 
    1850     status = (*ice->cb.on_tx_pkt)(ice, comp_id, cand_id, data, data_len,  
     1895    status = (*ice->cb.on_tx_pkt)(ice, comp_id, data, data_len,  
    18511896                                  &comp->valid_check->rcand->addr,  
    18521897                                  sizeof(pj_sockaddr_in)); 
     
    18581903 
    18591904 
    1860 PJ_DEF(pj_status_t) pj_ice_sess_on_rx_pkt( pj_ice_sess *ice, 
    1861                                       unsigned comp_id, 
    1862                                       unsigned cand_id, 
    1863                                       void *pkt, 
    1864                                       pj_size_t pkt_size, 
    1865                                       const pj_sockaddr_t *src_addr, 
    1866                                       int src_addr_len) 
     1905PJ_DEF(pj_status_t) pj_ice_sess_on_rx_pkt(pj_ice_sess *ice, 
     1906                                          unsigned comp_id, 
     1907                                          void *pkt, 
     1908                                          pj_size_t pkt_size, 
     1909                                          const pj_sockaddr_t *src_addr, 
     1910                                          int src_addr_len) 
    18671911{ 
    18681912    pj_status_t status = PJ_SUCCESS; 
    18691913    pj_ice_sess_comp *comp; 
    1870     pj_ice_sess_cand *lcand; 
    18711914    pj_status_t stun_status; 
    18721915 
     
    18811924    } 
    18821925 
    1883     lcand = &ice->lcand[cand_id]; 
    1884  
    18851926    stun_status = pj_stun_msg_check(pkt, pkt_size, PJ_STUN_IS_DATAGRAM); 
    18861927    if (stun_status == PJ_SUCCESS) { 
    1887         status = pj_stun_session_on_rx_pkt(lcand->stun_sess, pkt, pkt_size, 
     1928        status = pj_stun_session_on_rx_pkt(comp->stun_sess, pkt, pkt_size, 
    18881929                                           PJ_STUN_IS_DATAGRAM, 
    18891930                                           NULL, src_addr, src_addr_len); 
  • pjproject/trunk/pjnath/src/pjnath/ice_strans.c

    r1126 r1140  
    2424#include <pj/log.h> 
    2525#include <pj/pool.h> 
     26#include <pj/rand.h> 
    2627#include <pj/string.h> 
     28 
     29 
     30#if 0 
     31#  define TRACE_PKT(expr)           PJ_LOG(5,expr) 
     32#else 
     33#  define TRACE_PKT(expr) 
     34#endif 
    2735 
    2836 
     
    3139static void        on_ice_complete(pj_ice_sess *ice, pj_status_t status); 
    3240static pj_status_t ice_tx_pkt(pj_ice_sess *ice,  
    33                               unsigned comp_id, unsigned cand_id, 
     41                              unsigned comp_id, 
    3442                              const void *pkt, pj_size_t size, 
    3543                              const pj_sockaddr_t *dst_addr, 
     
    8593 
    8694    if (name == NULL) 
    87         name = "icest%p"; 
     95        name = "icstr%p"; 
    8896 
    8997    pool = pj_pool_create(stun_cfg->pf, name, 4000, 4000, NULL); 
     
    243251    pj_ice_strans_comp *comp; 
    244252    int retry, addr_len; 
     253    struct { 
     254        pj_uint32_t a1, a2, a3; 
     255    } tsx_id; 
    245256    pj_status_t status; 
    246257 
     
    251262    comp->sock = PJ_INVALID_SOCKET; 
    252263    comp->last_status = PJ_SUCCESS; 
     264 
     265    /* Create transaction ID for STUN keep alives */ 
     266    tsx_id.a1 = 0; 
     267    tsx_id.a2 = comp_id; 
     268    tsx_id.a3 = (pj_uint32_t) ice_st; 
     269    pj_memcpy(comp->ka_tsx_id, &tsx_id, sizeof(comp->ka_tsx_id)); 
    253270 
    254271    /* Create socket */ 
     
    438455         * The process below is just a workaround. 
    439456         */ 
    440         if (ice_st->ice) { 
    441             PJ_TODO(DISTINGUISH_BETWEEN_LOCAL_AND_RELAY); 
    442             status = pj_ice_sess_on_rx_pkt(ice_st->ice, comp->comp_id,  
    443                                       comp->cand_list[0].ice_cand_id, 
    444                                       comp->pkt, bytes_read, 
    445                                       &comp->src_addr, comp->src_addr_len); 
    446         } else if (comp->stun_sess) { 
    447             status = pj_stun_msg_check(comp->pkt, bytes_read,  
    448                                        PJ_STUN_IS_DATAGRAM); 
    449             if (status == PJ_SUCCESS) { 
     457        status = pj_stun_msg_check(comp->pkt, bytes_read,  
     458                                   PJ_STUN_IS_DATAGRAM); 
     459 
     460        if (status == PJ_SUCCESS) { 
     461            if (ice_st->ice==NULL || 
     462                pj_memcmp(comp->pkt+8, comp->ka_tsx_id, 12) == 0)  
     463            { 
    450464                status = pj_stun_session_on_rx_pkt(comp->stun_sess, comp->pkt, 
    451465                                                   bytes_read,  
     
    454468                                                   comp->src_addr_len); 
    455469            } else { 
    456                 (*ice_st->cb.on_rx_data)(ice_st, comp->comp_id,  
    457                                          comp->pkt, bytes_read,  
    458                                          &comp->src_addr, comp->src_addr_len); 
    459  
     470                PJ_TODO(DISTINGUISH_BETWEEN_LOCAL_AND_RELAY); 
     471 
     472                TRACE_PKT((comp->ice_st->obj_name,  
     473                          "Component %d RX packet from %s:%d", 
     474                          comp->comp_id, 
     475                          pj_inet_ntoa(comp->src_addr.ipv4.sin_addr), 
     476                          (int)pj_ntohs(comp->src_addr.ipv4.sin_port))); 
     477 
     478                status = pj_ice_sess_on_rx_pkt(ice_st->ice, comp->comp_id,  
     479                                               comp->pkt, bytes_read, 
     480                                               &comp->src_addr,  
     481                                               comp->src_addr_len); 
    460482            } 
    461483        } else { 
     
    528550        /* Create STUN binding request */ 
    529551        status = pj_stun_session_create_req(comp->stun_sess, 
    530                                             PJ_STUN_BINDING_REQUEST, &tdata); 
     552                                            PJ_STUN_BINDING_REQUEST,  
     553                                            comp->ka_tsx_id, &tdata); 
    531554        if (status != PJ_SUCCESS) 
    532555            continue; 
     
    555578        return; 
    556579 
    557     delay.sec = 20; 
    558     delay.msec = 0; 
     580    delay.sec = PJ_ICE_ST_KEEP_ALIVE_MIN; 
     581    delay.msec = pj_rand() % (PJ_ICE_ST_KEEP_ALIVE_MAX_RAND * 1000); 
     582    pj_time_val_normalize(&delay); 
    559583 
    560584    ice_st->ka_timer.cb = &ka_timer_cb; 
     
    617641    /* Create STUN binding request */ 
    618642    status = pj_stun_session_create_req(comp->stun_sess,  
    619                                         PJ_STUN_BINDING_REQUEST, &tdata); 
     643                                        PJ_STUN_BINDING_REQUEST,  
     644                                        comp->ka_tsx_id,  
     645                                        &tdata); 
    620646    if (status != PJ_SUCCESS) 
    621647        return status; 
     
    945971 */ 
    946972static pj_status_t ice_tx_pkt(pj_ice_sess *ice,  
    947                               unsigned comp_id, unsigned cand_id, 
     973                              unsigned comp_id,  
    948974                              const void *pkt, pj_size_t size, 
    949975                              const pj_sockaddr_t *dst_addr, 
     
    959985    PJ_ASSERT_RETURN(comp_id && comp_id <= ice_st->comp_cnt, PJ_EINVAL); 
    960986    comp = ice_st->comp[comp_id-1]; 
     987 
     988    TRACE_PKT((comp->ice_st->obj_name,  
     989              "Component %d TX packet to %s:%d", 
     990              comp_id, 
     991              pj_inet_ntoa(((pj_sockaddr_in*)dst_addr)->sin_addr), 
     992              (int)pj_ntohs(((pj_sockaddr_in*)dst_addr)->sin_port))); 
    961993 
    962994    pkt_size = size; 
     
    10271059    if (cand == NULL) { 
    10281060        /* This is keep-alive */ 
     1061        if (status != PJ_SUCCESS) { 
     1062            ice_st_perror(comp->ice_st, "STUN keep-alive request failed", 
     1063                          status); 
     1064        } 
    10291065        return; 
    10301066    } 
  • pjproject/trunk/pjnath/src/pjnath/stun_session.c

    r1126 r1140  
    5050 
    5151 
    52 static void tsx_on_complete(pj_stun_client_tsx *tsx, 
    53                             pj_status_t status,  
    54                             const pj_stun_msg *response); 
    55 static pj_status_t tsx_on_send_msg(pj_stun_client_tsx *tsx, 
    56                                    const void *stun_pkt, 
    57                                    pj_size_t pkt_size); 
     52static void stun_tsx_on_complete(pj_stun_client_tsx *tsx, 
     53                                 pj_status_t status,  
     54                                 const pj_stun_msg *response); 
     55static pj_status_t stun_tsx_on_send_msg(pj_stun_client_tsx *tsx, 
     56                                        const void *stun_pkt, 
     57                                        pj_size_t pkt_size); 
     58static void stun_tsx_on_destroy(pj_stun_client_tsx *tsx); 
    5859 
    5960static pj_stun_tsx_cb tsx_cb =  
    6061{ 
    61     &tsx_on_complete, 
    62     &tsx_on_send_msg 
     62    &stun_tsx_on_complete, 
     63    &stun_tsx_on_send_msg, 
     64    &stun_tsx_on_destroy 
    6365}; 
    6466 
     
    121123static pj_status_t create_request_tdata(pj_stun_session *sess, 
    122124                                        unsigned msg_type, 
     125                                        const pj_uint8_t tsx_id[12], 
    123126                                        pj_stun_tx_data **p_tdata) 
    124127{ 
     
    132135    /* Create STUN message */ 
    133136    status = pj_stun_msg_create(tdata->pool, msg_type,  PJ_STUN_MAGIC,  
    134                                 NULL, &tdata->msg); 
     137                                tsx_id, &tdata->msg); 
    135138    if (status != PJ_SUCCESS) { 
    136139        pj_pool_release(tdata->pool); 
     
    149152} 
    150153 
     154 
     155static void stun_tsx_on_destroy(pj_stun_client_tsx *tsx) 
     156{ 
     157    pj_stun_tx_data *tdata; 
     158 
     159    tdata = (pj_stun_tx_data*) pj_stun_client_tsx_get_data(tsx); 
     160    pj_stun_client_tsx_destroy(tsx); 
     161    pj_pool_release(tdata->pool); 
     162} 
     163 
    151164static void destroy_tdata(pj_stun_tx_data *tdata) 
    152165{ 
    153     if (tdata->client_tsx) { 
    154         tsx_erase(tdata->sess, tdata); 
    155         pj_stun_client_tsx_destroy(tdata->client_tsx); 
    156         tdata->client_tsx = NULL; 
    157     } 
    158166    if (tdata->res_timer.id != PJ_FALSE) { 
    159167        pj_timer_heap_cancel(tdata->sess->cfg->timer_heap,  
     
    162170        pj_list_erase(tdata); 
    163171    } 
    164     pj_pool_release(tdata->pool); 
     172 
     173    if (tdata->client_tsx) { 
     174        pj_time_val delay = {2, 0}; 
     175        tsx_erase(tdata->sess, tdata); 
     176        pj_stun_client_tsx_schedule_destroy(tdata->client_tsx, &delay); 
     177        tdata->client_tsx = NULL; 
     178 
     179    } else { 
     180        pj_pool_release(tdata->pool); 
     181    } 
    165182} 
    166183 
     
    307324 
    308325 
    309 static void tsx_on_complete(pj_stun_client_tsx *tsx, 
    310                             pj_status_t status,  
    311                             const pj_stun_msg *response) 
     326static void stun_tsx_on_complete(pj_stun_client_tsx *tsx, 
     327                                pj_status_t status,  
     328                                const pj_stun_msg *response) 
    312329{ 
    313330    pj_stun_tx_data *tdata; 
     
    321338} 
    322339 
    323 static pj_status_t tsx_on_send_msg(pj_stun_client_tsx *tsx, 
    324                                    const void *stun_pkt, 
    325                                    pj_size_t pkt_size) 
     340static pj_status_t stun_tsx_on_send_msg(pj_stun_client_tsx *tsx, 
     341                                        const void *stun_pkt, 
     342                                        pj_size_t pkt_size) 
    326343{ 
    327344    pj_stun_tx_data *tdata; 
     
    442459PJ_DEF(pj_status_t) pj_stun_session_create_req(pj_stun_session *sess, 
    443460                                               int method, 
     461                                               const pj_uint8_t tsx_id[12], 
    444462                                               pj_stun_tx_data **p_tdata) 
    445463{ 
     
    449467    PJ_ASSERT_RETURN(sess && p_tdata, PJ_EINVAL); 
    450468 
    451     status = create_request_tdata(sess, method, &tdata); 
     469    status = create_request_tdata(sess, method, tsx_id, &tdata); 
    452470    if (status != PJ_SUCCESS) 
    453471        return status; 
     
    766784    tdata = tsx_lookup(sess, msg); 
    767785    if (tdata == NULL) { 
    768         PJ_LOG(5,(SNAME(sess),  
     786        PJ_LOG(4,(SNAME(sess),  
    769787                  "Transaction not found, response silently discarded")); 
    770788        return PJ_SUCCESS; 
  • pjproject/trunk/pjnath/src/pjnath/stun_transaction.c

    r1126 r1140  
    3737 
    3838    pj_bool_t            complete; 
    39     \ 
     39 
    4040    pj_bool_t            require_retransmit; 
    41     pj_timer_entry       timer; 
     41    pj_timer_entry       retransmit_timer; 
    4242    unsigned             transmit_count; 
    4343    pj_time_val          retransmit_time; 
     44 
     45    pj_timer_entry       destroy_timer; 
    4446 
    4547    void                *last_pkt; 
     
    5052static void retransmit_timer_callback(pj_timer_heap_t *timer_heap,  
    5153                                      pj_timer_entry *timer); 
     54static void destroy_timer_callback(pj_timer_heap_t *timer_heap,  
     55                                   pj_timer_entry *timer); 
    5256 
    5357#define stun_perror(tsx,msg,rc) pjnath_perror(tsx->obj_name, msg, rc) 
     
    7074    pj_memcpy(&tsx->cb, cb, sizeof(*cb)); 
    7175 
    72     tsx->timer.cb = &retransmit_timer_callback; 
    73     tsx->timer.user_data = tsx; 
     76    tsx->retransmit_timer.cb = &retransmit_timer_callback; 
     77    tsx->retransmit_timer.user_data = tsx; 
     78 
     79    tsx->destroy_timer.cb = &destroy_timer_callback; 
     80    tsx->destroy_timer.user_data = tsx; 
    7481 
    7582    pj_ansi_snprintf(tsx->obj_name, sizeof(tsx->obj_name), "stuntsx%p", tsx); 
     
    8289 
    8390 
    84 /* 
    85  * . 
     91PJ_DEF(pj_status_t)  
     92pj_stun_client_tsx_schedule_destroy(pj_stun_client_tsx *tsx, 
     93                                    const pj_time_val *delay) 
     94{ 
     95    pj_status_t status; 
     96 
     97    PJ_ASSERT_RETURN(tsx && delay, PJ_EINVAL); 
     98    PJ_ASSERT_RETURN(tsx->cb.on_destroy, PJ_EINVAL); 
     99 
     100    /* Cancel previously registered timer */ 
     101    if (tsx->destroy_timer.id != 0) { 
     102        pj_timer_heap_cancel(tsx->cfg->timer_heap, &tsx->destroy_timer); 
     103        tsx->destroy_timer.id = 0; 
     104    } 
     105 
     106    /* Stop retransmission, just in case */ 
     107    if (tsx->retransmit_timer.id != 0) { 
     108        pj_timer_heap_cancel(tsx->cfg->timer_heap, &tsx->retransmit_timer); 
     109        tsx->retransmit_timer.id = 0; 
     110    } 
     111 
     112    status = pj_timer_heap_schedule(tsx->cfg->timer_heap, 
     113                                    &tsx->destroy_timer, delay); 
     114    if (status != PJ_SUCCESS) 
     115        return status; 
     116 
     117    tsx->destroy_timer.id = TIMER_ACTIVE; 
     118 
     119    return PJ_SUCCESS; 
     120} 
     121 
     122 
     123/* 
     124 * Destroy transaction immediately. 
    86125 */ 
    87126PJ_DEF(pj_status_t) pj_stun_client_tsx_destroy(pj_stun_client_tsx *tsx) 
     
    89128    PJ_ASSERT_RETURN(tsx, PJ_EINVAL); 
    90129 
    91     if (tsx->timer.id != 0) { 
    92         pj_timer_heap_cancel(tsx->cfg->timer_heap, &tsx->timer); 
    93         tsx->timer.id = 0; 
    94     } 
     130    if (tsx->retransmit_timer.id != 0) { 
     131        pj_timer_heap_cancel(tsx->cfg->timer_heap, &tsx->retransmit_timer); 
     132        tsx->retransmit_timer.id = 0; 
     133    } 
     134    if (tsx->destroy_timer.id != 0) { 
     135        pj_timer_heap_cancel(tsx->cfg->timer_heap, &tsx->destroy_timer); 
     136        tsx->destroy_timer.id = 0; 
     137    } 
     138 
     139    PJ_LOG(5,(tsx->obj_name, "STUN client transaction destroyed")); 
    95140    return PJ_SUCCESS; 
    96141} 
     
    136181    pj_status_t status; 
    137182 
    138     PJ_ASSERT_RETURN(tsx->timer.id == 0, PJ_EBUSY); 
     183    PJ_ASSERT_RETURN(tsx->retransmit_timer.id == 0, PJ_EBUSY); 
    139184 
    140185    if (tsx->require_retransmit) { 
     
    161206         * cancel transmission). 
    162207         */; 
    163         status = pj_timer_heap_schedule(tsx->cfg->timer_heap, &tsx->timer, 
     208        status = pj_timer_heap_schedule(tsx->cfg->timer_heap,  
     209                                        &tsx->retransmit_timer, 
    164210                                        &tsx->retransmit_time); 
    165211        if (status != PJ_SUCCESS) { 
    166             tsx->timer.id = 0; 
     212            tsx->retransmit_timer.id = 0; 
    167213            return status; 
    168214        } 
    169         tsx->timer.id = TIMER_ACTIVE; 
     215        tsx->retransmit_timer.id = TIMER_ACTIVE; 
    170216    } 
    171217 
     
    174220    status = tsx->cb.on_send_msg(tsx, tsx->last_pkt, tsx->last_pkt_size); 
    175221    if (status != PJ_SUCCESS) { 
    176         if (tsx->timer.id != 0) { 
    177             pj_timer_heap_cancel(tsx->cfg->timer_heap, &tsx->timer); 
    178             tsx->timer.id = 0; 
     222        if (tsx->retransmit_timer.id != 0) { 
     223            pj_timer_heap_cancel(tsx->cfg->timer_heap,  
     224                                 &tsx->retransmit_timer); 
     225            tsx->retransmit_timer.id = 0; 
    179226        } 
    180227        stun_perror(tsx, "STUN error sending message", status); 
     
    199246{ 
    200247    PJ_ASSERT_RETURN(tsx && pkt && pkt_len, PJ_EINVAL); 
    201     PJ_ASSERT_RETURN(tsx->timer.id == 0, PJ_EBUSY); 
     248    PJ_ASSERT_RETURN(tsx->retransmit_timer.id == 0, PJ_EBUSY); 
    202249 
    203250    /* Encode message */ 
     
    224271    if (tsx->transmit_count >= PJ_STUN_MAX_RETRANSMIT_COUNT) { 
    225272        /* Retransmission count exceeded. Transaction has failed */ 
    226         tsx->timer.id = 0; 
     273        tsx->retransmit_timer.id = 0; 
    227274        PJ_LOG(4,(tsx->obj_name, "STUN timeout waiting for response")); 
    228         tsx->complete = PJ_TRUE; 
    229         if (tsx->cb.on_complete) { 
    230             tsx->cb.on_complete(tsx, PJNATH_ESTUNTIMEDOUT, NULL); 
     275        if (!tsx->complete) { 
     276            tsx->complete = PJ_TRUE; 
     277            if (tsx->cb.on_complete) { 
     278                tsx->cb.on_complete(tsx, PJNATH_ESTUNTIMEDOUT, NULL); 
     279            } 
    231280        } 
    232281        return; 
    233282    } 
    234283 
    235     tsx->timer.id = 0; 
     284    tsx->retransmit_timer.id = 0; 
    236285    status = tsx_transmit_msg(tsx); 
    237286    if (status != PJ_SUCCESS) { 
    238         tsx->timer.id = 0; 
    239         tsx->complete = PJ_TRUE; 
    240         if (tsx->cb.on_complete) { 
    241             tsx->cb.on_complete(tsx, status, NULL); 
    242         } 
    243     } 
    244 } 
    245  
     287        tsx->retransmit_timer.id = 0; 
     288        if (!tsx->complete) { 
     289            tsx->complete = PJ_TRUE; 
     290            if (tsx->cb.on_complete) { 
     291                tsx->cb.on_complete(tsx, status, NULL); 
     292            } 
     293        } 
     294    } 
     295} 
     296 
     297 
     298/* Timer callback to destroy transaction */ 
     299static void destroy_timer_callback(pj_timer_heap_t *timer_heap,  
     300                                   pj_timer_entry *timer) 
     301{ 
     302    pj_stun_client_tsx *tsx = (pj_stun_client_tsx *) timer->user_data; 
     303 
     304    PJ_UNUSED_ARG(timer_heap); 
     305 
     306    tsx->destroy_timer.id = PJ_FALSE; 
     307    tsx->cb.on_destroy(tsx); 
     308    /* Don't access transaction after this */ 
     309} 
    246310 
    247311 
     
    268332     * We can cancel retransmit timer now. 
    269333     */ 
    270     if (tsx->timer.id) { 
    271         pj_timer_heap_cancel(tsx->cfg->timer_heap, &tsx->timer); 
    272         tsx->timer.id = 0; 
     334    if (tsx->retransmit_timer.id) { 
     335        pj_timer_heap_cancel(tsx->cfg->timer_heap, &tsx->retransmit_timer); 
     336        tsx->retransmit_timer.id = 0; 
    273337    } 
    274338 
     
    297361 
    298362    /* Call callback */ 
    299     tsx->complete = PJ_TRUE; 
    300     if (tsx->cb.on_complete) { 
    301         tsx->cb.on_complete(tsx, status, msg); 
    302     } 
    303  
    304     return PJ_SUCCESS; 
    305  
    306 } 
    307  
     363    if (!tsx->complete) { 
     364        tsx->complete = PJ_TRUE; 
     365        if (tsx->cb.on_complete) { 
     366            tsx->cb.on_complete(tsx, status, msg); 
     367        } 
     368    } 
     369 
     370    return PJ_SUCCESS; 
     371 
     372} 
     373 
Note: See TracChangeset for help on using the changeset viewer.