Changeset 1867
- Timestamp:
- Mar 13, 2008 3:11:29 PM (17 years ago)
- Location:
- pjproject/trunk
- Files:
-
- 10 edited
- 3 moved
Legend:
- Unmodified
- Added
- Removed
-
pjproject/trunk/pjlib-util/build/pjlib_util.vcproj
r1765 r1867 4 4 Version="8.00" 5 5 Name="pjlib_util" 6 ProjectGUID="{ FE07F272-AE7F-4549-9E9F-EF9B80CB1693}"6 ProjectGUID="{E79CE31A-3681-4F0C-8BE1-C43C0702EFFB}" 7 7 RootNamespace="pjlib_util" 8 8 > -
pjproject/trunk/pjlib/build/pjlib.vcproj
r1405 r1867 4 4 Version="8.00" 5 5 Name="pjlib" 6 ProjectGUID="{D A0E03ED-53A7-4050-8A85-90541C5509F8}"6 ProjectGUID="{DE592F40-CEF0-4B82-8EFB-A92D0C88A1EF}" 7 7 RootNamespace="pjlib" 8 8 > -
pjproject/trunk/pjnath/build/pjnath.dsw
r1812 r1867 61 61 ############################################################################### 62 62 63 Project: "pjstun_ client"=.\pjstun_client.dsp - Package Owner=<4>63 Project: "pjstun_srv_test"=.\pjstun_srv_test.dsp - Package Owner=<4> 64 64 65 65 Package=<5> … … 82 82 ############################################################################### 83 83 84 Project: "pj stun_srv_test"=.\pjstun_srv_test.dsp - Package Owner=<4>84 Project: "pjturn_client"=.\pjturn_client.dsp - Package Owner=<4> 85 85 86 86 Package=<5> -
pjproject/trunk/pjnath/build/pjnath.vcproj
r1495 r1867 320 320 </FileConfiguration> 321 321 </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> 322 330 </Filter> 323 331 <Filter … … 374 382 </File> 375 383 <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" 377 389 > 378 390 </File> -
pjproject/trunk/pjnath/build/pjturn_client.dsp
r1863 r1867 1 # Microsoft Developer Studio Project File - Name="pj stun_client" - Package Owner=<4>1 # Microsoft Developer Studio Project File - Name="pjturn_client" - Package Owner=<4> 2 2 # Microsoft Developer Studio Generated Build File, Format Version 6.00 3 3 # ** DO NOT EDIT ** … … 5 5 # TARGTYPE "Win32 (x86) Console Application" 0x0103 6 6 7 CFG=pj stun_client - Win32 Debug7 CFG=pjturn_client - Win32 Debug 8 8 !MESSAGE This is not a valid makefile. To build this project using NMAKE, 9 9 !MESSAGE use the Export Makefile command and run 10 10 !MESSAGE 11 !MESSAGE NMAKE /f "pj stun_client.mak".11 !MESSAGE NMAKE /f "pjturn_client.mak". 12 12 !MESSAGE 13 13 !MESSAGE You can specify a configuration when running NMAKE 14 14 !MESSAGE by defining the macro CFG on the command line. For example: 15 15 !MESSAGE 16 !MESSAGE NMAKE /f "pj stun_client.mak" CFG="pjstun_client - Win32 Debug"16 !MESSAGE NMAKE /f "pjturn_client.mak" CFG="pjturn_client - Win32 Debug" 17 17 !MESSAGE 18 18 !MESSAGE Possible choices for configuration are: 19 19 !MESSAGE 20 !MESSAGE "pj stun_client - Win32 Release" (based on "Win32 (x86) Console Application")21 !MESSAGE "pj stun_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") 22 22 !MESSAGE 23 23 … … 29 29 RSC=rc.exe 30 30 31 !IF "$(CFG)" == "pj stun_client - Win32 Release"31 !IF "$(CFG)" == "pjturn_client - Win32 Release" 32 32 33 33 # PROP BASE Use_MFC 0 34 34 # PROP BASE Use_Debug_Libraries 0 35 # PROP BASE Output_Dir "./output/pj stun-client-i386-win32-vc6-release"36 # PROP BASE Intermediate_Dir "./output/pj stun-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" 37 37 # PROP BASE Target_Dir "" 38 38 # PROP Use_MFC 0 39 39 # PROP Use_Debug_Libraries 0 40 # PROP Output_Dir "./output/pj stun-client-i386-win32-vc6-release"41 # PROP Intermediate_Dir "./output/pj stun-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" 42 42 # PROP Ignore_Export_Lib 0 43 43 # PROP Target_Dir "" … … 51 51 LINK32=link.exe 52 52 # 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/pj stun-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" 54 54 55 !ELSEIF "$(CFG)" == "pj stun_client - Win32 Debug"55 !ELSEIF "$(CFG)" == "pjturn_client - Win32 Debug" 56 56 57 57 # PROP BASE Use_MFC 0 58 58 # PROP BASE Use_Debug_Libraries 1 59 # PROP BASE Output_Dir "./output/pj stun-client-i386-win32-vc6-debug"60 # PROP BASE Intermediate_Dir "./output/pj stun-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" 61 61 # PROP BASE Target_Dir "" 62 62 # PROP Use_MFC 0 63 63 # PROP Use_Debug_Libraries 1 64 # PROP Output_Dir "./output/pj stun-client-i386-win32-vc6-debug"65 # PROP Intermediate_Dir "./output/pj stun-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" 66 66 # PROP Ignore_Export_Lib 0 67 67 # PROP Target_Dir "" … … 75 75 LINK32=link.exe 76 76 # 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/pj stun-client-i386-win32-vc6-debug.exe" /pdbtype:sept77 # 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 78 78 79 79 !ENDIF … … 81 81 # Begin Target 82 82 83 # Name "pj stun_client - Win32 Release"84 # Name "pj stun_client - Win32 Debug"83 # Name "pjturn_client - Win32 Release" 84 # Name "pjturn_client - Win32 Debug" 85 85 # Begin Group "Source Files" 86 86 … … 88 88 # Begin Source File 89 89 90 SOURCE="..\src\pj stun-client\client_main.c"90 SOURCE="..\src\pjturn-client\client_main.c" 91 91 # End Source File 92 92 # End Group -
pjproject/trunk/pjnath/build/pjturn_client.vcproj
r1863 r1867 3 3 ProjectType="Visual C++" 4 4 Version="8.00" 5 Name="pj stun_client"5 Name="pjturn_client" 6 6 ProjectGUID="{D13A6424-23A4-4990-998D-F80C63704580}" 7 RootNamespace="pj stun_client"7 RootNamespace="pjturn_client" 8 8 > 9 9 <Platforms> … … 17 17 <Configuration 18 18 Name="Release|Win32" 19 OutputDirectory="./output/pj stun-client-i386-win32-vc8-release"20 IntermediateDirectory="./output/pj stun-client-i386-win32-vc8-release"19 OutputDirectory="./output/pjturn-client-i386-win32-vc8-release" 20 IntermediateDirectory="./output/pjturn-client-i386-win32-vc8-release" 21 21 ConfigurationType="1" 22 22 InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC60.vsprops" … … 39 39 <Tool 40 40 Name="VCMIDLTool" 41 TypeLibraryName="./output/pj stun-client-i386-win32-vc8-release/pjstun_client.tlb"41 TypeLibraryName="./output/pjturn-client-i386-win32-vc8-release/pjturn_client.tlb" 42 42 HeaderFileName="" 43 43 /> … … 51 51 RuntimeLibrary="2" 52 52 EnableFunctionLevelLinking="true" 53 PrecompiledHeaderFile="./output/pj stun-client-i386-win32-vc8-release/pjstun_client.pch"54 AssemblerListingLocation="./output/pj stun-client-i386-win32-vc8-release/"55 ObjectFile="./output/pj stun-client-i386-win32-vc8-release/"56 ProgramDataBaseFileName="./output/pj stun-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/" 57 57 BrowseInformation="1" 58 58 WarningLevel="3" … … 73 73 Name="VCLinkerTool" 74 74 AdditionalDependencies="netapi32.lib mswsock.lib ws2_32.lib odbc32.lib odbccp32.lib ole32.lib " 75 OutputFile="../bin/pj stun-client-i386-win32-vc8-release.exe"75 OutputFile="../bin/pjturn-client-i386-win32-vc8-release.exe" 76 76 LinkIncremental="1" 77 77 SuppressStartupBanner="true" 78 ProgramDatabaseFile="./output/pj stun-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" 79 79 SubSystem="1" 80 80 TargetMachine="1" … … 92 92 Name="VCBscMakeTool" 93 93 SuppressStartupBanner="true" 94 OutputFile="./output/pj stun-client-i386-win32-vc8-release/pjstun_client.bsc"94 OutputFile="./output/pjturn-client-i386-win32-vc8-release/pjturn_client.bsc" 95 95 /> 96 96 <Tool … … 109 109 <Configuration 110 110 Name="Debug|Win32" 111 OutputDirectory="./output/pj stun-client-i386-win32-vc8-debug"112 IntermediateDirectory="./output/pj stun-client-i386-win32-vc8-debug"111 OutputDirectory="./output/pjturn-client-i386-win32-vc8-debug" 112 IntermediateDirectory="./output/pjturn-client-i386-win32-vc8-debug" 113 113 ConfigurationType="1" 114 114 InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC60.vsprops" … … 131 131 <Tool 132 132 Name="VCMIDLTool" 133 TypeLibraryName="./output/pj stun-client-i386-win32-vc8-debug/pjstun_client.tlb"133 TypeLibraryName="./output/pjturn-client-i386-win32-vc8-debug/pjturn_client.tlb" 134 134 HeaderFileName="" 135 135 /> … … 142 142 BasicRuntimeChecks="3" 143 143 RuntimeLibrary="1" 144 PrecompiledHeaderFile="./output/pj stun-client-i386-win32-vc8-debug/pjstun_client.pch"145 AssemblerListingLocation="./output/pj stun-client-i386-win32-vc8-debug/"146 ObjectFile="./output/pj stun-client-i386-win32-vc8-debug/"147 ProgramDataBaseFileName="./output/pj stun-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/" 148 148 BrowseInformation="1" 149 149 WarningLevel="3" … … 165 165 Name="VCLinkerTool" 166 166 AdditionalDependencies="netapi32.lib ws2_32.lib odbc32.lib odbccp32.lib ole32.lib " 167 OutputFile="../bin/pj stun-client-i386-win32-vc8-debug.exe"167 OutputFile="../bin/pjturn-client-i386-win32-vc8-debug.exe" 168 168 LinkIncremental="2" 169 169 SuppressStartupBanner="true" 170 170 GenerateDebugInformation="true" 171 ProgramDatabaseFile="./output/pj stun-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" 172 172 SubSystem="1" 173 173 TargetMachine="1" … … 185 185 Name="VCBscMakeTool" 186 186 SuppressStartupBanner="true" 187 OutputFile="./output/pj stun-client-i386-win32-vc8-debug/pjstun_client.bsc"187 OutputFile="./output/pjturn-client-i386-win32-vc8-debug/pjturn_client.bsc" 188 188 /> 189 189 <Tool … … 209 209 > 210 210 <File 211 RelativePath="..\src\pj stun-client\client_main.c"211 RelativePath="..\src\pjturn-client\client_main.c" 212 212 > 213 213 <FileConfiguration -
pjproject/trunk/pjnath/include/pjnath.h
r1854 r1867 29 29 #include <pjnath/stun_transaction.h> 30 30 #include <pjnath/turn_session.h> 31 #include <pjnath/turn_udp.h> 31 32 #include <pjnath/types.h> 32 33 -
pjproject/trunk/pjnath/include/pjnath/turn_session.h
r1862 r1867 193 193 { 194 194 /** 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 /** 195 205 * The relay address 196 206 */ … … 198 208 199 209 /** 200 * The TURN server address for informational purpose.210 * The selected TURN server address. 201 211 */ 202 212 pj_sockaddr server; 213 214 /** 215 * Current seconds before allocation expires. 216 */ 217 int lifetime; 203 218 204 219 } pj_turn_session_info; … … 231 246 232 247 /** 248 * Get TURN session info. 249 */ 250 PJ_DECL(pj_status_t) pj_turn_session_get_info(pj_turn_session *sess, 251 pj_turn_session_info *info); 252 253 /** 233 254 * Re-assign user data. 234 255 */ -
pjproject/trunk/pjnath/include/pjnath/turn_udp.h
r1862 r1867 96 96 PJ_DECL(void*) pj_turn_udp_get_user_data(pj_turn_udp *udp_rel); 97 97 98 99 /** 100 * Get info. 101 */ 102 PJ_DECL(pj_status_t) pj_turn_udp_get_info(pj_turn_udp *udp_rel, 103 pj_turn_session_info *info); 104 98 105 /** 99 106 * Initialize. -
pjproject/trunk/pjnath/src/pjnath/turn_session.c
r1862 r1867 95 95 pj_bool_t pending_alloc; 96 96 pj_turn_alloc_param alloc_param; 97 98 pj_sockaddr relay_addr; 97 99 98 100 pj_hash_table_t *peer_table; … … 369 371 370 372 /* 373 * Get TURN session info. 374 */ 375 PJ_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 /* 371 400 * Re-assign user data. 372 401 */ … … 991 1020 } 992 1021 1022 /* Save relayed address */ 1023 pj_memcpy(&sess->relay_addr, &raddr_attr->sockaddr, sizeof(pj_sockaddr)); 993 1024 994 1025 /* Success */ -
pjproject/trunk/pjnath/src/pjnath/turn_udp.c
r1862 r1867 167 167 } 168 168 169 /** 170 * Get info. 171 */ 172 PJ_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 169 186 /* 170 187 * Initialize. … … 179 196 pj_status_t status; 180 197 198 PJ_ASSERT_RETURN(udp_rel && domain, PJ_EINVAL); 199 PJ_ASSERT_RETURN(udp_rel->sess, PJ_EINVALIDOP); 200 181 201 status = pj_turn_session_set_server(udp_rel->sess, domain, default_port, 182 202 resolver); … … 184 204 return status; 185 205 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 } 189 211 190 212 status = pj_turn_session_alloc(udp_rel->sess, param); … … 204 226 unsigned addr_len) 205 227 { 228 PJ_ASSERT_RETURN(udp_rel && addr && addr_len, PJ_EINVAL); 229 230 if (udp_rel->sess == NULL) 231 return PJ_EINVALIDOP; 232 206 233 return pj_turn_session_sendto(udp_rel->sess, pkt, pkt_len, 207 234 addr, addr_len); … … 215 242 unsigned addr_len) 216 243 { 244 PJ_ASSERT_RETURN(udp_rel && peer && addr_len, PJ_EINVAL); 245 PJ_ASSERT_RETURN(udp_rel->sess != NULL, PJ_EINVALIDOP); 246 217 247 return pj_turn_session_bind_channel(udp_rel->sess, peer, addr_len); 218 248 } … … 233 263 do { 234 264 /* Report incoming packet to TURN session */ 235 if (bytes_read > 0 ) {265 if (bytes_read > 0 && udp_rel->sess) { 236 266 pj_turn_session_on_rx_pkt(udp_rel->sess, udp_rel->pkt, 237 267 bytes_read, PJ_TRUE); … … 318 348 (*udp_rel->cb.on_state)(udp_rel, old_state, new_state); 319 349 } 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 34 34 35 35 36 struct peer 37 { 38 pj_sock_t sock; 39 pj_sockaddr addr; 40 }; 41 42 36 43 static struct global 37 44 { 45 pj_caching_pool cp; 46 pj_pool_t *pool; 38 47 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;45 48 pj_thread_t *thread; 46 49 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]; 54 55 } g; 55 56 … … 62 63 char *password; 63 64 char *nonce; 64 char *peer_addr;65 65 pj_bool_t use_fingerprint; 66 66 } o; 67 67 68 68 69 static int worker_thread(void *unused); 69 70 static pj_status_t parse_addr(const char *input, pj_sockaddr_in *addr); 71 static 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); 76 static void turn_on_state(pj_turn_udp *udp_rel, pj_turn_state_t old_state, 77 pj_turn_state_t new_state); 70 78 71 79 … … 78 86 } 79 87 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 94 static int init() 95 { 96 int i; 87 97 pj_status_t status; 88 98 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 150 static 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 189 static 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)); 139 236 } 140 break;141 237 } 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);227 238 } 228 239 … … 230 241 } 231 242 232 static int init()233 { 234 pj_ sockaddr addr;235 pj_stun_ session_cb stun_cb;236 int len;243 static 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; 237 248 pj_status_t status; 238 249 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) ); 312 260 313 261 if (o.user_name) { 314 pj_stun_auth_cred cred;315 316 262 pj_bzero(&cred, sizeof(cred)); 317 318 263 cred.type = PJ_STUN_AUTH_CRED_STATIC; 319 264 cred.data.static_cred.realm = pj_str(o.realm); … … 322 267 cred.data.static_cred.data = pj_str(o.password); 323 268 cred.data.static_cred.nonce = pj_str(o.nonce); 324 325 pj_stun_session_set_credential(g.sess, &cred);326 puts("Session credential set");327 269 } 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 ); 344 281 345 282 return PJ_SUCCESS; 346 283 } 347 284 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)); 285 static 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 294 static 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 309 static 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 } 544 317 } 545 318 … … 577 350 } 578 351 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: "); 352 static 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(">>> "); 588 388 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: ");647 389 } 648 390 … … 651 393 { 652 394 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; 654 399 655 400 menu(); … … 657 402 fgets(input, sizeof(input), stdin); 658 403 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; 696 458 } 697 459 } … … 701 463 static void usage(void) 702 464 { 703 puts("Usage: pj stun_client TARGET [OPTIONS]");465 puts("Usage: pjturn_client TARGET [OPTIONS]"); 704 466 puts(""); 705 467 puts("where TARGET is \"host[:port]\""); 706 468 puts(""); 707 469 puts("and OPTIONS:"); 708 puts(" --detect, -d Perform NAT type detection first");709 470 puts(" --realm, -r Set realm of the credential"); 710 471 puts(" --username, -u Set username of the credential"); … … 712 473 puts(" --nonce, -N Set NONCE"); 713 474 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");716 475 puts(" --help, -h"); 717 476 } … … 720 479 { 721 480 struct pj_getopt_option long_options[] = { 722 { "detect", 0, 0, 'd'},723 481 { "realm", 1, 0, 'r'}, 724 482 { "username", 1, 0, 'u'}, … … 726 484 { "nonce", 1, 0, 'N'}, 727 485 { "fingerprint",0, 0, 'F'}, 728 { "peer", 1, 0, 'P'},729 486 { "data", 1, 0, 'D'}, 730 487 { "help", 0, 0, 'h'} … … 734 491 pj_status_t status; 735 492 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) { 740 494 switch (c) { 741 case 'd':742 g.detect = PJ_TRUE;743 break;744 495 case 'r': 745 496 o.realm = pj_optarg; … … 759 510 case 'F': 760 511 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;767 512 break; 768 513 … … 787 532 } 788 533 789 status = init(); 790 if (status != PJ_SUCCESS) 534 if ((status=init()) != 0) 791 535 goto on_return; 792 536 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 799 540 console_main(); 800 541
Note: See TracChangeset
for help on using the changeset viewer.