Changeset 1104 for pjproject/trunk


Ignore:
Timestamp:
Mar 25, 2007 6:44:51 PM (18 years ago)
Author:
bennylp
Message:

ICE (work in progress): use single socket for all candidates in component, and implemented IP interface enumeration on Win32

Location:
pjproject/trunk
Files:
3 added
15 edited

Legend:

Unmodified
Added
Removed
  • pjproject/trunk/pjlib-util/build/pjlib_util.vcproj

    r1102 r1104  
    1717                <Configuration 
    1818                        Name="Release|Win32" 
    19                         OutputDirectory=".\./output/pjlib-util-i386-win32-vc6-release" 
    20                         IntermediateDirectory=".\./output/pjlib-util-i386-win32-vc6-release" 
     19                        OutputDirectory="./output/pjlib-util-i386-win32-vc8-release" 
     20                        IntermediateDirectory="./output/pjlib-util-i386-win32-vc8-release" 
    2121                        ConfigurationType="4" 
    2222                        InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC60.vsprops" 
     
    4949                                RuntimeLibrary="2" 
    5050                                EnableFunctionLevelLinking="true" 
    51                                 PrecompiledHeaderFile=".\./output/pjlib-util-i386-win32-vc6-release/pjlib_util.pch" 
    52                                 AssemblerListingLocation=".\./output/pjlib-util-i386-win32-vc6-release/" 
    53                                 ObjectFile=".\./output/pjlib-util-i386-win32-vc6-release/" 
    54                                 ProgramDataBaseFileName=".\./output/pjlib-util-i386-win32-vc6-release/" 
     51                                PrecompiledHeaderFile="./output/pjlib-util-i386-win32-vc8-release/pjlib_util.pch" 
     52                                AssemblerListingLocation="./output/pjlib-util-i386-win32-vc8-release/" 
     53                                ObjectFile="./output/pjlib-util-i386-win32-vc8-release/" 
     54                                ProgramDataBaseFileName="./output/pjlib-util-i386-win32-vc8-release/" 
    5555                                BrowseInformation="1" 
    5656                                WarningLevel="4" 
     
    7171                        <Tool 
    7272                                Name="VCLibrarianTool" 
    73                                 OutputFile="../lib/pjlib-util-i386-win32-vc6-release.lib" 
     73                                OutputFile="../lib/pjlib-util-i386-win32-vc8-release.lib" 
    7474                                SuppressStartupBanner="true" 
    7575                        /> 
     
    8383                                Name="VCBscMakeTool" 
    8484                                SuppressStartupBanner="true" 
    85                                 OutputFile=".\./output/pjlib-util-i386-win32-vc6-release/pjlib_util.bsc" 
     85                                OutputFile="./output/pjlib-util-i386-win32-vc8-release/pjlib_util.bsc" 
    8686                        /> 
    8787                        <Tool 
     
    9494                <Configuration 
    9595                        Name="Debug|Win32" 
    96                         OutputDirectory=".\./output/pjlib-util-i386-win32-vc6-debug" 
    97                         IntermediateDirectory=".\./output/pjlib-util-i386-win32-vc6-debug" 
     96                        OutputDirectory="./output/pjlib-util-i386-win32-vc8-debug" 
     97                        IntermediateDirectory="./output/pjlib-util-i386-win32-vc8-debug" 
    9898                        ConfigurationType="4" 
    9999                        InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC60.vsprops" 
     
    125125                                BasicRuntimeChecks="3" 
    126126                                RuntimeLibrary="1" 
    127                                 PrecompiledHeaderFile=".\./output/pjlib-util-i386-win32-vc6-debug/pjlib_util.pch" 
    128                                 AssemblerListingLocation=".\./output/pjlib-util-i386-win32-vc6-debug/" 
    129                                 ObjectFile=".\./output/pjlib-util-i386-win32-vc6-debug/" 
    130                                 ProgramDataBaseFileName=".\./output/pjlib-util-i386-win32-vc6-debug/" 
     127                                PrecompiledHeaderFile="./output/pjlib-util-i386-win32-vc8-debug/pjlib_util.pch" 
     128                                AssemblerListingLocation="./output/pjlib-util-i386-win32-vc8-debug/" 
     129                                ObjectFile="./output/pjlib-util-i386-win32-vc8-debug/" 
     130                                ProgramDataBaseFileName="./output/pjlib-util-i386-win32-vc8-debug/" 
    131131                                BrowseInformation="1" 
    132132                                WarningLevel="4" 
     
    147147                        <Tool 
    148148                                Name="VCLibrarianTool" 
    149                                 OutputFile="../lib/pjlib-util-i386-win32-vc6-debug.lib" 
     149                                OutputFile="../lib/pjlib-util-i386-win32-vc8-debug.lib" 
    150150                                SuppressStartupBanner="true" 
    151151                        /> 
     
    159159                                Name="VCBscMakeTool" 
    160160                                SuppressStartupBanner="true" 
    161                                 OutputFile=".\./output/pjlib-util-i386-win32-vc6-debug/pjlib_util.bsc" 
     161                                OutputFile="./output/pjlib-util-i386-win32-vc8-debug/pjlib_util.bsc" 
    162162                        /> 
    163163                        <Tool 
  • pjproject/trunk/pjlib/build/pjlib.dsp

    r950 r1104  
    111111# Begin Source File 
    112112 
     113SOURCE=..\src\pj\ip_helper_generic.c 
     114# PROP Exclude_From_Build 1 
     115# End Source File 
     116# Begin Source File 
     117 
    113118SOURCE=..\src\pj\log_writer_printk.c 
    114119# PROP Exclude_From_Build 1 
     
    252257!ENDIF  
    253258 
     259# End Source File 
     260# Begin Source File 
     261 
     262SOURCE=..\src\pj\ip_helper_win32.c 
    254263# End Source File 
    255264# Begin Source File 
     
    516525 
    517526SOURCE=..\include\pj\ioqueue.h 
     527# End Source File 
     528# Begin Source File 
     529 
     530SOURCE=..\include\pj\ip_helper.h 
    518531# End Source File 
    519532# Begin Source File 
  • pjproject/trunk/pjlib/build/pjlib.vcproj

    r1100 r1104  
    1717                <Configuration 
    1818                        Name="Debug|Win32" 
    19                         OutputDirectory=".\output\pjlib-i386-win32-vc6-debug" 
    20                         IntermediateDirectory=".\output\pjlib-i386-win32-vc6-debug" 
     19                        OutputDirectory=".\output\pjlib-i386-win32-vc8-debug" 
     20                        IntermediateDirectory=".\output\pjlib-i386-win32-vc8-debug" 
    2121                        ConfigurationType="4" 
    2222                        InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC60.vsprops" 
     
    4848                                BasicRuntimeChecks="3" 
    4949                                RuntimeLibrary="1" 
    50                                 PrecompiledHeaderFile=".\output\pjlib-i386-win32-vc6-debug/pjlib.pch" 
    51                                 AssemblerListingLocation=".\output\pjlib-i386-win32-vc6-debug/" 
    52                                 ObjectFile=".\output\pjlib-i386-win32-vc6-debug/" 
    53                                 ProgramDataBaseFileName=".\output\pjlib-i386-win32-vc6-debug/" 
     50                                PrecompiledHeaderFile=".\output\pjlib-i386-win32-vc8-debug/pjlib.pch" 
     51                                AssemblerListingLocation=".\output\pjlib-i386-win32-vc8-debug/" 
     52                                ObjectFile=".\output\pjlib-i386-win32-vc8-debug/" 
     53                                ProgramDataBaseFileName=".\output\pjlib-i386-win32-vc8-debug/" 
    5454                                BrowseInformation="1" 
    5555                                WarningLevel="4" 
     
    7070                        <Tool 
    7171                                Name="VCLibrarianTool" 
    72                                 OutputFile="../lib/pjlib-i386-win32-vc6-debug.lib" 
     72                                OutputFile="../lib/pjlib-i386-win32-vc8-debug.lib" 
    7373                                SuppressStartupBanner="true" 
    7474                        /> 
     
    8282                                Name="VCBscMakeTool" 
    8383                                SuppressStartupBanner="true" 
    84                                 OutputFile=".\output\pjlib-i386-win32-vc6-debug/pjlib.bsc" 
     84                                OutputFile=".\output\pjlib-i386-win32-vc8-debug/pjlib.bsc" 
    8585                        /> 
    8686                        <Tool 
     
    9393                <Configuration 
    9494                        Name="Release|Win32" 
    95                         OutputDirectory=".\output\pjlib-i386-win32-vc6-release" 
    96                         IntermediateDirectory=".\output\pjlib-i386-win32-vc6-release" 
     95                        OutputDirectory=".\output\pjlib-i386-win32-vc8-release" 
     96                        IntermediateDirectory=".\output\pjlib-i386-win32-vc8-release" 
    9797                        ConfigurationType="4" 
    9898                        InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC60.vsprops" 
     
    125125                                RuntimeLibrary="2" 
    126126                                EnableFunctionLevelLinking="true" 
    127                                 PrecompiledHeaderFile=".\output\pjlib-i386-win32-vc6-release/pjlib.pch" 
    128                                 AssemblerListingLocation=".\output\pjlib-i386-win32-vc6-release/" 
    129                                 ObjectFile=".\output\pjlib-i386-win32-vc6-release/" 
    130                                 ProgramDataBaseFileName=".\output\pjlib-i386-win32-vc6-release/" 
     127                                PrecompiledHeaderFile=".\output\pjlib-i386-win32-vc8-release/pjlib.pch" 
     128                                AssemblerListingLocation=".\output\pjlib-i386-win32-vc8-release/" 
     129                                ObjectFile=".\output\pjlib-i386-win32-vc8-release/" 
     130                                ProgramDataBaseFileName=".\output\pjlib-i386-win32-vc8-release/" 
    131131                                BrowseInformation="1" 
    132132                                WarningLevel="4" 
     
    147147                        <Tool 
    148148                                Name="VCLibrarianTool" 
    149                                 OutputFile="../lib/pjlib-i386-win32-vc6-release.lib" 
     149                                OutputFile="../lib/pjlib-i386-win32-vc8-release.lib" 
    150150                                SuppressStartupBanner="true" 
    151151                        /> 
     
    159159                                Name="VCBscMakeTool" 
    160160                                SuppressStartupBanner="true" 
    161                                 OutputFile=".\output\pjlib-i386-win32-vc6-release/pjlib.bsc" 
     161                                OutputFile=".\output\pjlib-i386-win32-vc8-release/pjlib.bsc" 
    162162                        /> 
    163163                        <Tool 
     
    539539                        </File> 
    540540                        <File 
     541                                RelativePath="..\src\pj\ip_helper_win32.c" 
     542                                > 
     543                        </File> 
     544                        <File 
    541545                                RelativePath="..\src\pj\list.c" 
    542546                                > 
     
    11181122                                                        AdditionalIncludeDirectories="" 
    11191123                                                        PreprocessorDefinitions="" 
     1124                                                /> 
     1125                                        </FileConfiguration> 
     1126                                </File> 
     1127                                <File 
     1128                                        RelativePath="..\src\pj\ip_helper_generic.c" 
     1129                                        > 
     1130                                        <FileConfiguration 
     1131                                                Name="Debug|Win32" 
     1132                                                ExcludedFromBuild="true" 
     1133                                                > 
     1134                                                <Tool 
     1135                                                        Name="VCCLCompilerTool" 
     1136                                                /> 
     1137                                        </FileConfiguration> 
     1138                                        <FileConfiguration 
     1139                                                Name="Release|Win32" 
     1140                                                ExcludedFromBuild="true" 
     1141                                                > 
     1142                                                <Tool 
     1143                                                        Name="VCCLCompilerTool" 
    11201144                                                /> 
    11211145                                        </FileConfiguration> 
     
    14601484                        </File> 
    14611485                        <File 
     1486                                RelativePath="..\include\pj\ip_helper.h" 
     1487                                > 
     1488                        </File> 
     1489                        <File 
    14621490                                RelativePath="..\include\pj\list.h" 
    14631491                                > 
  • pjproject/trunk/pjlib/include/pj/sock.h

    r1080 r1104  
    208208}; 
    209209 
     210#undef s6_addr 
    210211 
    211212/** 
  • pjproject/trunk/pjlib/include/pjlib.h

    r974 r1104  
    3838#include <pj/hash.h> 
    3939#include <pj/ioqueue.h> 
     40#include <pj/ip_helper.h> 
    4041#include <pj/list.h> 
    4142#include <pj/lock.h> 
  • pjproject/trunk/pjmedia/include/pjmedia/transport_ice.h

    r1098 r1104  
    4747PJ_DECL(pj_status_t) pjmedia_ice_destroy(pjmedia_transport *tp); 
    4848 
    49 PJ_DECL(pj_ice_st*) pjmedia_ice_get_ice_st(pjmedia_transport *tp); 
     49PJ_DECL(pj_status_t) pjmedia_ice_start_init(pjmedia_transport *tp, 
     50                                            unsigned options, 
     51                                            const pj_sockaddr_in *start_addr, 
     52                                            const pj_sockaddr_in *stun_srv, 
     53                                            const pj_sockaddr_in *turn_srv); 
     54PJ_DECL(pj_status_t) pjmedia_ice_get_init_status(pjmedia_transport *tp); 
    5055 
     56PJ_DECL(pj_status_t) pjmedia_ice_get_comp(pjmedia_transport *tp, 
     57                                          unsigned comp_id, 
     58                                          pj_ice_st_comp *comp); 
    5159 
    5260PJ_DECL(pj_status_t) pjmedia_ice_init_ice(pjmedia_transport *tp, 
  • pjproject/trunk/pjmedia/src/pjmedia/transport_ice.c

    r1101 r1104  
    7070 * And these are ICE callbacks. 
    7171 */ 
    72 static void ice_on_rx_data(pj_ice_st *ice_st, 
    73                            unsigned comp_id, unsigned cand_id, 
     72static void ice_on_rx_data(pj_ice_st *ice_st, unsigned comp_id,  
    7473                           void *pkt, pj_size_t size, 
    7574                           const pj_sockaddr_t *src_addr, 
     
    10099    pj_ice_st_cb ice_st_cb; 
    101100    struct transport_ice *tp_ice; 
    102     unsigned i; 
    103101    pj_status_t status; 
    104102 
     
    111109 
    112110    /* Create ICE */ 
    113     status = pj_ice_st_create(stun_cfg, name, NULL, &ice_st_cb, &ice_st); 
     111    status = pj_ice_st_create(stun_cfg, name, comp_cnt, NULL,  
     112                              &ice_st_cb, &ice_st); 
    114113    if (status != PJ_SUCCESS) 
    115114        return status; 
    116115 
    117     /* Add components */ 
    118     for (i=0; i<comp_cnt; ++i) { 
    119         status = pj_ice_st_add_comp(ice_st, i+1); 
    120         if (status != PJ_SUCCESS)  
    121             goto on_error; 
    122     } 
    123116 
    124117    /* Create transport instance and attach to ICE */ 
     
    136129 
    137130    return PJ_SUCCESS; 
    138  
    139 on_error: 
    140     pj_ice_st_destroy(ice_st); 
    141     return status; 
    142131} 
    143132 
     
    158147 
    159148 
    160 PJ_DECL(pj_ice_st*) pjmedia_ice_get_ice_st(pjmedia_transport *tp) 
     149PJ_DEF(pj_status_t) pjmedia_ice_start_init( pjmedia_transport *tp, 
     150                                            unsigned options, 
     151                                            const pj_sockaddr_in *start_addr, 
     152                                            const pj_sockaddr_in *stun_srv, 
     153                                            const pj_sockaddr_in *turn_srv) 
     154{ 
     155    struct transport_ice *tp_ice = (struct transport_ice*)tp; 
     156    unsigned comp_id; 
     157    pj_status_t status; 
     158 
     159    status = pj_ice_st_set_stun_srv(tp_ice->ice_st, stun_srv, turn_srv); 
     160    if (status != PJ_SUCCESS) 
     161        return status; 
     162 
     163    status = pj_ice_st_create_comp(tp_ice->ice_st, 1, options, start_addr,  
     164                                   &comp_id); 
     165    if (status != PJ_SUCCESS) 
     166        return status; 
     167 
     168    if (tp_ice->ice_st->comp_cnt > 1) { 
     169        pj_sockaddr_in addr; 
     170 
     171        pj_memcpy(&addr, &tp_ice->ice_st->comp[0]->local_addr.ipv4, 
     172                  sizeof(pj_sockaddr_in)); 
     173        if (start_addr) 
     174            addr.sin_addr.s_addr = start_addr->sin_addr.s_addr; 
     175        else 
     176            addr.sin_addr.s_addr = 0; 
     177 
     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); 
     181        if (status != PJ_SUCCESS) 
     182            return status; 
     183    } 
     184    return status; 
     185} 
     186 
     187 
     188PJ_DEF(pj_status_t) pjmedia_ice_get_init_status(pjmedia_transport *tp) 
     189{ 
     190    struct transport_ice *tp_ice = (struct transport_ice*)tp; 
     191    return pj_ice_st_get_comps_status(tp_ice->ice_st); 
     192} 
     193 
     194 
     195PJ_DEF(pj_status_t) pjmedia_ice_get_comp( pjmedia_transport *tp, 
     196                                          unsigned comp_id, 
     197                                          pj_ice_st_comp *comp) 
     198{ 
     199    struct transport_ice *tp_ice = (struct transport_ice*)tp; 
     200    PJ_ASSERT_RETURN(tp && comp_id && comp_id <= tp_ice->ice_st->comp_cnt && 
     201                     comp, PJ_EINVAL); 
     202 
     203    pj_memcpy(comp, tp_ice->ice_st->comp[comp_id-1], sizeof(pj_ice_st_comp)); 
     204    return PJ_SUCCESS;               
     205} 
     206 
     207PJ_DEF(pj_ice_st*) pjmedia_ice_get_ice_st(pjmedia_transport *tp) 
    161208{ 
    162209    struct transport_ice *tp_ice = (struct transport_ice*)tp; 
     
    416463{ 
    417464    struct transport_ice *tp_ice = (struct transport_ice*)tp; 
    418     int rel_idx = -1, srflx_idx = -1, host_idx = -1, idx = -1; 
    419     unsigned i; 
     465    pj_ice_st *ice_st = tp_ice->ice_st; 
     466    pj_ice_st_comp *comp; 
    420467 
    421468    pj_bzero(info, sizeof(*info)); 
    422469    info->rtp_sock = info->rtcp_sock = PJ_INVALID_SOCKET; 
    423470 
    424     for (i=0; i<tp_ice->ice_st->itf_cnt; ++i) { 
    425         pj_ice_st_interface *itf = tp_ice->ice_st->itfs[i]; 
    426  
    427         if (itf->type == PJ_ICE_CAND_TYPE_HOST && host_idx == -1) 
    428             host_idx = i; 
    429         else if (itf->type == PJ_ICE_CAND_TYPE_RELAYED && rel_idx == -1) 
    430             rel_idx = i; 
    431         else if (itf->type == PJ_ICE_CAND_TYPE_SRFLX && srflx_idx == -1) 
    432             srflx_idx = i; 
    433     } 
    434  
    435     if (idx == -1 && srflx_idx != -1) 
    436         idx = srflx_idx; 
    437     else if (idx == -1 && rel_idx != -1) 
    438         idx = rel_idx; 
    439     else if (idx == -1 && host_idx != -1) 
    440         idx = host_idx; 
    441  
    442     PJ_ASSERT_RETURN(idx != -1, PJ_EBUG); 
    443  
    444     pj_memcpy(&info->rtp_addr_name, &tp_ice->ice_st->itfs[idx]->addr, 
     471    /* Retrieve address of default candidate for component 1 (RTP) */ 
     472    comp = ice_st->comp[0]; 
     473    pj_assert(comp->default_cand >= 0); 
     474    info->rtp_sock = comp->sock; 
     475    pj_memcpy(&info->rtp_addr_name,  
     476              &comp->cand_list[comp->default_cand].addr, 
    445477              sizeof(pj_sockaddr_in)); 
     478 
     479    /* Retrieve address of default candidate for component 12(RTCP) */ 
     480    if (ice_st->comp_cnt > 1) { 
     481        comp = ice_st->comp[1]; 
     482        pj_assert(comp->default_cand >= 0); 
     483        info->rtp_sock = comp->sock; 
     484        pj_memcpy(&info->rtp_addr_name,  
     485                  &comp->cand_list[comp->default_cand].addr, 
     486                  sizeof(pj_sockaddr_in)); 
     487    } 
     488 
    446489 
    447490    return PJ_SUCCESS; 
     
    492535{ 
    493536    struct transport_ice *tp_ice = (struct transport_ice*)tp; 
    494     if (tp_ice->ice_st->ice) { 
    495         return pj_ice_st_send_data(tp_ice->ice_st, 1, pkt, size); 
    496     } else { 
    497         return pj_ice_st_sendto(tp_ice->ice_st, 1, 0, 
    498                                 pkt, size, &tp_ice->remote_rtp, 
    499                                 sizeof(pj_sockaddr_in)); 
    500     } 
     537    return pj_ice_st_sendto(tp_ice->ice_st, 1,  
     538                            pkt, size, &tp_ice->remote_rtp, 
     539                            sizeof(pj_sockaddr_in)); 
    501540} 
    502541 
     
    506545                                pj_size_t size) 
    507546{ 
    508 #if 0 
    509     struct transport_ice *tp_ice = (struct transport_ice*)tp; 
    510     return pj_ice_st_send_data(tp_ice->ice_st, 1, pkt, size); 
    511 #else 
    512     PJ_TODO(SUPPORT_RTCP); 
    513     PJ_UNUSED_ARG(tp); 
    514     PJ_UNUSED_ARG(pkt); 
    515     PJ_UNUSED_ARG(size); 
    516     return PJ_SUCCESS; 
    517 #endif 
    518 } 
    519  
    520  
    521 static void ice_on_rx_data(pj_ice_st *ice_st, 
    522                            unsigned comp_id, unsigned cand_id, 
     547    struct transport_ice *tp_ice = (struct transport_ice*)tp; 
     548    if (tp_ice->ice_st->comp_cnt > 1) { 
     549        return pj_ice_st_sendto(tp_ice->ice_st, 2,  
     550                                pkt, size, &tp_ice->remote_rtp, 
     551                                sizeof(pj_sockaddr_in)); 
     552    } else { 
     553        return PJ_SUCCESS; 
     554    } 
     555} 
     556 
     557 
     558static void ice_on_rx_data(pj_ice_st *ice_st, unsigned comp_id,  
    523559                           void *pkt, pj_size_t size, 
    524560                           const pj_sockaddr_t *src_addr, 
     
    532568        (*tp_ice->rtcp_cb)(tp_ice->stream, pkt, size); 
    533569 
    534     PJ_UNUSED_ARG(cand_id); 
    535570    PJ_UNUSED_ARG(src_addr); 
    536571    PJ_UNUSED_ARG(src_addr_len); 
     572 
     573    PJ_TODO(SWITCH_SOURCE_ADDRESS); 
    537574} 
    538575 
  • pjproject/trunk/pjnath/include/pjnath/ice.h

    r1101 r1104  
    151151                             unsigned dst_addr_len); 
    152152    void        (*on_rx_data)(pj_ice *ice, unsigned comp_id, 
    153                               unsigned cand_id, 
    154153                              void *pkt, pj_size_t size, 
    155154                              const pj_sockaddr_t *src_addr, 
  • pjproject/trunk/pjnath/include/pjnath/ice_stream_transport.h

    r1099 r1104  
    4545{ 
    4646    void    (*on_rx_data)(pj_ice_st *ice_st, 
    47                           unsigned comp_id, unsigned cand_id, 
     47                          unsigned comp_id,  
    4848                          void *pkt, pj_size_t size, 
    4949                          const pj_sockaddr_t *src_addr, 
     
    5555 
    5656 
     57#ifndef PJ_ICE_ST_MAX_ALIASES 
     58#   define PJ_ICE_ST_MAX_ALIASES        8 
     59#endif 
     60 
     61enum pj_ice_st_option 
     62{ 
     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, 
     66}; 
     67 
     68 
     69typedef struct pj_ice_st_cand 
     70{ 
     71    pj_ice_cand_type    type; 
     72    pj_status_t         status; 
     73    pj_sockaddr         addr; 
     74    int                 cand_id; 
     75    pj_uint16_t         local_pref; 
     76    pj_str_t            foundation; 
     77} pj_ice_st_cand; 
     78 
     79 
    5780typedef struct pj_ice_st_comp 
    5881{ 
     82    pj_ice_st           *ice_st; 
    5983    unsigned             comp_id; 
    60 } pj_ice_st_comp; 
     84    pj_uint32_t          options; 
     85    pj_sock_t            sock; 
    6186 
     87    pj_stun_session     *stun_sess; 
    6288 
    63 typedef struct pj_ice_st_interface 
    64 { 
    65     pj_ice_st           *ice_st; 
    66     pj_ice_cand_type     type; 
    67     pj_status_t          status; 
    68     unsigned             comp_id; 
    69     int                  cand_id; 
    70     pj_str_t             foundation; 
    71     pj_uint16_t          local_pref; 
    72     pj_sock_t            sock; 
    73     pj_sockaddr          addr; 
    74     pj_sockaddr          base_addr; 
     89    pj_sockaddr          local_addr; 
     90 
     91    unsigned             pending_cnt; 
     92    pj_status_t          last_status; 
     93 
     94    unsigned             cand_cnt; 
     95    pj_ice_st_cand       cand_list[PJ_ICE_ST_MAX_ALIASES]; 
     96    int                  default_cand; 
     97 
    7598    pj_ioqueue_key_t    *key; 
    7699    pj_uint8_t           pkt[1500]; 
     
    79102    pj_sockaddr          src_addr; 
    80103    int                  src_addr_len; 
    81     pj_stun_session     *stun_sess; 
    82 } pj_ice_st_interface; 
     104 
     105} pj_ice_st_comp; 
    83106 
    84107 
     
    94117 
    95118    unsigned                 comp_cnt; 
    96     unsigned                 comps[PJ_ICE_MAX_COMP]; 
    97  
    98     unsigned                 itf_cnt; 
    99     pj_ice_st_interface     *itfs[PJ_ICE_MAX_CAND]; 
     119    pj_ice_st_comp         **comp; 
    100120 
    101121    pj_dns_resolver         *resolver; 
    102     pj_bool_t                relay_enabled; 
    103     pj_str_t                 stun_domain; 
     122    pj_bool_t                has_resolver_job; 
    104123    pj_sockaddr_in           stun_srv; 
     124    pj_sockaddr_in           turn_srv; 
    105125}; 
    106126 
     
    108128PJ_DECL(pj_status_t) pj_ice_st_create(pj_stun_config *stun_cfg, 
    109129                                      const char *name, 
     130                                      unsigned comp_cnt, 
    110131                                      void *user_data, 
    111132                                      const pj_ice_st_cb *cb, 
     
    113134PJ_DECL(pj_status_t) pj_ice_st_destroy(pj_ice_st *ice_st); 
    114135 
    115 PJ_DECL(pj_status_t) pj_ice_st_set_stun(pj_ice_st *ice_st, 
    116                                         pj_dns_resolver *resolver, 
    117                                         pj_bool_t enable_relay, 
    118                                         const pj_str_t *domain); 
    119 PJ_DECL(pj_status_t) pj_ice_st_set_stun_addr(pj_ice_st *ice_st, 
    120                                              pj_bool_t enable_relay, 
    121                                              const pj_sockaddr_in *srv_addr); 
     136PJ_DECL(pj_status_t) pj_ice_st_set_stun_domain(pj_ice_st *ice_st, 
     137                                               pj_dns_resolver *resolver, 
     138                                               const pj_str_t *domain); 
     139PJ_DECL(pj_status_t) pj_ice_st_set_stun_srv(pj_ice_st *ice_st, 
     140                                            const pj_sockaddr_in *stun_srv, 
     141                                            const pj_sockaddr_in *turn_srv); 
    122142 
    123 PJ_DECL(pj_status_t) pj_ice_st_add_comp(pj_ice_st *ice_st, 
    124                                         unsigned comp_id); 
     143PJ_DECL(pj_status_t) pj_ice_st_create_comp(pj_ice_st *ice_st, 
     144                                           unsigned comp_id, 
     145                                           pj_uint32_t options, 
     146                                           const pj_sockaddr_in *addr, 
     147                                           unsigned *p_itf_id); 
    125148 
    126 PJ_DECL(pj_status_t) pj_ice_st_add_host_interface(pj_ice_st *ice_st, 
    127                                                   unsigned comp_id, 
    128                                                   pj_uint16_t local_pref, 
    129                                                   const pj_sockaddr_in *addr, 
    130                                                   unsigned *p_itf_id); 
    131 PJ_DECL(pj_status_t) pj_ice_st_add_all_host_interfaces(pj_ice_st *ice_st, 
    132                                                        unsigned comp_id, 
    133                                                        unsigned port); 
    134 PJ_DECL(pj_status_t) pj_ice_st_add_stun_interface(pj_ice_st *ice_st, 
    135                                                   unsigned comp_id, 
    136                                                   unsigned local_port, 
    137                                                   unsigned *p_itf_id); 
    138 PJ_DECL(pj_status_t) pj_ice_st_add_relay_interface(pj_ice_st *ice_st, 
    139                                                    unsigned comp_id, 
    140                                                    unsigned local_port, 
    141                                                    pj_bool_t notify, 
    142                                                    void *notify_data); 
    143 PJ_DECL(pj_status_t) pj_ice_st_get_interfaces_status(pj_ice_st *ice_st); 
     149PJ_DECL(pj_status_t) pj_ice_st_get_comps_status(pj_ice_st *ice_st); 
    144150 
    145151PJ_DECL(pj_status_t) pj_ice_st_init_ice(pj_ice_st *ice_st, 
     
    157163PJ_DECL(pj_status_t) pj_ice_st_stop_ice(pj_ice_st *ice_st); 
    158164 
    159 PJ_DECL(pj_status_t) pj_ice_st_send_data(pj_ice_st *ice_st, 
    160                                          unsigned comp_id, 
    161                                          const void *data, 
    162                                          pj_size_t data_len); 
    163165PJ_DECL(pj_status_t) pj_ice_st_sendto(pj_ice_st *ice_st, 
    164166                                      unsigned comp_id, 
    165                                       unsigned itf_id, 
    166167                                      const void *data, 
    167168                                      pj_size_t data_len, 
  • pjproject/trunk/pjnath/src/pjnath/ice.c

    r1101 r1104  
    17101710                                           NULL, src_addr, src_addr_len); 
    17111711    } else { 
    1712         (*ice->cb.on_rx_data)(ice, comp_id, cand_id, pkt, pkt_size,  
     1712        (*ice->cb.on_rx_data)(ice, comp_id, pkt, pkt_size,  
    17131713                              src_addr, src_addr_len); 
    17141714    } 
  • pjproject/trunk/pjnath/src/pjnath/ice_stream_transport.c

    r1101 r1104  
    2121#include <pj/addr_resolv.h> 
    2222#include <pj/assert.h> 
     23#include <pj/ip_helper.h> 
    2324#include <pj/log.h> 
    2425#include <pj/pool.h> 
     
    2930/* ICE callbacks */ 
    3031static void        on_ice_complete(pj_ice *ice, pj_status_t status); 
    31 static pj_status_t on_tx_pkt(pj_ice *ice,  
    32                              unsigned comp_id, unsigned cand_id, 
    33                              const void *pkt, pj_size_t size, 
    34                              const pj_sockaddr_t *dst_addr, 
    35                              unsigned dst_addr_len); 
    36 static void        on_rx_data(pj_ice *ice,  
     32static pj_status_t ice_tx_pkt(pj_ice *ice,  
    3733                              unsigned comp_id, unsigned cand_id, 
     34                              const void *pkt, pj_size_t size, 
     35                              const pj_sockaddr_t *dst_addr, 
     36                              unsigned dst_addr_len); 
     37static void        ice_rx_data(pj_ice *ice,  
     38                              unsigned comp_id,  
    3839                              void *pkt, pj_size_t size, 
    3940                              const pj_sockaddr_t *src_addr, 
     
    4546                             pj_ssize_t bytes_read); 
    4647 
    47 static void destroy_ice_interface(pj_ice_st_interface *is); 
     48static void destroy_component(pj_ice_st_comp *comp); 
    4849static void destroy_ice_st(pj_ice_st *ice_st, pj_status_t reason); 
    4950 
     
    8687 
    8788/*  
    88  * Create new interface (i.e. socket)  
    89  */ 
    90 static pj_status_t create_ice_interface(pj_ice_st *ice_st, 
    91                                         pj_ice_cand_type type, 
    92                                         unsigned comp_id, 
    93                                         pj_uint16_t local_pref, 
    94                                         const pj_sockaddr_in *addr, 
    95                                         pj_ice_st_interface **p_is) 
    96 { 
    97     pj_ioqueue_callback ioqueue_cb; 
    98     pj_ice_st_interface *is; 
    99     char foundation[32]; 
    100     int addr_len; 
    101     pj_status_t status; 
    102  
    103     is = PJ_POOL_ZALLOC_T(ice_st->pool, pj_ice_st_interface); 
    104     is->type = type; 
    105     is->comp_id = comp_id; 
    106     is->cand_id = -1; 
    107     is->sock = PJ_INVALID_SOCKET; 
    108     is->ice_st = ice_st; 
    109     is->local_pref = local_pref; 
    110  
    111     status = pj_sock_socket(PJ_AF_INET, PJ_SOCK_DGRAM, 0, &is->sock); 
    112     if (status != PJ_SUCCESS) 
    113         return status; 
    114  
    115     /* Bind and get the local IP address */ 
    116     if (addr)  
    117         pj_memcpy(&is->base_addr, addr, sizeof(pj_sockaddr_in)); 
    118     else  
    119         pj_sockaddr_in_init(&is->base_addr.ipv4, NULL, 0); 
    120  
    121     status = pj_sock_bind(is->sock, &is->base_addr, sizeof(pj_sockaddr_in)); 
    122     if (status != PJ_SUCCESS) 
    123         goto on_error; 
    124  
    125     addr_len = sizeof(is->base_addr); 
    126     status = pj_sock_getsockname(is->sock, &is->base_addr, &addr_len); 
    127     if (status != PJ_SUCCESS) 
    128         goto on_error; 
    129  
    130     if (is->base_addr.ipv4.sin_addr.s_addr == 0) { 
    131         status = pj_gethostip(&is->base_addr.ipv4.sin_addr); 
    132         if (status != PJ_SUCCESS)  
    133             goto on_error; 
    134     } 
    135  
    136     /* Assign foundation */ 
    137     pj_ansi_snprintf(foundation, sizeof(foundation), "%c%x",  
    138                      get_type_prefix(type), 
    139                      (int)pj_ntohl(is->base_addr.ipv4.sin_addr.s_addr)); 
    140     pj_strdup2(ice_st->pool, &is->foundation, foundation); 
    141  
    142  
    143     /* Register to ioqueue */ 
    144     pj_bzero(&ioqueue_cb, sizeof(ioqueue_cb)); 
    145     ioqueue_cb.on_read_complete = &on_read_complete; 
    146     status = pj_ioqueue_register_sock(ice_st->pool, ice_st->stun_cfg.ioqueue,  
    147                                       is->sock, is, &ioqueue_cb, &is->key); 
    148     if (status != PJ_SUCCESS) 
    149         goto on_error; 
    150  
    151     pj_ioqueue_op_key_init(&is->read_op, sizeof(is->read_op)); 
    152     pj_ioqueue_op_key_init(&is->write_op, sizeof(is->write_op)); 
    153  
    154     /* Kick start reading the socket */ 
    155     on_read_complete(is->key, &is->read_op, 0); 
    156  
    157     /* Done */ 
    158     *p_is = is; 
    159     return PJ_SUCCESS; 
    160  
    161 on_error: 
    162     destroy_ice_interface(is); 
    163     return status; 
    164 } 
    165  
    166 /*  
    167  * This is callback called by ioqueue on incoming packet  
    168  */ 
    169 static void on_read_complete(pj_ioqueue_key_t *key,  
    170                              pj_ioqueue_op_key_t *op_key,  
    171                              pj_ssize_t bytes_read) 
    172 { 
    173     pj_ice_st_interface *is = (pj_ice_st_interface*)  
    174                               pj_ioqueue_get_user_data(key); 
    175     pj_ice_st *ice_st = is->ice_st; 
    176     pj_ssize_t pkt_size; 
    177     pj_status_t status; 
    178  
    179     if (bytes_read > 0) { 
    180  
    181         /* If we have an active ICE session, hand over all incoming 
    182          * packets to the ICE session. Otherwise just drop the packet. 
    183          */ 
    184         if (ice_st->ice) { 
    185             status = pj_ice_on_rx_pkt(ice_st->ice,  
    186                                       is->comp_id, is->cand_id, 
    187                                       is->pkt, bytes_read, 
    188                                       &is->src_addr, is->src_addr_len); 
    189         } else if (is->stun_sess) { 
    190             status = pj_stun_msg_check(is->pkt, bytes_read, PJ_STUN_IS_DATAGRAM); 
    191             if (status == PJ_SUCCESS) { 
    192                 status = pj_stun_session_on_rx_pkt(is->stun_sess, is->pkt,  
    193                                                    bytes_read,  
    194                                                    PJ_STUN_IS_DATAGRAM, NULL, 
    195                                                    &is->src_addr,  
    196                                                    is->src_addr_len); 
    197             } else { 
    198                 (*ice_st->cb.on_rx_data)(ice_st, is->comp_id, is->cand_id,  
    199                                          is->pkt, bytes_read,  
    200                                          &is->src_addr, is->src_addr_len); 
    201  
    202             } 
    203         } else { 
    204             (*ice_st->cb.on_rx_data)(ice_st, is->comp_id, is->cand_id,  
    205                                      is->pkt, bytes_read,  
    206                                      &is->src_addr, is->src_addr_len); 
    207         } 
    208  
    209     } else if (bytes_read < 0) { 
    210         ice_st_perror(is->ice_st, "ioqueue read callback error", -bytes_read); 
    211     } 
    212  
    213     /* Read next packet */ 
    214     pkt_size = sizeof(is->pkt); 
    215     is->src_addr_len = sizeof(is->src_addr); 
    216     status = pj_ioqueue_recvfrom(key, op_key, is->pkt, &pkt_size,  
    217                                  PJ_IOQUEUE_ALWAYS_ASYNC, 
    218                                  &is->src_addr, &is->src_addr_len); 
    219     if (status != PJ_SUCCESS && status != PJ_EPENDING) { 
    220         ice_st_perror(is->ice_st, "ioqueue recvfrom() error", status); 
    221     } 
    222 } 
    223  
    224 /*  
    225  * Destroy an interface  
    226  */ 
    227 static void destroy_ice_interface(pj_ice_st_interface *is) 
    228 { 
    229     if (is->stun_sess) { 
    230         pj_stun_session_destroy(is->stun_sess); 
    231         is->stun_sess = NULL; 
    232     } 
    233  
    234     if (is->key) { 
    235         pj_ioqueue_unregister(is->key); 
    236         is->key = NULL; 
    237         is->sock = PJ_INVALID_SOCKET; 
    238     } else if (is->sock != PJ_INVALID_SOCKET && is->sock != 0) { 
    239         pj_sock_close(is->sock); 
    240         is->sock = PJ_INVALID_SOCKET; 
    241     } 
    242 } 
    243  
    244 /*  
    24589 * Create ICE stream transport  
    24690 */ 
    24791PJ_DECL(pj_status_t) pj_ice_st_create(pj_stun_config *stun_cfg, 
    24892                                      const char *name, 
     93                                      unsigned comp_cnt, 
    24994                                      void *user_data, 
    25095                                      const pj_ice_st_cb *cb, 
     
    25499    pj_ice_st *ice_st; 
    255100 
    256     PJ_ASSERT_RETURN(stun_cfg && cb && p_ice_st, PJ_EINVAL); 
     101    PJ_ASSERT_RETURN(stun_cfg && comp_cnt && cb && p_ice_st, PJ_EINVAL); 
    257102    PJ_ASSERT_RETURN(stun_cfg->ioqueue && stun_cfg->timer_heap, PJ_EINVAL); 
    258103 
     
    266111    ice_st->user_data = user_data; 
    267112     
     113    ice_st->comp_cnt = comp_cnt; 
     114    ice_st->comp = (pj_ice_st_comp**) pj_pool_calloc(pool, comp_cnt,  
     115                                                     sizeof(void*)); 
     116 
    268117    pj_memcpy(&ice_st->cb, cb, sizeof(*cb)); 
    269118    pj_memcpy(&ice_st->stun_cfg, stun_cfg, sizeof(*stun_cfg)); 
    270119 
     120 
    271121    PJ_LOG(4,(ice_st->obj_name, "ICE stream transport created")); 
    272122 
     
    275125} 
    276126 
     127/* Destroy ICE */ 
    277128static void destroy_ice_st(pj_ice_st *ice_st, pj_status_t reason) 
    278129{ 
     
    291142    } 
    292143 
    293     /* Destroy all interfaces */ 
    294     for (i=0; i<ice_st->itf_cnt; ++i) { 
    295         destroy_ice_interface(ice_st->itfs[i]); 
    296         ice_st->itfs[i] = NULL; 
    297     } 
    298     ice_st->itf_cnt = 0; 
     144    /* Destroy all components */ 
     145    for (i=0; i<ice_st->comp_cnt; ++i) { 
     146        if (ice_st->comp[i]) { 
     147            destroy_component(ice_st->comp[i]); 
     148            ice_st->comp[i] = NULL; 
     149        } 
     150    } 
     151    ice_st->comp_cnt = 0; 
    299152 
    300153    /* Done */ 
     
    318171 * Resolve STUN server 
    319172 */ 
    320 PJ_DEF(pj_status_t) pj_ice_st_set_stun( pj_ice_st *ice_st, 
    321                                         pj_dns_resolver *resolver, 
    322                                         pj_bool_t enable_relay, 
    323                                         const pj_str_t *domain) 
     173PJ_DEF(pj_status_t) pj_ice_st_set_stun_domain(pj_ice_st *ice_st, 
     174                                              pj_dns_resolver *resolver, 
     175                                              const pj_str_t *domain) 
    324176{ 
    325177    /* Yeah, TODO */ 
    326178    PJ_UNUSED_ARG(ice_st); 
    327179    PJ_UNUSED_ARG(resolver); 
    328     PJ_UNUSED_ARG(enable_relay); 
    329180    PJ_UNUSED_ARG(domain); 
    330181    return -1; 
     
    334185 * Set STUN server address. 
    335186 */ 
    336 PJ_DEF(pj_status_t) pj_ice_st_set_stun_addr( pj_ice_st *ice_st, 
    337                                              pj_bool_t enable_relay, 
    338                                              const pj_sockaddr_in *srv_addr) 
    339 { 
    340  
    341     PJ_ASSERT_RETURN(ice_st && srv_addr, PJ_EINVAL); 
    342      
    343     ice_st->relay_enabled = enable_relay; 
    344     pj_strdup2(ice_st->pool, &ice_st->stun_domain, 
    345                pj_inet_ntoa(srv_addr->sin_addr)); 
    346     pj_memcpy(&ice_st->stun_srv, srv_addr, sizeof(pj_sockaddr_in)); 
     187PJ_DEF(pj_status_t) pj_ice_st_set_stun_srv( pj_ice_st *ice_st, 
     188                                            const pj_sockaddr_in *stun_srv, 
     189                                            const pj_sockaddr_in *turn_srv) 
     190{ 
     191    PJ_ASSERT_RETURN(ice_st, PJ_EINVAL); 
     192    /* Must not have pending resolver job */ 
     193    PJ_ASSERT_RETURN(ice_st->has_resolver_job==PJ_FALSE, PJ_EINVALIDOP); 
     194 
     195    if (stun_srv) { 
     196        pj_memcpy(&ice_st->stun_srv, stun_srv, sizeof(pj_sockaddr_in)); 
     197    } else { 
     198        pj_bzero(&ice_st->stun_srv, sizeof(pj_sockaddr_in)); 
     199    } 
     200 
     201    if (turn_srv) { 
     202        pj_memcpy(&ice_st->turn_srv, turn_srv, sizeof(pj_sockaddr_in)); 
     203    } else { 
     204        pj_bzero(&ice_st->turn_srv, sizeof(pj_sockaddr_in)); 
     205    } 
    347206 
    348207    return PJ_SUCCESS; 
    349208} 
    350209 
    351 /* 
    352  * Add new component. 
    353  */ 
    354 PJ_DEF(pj_status_t) pj_ice_st_add_comp(pj_ice_st *ice_st, 
    355                                        unsigned comp_id) 
    356 { 
    357     /* Verify arguments */ 
    358     PJ_ASSERT_RETURN(ice_st && comp_id, PJ_EINVAL); 
    359  
    360     /* Can only add component when we don't have active ICE session */ 
    361     PJ_ASSERT_RETURN(ice_st->ice == NULL, PJ_EBUSY); 
    362  
    363     /* Check that we don't have too many components */ 
    364     PJ_ASSERT_RETURN(ice_st->comp_cnt < PJ_ICE_MAX_COMP, PJ_ETOOMANY); 
    365  
    366     /* Component ID must be valid */ 
    367     PJ_ASSERT_RETURN(comp_id <= PJ_ICE_MAX_COMP, PJNATH_EICEINCOMPID); 
    368  
    369     /* First component ID must be 1, second must be 2, etc., and  
    370      * they must be registered in order. 
    371      */ 
    372     PJ_ASSERT_RETURN(ice_st->comps[comp_id-1] == ice_st->comp_cnt,  
    373                      PJNATH_EICEINCOMPID); 
    374  
    375     /* All in order, add the component. */ 
    376     ice_st->comps[ice_st->comp_cnt++] = comp_id; 
    377  
    378     return PJ_SUCCESS; 
    379 } 
    380  
    381 /* Add interface */ 
    382 static void add_interface(pj_ice_st *ice_st, pj_ice_st_interface *is, 
    383                           unsigned *p_itf_id) 
    384 { 
    385     unsigned itf_id; 
    386  
    387     itf_id = ice_st->itf_cnt++; 
    388     ice_st->itfs[itf_id] = is; 
    389  
    390     if (p_itf_id) 
    391         *p_itf_id = itf_id; 
    392 } 
    393  
    394 /* 
    395  * Add new host interface. 
    396  */ 
    397 PJ_DEF(pj_status_t) pj_ice_st_add_host_interface(pj_ice_st *ice_st, 
    398                                                  unsigned comp_id, 
    399                                                  pj_uint16_t local_pref, 
    400                                                  const pj_sockaddr_in *addr, 
    401                                                  unsigned *p_itf_id) 
    402 { 
    403     pj_ice_st_interface *is; 
     210 
     211/* Calculate foundation */ 
     212static pj_str_t calc_foundation(pj_pool_t *pool, 
     213                                pj_ice_cand_type type, 
     214                                const pj_in_addr *base_addr) 
     215{ 
     216    char foundation[32]; 
     217    pj_str_t result; 
     218 
     219    pj_ansi_snprintf(foundation, sizeof(foundation), "%c%x",  
     220                     get_type_prefix(type), 
     221                     (int)pj_ntohl(base_addr->s_addr)); 
     222    pj_strdup2(pool, &result, foundation); 
     223 
     224    return result; 
     225} 
     226 
     227/*  Create new component (i.e. socket)  */ 
     228static pj_status_t create_component(pj_ice_st *ice_st, 
     229                                    unsigned comp_id, 
     230                                    pj_uint32_t options, 
     231                                    const pj_sockaddr_in *addr, 
     232                                    pj_ice_st_comp **p_comp) 
     233{ 
     234    enum { MAX_RETRY=100, PORT_INC=2 }; 
     235    pj_ioqueue_callback ioqueue_cb; 
     236    pj_ice_st_comp *comp; 
     237    int retry, addr_len; 
    404238    pj_status_t status; 
    405239 
    406     /* Verify arguments */ 
    407     PJ_ASSERT_RETURN(ice_st && comp_id, PJ_EINVAL); 
    408  
    409     /* Check that component ID present */ 
    410     PJ_ASSERT_RETURN(comp_id <= ice_st->comp_cnt, PJNATH_EICEINCOMPID); 
    411  
    412     /* Can't add new interface while ICE is running */ 
    413     PJ_ASSERT_RETURN(ice_st->ice == NULL, PJ_EBUSY); 
    414  
    415     /* Create interface */ 
    416     status = create_ice_interface(ice_st, PJ_ICE_CAND_TYPE_HOST, comp_id, 
    417                                   local_pref, addr, &is); 
     240    comp = PJ_POOL_ZALLOC_T(ice_st->pool, pj_ice_st_comp); 
     241    comp->ice_st = ice_st; 
     242    comp->comp_id = comp_id; 
     243    comp->options = options; 
     244    comp->sock = PJ_INVALID_SOCKET; 
     245    comp->last_status = PJ_SUCCESS; 
     246 
     247    /* Create socket */ 
     248    status = pj_sock_socket(PJ_AF_INET, PJ_SOCK_DGRAM, 0, &comp->sock); 
    418249    if (status != PJ_SUCCESS) 
    419250        return status; 
    420251 
    421     /* For host interface, the address is the base address */ 
    422     pj_memcpy(&is->addr, &is->base_addr, sizeof(is->addr)); 
    423  
    424     /* Store this interface */ 
    425     add_interface(ice_st, is, p_itf_id); 
    426  
    427     /* Set interface status to SUCCESS */ 
    428     is->status = PJ_SUCCESS; 
     252    /* Init address */ 
     253    if (addr)  
     254        pj_memcpy(&comp->local_addr, addr, sizeof(pj_sockaddr_in)); 
     255    else  
     256        pj_sockaddr_in_init(&comp->local_addr.ipv4, NULL, 0); 
     257 
     258    /* Retry binding socket */ 
     259    for (retry=0; retry<MAX_RETRY; ++retry) { 
     260        pj_uint16_t port; 
     261 
     262        status = pj_sock_bind(comp->sock, &comp->local_addr,  
     263                              sizeof(pj_sockaddr_in)); 
     264        if (status == PJ_SUCCESS) 
     265            break; 
     266 
     267        if (options & PJ_ICE_ST_OPT_NO_PORT_RETRY) 
     268            goto on_error; 
     269 
     270        port = pj_ntohs(comp->local_addr.ipv4.sin_port); 
     271        port += PORT_INC; 
     272        comp->local_addr.ipv4.sin_port = pj_htons(port); 
     273    } 
     274 
     275    /* Get the actual port where the socket is bound to. 
     276     * (don't care about the address, it will be retrieved later) 
     277     */ 
     278    addr_len = sizeof(comp->local_addr); 
     279    status = pj_sock_getsockname(comp->sock, &comp->local_addr, &addr_len); 
     280    if (status != PJ_SUCCESS) 
     281        goto on_error; 
     282 
     283    /* Register to ioqueue */ 
     284    pj_bzero(&ioqueue_cb, sizeof(ioqueue_cb)); 
     285    ioqueue_cb.on_read_complete = &on_read_complete; 
     286    status = pj_ioqueue_register_sock(ice_st->pool, ice_st->stun_cfg.ioqueue,  
     287                                      comp->sock, comp, &ioqueue_cb,  
     288                                      &comp->key); 
     289    if (status != PJ_SUCCESS) 
     290        goto on_error; 
     291 
     292    pj_ioqueue_op_key_init(&comp->read_op, sizeof(comp->read_op)); 
     293    pj_ioqueue_op_key_init(&comp->write_op, sizeof(comp->write_op)); 
     294 
     295    /* Kick start reading the socket */ 
     296    on_read_complete(comp->key, &comp->read_op, 0); 
     297 
     298    /* If the socket is bound to INADDR_ANY, then lookup all interfaces in 
     299     * the host and add them into cand_list. Otherwise if the socket is bound 
     300     * to a specific interface, then only add that specific interface to 
     301     * cand_list. 
     302     */ 
     303    if (comp->local_addr.ipv4.sin_addr.s_addr == 0) { 
     304        /* Socket is bound to INADDR_ANY */ 
     305        unsigned i, ifs_cnt; 
     306        pj_in_addr ifs[PJ_ICE_ST_MAX_ALIASES-2]; 
     307 
     308        /* Reset default candidate */ 
     309        comp->default_cand = -1; 
     310 
     311        /* Enum all IP interfaces in the host */ 
     312        ifs_cnt = PJ_ARRAY_SIZE(ifs); 
     313        status = pj_enum_ip_interface(&ifs_cnt, ifs); 
     314        if (status != PJ_SUCCESS) 
     315            goto on_error; 
     316 
     317        /* Set default IP interface as the base address */ 
     318        status = pj_gethostip(&comp->local_addr.ipv4.sin_addr); 
     319        if (status != PJ_SUCCESS) 
     320            return status; 
     321 
     322        /* Add candidate entry for each interface */ 
     323        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); 
     335 
     336            /* If the IP address is equal to local address, assign it 
     337             * as default candidate. 
     338             */ 
     339            if (cand->addr.ipv4.sin_addr.s_addr == 
     340                comp->local_addr.ipv4.sin_addr.s_addr) 
     341            { 
     342                comp->default_cand = i; 
     343            } 
     344 
     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)); 
     349        } 
     350        comp->cand_cnt = ifs_cnt; 
     351 
     352 
     353    } else { 
     354        /* Socket is bound to specific address.  
     355         * In this case only add that address as a single entry in the 
     356         * cand_list table. 
     357         */ 
     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    } 
     378 
     379    /* Done */ 
     380    if (p_comp) 
     381        *p_comp = comp; 
    429382 
    430383    return PJ_SUCCESS; 
    431 } 
    432  
    433 /* 
    434  * Enumerate and add all host interfaces. 
    435  */ 
    436 PJ_DEF(pj_status_t) pj_ice_st_add_all_host_interfaces(pj_ice_st *ice_st, 
    437                                                       unsigned comp_id, 
    438                                                       unsigned port) 
    439 { 
    440     pj_sockaddr_in addr; 
     384 
     385on_error: 
     386    destroy_component(comp); 
     387    return status; 
     388} 
     389 
     390/*  
     391 * This is callback called by ioqueue on incoming packet  
     392 */ 
     393static void on_read_complete(pj_ioqueue_key_t *key,  
     394                             pj_ioqueue_op_key_t *op_key,  
     395                             pj_ssize_t bytes_read) 
     396{ 
     397    pj_ice_st_comp *comp = (pj_ice_st_comp*)  
     398                            pj_ioqueue_get_user_data(key); 
     399    pj_ice_st *ice_st = comp->ice_st; 
     400    pj_ssize_t pkt_size; 
    441401    pj_status_t status; 
    442402 
    443     /* Yeah, TODO. 
    444      * For now just add the default interface. 
    445      */ 
    446     pj_sockaddr_in_init(&addr, NULL, (pj_uint16_t)port); 
    447      
    448     status = pj_gethostip(&addr.sin_addr); 
    449     if (status != PJ_SUCCESS) 
    450         return status; 
    451  
    452     return pj_ice_st_add_host_interface(ice_st, comp_id, 65535, &addr, NULL); 
    453 } 
    454  
    455 /* 
    456  * Add STUN mapping interface. 
    457  */ 
    458 PJ_DEF(pj_status_t) pj_ice_st_add_stun_interface(pj_ice_st *ice_st, 
    459                                                  unsigned comp_id, 
    460                                                  unsigned local_port, 
    461                                                  unsigned *p_itf_id) 
    462 { 
    463     pj_ice_st_interface *is; 
    464     pj_sockaddr_in local_addr; 
     403    if (bytes_read > 0) { 
     404        /* 
     405         * Okay, we got a packet from the socket for the component. There is 
     406         * a bit of situation here, since this packet could be one of these: 
     407         * 
     408         * 1) this could be the response of STUN binding request sent by 
     409         *    this component to a) an initial request to get the STUN mapped 
     410         *    address of this component, or b) subsequent request to keep 
     411         *    the binding alive. 
     412         *  
     413         * 2) this could be a packet (STUN or not STUN) sent from the STUN 
     414         *    relay server. In this case, still there are few options to do 
     415         *    for this packet: a) process this locally if this packet is 
     416         *    related to TURN session management (e.g. Allocate response), 
     417         *    b) forward this packet to ICE if this is related to ICE 
     418         *    discovery process. 
     419         * 
     420         * 3) this could be a STUN request or response sent as part of ICE 
     421         *    discovery process. 
     422         * 
     423         * 4) this could be application's packet, e.g. when ICE processing 
     424         *    is done and agents start sending RTP/RTCP packets to each 
     425         *    other, or when ICE processing is not done and this ICE stream 
     426         *    transport decides to allow sending data. 
     427         * 
     428         * So far we don't have good solution for this. 
     429         * The process below is just a workaround. 
     430         */ 
     431        if (ice_st->ice) { 
     432            PJ_TODO(DISTINGUISH_BETWEEN_LOCAL_AND_RELAY); 
     433            status = pj_ice_on_rx_pkt(ice_st->ice, comp->comp_id,  
     434                                      comp->cand_list[0].cand_id, 
     435                                      comp->pkt, bytes_read, 
     436                                      &comp->src_addr, comp->src_addr_len); 
     437        } else if (comp->stun_sess) { 
     438            status = pj_stun_msg_check(comp->pkt, bytes_read,  
     439                                       PJ_STUN_IS_DATAGRAM); 
     440            if (status == PJ_SUCCESS) { 
     441                status = pj_stun_session_on_rx_pkt(comp->stun_sess, comp->pkt, 
     442                                                   bytes_read,  
     443                                                   PJ_STUN_IS_DATAGRAM, NULL, 
     444                                                   &comp->src_addr,  
     445                                                   comp->src_addr_len); 
     446            } else { 
     447                (*ice_st->cb.on_rx_data)(ice_st, comp->comp_id,  
     448                                         comp->pkt, bytes_read,  
     449                                         &comp->src_addr, comp->src_addr_len); 
     450 
     451            } 
     452        } else { 
     453            (*ice_st->cb.on_rx_data)(ice_st, comp->comp_id,  
     454                                     comp->pkt, bytes_read,  
     455                                     &comp->src_addr, comp->src_addr_len); 
     456        } 
     457 
     458    } else if (bytes_read < 0) { 
     459        ice_st_perror(comp->ice_st, "ioqueue read callback error",  
     460                      -bytes_read); 
     461    } 
     462 
     463    /* Read next packet */ 
     464    pkt_size = sizeof(comp->pkt); 
     465    comp->src_addr_len = sizeof(comp->src_addr); 
     466    status = pj_ioqueue_recvfrom(key, op_key, comp->pkt, &pkt_size,  
     467                                 PJ_IOQUEUE_ALWAYS_ASYNC, 
     468                                 &comp->src_addr, &comp->src_addr_len); 
     469    if (status != PJ_SUCCESS && status != PJ_EPENDING) { 
     470        ice_st_perror(comp->ice_st, "ioqueue recvfrom() error", status); 
     471    } 
     472} 
     473 
     474/*  
     475 * Destroy a component  
     476 */ 
     477static void destroy_component(pj_ice_st_comp *comp) 
     478{ 
     479    if (comp->stun_sess) { 
     480        pj_stun_session_destroy(comp->stun_sess); 
     481        comp->stun_sess = NULL; 
     482    } 
     483 
     484    if (comp->key) { 
     485        pj_ioqueue_unregister(comp->key); 
     486        comp->key = NULL; 
     487        comp->sock = PJ_INVALID_SOCKET; 
     488    } else if (comp->sock != PJ_INVALID_SOCKET && comp->sock != 0) { 
     489        pj_sock_close(comp->sock); 
     490        comp->sock = PJ_INVALID_SOCKET; 
     491    } 
     492} 
     493 
     494 
     495 
     496/* 
     497 * Add STUN mapping to a component. 
     498 */ 
     499static pj_status_t get_stun_mapped_addr(pj_ice_st *ice_st, 
     500                                        pj_ice_st_comp *comp) 
     501{ 
     502    pj_ice_st_cand *cand; 
    465503    pj_stun_session_cb sess_cb; 
    466504    pj_stun_tx_data *tdata; 
    467505    pj_status_t status; 
    468506 
    469     PJ_ASSERT_RETURN(ice_st && comp_id, PJ_EINVAL); 
     507    PJ_ASSERT_RETURN(ice_st && comp, PJ_EINVAL); 
    470508     
    471     /* STUN server must have been configured */ 
    472     PJ_ASSERT_RETURN(ice_st->stun_srv.sin_family != 0, PJ_EINVALIDOP); 
    473  
    474  
    475     /* Create interface */ 
    476     pj_sockaddr_in_init(&local_addr, NULL, (pj_uint16_t)local_port); 
    477     status = create_ice_interface(ice_st, PJ_ICE_CAND_TYPE_SRFLX, comp_id, 
    478                                   65535, &local_addr, &is); 
    479     if (status != PJ_SUCCESS) 
    480         return status; 
    481  
    482     /* Create STUN session */ 
     509    /* Bail out if STUN server is still being resolved */ 
     510    if (ice_st->has_resolver_job) 
     511        return PJ_EBUSY; 
     512 
     513    /* Just return (successfully) if STUN server is not configured */ 
     514    if (ice_st->stun_srv.sin_family == 0) 
     515        return PJ_SUCCESS; 
     516 
     517 
     518    /* Create STUN session for this component */ 
    483519    pj_bzero(&sess_cb, sizeof(sess_cb)); 
    484520    sess_cb.on_request_complete = &stun_on_request_complete; 
    485521    sess_cb.on_send_msg = &stun_on_send_msg; 
    486522    status = pj_stun_session_create(&ice_st->stun_cfg, ice_st->obj_name, 
    487                                     &sess_cb, PJ_FALSE, &is->stun_sess); 
     523                                    &sess_cb, PJ_FALSE, &comp->stun_sess); 
    488524    if (status != PJ_SUCCESS) 
    489         goto on_error; 
    490  
    491     /* Associate interface with STUN session */ 
    492     pj_stun_session_set_user_data(is->stun_sess, (void*)is); 
    493  
    494     /* Create and send STUN binding request */ 
    495     status = pj_stun_session_create_req(is->stun_sess,  
     525        return status; 
     526 
     527    /* Associate component with STUN session */ 
     528    pj_stun_session_set_user_data(comp->stun_sess, (void*)comp); 
     529 
     530    /* Create STUN binding request */ 
     531    status = pj_stun_session_create_req(comp->stun_sess,  
    496532                                        PJ_STUN_BINDING_REQUEST, &tdata); 
    497533    if (status != PJ_SUCCESS) 
    498         goto on_error; 
    499  
    500     status = pj_stun_session_send_msg(is->stun_sess, PJ_FALSE,  
     534        return status; 
     535 
     536    /* Attach alias instance to tdata */ 
     537    cand = &comp->cand_list[comp->cand_cnt]; 
     538    tdata->user_data = (void*)cand; 
     539 
     540    /* Send STUN binding request */ 
     541    status = pj_stun_session_send_msg(comp->stun_sess, PJ_FALSE,  
    501542                                      &ice_st->stun_srv,  
    502543                                      sizeof(pj_sockaddr_in), tdata); 
    503544    if (status != PJ_SUCCESS) 
    504         goto on_error; 
    505  
    506     /* Mark interface as pending */ 
    507     is->status = PJ_EPENDING; 
    508  
    509     add_interface(ice_st, is, p_itf_id); 
     545        return status; 
     546 
     547 
     548    /* Add new alias to this component */ 
     549    cand->type = PJ_ICE_CAND_TYPE_SRFLX; 
     550    cand->status = PJ_EPENDING; 
     551    cand->cand_id = -1; 
     552    cand->local_pref = 65535; 
     553    cand->foundation = calc_foundation(ice_st->pool, PJ_ICE_CAND_TYPE_SRFLX, 
     554                                       &comp->local_addr.ipv4.sin_addr); 
     555 
     556    ++comp->cand_cnt; 
     557 
     558    /* Add pending count for this component */ 
     559    comp->pending_cnt++; 
    510560 
    511561    return PJ_SUCCESS; 
    512  
    513 on_error: 
    514     destroy_ice_interface(is); 
    515     return status; 
    516 } 
    517  
    518 /* 
    519  * Add TURN mapping interface. 
    520  */ 
    521 PJ_DEF(pj_status_t) pj_ice_st_add_relay_interface(pj_ice_st *ice_st, 
    522                                                   unsigned comp_id, 
    523                                                   unsigned local_port, 
    524                                                   pj_bool_t notify, 
    525                                                   void *notify_data) 
    526 { 
    527     /* Yeah, TODO */ 
    528     PJ_UNUSED_ARG(ice_st); 
    529     PJ_UNUSED_ARG(comp_id); 
    530     PJ_UNUSED_ARG(local_port); 
    531     PJ_UNUSED_ARG(notify); 
    532     PJ_UNUSED_ARG(notify_data); 
    533     return -1; 
    534 } 
    535  
    536 PJ_DEF(pj_status_t) pj_ice_st_get_interfaces_status(pj_ice_st *ice_st) 
     562} 
     563 
     564 
     565/* 
     566 * Create the component. 
     567 */ 
     568PJ_DEF(pj_status_t) pj_ice_st_create_comp(pj_ice_st *ice_st, 
     569                                          unsigned comp_id, 
     570                                          pj_uint32_t options, 
     571                                          const pj_sockaddr_in *addr, 
     572                                          unsigned *p_itf_id) 
     573{ 
     574    pj_ice_st_comp *comp; 
     575    pj_status_t status; 
     576 
     577    /* Verify arguments */ 
     578    PJ_ASSERT_RETURN(ice_st && comp_id, PJ_EINVAL); 
     579 
     580    /* Check that component ID present */ 
     581    PJ_ASSERT_RETURN(comp_id <= ice_st->comp_cnt, PJNATH_EICEINCOMPID); 
     582 
     583    /* Can't add new component while ICE is running */ 
     584    PJ_ASSERT_RETURN(ice_st->ice == NULL, PJ_EBUSY); 
     585     
     586    /* Can't add new component while resolver is running */ 
     587    PJ_ASSERT_RETURN(ice_st->has_resolver_job == PJ_FALSE, PJ_EBUSY); 
     588 
     589 
     590    /* Create component */ 
     591    status = create_component(ice_st, comp_id, options, addr, &comp); 
     592    if (status != PJ_SUCCESS) 
     593        return status; 
     594 
     595    if ((options & PJ_ICE_ST_OPT_DISABLE_STUN) == 0) { 
     596        status = get_stun_mapped_addr(ice_st, comp); 
     597        if (status != PJ_SUCCESS) { 
     598            destroy_component(comp); 
     599            return status; 
     600        } 
     601    } 
     602 
     603    /* Store this component */ 
     604    if (p_itf_id) 
     605        *p_itf_id = ice_st->comp_cnt; 
     606 
     607    ice_st->comp[comp_id-1] = comp; 
     608 
     609    return PJ_SUCCESS; 
     610} 
     611 
     612 
     613PJ_DEF(pj_status_t) pj_ice_st_get_comps_status(pj_ice_st *ice_st) 
    537614{ 
    538615    unsigned i; 
    539616    pj_status_t worst = PJ_SUCCESS; 
    540617 
    541     for (i=0; i<ice_st->itf_cnt; ++i) { 
    542         pj_ice_st_interface *itf = ice_st->itfs[i]; 
    543  
    544         if (itf->status == PJ_SUCCESS) { 
     618    for (i=0; i<ice_st->comp_cnt; ++i) { 
     619        pj_ice_st_comp *comp = ice_st->comp[i]; 
     620 
     621        if (comp->last_status == PJ_SUCCESS) { 
    545622            /* okay */ 
    546         } else if (itf->status == PJ_EPENDING && worst==PJ_SUCCESS) { 
    547             worst = itf->status; 
    548         } else { 
    549             worst = itf->status; 
     623        } else if (comp->pending_cnt && worst==PJ_SUCCESS) { 
     624            worst = PJ_EPENDING; 
     625            break; 
     626        } else if (comp->last_status != PJ_SUCCESS) { 
     627            worst = comp->last_status; 
     628            break; 
    550629        } 
     630 
     631        if (worst != PJ_SUCCESS) 
     632            break; 
    551633    } 
    552634 
     
    574656    pj_bzero(&ice_cb, sizeof(ice_cb)); 
    575657    ice_cb.on_ice_complete = &on_ice_complete; 
    576     ice_cb.on_rx_data = &on_rx_data; 
    577     ice_cb.on_tx_pkt = &on_tx_pkt; 
     658    ice_cb.on_rx_data = &ice_rx_data; 
     659    ice_cb.on_tx_pkt = &ice_tx_pkt; 
    578660 
    579661    /* Create! */ 
     
    588670 
    589671    /* Add candidates */ 
    590     for (i=0; i<ice_st->itf_cnt; ++i) { 
    591         pj_ice_st_interface *is= ice_st->itfs[i]; 
    592         status = pj_ice_add_cand(ice_st->ice, is->comp_id, is->type,  
    593                                  is->local_pref, &is->foundation, 
    594                                  &is->addr, &is->base_addr, NULL,  
    595                                  sizeof(pj_sockaddr_in),  
    596                                  (unsigned*)&is->cand_id); 
    597         if (status != PJ_SUCCESS) 
    598             goto on_error; 
     672    for (i=0; i<ice_st->comp_cnt; ++i) { 
     673        unsigned j; 
     674        pj_ice_st_comp *comp= ice_st->comp[i]; 
     675 
     676        for (j=0; j<comp->cand_cnt; ++j) { 
     677            pj_ice_st_cand *cand = &comp->cand_list[j]; 
     678 
     679            /* Skip if candidate is not ready */ 
     680            if (cand->status != PJ_SUCCESS) { 
     681                PJ_LOG(5,(ice_st->obj_name,  
     682                          "Candidate %d in component %d is not added", 
     683                          j, i)); 
     684                continue; 
     685            } 
     686 
     687            status = pj_ice_add_cand(ice_st->ice, comp->comp_id, cand->type, 
     688                                     cand->local_pref, &cand->foundation, 
     689                                     &cand->addr, &comp->local_addr, NULL,  
     690                                     sizeof(pj_sockaddr_in),  
     691                                     (unsigned*)&cand->cand_id); 
     692            if (status != PJ_SUCCESS) 
     693                goto on_error; 
     694        } 
    599695    } 
    600696 
     
    602698 
    603699on_error: 
    604     for (i=0; i<ice_st->itf_cnt; ++i) { 
    605         ice_st->itfs[i]->cand_id = -1; 
    606     } 
    607     if (ice_st->ice) { 
    608         pj_ice_destroy(ice_st->ice); 
    609         ice_st->ice = NULL; 
    610     } 
     700    pj_ice_st_stop_ice(ice_st); 
    611701    return status; 
    612702} 
     
    654744        return status; 
    655745 
    656     return pj_ice_start_check(ice_st->ice); 
     746    status = pj_ice_start_check(ice_st->ice); 
     747    if (status != PJ_SUCCESS) { 
     748        pj_ice_st_stop_ice(ice_st); 
     749    } 
     750 
     751    return status; 
    657752} 
    658753 
     
    662757PJ_DECL(pj_status_t) pj_ice_st_stop_ice(pj_ice_st *ice_st) 
    663758{ 
     759    unsigned i; 
     760 
    664761    if (ice_st->ice) { 
    665762        pj_ice_destroy(ice_st->ice); 
     
    667764    } 
    668765 
     766    /* Invalidate all candidate Ids */ 
     767    for (i=0; i<ice_st->comp_cnt; ++i) { 
     768        unsigned j; 
     769        for (j=0; j<ice_st->comp[i]->cand_cnt; ++j) { 
     770            ice_st->comp[i]->cand_list[j].cand_id = -1; 
     771        } 
     772    } 
     773 
    669774    return PJ_SUCCESS; 
    670 } 
    671  
    672 /* 
    673  * Send data to peer agent. 
    674  */ 
    675 PJ_DEF(pj_status_t) pj_ice_st_send_data( pj_ice_st *ice_st, 
    676                                          unsigned comp_id, 
    677                                          const void *data, 
    678                                          pj_size_t data_len) 
    679 { 
    680     if (!ice_st->ice) 
    681         return PJNATH_ENOICE; 
    682  
    683     return pj_ice_send_data(ice_st->ice, comp_id, data, data_len); 
    684775} 
    685776 
     
    689780PJ_DEF(pj_status_t) pj_ice_st_sendto( pj_ice_st *ice_st, 
    690781                                      unsigned comp_id, 
    691                                       unsigned itf_id, 
    692782                                      const void *data, 
    693783                                      pj_size_t data_len, 
     
    696786{ 
    697787    pj_ssize_t pkt_size; 
    698     pj_ice_st_interface *is = ice_st->itfs[itf_id]; 
     788    pj_ice_st_comp *comp; 
    699789    pj_status_t status; 
    700790 
     791    PJ_ASSERT_RETURN(ice_st && comp_id && comp_id <= ice_st->comp_cnt && 
     792                     dst_addr && dst_addr_len, PJ_EINVAL); 
     793 
     794    comp = ice_st->comp[comp_id-1]; 
     795 
     796    /* If ICE is available, send data with ICE */ 
     797    if (ice_st->ice) { 
     798        return pj_ice_send_data(ice_st->ice, comp_id, data, data_len); 
     799    } 
     800 
     801    /* Otherwise send direcly with the socket */ 
    701802    pkt_size = data_len; 
    702     status = pj_ioqueue_sendto(is->key, &is->write_op,  
     803    status = pj_ioqueue_sendto(comp->key, &comp->write_op,  
    703804                               data, &pkt_size, 0, 
    704805                               dst_addr, dst_addr_len); 
     
    722823 * Callback called by ICE session when it wants to send outgoing packet. 
    723824 */ 
    724 static pj_status_t on_tx_pkt(pj_ice *ice,  
    725                              unsigned comp_id, unsigned cand_id, 
    726                              const void *pkt, pj_size_t size, 
    727                              const pj_sockaddr_t *dst_addr, 
    728                              unsigned dst_addr_len) 
     825static pj_status_t ice_tx_pkt(pj_ice *ice,  
     826                              unsigned comp_id, unsigned cand_id, 
     827                              const void *pkt, pj_size_t size, 
     828                              const pj_sockaddr_t *dst_addr, 
     829                              unsigned dst_addr_len) 
    729830{ 
    730831    pj_ice_st *ice_st = (pj_ice_st*)ice->user_data; 
    731     pj_ice_st_interface *is = NULL; 
    732     unsigned i; 
     832    pj_ice_st_comp *comp = NULL; 
    733833    pj_ssize_t pkt_size; 
    734834    pj_status_t status; 
    735835 
    736     PJ_UNUSED_ARG(comp_id); 
    737  
    738     for (i=0; i<ice_st->itf_cnt; ++i) { 
    739         if (ice_st->itfs[i]->cand_id == (int)cand_id) { 
    740             is = ice_st->itfs[i]; 
    741             break; 
    742         } 
    743     } 
    744     if (is == NULL) { 
    745         return PJNATH_EICEINCANDID; 
    746     } 
     836    PJ_TODO(TX_TO_RELAY); 
     837 
     838    PJ_ASSERT_RETURN(comp_id && comp_id <= ice_st->comp_cnt, PJ_EINVAL); 
     839    comp = ice_st->comp[comp_id-1]; 
    747840 
    748841    pkt_size = size; 
    749     status = pj_ioqueue_sendto(is->key, &is->write_op,  
     842    status = pj_ioqueue_sendto(comp->key, &comp->write_op,  
    750843                               pkt, &pkt_size, 0, 
    751844                               dst_addr, dst_addr_len); 
     
    757850 * Callback called by ICE session when it receives application data. 
    758851 */ 
    759 static void on_rx_data(pj_ice *ice,  
    760                        unsigned comp_id, unsigned cand_id, 
    761                        void *pkt, pj_size_t size, 
    762                        const pj_sockaddr_t *src_addr, 
    763                        unsigned src_addr_len) 
     852static void ice_rx_data(pj_ice *ice,  
     853                        unsigned comp_id,  
     854                        void *pkt, pj_size_t size, 
     855                        const pj_sockaddr_t *src_addr, 
     856                        unsigned src_addr_len) 
    764857{ 
    765858    pj_ice_st *ice_st = (pj_ice_st*)ice->user_data; 
    766859 
    767860    if (ice_st->cb.on_rx_data) { 
    768         (*ice_st->cb.on_rx_data)(ice_st, comp_id, cand_id,  
    769                                  pkt, size, src_addr, src_addr_len); 
     861        (*ice_st->cb.on_rx_data)(ice_st, comp_id, pkt, size,  
     862                                 src_addr, src_addr_len); 
    770863    } 
    771864} 
     
    780873                                    unsigned dst_addr_len) 
    781874{ 
    782     pj_ice_st_interface *is; 
     875    pj_ice_st_comp *comp; 
    783876    pj_ssize_t pkt_size; 
    784877    pj_status_t status; 
    785878 
    786     is = (pj_ice_st_interface*) pj_stun_session_get_user_data(sess); 
     879    comp = (pj_ice_st_comp*) pj_stun_session_get_user_data(sess); 
    787880    pkt_size = size; 
    788     status = pj_ioqueue_sendto(is->key, &is->write_op,  
     881    status = pj_ioqueue_sendto(comp->key, &comp->write_op,  
    789882                               pkt, &pkt_size, 0, 
    790883                               dst_addr, dst_addr_len); 
     
    802895                                     const pj_stun_msg *response) 
    803896{ 
    804     pj_ice_st_interface *is; 
     897    pj_ice_st_comp *comp; 
     898    pj_ice_st_cand *cand = NULL; 
    805899    pj_stun_xor_mapped_addr_attr *xa; 
    806900    pj_stun_mapped_addr_attr *ma; 
    807901    pj_sockaddr *mapped_addr; 
    808902 
    809     PJ_UNUSED_ARG(tdata); 
    810  
    811     is = (pj_ice_st_interface*) pj_stun_session_get_user_data(sess); 
     903    comp = (pj_ice_st_comp*) pj_stun_session_get_user_data(sess); 
     904    cand = (pj_ice_st_cand*) tdata->user_data; 
     905 
     906    /* Decrement pending count for this component */ 
     907    pj_assert(comp->pending_cnt > 0); 
     908    comp->pending_cnt--; 
     909 
    812910    if (status != PJ_SUCCESS) { 
    813         is->status = status; 
    814         ice_st_perror(is->ice_st, "STUN Binding request failed", is->status); 
     911        comp->last_status = cand->status = status; 
     912        ice_st_perror(comp->ice_st, "STUN Binding request failed",  
     913                      cand->status); 
    815914        return; 
    816915    } 
     
    826925        mapped_addr = &ma->sockaddr; 
    827926    else { 
    828         is->status = PJNATH_ESTUNNOMAPPEDADDR; 
    829         ice_st_perror(is->ice_st, "STUN Binding request failed", is->status); 
     927        cand->status = PJNATH_ESTUNNOMAPPEDADDR; 
     928        ice_st_perror(comp->ice_st, "STUN Binding request failed",  
     929                      cand->status); 
    830930        return; 
    831931    } 
    832932 
    833     PJ_LOG(4,(is->ice_st->obj_name,  
     933    PJ_LOG(4,(comp->ice_st->obj_name,  
    834934              "STUN mapped address: %s:%d", 
    835935              pj_inet_ntoa(mapped_addr->ipv4.sin_addr), 
    836936              (int)pj_ntohs(mapped_addr->ipv4.sin_port))); 
    837     pj_memcpy(&is->addr, mapped_addr, sizeof(pj_sockaddr_in)); 
    838     is->status = PJ_SUCCESS; 
    839  
    840 } 
    841  
     937    pj_memcpy(&cand->addr, mapped_addr, sizeof(pj_sockaddr_in)); 
     938    cand->status = PJ_SUCCESS; 
     939 
     940    /* Set this candidate as the default candidate */ 
     941    comp->default_cand = (cand - comp->cand_list); 
     942    comp->last_status = PJ_SUCCESS; 
     943} 
     944 
  • pjproject/trunk/pjsip-apps/build/Samples-vc.mak

    r1100 r1104  
    2020 
    2121LIBS = $(PJSUA_LIB_LIB) $(PJSIP_UA_LIB) $(PJSIP_SIMPLE_LIB) \ 
    22           $(PJSIP_LIB) $(PJNATH_LIB) $(PJMEDIA_CODEC_LIB) $(PJMEDIA_LIB) \ 
     22          $(PJSIP_LIB) $(PJMEDIA_CODEC_LIB) $(PJMEDIA_LIB) $(PJNATH_LIB) \ 
    2323          $(PJLIB_UTIL_LIB) $(PJLIB_LIB) 
    2424 
     
    3030          -I..\..\pjnath/include 
    3131LDFLAGS = $(BUILD_FLAGS) $(LIBS) \ 
    32           ole32.lib user32.lib dsound.lib dxguid.lib netapi32.lib \ 
     32          Iphlpapi.lib ole32.lib user32.lib dsound.lib dxguid.lib netapi32.lib \ 
    3333          mswsock.lib ws2_32.lib  
    3434 
  • pjproject/trunk/pjsip-apps/build/pjsua.dsp

    r1098 r1104  
    5252LINK32=link.exe 
    5353# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 
    54 # ADD LINK32 ole32.lib user32.lib dsound.lib dxguid.lib netapi32.lib mswsock.lib ws2_32.lib kernel32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /map:"..\bin\pjsua_vc6.map" /debug /machine:I386 /out:"../bin/pjsua_vc6.exe" /fixed:no 
     54# ADD LINK32 Iphlpapi.lib ole32.lib user32.lib dsound.lib dxguid.lib netapi32.lib mswsock.lib ws2_32.lib kernel32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /map:"..\bin\pjsua_vc6.map" /debug /machine:I386 /out:"../bin/pjsua_vc6.exe" /fixed:no 
    5555# SUBTRACT LINK32 /pdb:none 
    5656 
     
    7878LINK32=link.exe 
    7979# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept 
    80 # ADD LINK32 ole32.lib user32.lib dsound.lib dxguid.lib netapi32.lib mswsock.lib ws2_32.lib kernel32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /out:"../bin/pjsua_vc6d.exe" /pdbtype:sept 
     80# ADD LINK32 Iphlpapi.lib ole32.lib user32.lib dsound.lib dxguid.lib netapi32.lib mswsock.lib ws2_32.lib kernel32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /out:"../bin/pjsua_vc6d.exe" /pdbtype:sept 
    8181 
    8282!ENDIF  
  • pjproject/trunk/pjsip-apps/build/pjsua.vcproj

    r1100 r1104  
    7474                                Name="VCLinkerTool" 
    7575                                AdditionalOptions="/FIXED:NO" 
    76                                 AdditionalDependencies="dsound.lib dxguid.lib netapi32.lib mswsock.lib ws2_32.lib odbc32.lib odbccp32.lib ole32.lib user32.lib" 
     76                                AdditionalDependencies="Iphlpapi.lib dsound.lib dxguid.lib netapi32.lib mswsock.lib ws2_32.lib odbc32.lib odbccp32.lib ole32.lib user32.lib" 
    7777                                OutputFile="../bin/pjsua_vc8.exe" 
    7878                                LinkIncremental="1" 
     
    169169                        <Tool 
    170170                                Name="VCLinkerTool" 
    171                                 AdditionalDependencies="dsound.lib dxguid.lib netapi32.lib mswsock.lib ws2_32.lib odbc32.lib odbccp32.lib ole32.lib user32.lib" 
     171                                AdditionalDependencies="Iphlpapi.lib  dsound.lib dxguid.lib netapi32.lib mswsock.lib ws2_32.lib odbc32.lib odbccp32.lib ole32.lib user32.lib" 
    172172                                OutputFile="../bin/pjsua_vc8d.exe" 
    173173                                LinkIncremental="2" 
  • pjproject/trunk/pjsip/src/pjsua-lib/pjsua_media.c

    r1099 r1104  
    554554{ 
    555555    unsigned i; 
     556    pj_sockaddr_in addr; 
    556557    pj_status_t status; 
     558 
     559    pj_sockaddr_in_init(&addr, 0, (pj_uint16_t)cfg->port); 
    557560 
    558561    /* Create each media transport */ 
    559562    for (i=0; i<pjsua_var.ua_cfg.max_calls; ++i) { 
    560         pj_ice_st *ice_st; 
     563        pj_ice_st_comp comp; 
     564        int next_port; 
    561565 
    562566        status = pjmedia_ice_create(pjsua_var.med_endpt, NULL, 1, 
     
    569573        } 
    570574 
    571         ice_st = pjmedia_ice_get_ice_st(pjsua_var.calls[i].med_tp); 
    572  
    573         /* Add host candidates for RTP */ 
    574         status = pj_ice_st_add_all_host_interfaces(ice_st, 1, 0); 
     575        status = pjmedia_ice_start_init(pjsua_var.calls[i].med_tp, 0, &addr, 
     576                                        &pjsua_var.stun_srv.ipv4, NULL); 
    575577        if (status != PJ_SUCCESS) { 
    576             pjsua_perror(THIS_FILE, "Error adding ICE host candidates", 
     578            pjsua_perror(THIS_FILE, "Error starting ICE transport", 
    577579                         status); 
    578580            goto on_error; 
    579581        } 
    580582 
    581         /* Configure STUN server */ 
    582         if (pjsua_var.stun_srv.addr.sa_family != 0) { 
    583          
    584             status = pj_ice_st_set_stun_addr(ice_st,  
    585                                              pjsua_var.media_cfg.enable_relay, 
    586                                              &pjsua_var.stun_srv.ipv4); 
    587             if (status != PJ_SUCCESS) { 
    588                 pjsua_perror(THIS_FILE, "Error setting ICE's STUN server", 
    589                              status); 
    590                 goto on_error; 
    591             } 
    592  
    593             /* Add STUN server reflexive candidate for RTP */ 
    594             status = pj_ice_st_add_stun_interface(ice_st, 1, 0, NULL); 
    595             if (status != PJ_SUCCESS) { 
    596                 pjsua_perror(THIS_FILE, "Error adding ICE address", 
    597                              status); 
    598                 goto on_error; 
    599             } 
    600         } 
     583        pjmedia_ice_get_comp(pjsua_var.calls[i].med_tp, 1, &comp); 
     584        next_port = pj_ntohs(comp.local_addr.ipv4.sin_port); 
     585        next_port += 2; 
     586        addr.sin_port = pj_htons((pj_uint16_t)next_port); 
    601587    } 
    602588 
    603589    /* Wait until all ICE transports are ready */ 
    604590    for (i=0; i<pjsua_var.ua_cfg.max_calls; ++i) { 
    605         pj_ice_st *ice_st; 
    606  
    607         ice_st = pjmedia_ice_get_ice_st(pjsua_var.calls[i].med_tp); 
    608591 
    609592        /* Wait until interface status is PJ_SUCCESS */ 
    610593        for (;;) { 
    611             status = pj_ice_st_get_interfaces_status(ice_st); 
     594            status = pjmedia_ice_get_init_status(pjsua_var.calls[i].med_tp); 
    612595            if (status == PJ_EPENDING) 
    613596                pjsua_handle_events(100); 
Note: See TracChangeset for help on using the changeset viewer.