Changeset 1867


Ignore:
Timestamp:
Mar 13, 2008 3:11:29 PM (16 years ago)
Author:
bennylp
Message:

More ticket #485: added TURN client application

Location:
pjproject/trunk
Files:
10 edited
3 moved

Legend:

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

    r1765 r1867  
    44        Version="8.00" 
    55        Name="pjlib_util" 
    6         ProjectGUID="{FE07F272-AE7F-4549-9E9F-EF9B80CB1693}" 
     6        ProjectGUID="{E79CE31A-3681-4F0C-8BE1-C43C0702EFFB}" 
    77        RootNamespace="pjlib_util" 
    88        > 
  • pjproject/trunk/pjlib/build/pjlib.vcproj

    r1405 r1867  
    44        Version="8.00" 
    55        Name="pjlib" 
    6         ProjectGUID="{DA0E03ED-53A7-4050-8A85-90541C5509F8}" 
     6        ProjectGUID="{DE592F40-CEF0-4B82-8EFB-A92D0C88A1EF}" 
    77        RootNamespace="pjlib" 
    88        > 
  • pjproject/trunk/pjnath/build/pjnath.dsw

    r1812 r1867  
    6161############################################################################### 
    6262 
    63 Project: "pjstun_client"=.\pjstun_client.dsp - Package Owner=<4> 
     63Project: "pjstun_srv_test"=.\pjstun_srv_test.dsp - Package Owner=<4> 
    6464 
    6565Package=<5> 
     
    8282############################################################################### 
    8383 
    84 Project: "pjstun_srv_test"=.\pjstun_srv_test.dsp - Package Owner=<4> 
     84Project: "pjturn_client"=.\pjturn_client.dsp - Package Owner=<4> 
    8585 
    8686Package=<5> 
  • pjproject/trunk/pjnath/build/pjnath.vcproj

    r1495 r1867  
    320320                                </FileConfiguration> 
    321321                        </File> 
     322                        <File 
     323                                RelativePath="..\src\pjnath\turn_session.c" 
     324                                > 
     325                        </File> 
     326                        <File 
     327                                RelativePath="..\src\pjnath\turn_udp.c" 
     328                                > 
     329                        </File> 
    322330                </Filter> 
    323331                <Filter 
     
    374382                        </File> 
    375383                        <File 
    376                                 RelativePath="..\include\pjnath\turn_client.h" 
     384                                RelativePath="..\include\pjnath\turn_session.h" 
     385                                > 
     386                        </File> 
     387                        <File 
     388                                RelativePath="..\include\pjnath\turn_udp.h" 
    377389                                > 
    378390                        </File> 
  • pjproject/trunk/pjnath/build/pjturn_client.dsp

    r1863 r1867  
    1 # Microsoft Developer Studio Project File - Name="pjstun_client" - Package Owner=<4> 
     1# Microsoft Developer Studio Project File - Name="pjturn_client" - Package Owner=<4> 
    22# Microsoft Developer Studio Generated Build File, Format Version 6.00 
    33# ** DO NOT EDIT ** 
     
    55# TARGTYPE "Win32 (x86) Console Application" 0x0103 
    66 
    7 CFG=pjstun_client - Win32 Debug 
     7CFG=pjturn_client - Win32 Debug 
    88!MESSAGE This is not a valid makefile. To build this project using NMAKE, 
    99!MESSAGE use the Export Makefile command and run 
    1010!MESSAGE  
    11 !MESSAGE NMAKE /f "pjstun_client.mak". 
     11!MESSAGE NMAKE /f "pjturn_client.mak". 
    1212!MESSAGE  
    1313!MESSAGE You can specify a configuration when running NMAKE 
    1414!MESSAGE by defining the macro CFG on the command line. For example: 
    1515!MESSAGE  
    16 !MESSAGE NMAKE /f "pjstun_client.mak" CFG="pjstun_client - Win32 Debug" 
     16!MESSAGE NMAKE /f "pjturn_client.mak" CFG="pjturn_client - Win32 Debug" 
    1717!MESSAGE  
    1818!MESSAGE Possible choices for configuration are: 
    1919!MESSAGE  
    20 !MESSAGE "pjstun_client - Win32 Release" (based on "Win32 (x86) Console Application") 
    21 !MESSAGE "pjstun_client - Win32 Debug" (based on "Win32 (x86) Console Application") 
     20!MESSAGE "pjturn_client - Win32 Release" (based on "Win32 (x86) Console Application") 
     21!MESSAGE "pjturn_client - Win32 Debug" (based on "Win32 (x86) Console Application") 
    2222!MESSAGE  
    2323 
     
    2929RSC=rc.exe 
    3030 
    31 !IF  "$(CFG)" == "pjstun_client - Win32 Release" 
     31!IF  "$(CFG)" == "pjturn_client - Win32 Release" 
    3232 
    3333# PROP BASE Use_MFC 0 
    3434# PROP BASE Use_Debug_Libraries 0 
    35 # PROP BASE Output_Dir "./output/pjstun-client-i386-win32-vc6-release" 
    36 # PROP BASE Intermediate_Dir "./output/pjstun-client-i386-win32-vc6-release" 
     35# PROP BASE Output_Dir "./output/pjturn-client-i386-win32-vc6-release" 
     36# PROP BASE Intermediate_Dir "./output/pjturn-client-i386-win32-vc6-release" 
    3737# PROP BASE Target_Dir "" 
    3838# PROP Use_MFC 0 
    3939# PROP Use_Debug_Libraries 0 
    40 # PROP Output_Dir "./output/pjstun-client-i386-win32-vc6-release" 
    41 # PROP Intermediate_Dir "./output/pjstun-client-i386-win32-vc6-release" 
     40# PROP Output_Dir "./output/pjturn-client-i386-win32-vc6-release" 
     41# PROP Intermediate_Dir "./output/pjturn-client-i386-win32-vc6-release" 
    4242# PROP Ignore_Export_Lib 0 
    4343# PROP Target_Dir "" 
     
    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/pjstun-client-i386-win32-vc6-release.exe" 
     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/pjturn-client-i386-win32-vc6-release.exe" 
    5454 
    55 !ELSEIF  "$(CFG)" == "pjstun_client - Win32 Debug" 
     55!ELSEIF  "$(CFG)" == "pjturn_client - Win32 Debug" 
    5656 
    5757# PROP BASE Use_MFC 0 
    5858# PROP BASE Use_Debug_Libraries 1 
    59 # PROP BASE Output_Dir "./output/pjstun-client-i386-win32-vc6-debug" 
    60 # PROP BASE Intermediate_Dir "./output/pjstun-client-i386-win32-vc6-debug" 
     59# PROP BASE Output_Dir "./output/pjturn-client-i386-win32-vc6-debug" 
     60# PROP BASE Intermediate_Dir "./output/pjturn-client-i386-win32-vc6-debug" 
    6161# PROP BASE Target_Dir "" 
    6262# PROP Use_MFC 0 
    6363# PROP Use_Debug_Libraries 1 
    64 # PROP Output_Dir "./output/pjstun-client-i386-win32-vc6-debug" 
    65 # PROP Intermediate_Dir "./output/pjstun-client-i386-win32-vc6-debug" 
     64# PROP Output_Dir "./output/pjturn-client-i386-win32-vc6-debug" 
     65# PROP Intermediate_Dir "./output/pjturn-client-i386-win32-vc6-debug" 
    6666# PROP Ignore_Export_Lib 0 
    6767# PROP Target_Dir "" 
     
    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/pjstun-client-i386-win32-vc6-debug.exe" /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/pjturn-client-i386-win32-vc6-debug.exe" /pdbtype:sept 
    7878 
    7979!ENDIF  
     
    8181# Begin Target 
    8282 
    83 # Name "pjstun_client - Win32 Release" 
    84 # Name "pjstun_client - Win32 Debug" 
     83# Name "pjturn_client - Win32 Release" 
     84# Name "pjturn_client - Win32 Debug" 
    8585# Begin Group "Source Files" 
    8686 
     
    8888# Begin Source File 
    8989 
    90 SOURCE="..\src\pjstun-client\client_main.c" 
     90SOURCE="..\src\pjturn-client\client_main.c" 
    9191# End Source File 
    9292# End Group 
  • pjproject/trunk/pjnath/build/pjturn_client.vcproj

    r1863 r1867  
    33        ProjectType="Visual C++" 
    44        Version="8.00" 
    5         Name="pjstun_client" 
     5        Name="pjturn_client" 
    66        ProjectGUID="{D13A6424-23A4-4990-998D-F80C63704580}" 
    7         RootNamespace="pjstun_client" 
     7        RootNamespace="pjturn_client" 
    88        > 
    99        <Platforms> 
     
    1717                <Configuration 
    1818                        Name="Release|Win32" 
    19                         OutputDirectory="./output/pjstun-client-i386-win32-vc8-release" 
    20                         IntermediateDirectory="./output/pjstun-client-i386-win32-vc8-release" 
     19                        OutputDirectory="./output/pjturn-client-i386-win32-vc8-release" 
     20                        IntermediateDirectory="./output/pjturn-client-i386-win32-vc8-release" 
    2121                        ConfigurationType="1" 
    2222                        InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC60.vsprops" 
     
    3939                        <Tool 
    4040                                Name="VCMIDLTool" 
    41                                 TypeLibraryName="./output/pjstun-client-i386-win32-vc8-release/pjstun_client.tlb" 
     41                                TypeLibraryName="./output/pjturn-client-i386-win32-vc8-release/pjturn_client.tlb" 
    4242                                HeaderFileName="" 
    4343                        /> 
     
    5151                                RuntimeLibrary="2" 
    5252                                EnableFunctionLevelLinking="true" 
    53                                 PrecompiledHeaderFile="./output/pjstun-client-i386-win32-vc8-release/pjstun_client.pch" 
    54                                 AssemblerListingLocation="./output/pjstun-client-i386-win32-vc8-release/" 
    55                                 ObjectFile="./output/pjstun-client-i386-win32-vc8-release/" 
    56                                 ProgramDataBaseFileName="./output/pjstun-client-i386-win32-vc8-release/" 
     53                                PrecompiledHeaderFile="./output/pjturn-client-i386-win32-vc8-release/pjturn_client.pch" 
     54                                AssemblerListingLocation="./output/pjturn-client-i386-win32-vc8-release/" 
     55                                ObjectFile="./output/pjturn-client-i386-win32-vc8-release/" 
     56                                ProgramDataBaseFileName="./output/pjturn-client-i386-win32-vc8-release/" 
    5757                                BrowseInformation="1" 
    5858                                WarningLevel="3" 
     
    7373                                Name="VCLinkerTool" 
    7474                                AdditionalDependencies="netapi32.lib mswsock.lib ws2_32.lib odbc32.lib odbccp32.lib ole32.lib " 
    75                                 OutputFile="../bin/pjstun-client-i386-win32-vc8-release.exe" 
     75                                OutputFile="../bin/pjturn-client-i386-win32-vc8-release.exe" 
    7676                                LinkIncremental="1" 
    7777                                SuppressStartupBanner="true" 
    78                                 ProgramDatabaseFile="./output/pjstun-client-i386-win32-vc8-release/pjstun-client-i386-win32-vc8-release.pdb" 
     78                                ProgramDatabaseFile="./output/pjturn-client-i386-win32-vc8-release/pjturn-client-i386-win32-vc8-release.pdb" 
    7979                                SubSystem="1" 
    8080                                TargetMachine="1" 
     
    9292                                Name="VCBscMakeTool" 
    9393                                SuppressStartupBanner="true" 
    94                                 OutputFile="./output/pjstun-client-i386-win32-vc8-release/pjstun_client.bsc" 
     94                                OutputFile="./output/pjturn-client-i386-win32-vc8-release/pjturn_client.bsc" 
    9595                        /> 
    9696                        <Tool 
     
    109109                <Configuration 
    110110                        Name="Debug|Win32" 
    111                         OutputDirectory="./output/pjstun-client-i386-win32-vc8-debug" 
    112                         IntermediateDirectory="./output/pjstun-client-i386-win32-vc8-debug" 
     111                        OutputDirectory="./output/pjturn-client-i386-win32-vc8-debug" 
     112                        IntermediateDirectory="./output/pjturn-client-i386-win32-vc8-debug" 
    113113                        ConfigurationType="1" 
    114114                        InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC60.vsprops" 
     
    131131                        <Tool 
    132132                                Name="VCMIDLTool" 
    133                                 TypeLibraryName="./output/pjstun-client-i386-win32-vc8-debug/pjstun_client.tlb" 
     133                                TypeLibraryName="./output/pjturn-client-i386-win32-vc8-debug/pjturn_client.tlb" 
    134134                                HeaderFileName="" 
    135135                        /> 
     
    142142                                BasicRuntimeChecks="3" 
    143143                                RuntimeLibrary="1" 
    144                                 PrecompiledHeaderFile="./output/pjstun-client-i386-win32-vc8-debug/pjstun_client.pch" 
    145                                 AssemblerListingLocation="./output/pjstun-client-i386-win32-vc8-debug/" 
    146                                 ObjectFile="./output/pjstun-client-i386-win32-vc8-debug/" 
    147                                 ProgramDataBaseFileName="./output/pjstun-client-i386-win32-vc8-debug/" 
     144                                PrecompiledHeaderFile="./output/pjturn-client-i386-win32-vc8-debug/pjturn_client.pch" 
     145                                AssemblerListingLocation="./output/pjturn-client-i386-win32-vc8-debug/" 
     146                                ObjectFile="./output/pjturn-client-i386-win32-vc8-debug/" 
     147                                ProgramDataBaseFileName="./output/pjturn-client-i386-win32-vc8-debug/" 
    148148                                BrowseInformation="1" 
    149149                                WarningLevel="3" 
     
    165165                                Name="VCLinkerTool" 
    166166                                AdditionalDependencies="netapi32.lib ws2_32.lib odbc32.lib odbccp32.lib ole32.lib " 
    167                                 OutputFile="../bin/pjstun-client-i386-win32-vc8-debug.exe" 
     167                                OutputFile="../bin/pjturn-client-i386-win32-vc8-debug.exe" 
    168168                                LinkIncremental="2" 
    169169                                SuppressStartupBanner="true" 
    170170                                GenerateDebugInformation="true" 
    171                                 ProgramDatabaseFile="./output/pjstun-client-i386-win32-vc8-debug/pjstun-client-i386-win32-vc8-debug.pdb" 
     171                                ProgramDatabaseFile="./output/pjturn-client-i386-win32-vc8-debug/pjturn-client-i386-win32-vc8-debug.pdb" 
    172172                                SubSystem="1" 
    173173                                TargetMachine="1" 
     
    185185                                Name="VCBscMakeTool" 
    186186                                SuppressStartupBanner="true" 
    187                                 OutputFile="./output/pjstun-client-i386-win32-vc8-debug/pjstun_client.bsc" 
     187                                OutputFile="./output/pjturn-client-i386-win32-vc8-debug/pjturn_client.bsc" 
    188188                        /> 
    189189                        <Tool 
     
    209209                        > 
    210210                        <File 
    211                                 RelativePath="..\src\pjstun-client\client_main.c" 
     211                                RelativePath="..\src\pjturn-client\client_main.c" 
    212212                                > 
    213213                                <FileConfiguration 
  • pjproject/trunk/pjnath/include/pjnath.h

    r1854 r1867  
    2929#include <pjnath/stun_transaction.h> 
    3030#include <pjnath/turn_session.h> 
     31#include <pjnath/turn_udp.h> 
    3132#include <pjnath/types.h> 
    3233 
  • pjproject/trunk/pjnath/include/pjnath/turn_session.h

    r1862 r1867  
    193193{ 
    194194    /** 
     195     * Session state. 
     196     */ 
     197    pj_turn_state_t state; 
     198 
     199    /** 
     200     * Type of connection to the TURN server. 
     201     */ 
     202    pj_turn_tp_type tp_type; 
     203 
     204    /** 
    195205     * The relay address 
    196206     */ 
     
    198208 
    199209    /** 
    200      * The TURN server address for informational purpose. 
     210     * The selected TURN server address. 
    201211     */ 
    202212    pj_sockaddr     server; 
     213 
     214    /** 
     215     * Current seconds before allocation expires. 
     216     */ 
     217    int             lifetime; 
    203218 
    204219} pj_turn_session_info; 
     
    231246 
    232247/** 
     248 * Get TURN session info. 
     249 */ 
     250PJ_DECL(pj_status_t) pj_turn_session_get_info(pj_turn_session *sess, 
     251                                              pj_turn_session_info *info); 
     252 
     253/** 
    233254 * Re-assign user data. 
    234255 */ 
  • pjproject/trunk/pjnath/include/pjnath/turn_udp.h

    r1862 r1867  
    9696PJ_DECL(void*) pj_turn_udp_get_user_data(pj_turn_udp *udp_rel); 
    9797 
     98 
     99/** 
     100 * Get info. 
     101 */ 
     102PJ_DECL(pj_status_t) pj_turn_udp_get_info(pj_turn_udp *udp_rel, 
     103                                          pj_turn_session_info *info); 
     104 
    98105/** 
    99106 * Initialize. 
  • pjproject/trunk/pjnath/src/pjnath/turn_session.c

    r1862 r1867  
    9595    pj_bool_t            pending_alloc; 
    9696    pj_turn_alloc_param  alloc_param; 
     97 
     98    pj_sockaddr          relay_addr; 
    9799 
    98100    pj_hash_table_t     *peer_table; 
     
    369371 
    370372/* 
     373 * Get TURN session info. 
     374 */ 
     375PJ_DEF(pj_status_t) pj_turn_session_get_info( pj_turn_session *sess, 
     376                                              pj_turn_session_info *info) 
     377{ 
     378    pj_time_val now; 
     379 
     380    PJ_ASSERT_RETURN(sess && info, PJ_EINVAL); 
     381 
     382    pj_gettimeofday(&now); 
     383 
     384    info->state = sess->state; 
     385    info->tp_type = sess->tp_type; 
     386    info->lifetime = sess->expiry.sec - now.sec; 
     387 
     388    if (sess->srv_addr) 
     389        pj_memcpy(&info->server, sess->srv_addr, sizeof(info->server)); 
     390    else 
     391        pj_bzero(&info->server, sizeof(info->server)); 
     392 
     393    pj_memcpy(&info->relay_addr, &sess->relay_addr, sizeof(sess->relay_addr)); 
     394 
     395    return PJ_SUCCESS; 
     396} 
     397 
     398 
     399/* 
    371400 * Re-assign user data. 
    372401 */ 
     
    9911020    } 
    9921021     
     1022    /* Save relayed address */ 
     1023    pj_memcpy(&sess->relay_addr, &raddr_attr->sockaddr, sizeof(pj_sockaddr)); 
    9931024 
    9941025    /* Success */ 
  • pjproject/trunk/pjnath/src/pjnath/turn_udp.c

    r1862 r1867  
    167167} 
    168168 
     169/** 
     170 * Get info. 
     171 */ 
     172PJ_DEF(pj_status_t) pj_turn_udp_get_info(pj_turn_udp *udp_rel, 
     173                                         pj_turn_session_info *info) 
     174{ 
     175    PJ_ASSERT_RETURN(udp_rel && info, PJ_EINVAL); 
     176 
     177    if (udp_rel->sess) { 
     178        return pj_turn_session_get_info(udp_rel->sess, info); 
     179    } else { 
     180        pj_bzero(info, sizeof(*info)); 
     181        info->state = PJ_TURN_STATE_NULL; 
     182        return PJ_SUCCESS; 
     183    } 
     184} 
     185 
    169186/* 
    170187 * Initialize. 
     
    179196    pj_status_t status; 
    180197 
     198    PJ_ASSERT_RETURN(udp_rel && domain, PJ_EINVAL); 
     199    PJ_ASSERT_RETURN(udp_rel->sess, PJ_EINVALIDOP); 
     200 
    181201    status = pj_turn_session_set_server(udp_rel->sess, domain, default_port, 
    182202                                        resolver); 
     
    184204        return status; 
    185205 
    186     status = pj_turn_session_set_cred(udp_rel->sess, cred); 
    187     if (status != PJ_SUCCESS) 
    188         return status; 
     206    if (cred) { 
     207        status = pj_turn_session_set_cred(udp_rel->sess, cred); 
     208        if (status != PJ_SUCCESS) 
     209            return status; 
     210    } 
    189211 
    190212    status = pj_turn_session_alloc(udp_rel->sess, param); 
     
    204226                                        unsigned addr_len) 
    205227{ 
     228    PJ_ASSERT_RETURN(udp_rel && addr && addr_len, PJ_EINVAL); 
     229 
     230    if (udp_rel->sess == NULL) 
     231        return PJ_EINVALIDOP; 
     232 
    206233    return pj_turn_session_sendto(udp_rel->sess, pkt, pkt_len,  
    207234                                  addr, addr_len); 
     
    215242                                              unsigned addr_len) 
    216243{ 
     244    PJ_ASSERT_RETURN(udp_rel && peer && addr_len, PJ_EINVAL); 
     245    PJ_ASSERT_RETURN(udp_rel->sess != NULL, PJ_EINVALIDOP); 
     246 
    217247    return pj_turn_session_bind_channel(udp_rel->sess, peer, addr_len); 
    218248} 
     
    233263    do { 
    234264        /* Report incoming packet to TURN session */ 
    235         if (bytes_read > 0) { 
     265        if (bytes_read > 0 && udp_rel->sess) { 
    236266            pj_turn_session_on_rx_pkt(udp_rel->sess, udp_rel->pkt,  
    237267                                      bytes_read, PJ_TRUE); 
     
    318348        (*udp_rel->cb.on_state)(udp_rel, old_state, new_state); 
    319349    } 
    320 } 
    321  
    322  
     350 
     351    if (new_state > PJ_TURN_STATE_READY) { 
     352        udp_rel->sess = NULL; 
     353    } 
     354} 
     355 
     356 
  • pjproject/trunk/pjnath/src/pjturn-client/client_main.c

    r1611 r1867  
    3434 
    3535 
     36struct peer 
     37{ 
     38    pj_sock_t   sock; 
     39    pj_sockaddr addr; 
     40}; 
     41 
     42 
    3643static struct global 
    3744{ 
     45    pj_caching_pool      cp; 
     46    pj_pool_t           *pool; 
    3847    pj_stun_config       stun_config; 
    39     pj_pool_t           *pool; 
    40     pj_caching_pool      cp; 
    41     pj_timer_heap_t     *th; 
    42     pj_stun_session     *sess; 
    43     pj_sock_t            sock; 
    44     pj_sock_t            peer_sock; 
    4548    pj_thread_t         *thread; 
    4649    pj_bool_t            quit; 
    47     pj_sockaddr_in       peer_addr; 
    48     pj_sockaddr_in       srv_addr; 
    49     pj_sockaddr_in       relay_addr; 
    50     char                 data_buf[256]; 
    51     char                *data; 
    52     pj_bool_t            detect; 
    53     pj_status_t          detect_result; 
     50 
     51    pj_turn_udp         *udp_rel; 
     52    pj_sockaddr          relay_addr; 
     53 
     54    struct peer          peer[2]; 
    5455} g; 
    5556 
     
    6263    char    *password; 
    6364    char    *nonce; 
    64     char    *peer_addr; 
    6565    pj_bool_t use_fingerprint; 
    6666} o; 
    6767 
    6868 
     69static int worker_thread(void *unused); 
    6970static pj_status_t parse_addr(const char *input, pj_sockaddr_in *addr); 
     71static void turn_on_rx_data(pj_turn_udp *udp_rel, 
     72                            const pj_uint8_t *pkt, 
     73                            unsigned pkt_len, 
     74                            const pj_sockaddr_t *peer_addr, 
     75                            unsigned addr_len); 
     76static void turn_on_state(pj_turn_udp *udp_rel, pj_turn_state_t old_state, 
     77                          pj_turn_state_t new_state); 
    7078 
    7179 
     
    7886} 
    7987 
    80 static pj_status_t on_send_msg(pj_stun_session *sess, 
    81                                const void *pkt, 
    82                                pj_size_t pkt_size, 
    83                                const pj_sockaddr_t *srv_addr, 
    84                                unsigned addr_len) 
    85 { 
    86     pj_ssize_t len; 
     88#define CHECK(expr)     status=expr; \ 
     89                        if (status!=PJ_SUCCESS) { \ 
     90                            my_perror(#expr, status); \ 
     91                            return status; \ 
     92                        } 
     93 
     94static int init() 
     95{ 
     96    int i; 
    8797    pj_status_t status; 
    8898 
    89     len = pkt_size; 
    90     status = pj_sock_sendto(g.sock, pkt, &len, 0, srv_addr, addr_len); 
    91  
    92     if (status != PJ_SUCCESS) 
    93         my_perror("Error sending packet", status); 
    94  
    95     return status; 
    96 } 
    97  
    98 static void on_request_complete(pj_stun_session *sess, 
    99                                 pj_status_t status, 
    100                                 pj_stun_tx_data *tdata, 
    101                                 const pj_stun_msg *response, 
    102                                 const pj_sockaddr_t *src_addr, 
    103                                 unsigned src_addr_len) 
    104 { 
    105     PJ_UNUSED_ARG(src_addr); 
    106     PJ_UNUSED_ARG(src_addr_len); 
    107  
    108     if (status == PJ_SUCCESS) { 
    109         switch (response->hdr.type) { 
    110         case PJ_STUN_ALLOCATE_RESPONSE: 
    111             { 
    112                 pj_stun_relay_addr_attr *ar; 
    113                 pj_stun_lifetime_attr *al; 
    114  
    115                 al = (pj_stun_lifetime_attr*) 
    116                      pj_stun_msg_find_attr(response,  
    117                                            PJ_STUN_ATTR_LIFETIME, 0); 
    118                 if (!al) { 
    119                     PJ_LOG(1,(THIS_FILE, "Error: LIFETIME attribute not present")); 
    120                     return; 
    121                 } 
    122  
    123                 ar = (pj_stun_relay_addr_attr*) 
    124                      pj_stun_msg_find_attr(response,  
    125                                            PJ_STUN_ATTR_RELAY_ADDR, 0); 
    126                 if (ar) { 
    127                     pj_memcpy(&g.relay_addr, &ar->sockaddr.ipv4, 
    128                               sizeof(pj_sockaddr_in)); 
    129                     PJ_LOG(3,(THIS_FILE, "Relay address is %s:%d", 
    130                               pj_inet_ntoa(g.relay_addr.sin_addr), 
    131                               (int)pj_ntohs(g.relay_addr.sin_port))); 
    132                 } else { 
    133                     pj_memset(&g.relay_addr, 0, sizeof(g.relay_addr)); 
    134                 } 
    135  
    136                 if (al->value == 0) { 
    137                     PJ_LOG(3,(THIS_FILE, "Relay deallocated")); 
    138                 } 
     99    CHECK( pj_init() ); 
     100    CHECK( pjlib_util_init() ); 
     101    CHECK( pjnath_init() ); 
     102 
     103    /* Check that server is specified */ 
     104    if (!o.srv_addr) { 
     105        printf("Error: server must be specified\n"); 
     106        return PJ_EINVAL; 
     107    } 
     108 
     109    pj_caching_pool_init(&g.cp, &pj_pool_factory_default_policy, 0); 
     110 
     111    g.pool = pj_pool_create(&g.cp.factory, "main", 1000, 1000, NULL); 
     112 
     113    /* Init global STUN config */ 
     114    pj_stun_config_init(&g.stun_config, &g.cp.factory, 0, NULL, NULL); 
     115 
     116    /* Create global timer heap */ 
     117    CHECK( pj_timer_heap_create(g.pool, 1000, &g.stun_config.timer_heap) ); 
     118 
     119    /* Create global ioqueue */ 
     120    CHECK( pj_ioqueue_create(g.pool, 16, &g.stun_config.ioqueue) ); 
     121 
     122    /*  
     123     * Create peers 
     124     */ 
     125    for (i=0; i<PJ_ARRAY_SIZE(g.peer); ++i) { 
     126        int len; 
     127        pj_sockaddr addr; 
     128        pj_uint16_t port; 
     129 
     130        CHECK( pj_sock_socket(pj_AF_INET(), pj_SOCK_DGRAM(), 0, &g.peer[i].sock) ); 
     131        CHECK( pj_sock_bind_in(g.peer[i].sock, 0, 0) ); 
     132 
     133        len = sizeof(addr); 
     134        CHECK( pj_sock_getsockname(g.peer[i].sock, &addr, &len) ); 
     135        port = pj_sockaddr_get_port(&g.peer[i].addr); 
     136 
     137        CHECK( pj_gethostip(pj_AF_INET(), &g.peer[i].addr) ); 
     138        pj_sockaddr_set_port(&g.peer[0].addr, port); 
     139 
     140    } 
     141 
     142    /* Start the worker thread */ 
     143    CHECK( pj_thread_create(g.pool, "stun", &worker_thread, NULL, 0, 0, &g.thread) ); 
     144 
     145 
     146    return PJ_SUCCESS; 
     147} 
     148 
     149 
     150static int shutdown() 
     151{ 
     152    unsigned i; 
     153 
     154    if (g.thread) { 
     155        g.quit = 1; 
     156        pj_thread_join(g.thread); 
     157        pj_thread_destroy(g.thread); 
     158        g.thread = NULL; 
     159    } 
     160    if (g.udp_rel) { 
     161        pj_turn_udp_destroy(g.udp_rel); 
     162        g.udp_rel = NULL; 
     163    } 
     164    for (i=0; i<PJ_ARRAY_SIZE(g.peer); ++i) { 
     165        if (g.peer[i].sock) { 
     166            pj_sock_close(g.peer[i].sock); 
     167            g.peer[i].sock = 0; 
     168        } 
     169    } 
     170    if (g.stun_config.timer_heap) { 
     171        pj_timer_heap_destroy(g.stun_config.timer_heap); 
     172        g.stun_config.timer_heap = NULL; 
     173    } 
     174    if (g.stun_config.ioqueue) { 
     175        pj_ioqueue_destroy(g.stun_config.ioqueue); 
     176        g.stun_config.ioqueue = NULL; 
     177    } 
     178    if (g.pool) { 
     179        pj_pool_release(g.pool); 
     180        g.pool = NULL; 
     181    } 
     182    pj_pool_factory_dump(&g.cp.factory, PJ_TRUE); 
     183    pj_caching_pool_destroy(&g.cp); 
     184 
     185    return PJ_SUCCESS; 
     186} 
     187 
     188 
     189static int worker_thread(void *unused) 
     190{ 
     191    PJ_UNUSED_ARG(unused); 
     192 
     193    while (!g.quit) { 
     194        const pj_time_val delay = {0, 10}; 
     195        int i; 
     196        pj_fd_set_t readset; 
     197 
     198        /* Poll ioqueue for the TURN client */ 
     199        pj_ioqueue_poll(g.stun_config.ioqueue, &delay); 
     200 
     201        /* Poll the timer heap */ 
     202        pj_timer_heap_poll(g.stun_config.timer_heap, NULL); 
     203 
     204        /* Poll peer sockets */ 
     205        PJ_FD_ZERO(&readset); 
     206        for (i=0; i<PJ_ARRAY_SIZE(g.peer); ++i) { 
     207            PJ_FD_SET(g.peer[i].sock, &readset); 
     208        } 
     209 
     210        if (pj_sock_select(64, &readset, NULL, NULL, &delay) <= 0) 
     211            continue; 
     212 
     213        /* Handle incoming data on peer socket */ 
     214        for (i=0; i<PJ_ARRAY_SIZE(g.peer); ++i) { 
     215            char buf[128]; 
     216            pj_ssize_t len; 
     217            pj_sockaddr src_addr; 
     218            int src_addr_len; 
     219            pj_status_t status; 
     220 
     221            if (!PJ_FD_ISSET(g.peer[i].sock, &readset)) 
     222                continue; 
     223 
     224            len = sizeof(buf); 
     225            src_addr_len = sizeof(src_addr); 
     226 
     227            status = pj_sock_recvfrom(g.peer[i].sock, buf, &len, 0,  
     228                                      &src_addr, &src_addr_len); 
     229            if (status != PJ_SUCCESS) { 
     230                my_perror("recvfrom error", status); 
     231            } else { 
     232                char addrinfo[80]; 
     233                pj_sockaddr_print(&src_addr, addrinfo, sizeof(addrinfo), 3); 
     234                PJ_LOG(3,(THIS_FILE, "Peer%d received %d bytes from %s: %.*s", 
     235                          i, len, addrinfo, len, buf)); 
    139236            } 
    140             break; 
    141237        } 
    142     } else { 
    143         my_perror("Client transaction error", status); 
    144     } 
    145 } 
    146  
    147 static int worker_thread(void *unused) 
    148 { 
    149     PJ_UNUSED_ARG(unused); 
    150  
    151     while (!g.quit) { 
    152         pj_time_val timeout =  {0, 50}; 
    153         pj_fd_set_t readset; 
    154         int n; 
    155  
    156         pj_timer_heap_poll(g.th, NULL); 
    157         pj_ioqueue_poll(g.stun_config.ioqueue, &timeout); 
    158  
    159         PJ_FD_ZERO(&readset); 
    160         PJ_FD_SET(g.sock, &readset); 
    161         PJ_FD_SET(g.peer_sock, &readset); 
    162  
    163         n = (g.peer_sock > g.sock) ? g.peer_sock : g.sock; 
    164         n = pj_sock_select(n+1, &readset, NULL, NULL, &timeout); 
    165         if (n > 0) { 
    166             if (PJ_FD_ISSET(g.sock, &readset)) { 
    167                 pj_uint8_t buffer[512]; 
    168                 pj_ssize_t len; 
    169                 pj_sockaddr_in addr; 
    170                 int addrlen; 
    171                 pj_status_t rc; 
    172  
    173                 len = sizeof(buffer); 
    174                 addrlen = sizeof(addr); 
    175                 rc = pj_sock_recvfrom(g.sock, buffer, &len, 0, &addr, &addrlen); 
    176                 if (rc != PJ_SUCCESS || len <= 0) 
    177                     continue; 
    178  
    179                 if (pj_stun_msg_check(buffer, len, PJ_STUN_IS_DATAGRAM)==PJ_SUCCESS) { 
    180                     rc = pj_stun_session_on_rx_pkt(g.sess, buffer, len,  
    181                                                    OPTIONS,  
    182                                                    NULL, &addr, addrlen); 
    183                     if (rc != PJ_SUCCESS) 
    184                         my_perror("Error processing packet", rc); 
    185  
    186                 } else { 
    187                     buffer[len] = '\0'; 
    188                     PJ_LOG(3,(THIS_FILE, "Received data on client sock: %s", (char*)buffer)); 
    189                 } 
    190  
    191             } else if (PJ_FD_ISSET(g.peer_sock, &readset)) { 
    192                 pj_uint8_t buffer[512]; 
    193                 pj_ssize_t len; 
    194                 pj_sockaddr_in addr; 
    195                 int addrlen; 
    196                 pj_status_t rc; 
    197  
    198                 len = sizeof(buffer); 
    199                 addrlen = sizeof(addr); 
    200                 rc = pj_sock_recvfrom(g.peer_sock, buffer, &len, 0, &addr, &addrlen); 
    201                 if (rc != PJ_SUCCESS || len <= 0) 
    202                     continue; 
    203  
    204                 buffer[len] = '\0'; 
    205  
    206                 if (pj_stun_msg_check(buffer, len, PJ_STUN_IS_DATAGRAM)==PJ_SUCCESS) { 
    207                     pj_stun_msg *msg; 
    208  
    209                     rc = pj_stun_msg_decode(g.pool, (pj_uint8_t*)buffer, len, 0, 
    210                                             &msg, NULL, NULL); 
    211                     if (rc != PJ_SUCCESS) { 
    212                         my_perror("Error decoding packet on peer sock", rc); 
    213                     } else { 
    214                         pj_stun_msg_dump(msg, (char*)buffer, sizeof(buffer), NULL); 
    215                         PJ_LOG(3,(THIS_FILE, "Received STUN packet on peer sock: %s", 
    216                                   buffer)); 
    217                     } 
    218  
    219                 } else { 
    220                     PJ_LOG(3,(THIS_FILE, "Received data on peer sock: %s", (char*)buffer)); 
    221                 } 
    222  
    223             } 
    224  
    225         } else if (n < 0) 
    226             pj_thread_sleep(50); 
    227238    } 
    228239 
     
    230241} 
    231242 
    232 static int init() 
    233 { 
    234     pj_sockaddr addr; 
    235     pj_stun_session_cb stun_cb; 
    236     int len; 
     243static pj_status_t create_relay(void) 
     244{ 
     245    pj_turn_udp_cb rel_cb; 
     246    pj_stun_auth_cred cred; 
     247    pj_str_t srv; 
    237248    pj_status_t status; 
    238249 
    239     g.sock = PJ_INVALID_SOCKET; 
    240  
    241     status = pj_init(); 
    242     status = pjlib_util_init(); 
    243     status = pjnath_init(); 
    244  
    245     pj_caching_pool_init(&g.cp, &pj_pool_factory_default_policy, 0); 
    246  
    247     if (o.srv_addr) { 
    248         pj_str_t s; 
    249         pj_uint16_t port; 
    250  
    251         if (o.srv_port) 
    252             port = (pj_uint16_t) atoi(o.srv_port); 
    253         else 
    254             port = PJ_STUN_PORT; 
    255  
    256         status = pj_sockaddr_in_init(&g.srv_addr, pj_cstr(&s, o.srv_addr), port); 
    257         if (status != PJ_SUCCESS) { 
    258             my_perror("Invalid address", status); 
    259             return status; 
    260         } 
    261  
    262         printf("Destination address set to %s:%d\n", o.srv_addr, (int)port); 
    263     } else { 
    264         printf("Error: address must be specified\n"); 
    265         return PJ_EINVAL; 
    266     } 
    267  
    268     g.pool = pj_pool_create(&g.cp.factory, NULL, 1000, 1000, NULL); 
    269  
    270     status = pj_timer_heap_create(g.pool, 1000, &g.th); 
    271     pj_assert(status == PJ_SUCCESS); 
    272  
    273     pj_stun_config_init(&g.stun_config, &g.cp.factory, 0, NULL, g.th); 
    274     pj_assert(status == PJ_SUCCESS); 
    275  
    276     status = pj_sock_socket(pj_AF_INET(), pj_SOCK_DGRAM(), 0, &g.peer_sock); 
    277     pj_assert(status == PJ_SUCCESS); 
    278  
    279     status = pj_sock_bind_in(g.peer_sock, 0, 0); 
    280     pj_assert(status == PJ_SUCCESS); 
    281  
    282     status = pj_sock_socket(pj_AF_INET(), pj_SOCK_DGRAM(), 0, &g.sock); 
    283     pj_assert(status == PJ_SUCCESS); 
    284  
    285     status = pj_sockaddr_in_init(&addr.ipv4, NULL, 0); 
    286     pj_assert(status == PJ_SUCCESS); 
    287  
    288     addr.ipv4.sin_port = pj_htons((pj_uint16_t)LOCAL_PORT); 
    289     status = pj_sock_bind(g.sock, &addr, sizeof(addr)); 
    290     pj_assert(status == PJ_SUCCESS); 
    291  
    292     len = sizeof(addr); 
    293     status = pj_sock_getsockname(g.sock, &addr, &len); 
    294     pj_assert(status == PJ_SUCCESS); 
    295  
    296     PJ_LOG(3,(THIS_FILE, "Listening on port %d", (int)pj_ntohs(addr.ipv4.sin_port))); 
    297  
    298     len = sizeof(g.peer_addr); 
    299     status = pj_sock_getsockname(g.peer_sock, &g.peer_addr, &len); 
    300     if (g.peer_addr.sin_addr.s_addr == 0) 
    301         pj_gethostip(pj_AF_INET(), (pj_sockaddr*)&g.peer_addr.sin_addr); 
    302  
    303     PJ_LOG(3,(THIS_FILE, "Peer is on port %d", (int)pj_ntohs(g.peer_addr.sin_port))); 
    304  
    305     pj_memset(&stun_cb, 0, sizeof(stun_cb)); 
    306     stun_cb.on_send_msg = &on_send_msg; 
    307     stun_cb.on_request_complete = &on_request_complete; 
    308  
    309     status = pj_stun_session_create(&g.stun_config, NULL, &stun_cb,  
    310                                     o.use_fingerprint!=0, &g.sess); 
    311     pj_assert(status == PJ_SUCCESS); 
     250    if (g.udp_rel) { 
     251        PJ_LOG(1,(THIS_FILE, "Relay already created")); 
     252        return -1; 
     253    } 
     254 
     255    pj_bzero(&rel_cb, sizeof(rel_cb)); 
     256    rel_cb.on_rx_data = &turn_on_rx_data; 
     257    rel_cb.on_state = &turn_on_state; 
     258    CHECK( pj_turn_udp_create(&g.stun_config, pj_AF_INET(), &rel_cb, 0, 
     259                              NULL, &g.udp_rel) ); 
    312260 
    313261    if (o.user_name) { 
    314         pj_stun_auth_cred cred; 
    315  
    316262        pj_bzero(&cred, sizeof(cred)); 
    317  
    318263        cred.type = PJ_STUN_AUTH_CRED_STATIC; 
    319264        cred.data.static_cred.realm = pj_str(o.realm); 
     
    322267        cred.data.static_cred.data = pj_str(o.password); 
    323268        cred.data.static_cred.nonce = pj_str(o.nonce); 
    324  
    325         pj_stun_session_set_credential(g.sess, &cred); 
    326         puts("Session credential set"); 
    327269    } else { 
    328         puts("Credential not set"); 
    329     } 
    330  
    331     if (o.peer_addr) { 
    332         if (parse_addr(o.peer_addr, &g.peer_addr)!=PJ_SUCCESS) 
    333             return -1; 
    334     } 
    335  
    336     status = pj_ioqueue_create(g.pool, 16, &g.stun_config.ioqueue); 
    337     if (status != PJ_SUCCESS) 
    338         return status; 
    339  
    340     status = pj_thread_create(g.pool, "stun", &worker_thread, NULL,  
    341                               0, 0, &g.thread); 
    342     if (status != PJ_SUCCESS) 
    343         return status; 
     270        PJ_LOG(2,(THIS_FILE, "Warning: no credential is set")); 
     271    } 
     272 
     273    srv = pj_str(o.srv_addr); 
     274    CHECK( pj_turn_udp_init(g.udp_rel,                           /* the relay */ 
     275                            &srv,                                /* srv addr */ 
     276                            (o.srv_port?atoi(o.srv_port):PJ_STUN_PORT),/* def port */ 
     277                            NULL,                                /* resolver */ 
     278                            (o.user_name?&cred:NULL),            /* credential */ 
     279                            NULL)                                /* alloc param */ 
     280                            ); 
    344281 
    345282    return PJ_SUCCESS; 
    346283} 
    347284 
    348  
    349 static int shutdown() 
    350 { 
    351     if (g.thread) { 
    352         g.quit = 1; 
    353         pj_thread_join(g.thread); 
    354         pj_thread_destroy(g.thread); 
    355         g.thread = NULL; 
    356     } 
    357     if (g.sess) 
    358         pj_stun_session_destroy(g.sess); 
    359     if (g.sock != PJ_INVALID_SOCKET) 
    360         pj_sock_close(g.sock); 
    361     if (g.th) 
    362         pj_timer_heap_destroy(g.th); 
    363     if (g.pool) 
    364         pj_pool_release(g.pool); 
    365  
    366     pj_pool_factory_dump(&g.cp.factory, PJ_TRUE); 
    367     pj_caching_pool_destroy(&g.cp); 
    368  
    369     return PJ_SUCCESS; 
    370 } 
    371  
    372 static void send_bind_request(void) 
    373 { 
    374     pj_stun_tx_data *tdata; 
    375     pj_status_t rc; 
    376  
    377     rc = pj_stun_session_create_req(g.sess, PJ_STUN_BINDING_REQUEST,  
    378                                     PJ_STUN_MAGIC, NULL, &tdata); 
    379     pj_assert(rc == PJ_SUCCESS); 
    380  
    381     rc = pj_stun_session_send_msg(g.sess, PJ_FALSE,  
    382                                   &g.srv_addr, sizeof(g.srv_addr), 
    383                                   tdata); 
    384     if (rc != PJ_SUCCESS) 
    385         my_perror("Error sending STUN request", rc); 
    386 } 
    387  
    388 static void send_allocate_request(pj_bool_t allocate) 
    389 { 
    390     pj_stun_tx_data *tdata; 
    391     pj_status_t rc; 
    392  
    393     rc = pj_stun_session_create_req(g.sess, PJ_STUN_ALLOCATE_REQUEST,  
    394                                     PJ_STUN_MAGIC, NULL, &tdata); 
    395     pj_assert(rc == PJ_SUCCESS); 
    396  
    397  
    398     if (BANDWIDTH != -1) { 
    399         pj_stun_msg_add_uint_attr(tdata->pool, tdata->msg,  
    400                                   PJ_STUN_ATTR_BANDWIDTH, BANDWIDTH); 
    401     } 
    402  
    403     if (!allocate) { 
    404         pj_stun_msg_add_uint_attr(tdata->pool, tdata->msg,  
    405                                   PJ_STUN_ATTR_LIFETIME, 0); 
    406  
    407     } else { 
    408         if (LIFETIME != -1) { 
    409             pj_stun_msg_add_uint_attr(tdata->pool, tdata->msg,  
    410                                       PJ_STUN_ATTR_LIFETIME, LIFETIME); 
    411         } 
    412  
    413         if (REQ_TRANSPORT != -1) { 
    414             pj_stun_msg_add_uint_attr(tdata->pool, tdata->msg,  
    415                                       PJ_STUN_ATTR_REQ_TRANSPORT, REQ_TRANSPORT); 
    416         } 
    417  
    418         if (REQ_PORT_PROPS != -1) { 
    419             pj_stun_msg_add_uint_attr(tdata->pool, tdata->msg,  
    420                                       PJ_STUN_ATTR_REQ_PORT_PROPS, REQ_PORT_PROPS); 
    421         } 
    422  
    423         if (REQ_IP) { 
    424             pj_sockaddr_in addr; 
    425             pj_str_t tmp; 
    426  
    427             pj_sockaddr_in_init(&addr, pj_cstr(&tmp, REQ_IP), 0); 
    428             pj_stun_msg_add_sockaddr_attr(tdata->pool, tdata->msg, 
    429                                          PJ_STUN_ATTR_REQ_IP, PJ_FALSE, 
    430                                          &addr, sizeof(addr)); 
    431         } 
    432     } 
    433  
    434     rc = pj_stun_session_send_msg(g.sess, PJ_FALSE,  
    435                                   &g.srv_addr, sizeof(g.srv_addr), 
    436                                   tdata); 
    437     pj_assert(rc == PJ_SUCCESS); 
    438 } 
    439  
    440 static void send_sad_request(pj_bool_t set) 
    441 { 
    442     pj_stun_tx_data *tdata; 
    443     pj_status_t rc; 
    444  
    445     if (g.peer_addr.sin_addr.s_addr == 0 || 
    446         g.peer_addr.sin_port == 0) 
    447     { 
    448         puts("Error: peer address is not set"); 
    449         return; 
    450     } 
    451  
    452     rc = pj_stun_session_create_req(g.sess,  
    453                                     PJ_STUN_SET_ACTIVE_DESTINATION_REQUEST,  
    454                                     PJ_STUN_MAGIC, NULL, &tdata); 
    455     pj_assert(rc == PJ_SUCCESS); 
    456  
    457     if (set) { 
    458         pj_stun_msg_add_sockaddr_attr(tdata->pool, tdata->msg, 
    459                                      PJ_STUN_ATTR_REMOTE_ADDR, PJ_FALSE, 
    460                                      &g.peer_addr, sizeof(g.peer_addr)); 
    461     } 
    462  
    463     rc = pj_stun_session_send_msg(g.sess, PJ_FALSE,  
    464                                   &g.srv_addr, sizeof(g.srv_addr), 
    465                                   tdata); 
    466     pj_assert(rc == PJ_SUCCESS); 
    467 } 
    468  
    469 static void send_send_ind(void) 
    470 { 
    471     pj_stun_tx_data *tdata; 
    472     int len; 
    473     pj_status_t rc; 
    474  
    475     if (g.peer_addr.sin_addr.s_addr == 0 || 
    476         g.peer_addr.sin_port == 0) 
    477     { 
    478         puts("Error: peer address is not set"); 
    479         return; 
    480     } 
    481  
    482     len = strlen(g.data); 
    483     if (len==0) { 
    484         puts("Error: data is not set"); 
    485         return; 
    486     } 
    487  
    488     rc = pj_stun_session_create_ind(g.sess, PJ_STUN_SEND_INDICATION, &tdata); 
    489     pj_assert(rc == PJ_SUCCESS); 
    490  
    491     pj_stun_msg_add_sockaddr_attr(tdata->pool, tdata->msg, 
    492                                   PJ_STUN_ATTR_REMOTE_ADDR, PJ_FALSE, 
    493                                   &g.peer_addr, sizeof(g.peer_addr)); 
    494     pj_stun_msg_add_binary_attr(tdata->pool, tdata->msg, 
    495                                 PJ_STUN_ATTR_DATA, (pj_uint8_t*)g.data, len); 
    496  
    497     rc = pj_stun_session_send_msg(g.sess, PJ_FALSE,  
    498                                   &g.srv_addr, sizeof(g.srv_addr), 
    499                                   tdata); 
    500     pj_assert(rc == PJ_SUCCESS); 
    501  
    502 } 
    503  
    504 static void send_raw_data_to_srv(void) 
    505 { 
    506     pj_ssize_t len; 
    507  
    508     if (g.srv_addr.sin_addr.s_addr == 0 || 
    509         g.srv_addr.sin_port == 0) 
    510     { 
    511         puts("Error: server address is not set"); 
    512         return; 
    513     } 
    514  
    515     len = strlen(g.data); 
    516     if (len==0) { 
    517         puts("Error: data is not set"); 
    518         return; 
    519     } 
    520  
    521     len = strlen(g.data); 
    522     pj_sock_sendto(g.sock, g.data, &len, 0, &g.srv_addr, sizeof(g.srv_addr)); 
    523 } 
    524  
    525 static void send_raw_data_to_relay(void) 
    526 { 
    527     pj_ssize_t len; 
    528  
    529     if (g.relay_addr.sin_addr.s_addr == 0 || 
    530         g.relay_addr.sin_port == 0) 
    531     { 
    532         puts("Error: relay address is not set"); 
    533         return; 
    534     } 
    535  
    536     len = strlen(g.data); 
    537     if (len==0) { 
    538         puts("Error: data is not set"); 
    539         return; 
    540     } 
    541  
    542     len = strlen(g.data); 
    543     pj_sock_sendto(g.peer_sock, g.data, &len, 0, &g.relay_addr, sizeof(g.relay_addr)); 
     285static void destroy_relay(void) 
     286{ 
     287    if (g.udp_rel) { 
     288        pj_turn_udp_destroy(g.udp_rel); 
     289        g.udp_rel = NULL; 
     290    } 
     291} 
     292 
     293 
     294static void turn_on_rx_data(pj_turn_udp *udp_rel, 
     295                            const pj_uint8_t *pkt, 
     296                            unsigned pkt_len, 
     297                            const pj_sockaddr_t *peer_addr, 
     298                            unsigned addr_len) 
     299{ 
     300    char addrinfo[80]; 
     301 
     302    pj_sockaddr_print(peer_addr, addrinfo, sizeof(addrinfo), 3); 
     303 
     304    PJ_LOG(3,(THIS_FILE, "Client received %d bytes data from %s: %.*s", 
     305              pkt_len, addrinfo, pkt_len, pkt)); 
     306} 
     307 
     308 
     309static void turn_on_state(pj_turn_udp *udp_rel, pj_turn_state_t old_state, 
     310                          pj_turn_state_t new_state) 
     311{ 
     312    if (new_state == PJ_TURN_STATE_READY) { 
     313        pj_turn_session_info info; 
     314        pj_turn_udp_get_info(udp_rel, &info); 
     315        pj_memcpy(&g.relay_addr, &info.relay_addr, sizeof(pj_sockaddr)); 
     316    } 
    544317} 
    545318 
     
    577350} 
    578351 
    579 static void set_peer_addr(void) 
    580 { 
    581     char addr[64]; 
    582  
    583     printf("Current peer address: %s:%d\n",  
    584            pj_inet_ntoa(g.peer_addr.sin_addr),  
    585            pj_ntohs(g.peer_addr.sin_port)); 
    586  
    587     printf("Input peer address in IP:PORT format: "); 
     352static void menu(void) 
     353{ 
     354    pj_turn_session_info info; 
     355    char client_state[20], relay_addr[80], peer0_addr[80], peer1_addr[80]; 
     356 
     357    if (g.udp_rel) { 
     358        pj_turn_udp_get_info(g.udp_rel, &info); 
     359        strcpy(client_state, pj_turn_state_name(info.state)); 
     360        pj_sockaddr_print(&info.relay_addr, relay_addr, sizeof(relay_addr), 3); 
     361    } else { 
     362        strcpy(client_state, "NULL"); 
     363        strcpy(relay_addr, "0.0.0.0:0"); 
     364    } 
     365 
     366    pj_sockaddr_print(&g.peer[0].addr, peer0_addr, sizeof(peer0_addr), 3); 
     367    pj_sockaddr_print(&g.peer[1].addr, peer1_addr, sizeof(peer1_addr), 3); 
     368 
     369 
     370    puts("\n"); 
     371    puts("+====================================================================+"); 
     372    puts("|             CLIENT                |             PEER-0             |"); 
     373    puts("|                                   |                                |"); 
     374    printf("| State     : %12s          | Address: %21s |\n", 
     375           client_state, peer0_addr); 
     376    printf("| Relay addr: %21s |                                |\n", 
     377           relay_addr); 
     378    puts("|                                   | 0  Send data to relay address  |"); 
     379    puts("| A      Allocate relay             +--------------------------------+        "); 
     380    puts("| S[01]  Send data to peer 0/1      |             PEER-1             |"); 
     381    puts("| B[01]  BindChannel to peer 0/1    |                                |"); 
     382    printf("| X      Delete allocation          | Address: %21s |\n", 
     383          peer1_addr); 
     384    puts("+-----------------------------------+                                |"); 
     385    puts("| q  Quit                           | 1  Send data to relay adderss  |"); 
     386    puts("+-----------------------------------+--------------------------------+"); 
     387    printf(">>> "); 
    588388    fflush(stdout); 
    589     fgets(addr, sizeof(addr), stdin); 
    590  
    591     if (parse_addr(addr, &g.peer_addr) != PJ_SUCCESS) { 
    592         return; 
    593     } 
    594  
    595 } 
    596  
    597  
    598 static void nat_detect_cb(void *user_data, 
    599                           const pj_stun_nat_detect_result *res) 
    600 { 
    601     g.detect_result = res->status; 
    602  
    603     if (res->status == PJ_SUCCESS) { 
    604         PJ_LOG(3,(THIS_FILE, "NAT successfully detected as %s", res->nat_type_name)); 
    605     } else { 
    606         PJ_LOG(2,(THIS_FILE, "Error detecting NAT type: %s", res->status_text)); 
    607     } 
    608 } 
    609  
    610 static pj_status_t perform_detection() 
    611 { 
    612     pj_status_t status; 
    613  
    614     g.detect_result = PJ_EPENDING; 
    615     status = pj_stun_detect_nat_type(&g.srv_addr, &g.stun_config, NULL,  
    616                                      &nat_detect_cb); 
    617     if (status != PJ_SUCCESS) 
    618         return status; 
    619  
    620     while (g.detect_result == PJ_EPENDING) 
    621         pj_thread_sleep(100); 
    622  
    623     status = g.detect_result; 
    624  
    625     return status; 
    626 } 
    627  
    628  
    629 static void menu(void) 
    630 { 
    631     puts("Menu:"); 
    632     puts("  d       Perform NAT detection"); 
    633     printf("  pr      Set peer address (currently %s:%d)\n", 
    634            pj_inet_ntoa(g.peer_addr.sin_addr), pj_ntohs(g.peer_addr.sin_port)); 
    635     printf("  dt      Set data (currently \"%s\")\n", g.data); 
    636     puts("  br      Send Bind request"); 
    637     puts("  ar      Send Allocate request"); 
    638     puts("  dr      Send de-Allocate request"); 
    639     puts("  sr      Send Set Active Destination request"); 
    640     puts("  cr      Send clear Active Destination request"); 
    641     puts("  si      Send data with Send Indication"); 
    642     puts("  rw      Send raw data to TURN server"); 
    643     puts("  rW      Send raw data to relay address"); 
    644     puts("  q       Quit"); 
    645     puts(""); 
    646     printf("Choice: "); 
    647389} 
    648390 
     
    651393{ 
    652394    while (!g.quit) { 
    653         char input[10]; 
     395        char input[32]; 
     396        struct peer *peer; 
     397        pj_ssize_t len; 
     398        pj_status_t status; 
    654399 
    655400        menu(); 
     
    657402        fgets(input, sizeof(input), stdin); 
    658403         
    659         if (input[0] == 'd' && (input[1]=='\r' || input[1]=='\n')) { 
    660  
    661             perform_detection(); 
    662  
    663         } else if (input[0]=='d' && input[1]=='t') { 
    664             printf("Input data: "); 
    665             fgets(g.data, sizeof(g.data_buf), stdin); 
    666              
    667         } else if (input[0]=='p' && input[1]=='r') { 
    668             set_peer_addr(); 
    669              
    670         } else if (input[0]=='b' && input[1]=='r') { 
    671             send_bind_request(); 
    672              
    673         } else if (input[0]=='a' && input[1]=='r') { 
    674             send_allocate_request(PJ_TRUE); 
    675              
    676         } else if (input[0]=='d' && input[1]=='r') { 
    677             send_allocate_request(PJ_FALSE); 
    678              
    679         } else if (input[0]=='s' && input[1]=='r') { 
    680             send_sad_request(PJ_TRUE); 
    681              
    682         } else if (input[0]=='c' && input[1]=='r') { 
    683             send_sad_request(PJ_FALSE); 
    684              
    685         } else if (input[0]=='s' && input[1]=='i') { 
    686             send_send_ind(); 
    687              
    688         } else if (input[0]=='r' && input[1]=='w') { 
    689             send_raw_data_to_srv(); 
    690              
    691         } else if (input[0]=='r' && input[1]=='W') { 
    692             send_raw_data_to_relay(); 
    693              
    694         } else if (input[0]=='q') { 
    695             g.quit = 1; 
     404        switch (input[0]) { 
     405        case 'A': 
     406            create_relay(); 
     407            break; 
     408        case 'S': 
     409            if (g.udp_rel == NULL) { 
     410                puts("Error: no relay"); 
     411                continue; 
     412            } 
     413            if (input[1] != '0' && input[1] != '1') { 
     414                puts("Usage: S0 or S1"); 
     415                continue; 
     416            } 
     417            peer = &g.peer[input[1]-'0']; 
     418            strcpy(input, "Hello from client"); 
     419            status = pj_turn_udp_sendto(g.udp_rel, input, strlen(input)+1,  
     420                                        &peer->addr,  
     421                                        pj_sockaddr_get_len(&peer->addr)); 
     422            if (status != PJ_SUCCESS) 
     423                my_perror("turn_udp_sendto() failed", status); 
     424            break; 
     425        case 'B': 
     426            if (g.udp_rel == NULL) { 
     427                puts("Error: no relay"); 
     428                continue; 
     429            } 
     430            if (input[1] != '0' && input[1] != '1') { 
     431                puts("Usage: B0 or B1"); 
     432                continue; 
     433            } 
     434            peer = &g.peer[input[1]-'0']; 
     435            status = pj_turn_udp_bind_channel(g.udp_rel, &peer->addr, 
     436                                              pj_sockaddr_get_len(&peer->addr)); 
     437            if (status != PJ_SUCCESS) 
     438                my_perror("turn_udp_bind_channel() failed", status); 
     439            break; 
     440        case 'X': 
     441            if (g.udp_rel == NULL) { 
     442                puts("Error: no relay"); 
     443                continue; 
     444            } 
     445            destroy_relay(); 
     446            break; 
     447        case '0': 
     448        case '1': 
     449            peer = &g.peer[input[1]-'0']; 
     450            sprintf(input, "Hello from peer%d", input[0]-'0'); 
     451            len = strlen(input)+1; 
     452            pj_sock_sendto(peer->sock, input, &len, 0, &g.relay_addr,  
     453                           pj_sockaddr_get_len(&g.relay_addr)); 
     454            break; 
     455        case 'q': 
     456            g.quit = PJ_TRUE; 
     457            break; 
    696458        } 
    697459    } 
     
    701463static void usage(void) 
    702464{ 
    703     puts("Usage: pjstun_client TARGET [OPTIONS]"); 
     465    puts("Usage: pjturn_client TARGET [OPTIONS]"); 
    704466    puts(""); 
    705467    puts("where TARGET is \"host[:port]\""); 
    706468    puts(""); 
    707469    puts("and OPTIONS:"); 
    708     puts(" --detect, -d      Perform NAT type detection first"); 
    709470    puts(" --realm, -r       Set realm of the credential"); 
    710471    puts(" --username, -u    Set username of the credential"); 
     
    712473    puts(" --nonce, -N       Set NONCE");    
    713474    puts(" --fingerprint, -F Use fingerprint for outgoing requests"); 
    714     puts(" --peer, -P        Set peer address (address is in HOST:PORT format)"); 
    715     puts(" --data, -D        Set data"); 
    716475    puts(" --help, -h"); 
    717476} 
     
    720479{ 
    721480    struct pj_getopt_option long_options[] = { 
    722         { "detect",     0, 0, 'd'}, 
    723481        { "realm",      1, 0, 'r'}, 
    724482        { "username",   1, 0, 'u'}, 
     
    726484        { "nonce",      1, 0, 'N'}, 
    727485        { "fingerprint",0, 0, 'F'}, 
    728         { "peer",       1, 0, 'P'}, 
    729486        { "data",       1, 0, 'D'}, 
    730487        { "help",       0, 0, 'h'} 
     
    734491    pj_status_t status; 
    735492 
    736     g.data = g.data_buf; 
    737     pj_ansi_strcpy(g.data, "Hello world"); 
    738  
    739     while((c=pj_getopt_long(argc,argv, "r:u:p:N:dhF", long_options, &opt_id))!=-1) { 
     493    while((c=pj_getopt_long(argc,argv, "r:u:p:N:hF", long_options, &opt_id))!=-1) { 
    740494        switch (c) { 
    741         case 'd': 
    742             g.detect = PJ_TRUE; 
    743             break; 
    744495        case 'r': 
    745496            o.realm = pj_optarg; 
     
    759510        case 'F': 
    760511            o.use_fingerprint = PJ_TRUE; 
    761             break; 
    762         case 'P': 
    763             o.peer_addr = pj_optarg; 
    764             break; 
    765         case 'D': 
    766             g.data = pj_optarg; 
    767512            break; 
    768513 
     
    787532    } 
    788533 
    789     status = init(); 
    790     if (status != PJ_SUCCESS) 
     534    if ((status=init()) != 0) 
    791535        goto on_return; 
    792536     
    793     if (g.detect) { 
    794         status = perform_detection(); 
    795         if (status != PJ_SUCCESS) 
    796             goto on_return; 
    797     } 
    798  
     537    if ((status=create_relay()) != 0) 
     538        goto on_return; 
     539     
    799540    console_main(); 
    800541 
Note: See TracChangeset for help on using the changeset viewer.