Changeset 1106


Ignore:
Timestamp:
Mar 26, 2007 1:25:07 PM (17 years ago)
Author:
bennylp
Message:

ICE: implement RTCP component and cancelling check in progress

Location:
pjproject/trunk
Files:
11 edited

Legend:

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

    r1104 r1106  
    154154{ 
    155155    struct transport_ice *tp_ice = (struct transport_ice*)tp; 
    156     unsigned comp_id; 
    157156    pj_status_t status; 
    158157 
     
    161160        return status; 
    162161 
    163     status = pj_ice_st_create_comp(tp_ice->ice_st, 1, options, start_addr,  
    164                                    &comp_id); 
     162    status = pj_ice_st_create_comp(tp_ice->ice_st, 1, options, start_addr); 
    165163    if (status != PJ_SUCCESS) 
    166164        return status; 
     
    168166    if (tp_ice->ice_st->comp_cnt > 1) { 
    169167        pj_sockaddr_in addr; 
     168        pj_uint16_t port; 
    170169 
    171170        pj_memcpy(&addr, &tp_ice->ice_st->comp[0]->local_addr.ipv4, 
     
    176175            addr.sin_addr.s_addr = 0; 
    177176 
    178         addr.sin_port = (pj_uint16_t)(pj_ntohs(addr.sin_port)+1); 
    179         status = pj_ice_st_create_comp(tp_ice->ice_st, 2, options,  
    180                                        &addr, &comp_id); 
     177        port = pj_ntohs(addr.sin_port); 
     178        ++port; 
     179        addr.sin_port = pj_htons(port); 
     180        status = pj_ice_st_create_comp(tp_ice->ice_st, 2, options, &addr); 
    181181        if (status != PJ_SUCCESS) 
    182182            return status; 
     
    482482        pj_assert(comp->default_cand >= 0); 
    483483        info->rtp_sock = comp->sock; 
    484         pj_memcpy(&info->rtp_addr_name,  
     484        pj_memcpy(&info->rtcp_addr_name,  
    485485                  &comp->cand_list[comp->default_cand].addr, 
    486486                  sizeof(pj_sockaddr_in)); 
  • pjproject/trunk/pjnath/build/pjnath_test.dsp

    r1095 r1106  
    5151LINK32=link.exe 
    5252# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 
    53 # ADD LINK32 netapi32.lib mswsock.lib ws2_32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 /out:"../bin/pjnath-test-i386-win32-vc6-release.exe" 
     53# ADD LINK32 mswsock.lib iphlpapi.lib netapi32.lib ws2_32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 /out:"../bin/pjnath-test-i386-win32-vc6-release.exe" 
    5454 
    5555!ELSEIF  "$(CFG)" == "pjnath_test - Win32 Debug" 
     
    7575LINK32=link.exe 
    7676# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept 
    77 # ADD LINK32 netapi32.lib ws2_32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /out:"../bin/pjnath-test-i386-win32-vc6-debug.exe" /pdbtype:sept 
     77# ADD LINK32 iphlpapi.lib netapi32.lib ws2_32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /out:"../bin/pjnath-test-i386-win32-vc6-debug.exe" /pdbtype:sept 
    7878 
    7979!ENDIF  
  • pjproject/trunk/pjnath/include/pjnath/ice.h

    r1104 r1106  
    6969 
    7070typedef struct pj_ice pj_ice; 
    71  
     71typedef struct pj_ice_check pj_ice_check; 
    7272 
    7373#define PJ_ICE_MAX_CAND     16 
     
    8181typedef struct pj_ice_comp 
    8282{ 
    83     unsigned         comp_id; 
    84     int              nominated_check_id; 
     83    pj_ice_check        *valid_check; 
    8584} pj_ice_comp; 
    8685 
     
    111110 
    112111 
    113 typedef struct pj_ice_check 
     112struct pj_ice_check 
    114113{ 
    115114    pj_ice_cand         *lcand; 
     
    118117    pj_uint64_t          prio; 
    119118    pj_ice_check_state   state; 
     119    pj_stun_tx_data     *tdata; 
    120120    pj_bool_t            nominated; 
    121121    pj_status_t          err_code; 
    122 } pj_ice_check; 
     122}; 
    123123 
    124124 
     
    206206    pj_ice_checklist     valid_list; 
    207207}; 
     208 
     209PJ_DECL(const char*) pj_ice_get_cand_type_name(pj_ice_cand_type type); 
    208210 
    209211 
  • pjproject/trunk/pjnath/include/pjnath/ice_stream_transport.h

    r1104 r1106  
    6161enum pj_ice_st_option 
    6262{ 
    63     PJ_ICE_ST_OPT_DISABLE_STUN  = 1, 
    64     PJ_ICE_ST_OPT_DISABLE_RELAY = 2, 
    65     PJ_ICE_ST_OPT_NO_PORT_RETRY = 4, 
     63    PJ_ICE_ST_OPT_DONT_ADD_CAND = 1, 
     64    PJ_ICE_ST_OPT_DISABLE_STUN  = 2, 
     65    PJ_ICE_ST_OPT_DISABLE_RELAY = 4, 
     66    PJ_ICE_ST_OPT_NO_PORT_RETRY = 8, 
    6667}; 
    6768 
     
    144145                                           unsigned comp_id, 
    145146                                           pj_uint32_t options, 
    146                                            const pj_sockaddr_in *addr, 
    147                                            unsigned *p_itf_id); 
     147                                           const pj_sockaddr_in *addr); 
     148PJ_DECL(pj_status_t) pj_ice_st_add_cand(pj_ice_st *ice_st, 
     149                                        unsigned comp_id, 
     150                                        pj_ice_cand_type type, 
     151                                        pj_uint16_t local_pref, 
     152                                        const pj_sockaddr_in *addr, 
     153                                        pj_bool_t set_default); 
    148154 
    149155PJ_DECL(pj_status_t) pj_ice_st_get_comps_status(pj_ice_st *ice_st); 
  • pjproject/trunk/pjnath/include/pjnath/stun_session.h

    r1091 r1106  
    319319 
    320320/** 
     321 * Cancel outgoing STUN transaction. This operation is only valid for outgoing 
     322 * STUN request, to cease retransmission of the request and destroy the 
     323 * STUN client transaction that is used to send the request. 
     324 * 
     325 * @param sess      The STUN session instance. 
     326 * @param tdata     The request message previously sent. 
     327 * @param notify    Specify whether \a on_request_complete() callback should 
     328 *                  be called. 
     329 * @param status    If \a on_request_complete() callback is to be called, 
     330 *                  specify the error status to be given when calling the 
     331 *                  callback. This error status MUST NOT be PJ_SUCCESS. 
     332 * 
     333 * @return          PJ_SUCCESS if transaction is successfully cancelled. 
     334 */ 
     335PJ_DECL(pj_status_t) pj_stun_session_cancel_req(pj_stun_session *sess, 
     336                                                pj_stun_tx_data *tdata, 
     337                                                pj_bool_t notify, 
     338                                                pj_status_t status); 
     339 
     340/** 
    321341 * Application must call this function to notify the STUN session about 
    322342 * the arrival of STUN packet. The STUN packet MUST have been checked 
  • pjproject/trunk/pjnath/src/pjnath-test/ice_test.c

    r1100 r1106  
    1919#include "test.h" 
    2020 
    21 #define THIS_FILE   "ice.c" 
     21#define THIS_FILE   "ice_test.c" 
    2222 
    2323 
     
    4444    id->complete = PJ_TRUE; 
    4545    id->err_code = status; 
    46     PJ_LOG(3,(THIS_FILE, "    ICE %s complete %s", id->obj_name, 
     46    PJ_LOG(3,(THIS_FILE, "     ICE %s complete %s", id->obj_name, 
    4747              (status==PJ_SUCCESS ? "successfully" : "with failure"))); 
    4848} 
    4949 
    5050 
    51 static void on_rx_data(pj_ice_st *icest, 
    52                        unsigned comp_id, unsigned cand_id, 
     51static void on_rx_data(pj_ice_st *icest, unsigned comp_id,  
    5352                       void *pkt, pj_size_t size, 
    5453                       const pj_sockaddr_t *src_addr, 
     
    6968    } 
    7069 
    71     PJ_UNUSED_ARG(cand_id); 
    7270    PJ_UNUSED_ARG(src_addr); 
    7371    PJ_UNUSED_ARG(src_addr_len); 
     
    102100    icest_cb.on_rx_data = &on_rx_data; 
    103101 
    104     status = pj_ice_st_create(&stun_cfg, NULL, NULL, &icest_cb, &im); 
     102    status = pj_ice_st_create(&stun_cfg, "icetest", 2, NULL, &icest_cb, &im); 
    105103    if (status != PJ_SUCCESS) 
    106104        return -10; 
     
    127125} 
    128126 
     127 
     128struct dummy_cand 
     129{ 
     130    unsigned             comp_id; 
     131    pj_ice_cand_type     type; 
     132    const char          *addr; 
     133    unsigned             port; 
     134}; 
     135 
     136static int init_ice_st(pj_ice_st *ice_st, 
     137                       pj_bool_t add_valid_comp, 
     138                       unsigned dummy_cnt, 
     139                       struct dummy_cand cand[]) 
     140{ 
     141    pj_str_t a; 
     142    pj_status_t status; 
     143    unsigned i; 
     144 
     145    /* Create components */ 
     146    for (i=0; i<ice_st->comp_cnt; ++i) { 
     147        status = pj_ice_st_create_comp(ice_st, i+1, PJ_ICE_ST_OPT_DONT_ADD_CAND, NULL); 
     148        if (status != PJ_SUCCESS) 
     149            return -21; 
     150    } 
     151 
     152    /* Add dummy candidates */ 
     153    for (i=0; i<dummy_cnt; ++i) { 
     154        pj_sockaddr_in addr; 
     155 
     156        pj_sockaddr_in_init(&addr, pj_cstr(&a, cand[i].addr), (pj_uint16_t)cand[i].port); 
     157        status = pj_ice_st_add_cand(ice_st, cand[i].comp_id, cand[i].type, 
     158                                    65535, &addr, PJ_FALSE); 
     159        if (status != PJ_SUCCESS) 
     160            return -22; 
     161    } 
     162 
     163    /* Add the real candidate */ 
     164    if (add_valid_comp) { 
     165        for (i=0; i<ice_st->comp_cnt; ++i) { 
     166            status = pj_ice_st_add_cand(ice_st, i+1, PJ_ICE_CAND_TYPE_HOST, 65535, 
     167                                        &ice_st->comp[i]->local_addr.ipv4, PJ_TRUE); 
     168            if (status != PJ_SUCCESS) 
     169                return -23; 
     170        } 
     171    } 
     172 
     173    return 0; 
     174} 
     175 
     176 
     177/* When ICE completes, both agents should agree on the same candidate pair. 
     178 * Check that the remote address selected by agent1 is equal to the 
     179 * local address of selected by agent 2. 
     180 */ 
     181static int verify_address(pj_ice_st *agent1, pj_ice_st *agent2, 
     182                          unsigned comp_id) 
     183{ 
     184    pj_ice_cand *rcand, *lcand; 
     185    int lcand_id; 
     186 
     187    if (agent1->ice->comp[comp_id-1].valid_check == NULL) { 
     188        PJ_LOG(3,(THIS_FILE, "....error: valid_check not set for comp_id %d", comp_id)); 
     189        return -60; 
     190    } 
     191 
     192    /* Get default remote candidate of agent 1 */ 
     193    rcand = agent1->ice->comp[comp_id-1].valid_check->rcand; 
     194 
     195    /* Get default local candidate of agent 2 */ 
     196    pj_ice_find_default_cand(agent2->ice, comp_id, &lcand_id); 
     197    if (lcand_id < 0) 
     198        return -62; 
     199 
     200    lcand = &agent2->ice->lcand[lcand_id]; 
     201 
     202    if (pj_memcmp(&rcand->addr, &lcand->addr, sizeof(pj_sockaddr_in))!=0) { 
     203        PJ_LOG(3,(THIS_FILE, "....error: the selected addresses are incorrect for comp_id %d", comp_id)); 
     204        return -64; 
     205    } 
     206 
     207    return 0; 
     208} 
    129209 
    130210 
     
    142222 */ 
    143223static int perform_ice_test(const char *title, 
     224                            pj_bool_t expected_success, 
     225                            unsigned comp_cnt, 
     226                            pj_bool_t add_valid_comp, 
    144227                            unsigned wait_before_send, 
    145                             unsigned max_total_time) 
     228                            unsigned max_total_time, 
     229                            unsigned ocand_cnt, 
     230                            struct dummy_cand ocand[], 
     231                            unsigned acand_cnt, 
     232                            struct dummy_cand acand[]) 
    146233{ 
    147234    pj_ice_st *im1, *im2; 
     
    149236    struct ice_data *id1, *id2; 
    150237    pj_timestamp t_start, t_end; 
    151     pj_ice_cand *rcand; 
     238    unsigned i; 
    152239    pj_str_t data_from_offerer, data_from_answerer; 
    153240    pj_status_t status; 
    154241 
     242#define CHECK_COMPLETE()    if (id1->complete && id2->complete) { \ 
     243                                if (t_end.u32.lo==0) pj_get_timestamp(&t_end); \ 
     244                            } else {} 
     245 
    155246    PJ_LOG(3,(THIS_FILE, "...%s", title)); 
     247 
     248    pj_bzero(&t_end, sizeof(t_end)); 
    156249 
    157250    pj_bzero(&icest_cb, sizeof(icest_cb)); 
     
    160253 
    161254    /* Create first ICE */ 
    162     status = pj_ice_st_create(&stun_cfg, "offerer", NULL, &icest_cb, &im1); 
     255    status = pj_ice_st_create(&stun_cfg, "offerer", comp_cnt, NULL, &icest_cb, &im1); 
    163256    if (status != PJ_SUCCESS) 
    164257        return -20; 
     
    168261    im1->user_data = id1; 
    169262 
    170     /* Add first component */ 
    171     status = pj_ice_st_add_comp(im1, 1); 
    172     if (status != PJ_SUCCESS) 
    173         return -21; 
    174  
    175     /* Add host candidate */ 
    176     status = pj_ice_st_add_host_interface(im1, 1, 65535, NULL, NULL); 
    177     if (status != PJ_SUCCESS) 
    178         return -21; 
     263    /* Init components */ 
     264    status = init_ice_st(im1, add_valid_comp, ocand_cnt, ocand); 
     265    if (status != 0) 
     266        return status; 
    179267 
    180268    /* Create second ICE */ 
    181     status = pj_ice_st_create(&stun_cfg, "answerer", NULL, &icest_cb, &im2); 
     269    status = pj_ice_st_create(&stun_cfg, "answerer", comp_cnt, NULL, &icest_cb, &im2); 
    182270    if (status != PJ_SUCCESS) 
    183271        return -25; 
     
    187275    im2->user_data = id2; 
    188276 
    189     /* Add first component */ 
    190     status = pj_ice_st_add_comp(im2, 1); 
    191     if (status != PJ_SUCCESS) 
    192         return -26; 
    193  
    194     /* Add host candidate */ 
    195     status = pj_ice_st_add_host_interface(im2, 1, 65535, NULL, NULL); 
    196     if (status != PJ_SUCCESS) 
    197         return -27; 
     277    /* Init components */ 
     278    status = init_ice_st(im2, add_valid_comp, acand_cnt, acand); 
     279    if (status != 0) 
     280        return status; 
     281 
    198282 
    199283    /* Init ICE on im1 */ 
     
    217301        return -35; 
    218302 
     303    /* Apply delay to let other checks commence */ 
     304    pj_thread_sleep(40); 
     305 
    219306    /* Mark start time */ 
    220307    pj_get_timestamp(&t_start); 
    221308 
    222309    /* Poll for wait_before_send msecs before we send the first data */ 
    223     for (;;) { 
    224         pj_timestamp t_now; 
    225  
    226         handle_events(1); 
    227  
    228         pj_get_timestamp(&t_now); 
    229         if (pj_elapsed_msec(&t_start, &t_now) >= wait_before_send) 
    230             break; 
    231     } 
    232  
    233     /* Send data. It must be successful! */ 
    234     data_from_offerer = pj_str("from offerer"); 
    235     status = pj_ice_send_data(im1->ice, 1, data_from_offerer.ptr, data_from_offerer.slen); 
    236     if (status != PJ_SUCCESS) 
    237         return -47; 
    238  
    239     data_from_answerer = pj_str("from answerer"); 
    240     status = pj_ice_send_data(im2->ice, 1, data_from_answerer.ptr, data_from_answerer.slen); 
    241     if (status != PJ_SUCCESS) 
    242         return -48; 
    243  
    244     /* Poll to allow data to be received */ 
    245     for (;;) { 
    246         pj_timestamp t_now; 
    247         handle_events(1); 
    248         pj_get_timestamp(&t_now); 
    249         if (pj_elapsed_msec(&t_start, &t_now) >= (wait_before_send + 200)) 
    250             break; 
    251     } 
    252  
     310    if (expected_success) { 
     311        for (;;) { 
     312            pj_timestamp t_now; 
     313 
     314            handle_events(1); 
     315 
     316            CHECK_COMPLETE(); 
     317 
     318            pj_get_timestamp(&t_now); 
     319            if (pj_elapsed_msec(&t_start, &t_now) >= wait_before_send) 
     320                break; 
     321        } 
     322 
     323        /* Send data. It must be successful! */ 
     324        data_from_offerer = pj_str("from offerer"); 
     325        status = pj_ice_send_data(im1->ice, 1, data_from_offerer.ptr, data_from_offerer.slen); 
     326        if (status != PJ_SUCCESS) 
     327            return -47; 
     328 
     329        data_from_answerer = pj_str("from answerer"); 
     330        status = pj_ice_send_data(im2->ice, 1, data_from_answerer.ptr, data_from_answerer.slen); 
     331        if (status != PJ_SUCCESS) 
     332            return -48; 
     333 
     334        /* Poll to allow data to be received */ 
     335        for (;;) { 
     336            pj_timestamp t_now; 
     337            handle_events(1); 
     338            CHECK_COMPLETE(); 
     339            pj_get_timestamp(&t_now); 
     340            if (pj_elapsed_msec(&t_start, &t_now) >= (wait_before_send + 200)) 
     341                break; 
     342        } 
     343    } 
    253344 
    254345    /* Just wait until both completes, or timed out */ 
     
    258349        handle_events(1); 
    259350 
     351        CHECK_COMPLETE(); 
    260352        pj_get_timestamp(&t_now); 
    261353        if (pj_elapsed_msec(&t_start, &t_now) >= max_total_time) { 
     
    266358 
    267359    /* Mark end-time */ 
    268     pj_get_timestamp(&t_end); 
     360    CHECK_COMPLETE(); 
     361 
     362    /* If expected to fail, then just check that both fail */ 
     363    if (!expected_success) { 
     364        /* Check status */ 
     365        if (id1->err_code == PJ_SUCCESS) 
     366            return -51; 
     367        if (id2->err_code == PJ_SUCCESS) 
     368            return -52; 
     369        goto on_return; 
     370    } 
    269371 
    270372    /* Check status */ 
     
    275377 
    276378    /* Verify that offerer gets answerer's transport address */ 
    277     rcand = im1->ice->clist.checks[im1->ice->comp[0].nominated_check_id].rcand; 
    278     if (pj_memcmp(&rcand->addr, &im2->ice->lcand[0].addr, sizeof(pj_sockaddr_in))!=0) { 
    279         PJ_LOG(3,(THIS_FILE, "....error: address mismatch")); 
    280         return -60; 
     379    for (i=0; i<comp_cnt; ++i) { 
     380        status = verify_address(im1, im2, i+1); 
     381        if (status != 0) 
     382            return status; 
    281383    } 
    282384 
    283385    /* And the other way around */ 
    284     rcand = im2->ice->clist.checks[im2->ice->comp[0].nominated_check_id].rcand; 
    285     if (pj_memcmp(&rcand->addr, &im1->ice->lcand[0].addr, sizeof(pj_sockaddr_in))!=0) { 
    286         PJ_LOG(3,(THIS_FILE, "....error: address mismatch")); 
    287         return -70; 
     386    for (i=0; i<comp_cnt; ++i) { 
     387        status = verify_address(im2, im1, i+1); 
     388        if (status != 0) 
     389            return status; 
    288390    } 
    289391 
     
    309411 
    310412 
     413on_return: 
     414 
    311415    /* Done */ 
    312     PJ_LOG(3,(THIS_FILE, "....success: ICE completed in %d msec",  
     416    PJ_LOG(3,(THIS_FILE, "....success: ICE completed in %d msec, waiting..",  
    313417              pj_elapsed_msec(&t_start, &t_end))); 
    314418 
    315419    /* Wait for some more time */ 
    316     PJ_LOG(3,(THIS_FILE, ".....waiting..")); 
    317420    for (;;) { 
    318421        pj_timestamp t_now; 
     
    328431    pj_ice_st_destroy(im1); 
    329432    pj_ice_st_destroy(im2); 
     433    handle_events(100); 
    330434    return 0; 
    331435} 
     
    338442    pj_ioqueue_t *ioqueue; 
    339443    pj_timer_heap_t *timer_heap; 
     444    enum { D1=500, D2=5000, D3=15000 }; 
     445    struct dummy_cand ocand[] =  
     446    { 
     447        {1, PJ_ICE_CAND_TYPE_SRFLX, "127.1.1.1", 65534 }, 
     448        {2, PJ_ICE_CAND_TYPE_SRFLX, "127.1.1.1", 65535 }, 
     449    }; 
     450    struct dummy_cand acand[] = 
     451    { 
     452        {1, PJ_ICE_CAND_TYPE_SRFLX, "127.2.2.2", 65534 }, 
     453        {2, PJ_ICE_CAND_TYPE_SRFLX, "127.2.2.2", 65535 }, 
     454    }; 
    340455 
    341456    pool = pj_pool_create(mem, NULL, 4000, 4000, NULL); 
     
    345460    pj_stun_config_init(&stun_cfg, mem, 0, ioqueue, timer_heap); 
    346461 
    347     pj_log_set_level(5); 
     462    //pj_log_set_level(4); 
    348463 
    349464    /* Basic create/destroy */ 
     
    353468 
    354469    /* Direct communication */ 
    355     rc = perform_ice_test("Direct connection", 500, 1000); 
     470    rc = perform_ice_test("Simple test (1 component)", PJ_TRUE, 1, PJ_TRUE, D1, D2, 0, NULL, 0, NULL); 
     471    if (rc != 0) 
     472        goto on_return; 
     473 
     474    /* Failure case (all checks fail) */ 
     475    rc = perform_ice_test("Failure case (all checks fail)", PJ_FALSE, 1, PJ_FALSE, D3, D3, 1, ocand, 1, acand); 
    356476    if (rc != 0) 
    357477        goto on_return; 
    358478 
    359479    /* Direct communication with invalid address */ 
    360     rc = perform_ice_test("Direct connection with 1 invalid address", 500, 1000); 
     480    rc = perform_ice_test("With 1 unreachable address", PJ_TRUE, 1, PJ_TRUE, D1, D2, 1, ocand, 0, NULL); 
     481    if (rc != 0) 
     482        goto on_return; 
     483 
     484    /* Direct communication with invalid address */ 
     485    rc = perform_ice_test("With 2 unreachable addresses (one each)", PJ_TRUE, 1, PJ_TRUE, D1, D2, 1, ocand, 1, acand); 
    361486    if (rc != 0) 
    362487        goto on_return; 
    363488 
    364489    /* Direct communication with two components */ 
    365     rc = perform_ice_test("Direct connection with two components", 500, 1000); 
     490    rc = perform_ice_test("With two components (RTP and RTCP)", PJ_TRUE, 2, PJ_TRUE, D1, D2, 0, NULL, 0, NULL); 
     491    if (rc != 0) 
     492        goto on_return; 
     493 
     494    /* Direct communication with mismatch number of components */ 
     495 
     496    /* Direct communication with 2 components and 2 invalid address */ 
     497    rc = perform_ice_test("With 2 two components and 2 unreachable address", PJ_TRUE, 2, PJ_TRUE, D1, D2, 1, ocand, 1, acand); 
    366498    if (rc != 0) 
    367499        goto on_return; 
     
    370502 
    371503on_return: 
    372     pj_log_set_level(3); 
     504    //pj_log_set_level(3); 
    373505    pj_ioqueue_destroy(stun_cfg.ioqueue); 
    374506    pj_pool_release(pool); 
  • pjproject/trunk/pjnath/src/pjnath-test/test.c

    r1094 r1106  
    5050    mem = &caching_pool.factory; 
    5151 
    52 #if 0 
    5352    pj_log_set_level(3); 
    5453    pj_log_set_decor(PJ_LOG_HAS_NEWLINE | PJ_LOG_HAS_TIME |  
    5554                     PJ_LOG_HAS_MICRO_SEC); 
    56 #endif 
    5755 
    5856    rc = pj_init(); 
  • pjproject/trunk/pjnath/src/pjnath/ice.c

    r1104 r1106  
    5757}; 
    5858 
    59 #define CHECK_NAME_LEN      128 
    60 #define LOG4(expr)          PJ_LOG(4,expr) 
    61 #define LOG5(expr)          PJ_LOG(4,expr) 
    62 #define GET_LCAND_ID(cand)  (cand - ice->lcand) 
    63 #define GET_CHECK_ID(chk)   (chk - ice->clist.checks) 
     59#define CHECK_NAME_LEN          128 
     60#define LOG4(expr)              PJ_LOG(4,expr) 
     61#define LOG5(expr)              PJ_LOG(4,expr) 
     62#define GET_LCAND_ID(cand)      (cand - ice->lcand) 
     63#define GET_CHECK_ID(cl, chk)   (chk - (cl)->checks) 
    6464 
    6565 
     
    131131 
    132132 
     133PJ_DEF(const char*) pj_ice_get_cand_type_name(pj_ice_cand_type type) 
     134{ 
     135    return cand_type_names[type]; 
     136} 
     137 
     138 
    133139/* 
    134140 * Create ICE stream session. 
     
    177183        pj_ice_comp *comp; 
    178184        comp = &ice->comp[i]; 
    179         comp->comp_id = i+1; 
    180         comp->nominated_check_id = -1; 
     185        comp->valid_check = NULL; 
    181186    } 
    182187 
     
    412417                     foundation && addr && base_addr && addr_len, 
    413418                     PJ_EINVAL); 
     419    PJ_ASSERT_RETURN(comp_id <= ice->comp_cnt, PJ_EINVAL); 
    414420 
    415421    pj_mutex_lock(ice->mutex); 
     
    499505 
    500506    PJ_ASSERT_RETURN(ice && comp_id && cand_id, PJ_EINVAL); 
     507    PJ_ASSERT_RETURN(comp_id <= ice->comp_cnt, PJ_EINVAL); 
    501508 
    502509    *cand_id = -1; 
     
    586593 
    587594static const char *dump_check(char *buffer, unsigned bufsize, 
    588                               const pj_ice *ice, 
     595                              const pj_ice_checklist *clist, 
    589596                              const pj_ice_check *check) 
    590597{ 
     
    598605    if (lcand->addr.addr.sa_family == PJ_AF_INET) { 
    599606        len = pj_ansi_snprintf(buffer, bufsize, 
    600                                "%d: %s:%d-->%s:%d", 
    601                                GET_CHECK_ID(check), 
     607                               "%d: [%d] %s:%d-->%s:%d", 
     608                               GET_CHECK_ID(clist, check), 
     609                               check->lcand->comp_id, 
    602610                               laddr, (int)pj_ntohs(lcand->addr.ipv4.sin_port), 
    603611                               pj_inet_ntoa(rcand->addr.ipv4.sin_addr), 
     
    628636        const pj_ice_check *c = &clist->checks[i]; 
    629637        LOG4((ice->obj_name, " %s (%s, state=%s)", 
    630              dump_check(buffer, sizeof(buffer), ice, c), 
     638             dump_check(buffer, sizeof(buffer), clist, c), 
    631639             (c->nominated ? "nominated" : "not nominated"),  
    632640             check_state_name[c->state])); 
     
    647655 
    648656    LOG5((ice->obj_name, "Check %s: state changed from %s to %s", 
    649          dump_check(buf, sizeof(buf), ice, check), 
     657         dump_check(buf, sizeof(buf), &ice->clist, check), 
    650658         check_state_name[check->state], 
    651659         check_state_name[st])); 
     
    760768 
    761769                LOG5((ice->obj_name, "Check %s pruned", 
    762                     dump_check(buf, sizeof(buf), ice, &clist->checks[j]))); 
     770                    dump_check(buf, sizeof(buf), &ice->clist,  
     771                               &clist->checks[j]))); 
    763772 
    764773                pj_array_erase(clist->checks, sizeof(clist->checks[0]), 
     
    813822    if (check->err_code==PJ_SUCCESS && check->nominated) { 
    814823        pj_ice_comp *comp; 
     824        char buf[CHECK_NAME_LEN]; 
    815825 
    816826        LOG5((ice->obj_name, "Check %d is successful and nominated", 
    817              GET_CHECK_ID(check))); 
     827             GET_CHECK_ID(&ice->clist, check))); 
    818828 
    819829        for (i=0; i<ice->clist.count; ++i) { 
    820830            pj_ice_check *c = &ice->clist.checks[i]; 
    821             if (c->lcand->comp_id == check->lcand->comp_id && 
    822                 (c->state==PJ_ICE_CHECK_STATE_FROZEN || 
    823                  c->state==PJ_ICE_CHECK_STATE_WAITING)) 
    824             { 
    825                 LOG5((ice->obj_name,  
    826                      "Check %d to be failed because state is %s", 
    827                      i, check_state_name[c->state])); 
    828                 check_set_state(ice, c, PJ_ICE_CHECK_STATE_FAILED, 
    829                                 PJ_ECANCELLED); 
     831            if (c->lcand->comp_id == check->lcand->comp_id) { 
     832                if (c->state < PJ_ICE_CHECK_STATE_IN_PROGRESS) { 
     833                    /* Just fail Frozen/Waiting check */ 
     834                    LOG5((ice->obj_name,  
     835                         "Check %s to be failed because state is %s", 
     836                         dump_check(buf, sizeof(buf), &ice->clist, c),  
     837                         check_state_name[c->state])); 
     838                    check_set_state(ice, c, PJ_ICE_CHECK_STATE_FAILED, 
     839                                    PJ_ECANCELLED); 
     840 
     841                } else if (c->state == PJ_ICE_CHECK_STATE_IN_PROGRESS) { 
     842                    /* State is IN_PROGRESS, cancel transaction */ 
     843                    if (c->tdata) { 
     844                        LOG5((ice->obj_name,  
     845                             "Cancelling check %s (In Progress)", 
     846                             dump_check(buf, sizeof(buf), &ice->clist, c))); 
     847                        pj_stun_session_cancel_req(c->lcand->stun_sess,  
     848                                                   c->tdata, PJ_FALSE, 0); 
     849                        c->tdata = NULL; 
     850                        check_set_state(ice, c, PJ_ICE_CHECK_STATE_FAILED, 
     851                                        PJ_ECANCELLED); 
     852                    } 
     853                } 
    830854            } 
    831855        } 
     
    833857        /* Update the nominated check for the component */ 
    834858        comp = find_comp(ice, check->lcand->comp_id); 
    835         if (comp->nominated_check_id < 0) { 
    836             comp->nominated_check_id = GET_CHECK_ID(check); 
     859        if (comp->valid_check == NULL) { 
     860            comp->valid_check = check; 
    837861        } else { 
    838             pj_ice_check *nom_check; 
    839             nom_check = &ice->clist.checks[comp->nominated_check_id]; 
    840             if (nom_check->prio < check->prio) 
    841                 comp->nominated_check_id = GET_CHECK_ID(check); 
     862            if (comp->valid_check->prio < check->prio) 
     863                comp->valid_check = check; 
    842864        } 
    843865    } 
     
    878900     */ 
    879901    for (i=0; i<ice->comp_cnt; ++i) { 
    880         if (ice->comp[i].nominated_check_id == -1) 
     902        if (ice->comp[i].valid_check == NULL) 
    881903            break; 
    882904    } 
     
    950972    ice->rcand_cnt = 0; 
    951973    for (i=0; i<rcand_cnt; ++i) { 
    952         pj_ice_cand *cn = &ice->rcand[ice->rcand_cnt++]; 
     974        pj_ice_cand *cn = &ice->rcand[ice->rcand_cnt]; 
     975 
     976        /* Ignore candidate which has no matching component ID */ 
     977        pj_assert(rcand[i].comp_id > 0); 
     978        if (rcand[i].comp_id==0 || rcand[i].comp_id > ice->comp_cnt) { 
     979            continue; 
     980        } 
     981 
    953982        pj_memcpy(cn, &rcand[i], sizeof(pj_ice_cand)); 
    954983        pj_strdup(ice->pool, &cn->foundation, &rcand[i].foundation); 
     984        ice->rcand_cnt++; 
    955985    } 
    956986 
     
    967997                pj_mutex_unlock(ice->mutex); 
    968998                return PJ_ETOOMANY; 
    969             } else { 
    970                 clist->count++; 
    971             } 
     999            }  
    9721000 
    9731001            /* A local candidate is paired with a remote candidate if 
     
    9871015 
    9881016            chk->prio = CALC_CHECK_PRIO(ice, lcand, rcand); 
     1017 
     1018            clist->count++; 
    9891019        } 
    9901020    } 
     
    10271057                                 unsigned check_id) 
    10281058{ 
    1029     pj_stun_tx_data *tdata; 
    10301059    pj_ice_comp *comp; 
    10311060    struct req_data *rd; 
     
    10441073    LOG5((ice->obj_name,  
    10451074         "Sending connectivity check for check %s",  
    1046          dump_check(buffer, sizeof(buffer), ice, check))); 
     1075         dump_check(buffer, sizeof(buffer), clist, check))); 
    10471076 
    10481077    /* Create request */ 
    10491078    status = pj_stun_session_create_req(lcand->stun_sess,  
    1050                                         PJ_STUN_BINDING_REQUEST, &tdata); 
     1079                                        PJ_STUN_BINDING_REQUEST,  
     1080                                        &check->tdata); 
    10511081    if (status != PJ_SUCCESS) 
    10521082        return status; 
     
    10551085     * completes and on_stun_request_complete() callback is called. 
    10561086     */ 
    1057     rd = PJ_POOL_ZALLOC_T(tdata->pool, struct req_data); 
     1087    rd = PJ_POOL_ZALLOC_T(check->tdata->pool, struct req_data); 
    10581088    rd->ice = ice; 
    10591089    rd->clist = clist; 
    10601090    rd->ckid = check_id; 
    1061     tdata->user_data = (void*) rd; 
     1091    check->tdata->user_data = (void*) rd; 
    10621092 
    10631093    /* Add PRIORITY */ 
    10641094    prio = CALC_CAND_PRIO(PJ_ICE_CAND_TYPE_PRFLX, 65535,  
    10651095                          lcand->comp_id); 
    1066     pj_stun_msg_add_uint_attr(tdata->pool, tdata->msg, PJ_STUN_ATTR_PRIORITY, 
    1067                               prio); 
     1096    pj_stun_msg_add_uint_attr(check->tdata->pool, check->tdata->msg,  
     1097                              PJ_STUN_ATTR_PRIORITY, prio); 
    10681098 
    10691099    /* Add USE-CANDIDATE and set this check to nominated */ 
    10701100    if (ice->role == PJ_ICE_ROLE_CONTROLLING) { 
    1071         pj_stun_msg_add_empty_attr(tdata->pool, tdata->msg,  
     1101        pj_stun_msg_add_empty_attr(check->tdata->pool, check->tdata->msg,  
    10721102                                   PJ_STUN_ATTR_USE_CANDIDATE); 
    10731103        check->nominated = PJ_TRUE; 
     
    10811111    status = pj_stun_session_send_msg(lcand->stun_sess, PJ_FALSE,  
    10821112                                      &rcand->addr,  
    1083                                       sizeof(pj_sockaddr_in), tdata); 
    1084     if (status != PJ_SUCCESS) 
     1113                                      sizeof(pj_sockaddr_in), check->tdata); 
     1114    if (status != PJ_SUCCESS) { 
     1115        check->tdata = NULL; 
    10851116        return status; 
     1117    } 
    10861118 
    10871119    check_set_state(ice, check, PJ_ICE_CHECK_STATE_IN_PROGRESS, PJ_SUCCESS); 
     
    12501282    clist = rd->clist; 
    12511283 
     1284    /* Mark STUN transaction as complete */ 
     1285    pj_assert(tdata == check->tdata); 
     1286    check->tdata = NULL; 
     1287 
    12521288    pj_mutex_lock(ice->mutex); 
    12531289 
     
    12591295    LOG4((ice->obj_name,  
    12601296         "Check %s%s: connectivity check %s", 
    1261          dump_check(buffer, sizeof(buffer), ice, check), 
     1297         dump_check(buffer, sizeof(buffer), &ice->clist, check), 
    12621298         (check->nominated ? " (nominated)" : " (not nominated)"), 
    12631299         (status==PJ_SUCCESS ? "SUCCESS" : "FAILED"))); 
     
    15011537    if (i == ice->rcand_cnt) { 
    15021538        rcand = &ice->rcand[ice->rcand_cnt++]; 
    1503         rcand->comp_id = comp->comp_id; 
     1539        rcand->comp_id = lcand->comp_id; 
    15041540        rcand->type = PJ_ICE_CAND_TYPE_PRFLX; 
    15051541        rcand->prio = ap->value; 
     
    16491685    pj_ice_comp *comp; 
    16501686    unsigned cand_id; 
    1651     pj_ice_check *check; 
    1652  
    1653     PJ_ASSERT_RETURN(ice, PJ_EINVAL); 
     1687 
     1688    PJ_ASSERT_RETURN(ice && comp_id && comp_id <= ice->comp_cnt, PJ_EINVAL); 
    16541689     
    16551690    pj_mutex_lock(ice->mutex); 
     
    16611696    } 
    16621697 
    1663     if (comp->nominated_check_id == -1) { 
     1698    if (comp->valid_check == NULL) { 
    16641699        status = PJNATH_EICEINPROGRESS; 
    16651700        goto on_return; 
    16661701    } 
    16671702 
    1668     check = &ice->clist.checks[comp->nominated_check_id]; 
    1669     cand_id = GET_LCAND_ID(check->lcand); 
    1670  
     1703    cand_id = GET_LCAND_ID(comp->valid_check->lcand); 
    16711704    status = (*ice->cb.on_tx_pkt)(ice, comp_id, cand_id, data, data_len,  
    1672                                   &check->rcand->addr,  
     1705                                  &comp->valid_check->rcand->addr,  
    16731706                                  sizeof(pj_sockaddr_in)); 
    16741707 
  • pjproject/trunk/pjnath/src/pjnath/ice_stream_transport.c

    r1104 r1106  
    6161 
    6262/* Utility: print error */ 
     63#if PJ_LOG_MAX_LEVEL >= 3 
    6364static void ice_st_perror(pj_ice_st *ice_st, const char *title,  
    6465                          pj_status_t status) 
     
    6768 
    6869    pj_strerror(status, errmsg, sizeof(errmsg)); 
    69     PJ_LOG(1,(ice_st->obj_name, "%s: %s", title, errmsg)); 
    70 } 
     70    PJ_LOG(3,(ice_st->obj_name, "%s: %s", title, errmsg)); 
     71} 
     72#else 
     73#   define ice_st_perror(ice_st, title, status) 
     74#endif 
    7175 
    7276 
     
    225229} 
    226230 
     231/* Add new candidate */ 
     232static pj_status_t add_cand( pj_ice_st *ice_st, 
     233                             pj_ice_st_comp *comp, 
     234                             unsigned comp_id, 
     235                             pj_ice_cand_type type, 
     236                             pj_uint16_t local_pref, 
     237                             const pj_sockaddr_in *addr, 
     238                             pj_bool_t set_default) 
     239{ 
     240    pj_ice_st_cand *cand; 
     241 
     242    PJ_ASSERT_RETURN(ice_st && comp && addr, PJ_EINVAL); 
     243    PJ_ASSERT_RETURN(comp->cand_cnt < PJ_ICE_ST_MAX_ALIASES, PJ_ETOOMANY); 
     244 
     245    cand = &comp->cand_list[comp->cand_cnt]; 
     246 
     247    pj_bzero(cand, sizeof(*cand)); 
     248    cand->type = type; 
     249    cand->status = PJ_SUCCESS; 
     250    pj_memcpy(&cand->addr, addr, sizeof(pj_sockaddr_in)); 
     251    cand->cand_id = -1; 
     252    cand->local_pref = local_pref; 
     253    cand->foundation = calc_foundation(ice_st->pool, type, &addr->sin_addr); 
     254 
     255    if (set_default)  
     256        comp->default_cand = comp->cand_cnt; 
     257 
     258    PJ_LOG(5,(ice_st->obj_name,  
     259              "Candidate %s:%d (type=%s) added to component %d", 
     260              pj_inet_ntoa(addr->sin_addr), 
     261              (int)pj_ntohs(addr->sin_port),  
     262              pj_ice_get_cand_type_name(type), 
     263              comp_id)); 
     264     
     265    comp->cand_cnt++; 
     266    return PJ_SUCCESS; 
     267} 
     268 
    227269/*  Create new component (i.e. socket)  */ 
    228270static pj_status_t create_component(pj_ice_st *ice_st, 
     
    301343     * cand_list. 
    302344     */ 
    303     if (comp->local_addr.ipv4.sin_addr.s_addr == 0) { 
     345    if (((options & PJ_ICE_ST_OPT_DONT_ADD_CAND)==0) && 
     346        comp->local_addr.ipv4.sin_addr.s_addr == 0)  
     347    { 
    304348        /* Socket is bound to INADDR_ANY */ 
    305349        unsigned i, ifs_cnt; 
     
    318362        status = pj_gethostip(&comp->local_addr.ipv4.sin_addr); 
    319363        if (status != PJ_SUCCESS) 
    320             return status; 
     364            goto on_error; 
    321365 
    322366        /* Add candidate entry for each interface */ 
    323367        for (i=0; i<ifs_cnt; ++i) { 
    324             pj_ice_st_cand *cand = &comp->cand_list[i]; 
    325  
    326             cand->type = PJ_ICE_CAND_TYPE_HOST; 
    327             cand->status = PJ_SUCCESS; 
    328             pj_memcpy(&cand->addr, &comp->local_addr, sizeof(pj_sockaddr_in)); 
    329             cand->addr.ipv4.sin_addr.s_addr = ifs[i].s_addr; 
    330             cand->cand_id = -1; 
    331             cand->local_pref = 65535; 
    332             cand->foundation = calc_foundation(ice_st->pool,  
    333                                              PJ_ICE_CAND_TYPE_HOST, 
    334                                              &cand->addr.ipv4.sin_addr); 
     368            pj_sockaddr_in cand_addr; 
     369            pj_bool_t set_default; 
     370 
     371            /* Ignore 127.0.0.0/24 address */ 
     372            if ((pj_ntohl(ifs[i].s_addr) >> 24)==127) 
     373                continue; 
     374 
     375            pj_memcpy(&cand_addr, &comp->local_addr, sizeof(pj_sockaddr_in)); 
     376            cand_addr.sin_addr.s_addr = ifs[i].s_addr; 
     377 
    335378 
    336379            /* If the IP address is equal to local address, assign it 
    337380             * as default candidate. 
    338381             */ 
    339             if (cand->addr.ipv4.sin_addr.s_addr == 
    340                 comp->local_addr.ipv4.sin_addr.s_addr) 
    341             { 
    342                 comp->default_cand = i; 
     382            if (ifs[i].s_addr == comp->local_addr.ipv4.sin_addr.s_addr) { 
     383                set_default = PJ_TRUE; 
     384            } else { 
     385                set_default = PJ_FALSE; 
    343386            } 
    344387 
    345             PJ_LOG(5,(ice_st->obj_name,  
    346                       "Interface %s:%d added to component %d", 
    347                       pj_inet_ntoa(cand->addr.ipv4.sin_addr), 
    348                       (int)pj_ntohs(cand->addr.ipv4.sin_port), comp_id)); 
     388            status = add_cand(ice_st, comp, comp_id,  
     389                              PJ_ICE_CAND_TYPE_HOST,  
     390                              (pj_uint16_t)(65535-i), &cand_addr, 
     391                              set_default); 
     392            if (status != PJ_SUCCESS) 
     393                goto on_error; 
    349394        } 
    350         comp->cand_cnt = ifs_cnt; 
    351  
    352  
    353     } else { 
     395 
     396 
     397    } else if ((options & PJ_ICE_ST_OPT_DONT_ADD_CAND)==0) { 
    354398        /* Socket is bound to specific address.  
    355399         * In this case only add that address as a single entry in the 
    356400         * cand_list table. 
    357401         */ 
    358         pj_ice_st_cand *cand = &comp->cand_list[0]; 
    359  
    360         cand->type = PJ_ICE_CAND_TYPE_HOST; 
    361         cand->status = PJ_SUCCESS; 
    362         pj_memcpy(&cand->addr, &comp->local_addr, sizeof(pj_sockaddr_in)); 
    363         cand->cand_id = -1; 
    364         cand->local_pref = 65535; 
    365         cand->foundation = calc_foundation(ice_st->pool,  
    366                                          PJ_ICE_CAND_TYPE_HOST, 
    367                                          &cand->addr.ipv4.sin_addr); 
    368  
    369         comp->cand_cnt = 1; 
    370         comp->default_cand = 0; 
    371  
    372         PJ_LOG(5,(ice_st->obj_name,  
    373                   "Interface %s:%d added to component %d", 
    374                   pj_inet_ntoa(cand->addr.ipv4.sin_addr), 
    375                   (int)pj_ntohs(cand->addr.ipv4.sin_port), comp_id)); 
    376  
    377     } 
     402        status = add_cand(ice_st, comp, comp_id,  
     403                          PJ_ICE_CAND_TYPE_HOST,  
     404                          65535, &comp->local_addr.ipv4, 
     405                          PJ_TRUE); 
     406        if (status != PJ_SUCCESS) 
     407            goto on_error; 
     408 
     409    } else if (options & PJ_ICE_ST_OPT_DONT_ADD_CAND) { 
     410        /* If application doesn't want to add candidate, just fix local_addr 
     411         * in case its value is zero. 
     412         */ 
     413        if (comp->local_addr.ipv4.sin_addr.s_addr == 0) { 
     414            status = pj_gethostip(&comp->local_addr.ipv4.sin_addr); 
     415            if (status != PJ_SUCCESS) 
     416                return status; 
     417        } 
     418    } 
     419 
    378420 
    379421    /* Done */ 
     
    569611                                          unsigned comp_id, 
    570612                                          pj_uint32_t options, 
    571                                           const pj_sockaddr_in *addr, 
    572                                           unsigned *p_itf_id) 
     613                                          const pj_sockaddr_in *addr) 
    573614{ 
    574615    pj_ice_st_comp *comp; 
     
    602643 
    603644    /* Store this component */ 
    604     if (p_itf_id) 
    605         *p_itf_id = ice_st->comp_cnt; 
    606  
    607645    ice_st->comp[comp_id-1] = comp; 
    608646 
    609647    return PJ_SUCCESS; 
     648} 
     649 
     650 
     651PJ_DEF(pj_status_t) pj_ice_st_add_cand( pj_ice_st *ice_st, 
     652                                        unsigned comp_id, 
     653                                        pj_ice_cand_type type, 
     654                                        pj_uint16_t local_pref, 
     655                                        const pj_sockaddr_in *addr, 
     656                                        pj_bool_t set_default) 
     657{ 
     658    pj_ice_st_comp *comp; 
     659 
     660 
     661    PJ_ASSERT_RETURN(ice_st && comp_id && addr, PJ_EINVAL); 
     662    PJ_ASSERT_RETURN(comp_id <= ice_st->comp_cnt, PJ_EINVAL); 
     663    PJ_ASSERT_RETURN(ice_st->comp[comp_id-1] != NULL, PJ_EINVALIDOP); 
     664 
     665    comp = ice_st->comp[comp_id-1]; 
     666    return add_cand(ice_st, comp, comp_id, type, local_pref, addr,  
     667                    set_default); 
    610668} 
    611669 
     
    652710    /* Must not have ICE */ 
    653711    PJ_ASSERT_RETURN(ice_st->ice == NULL, PJ_EINVALIDOP); 
     712    /* Components must have been created */ 
     713    PJ_ASSERT_RETURN(ice_st->comp[0] != NULL, PJ_EINVALIDOP); 
    654714 
    655715    /* Init callback */ 
  • pjproject/trunk/pjnath/src/pjnath/stun_session.c

    r1099 r1106  
    678678} 
    679679 
     680/* 
     681 * Cancel outgoing STUN transaction.  
     682 */ 
     683PJ_DEF(pj_status_t) pj_stun_session_cancel_req( pj_stun_session *sess, 
     684                                                pj_stun_tx_data *tdata, 
     685                                                pj_bool_t notify, 
     686                                                pj_status_t notify_status) 
     687{ 
     688    PJ_ASSERT_RETURN(sess && tdata, PJ_EINVAL); 
     689    PJ_ASSERT_RETURN(!notify || notify_status!=PJ_SUCCESS, PJ_EINVAL); 
     690    PJ_ASSERT_RETURN(PJ_STUN_IS_REQUEST(tdata->msg->hdr.type), PJ_EINVAL); 
     691 
     692    pj_mutex_lock(sess->mutex); 
     693 
     694    if (notify) { 
     695        (sess->cb.on_request_complete)(sess, notify_status, tdata, NULL); 
     696    } 
     697 
     698    /* Just destroy tdata. This will destroy the transaction as well */ 
     699    pj_stun_msg_destroy_tdata(sess, tdata); 
     700 
     701    pj_mutex_unlock(sess->mutex); 
     702    return PJ_SUCCESS; 
     703 
     704} 
    680705 
    681706/* Send response */ 
  • pjproject/trunk/pjsip/src/pjsua-lib/pjsua_media.c

    r1104 r1106  
    564564        int next_port; 
    565565 
    566         status = pjmedia_ice_create(pjsua_var.med_endpt, NULL, 1, 
     566        status = pjmedia_ice_create(pjsua_var.med_endpt, NULL, 2, 
    567567                                    &pjsua_var.stun_cfg,  
    568568                                    &pjsua_var.calls[i].med_tp); 
Note: See TracChangeset for help on using the changeset viewer.