From f20afe7a03041e4191d55a4f1901866103b1e57b Mon Sep 17 00:00:00 2001 From: Benny Prijono Date: Wed, 14 Mar 2007 11:52:13 +0000 Subject: (big patch) Added top-level pjnath project and moved STUN related files to this new project git-svn-id: http://svn.pjsip.org/repos/pjproject/trunk@1062 74dad513-b988-da41-8d7b-12977e46ad98 --- pjlib-util/build/pjlib_util.dsp | 52 - pjlib-util/build/pjlib_util.dsw | 36 - pjlib-util/build/pjlib_util.vcproj | 49 +- pjlib-util/build/pjstun_client.dsp | 102 - pjlib-util/build/pjstun_srv_test.dsp | 122 - pjlib-util/build/wince-evc4/pjlib_util_wince.vcp | 3418 +--------------------- pjlib-util/include/pjlib-util.h | 8 - pjlib-util/include/pjlib-util/stun_auth.h | 275 -- pjlib-util/include/pjlib-util/stun_doc.h | 100 - pjlib-util/include/pjlib-util/stun_endpoint.h | 117 - pjlib-util/include/pjlib-util/stun_msg.h | 1539 ---------- pjlib-util/include/pjlib-util/stun_session.h | 372 --- pjlib-util/include/pjlib-util/stun_transaction.h | 217 -- pjlib-util/include/pjlib-util/turn_client.h | 132 - pjlib-util/src/pjlib-util/stun_auth.c | 341 --- pjlib-util/src/pjlib-util/stun_endpoint.c | 69 - pjlib-util/src/pjlib-util/stun_msg.c | 2162 -------------- pjlib-util/src/pjlib-util/stun_msg_dump.c | 250 -- pjlib-util/src/pjlib-util/stun_session.c | 903 ------ pjlib-util/src/pjlib-util/stun_transaction.c | 315 -- pjlib-util/src/pjstun-client/client_main.c | 680 ----- pjlib-util/src/pjstun-srv-test/bind_usage.c | 206 -- pjlib-util/src/pjstun-srv-test/main.c | 146 - pjlib-util/src/pjstun-srv-test/server.c | 185 -- pjlib-util/src/pjstun-srv-test/server.h | 135 - pjlib-util/src/pjstun-srv-test/turn_usage.c | 1408 --------- pjlib-util/src/pjstun-srv-test/usage.c | 271 -- pjlib/build/wince-evc4/pjlib_wince.vcp | 72 + pjnath/build/pjnath.dsw | 89 + pjnath/build/pjstun_client.dsp | 102 + pjnath/build/pjstun_srv_test.dsp | 122 + pjnath/include/pjnath/stun_auth.h | 275 ++ pjnath/include/pjnath/stun_doc.h | 100 + pjnath/include/pjnath/stun_endpoint.h | 117 + pjnath/include/pjnath/stun_msg.h | 1539 ++++++++++ pjnath/include/pjnath/stun_session.h | 372 +++ pjnath/include/pjnath/stun_transaction.h | 217 ++ pjnath/include/pjnath/turn_client.h | 132 + pjnath/src/pjnath/stun_auth.c | 341 +++ pjnath/src/pjnath/stun_endpoint.c | 69 + pjnath/src/pjnath/stun_msg.c | 2162 ++++++++++++++ pjnath/src/pjnath/stun_msg_dump.c | 250 ++ pjnath/src/pjnath/stun_session.c | 903 ++++++ pjnath/src/pjnath/stun_transaction.c | 315 ++ pjnath/src/pjstun-client/client_main.c | 680 +++++ pjnath/src/pjstun-srv-test/bind_usage.c | 206 ++ pjnath/src/pjstun-srv-test/main.c | 146 + pjnath/src/pjstun-srv-test/server.c | 185 ++ pjnath/src/pjstun-srv-test/server.h | 135 + pjnath/src/pjstun-srv-test/turn_usage.c | 1408 +++++++++ pjnath/src/pjstun-srv-test/usage.c | 271 ++ 51 files changed, 10315 insertions(+), 13503 deletions(-) delete mode 100644 pjlib-util/build/pjstun_client.dsp delete mode 100644 pjlib-util/build/pjstun_srv_test.dsp delete mode 100644 pjlib-util/include/pjlib-util/stun_auth.h delete mode 100644 pjlib-util/include/pjlib-util/stun_doc.h delete mode 100644 pjlib-util/include/pjlib-util/stun_endpoint.h delete mode 100644 pjlib-util/include/pjlib-util/stun_msg.h delete mode 100644 pjlib-util/include/pjlib-util/stun_session.h delete mode 100644 pjlib-util/include/pjlib-util/stun_transaction.h delete mode 100644 pjlib-util/include/pjlib-util/turn_client.h delete mode 100644 pjlib-util/src/pjlib-util/stun_auth.c delete mode 100644 pjlib-util/src/pjlib-util/stun_endpoint.c delete mode 100644 pjlib-util/src/pjlib-util/stun_msg.c delete mode 100644 pjlib-util/src/pjlib-util/stun_msg_dump.c delete mode 100644 pjlib-util/src/pjlib-util/stun_session.c delete mode 100644 pjlib-util/src/pjlib-util/stun_transaction.c delete mode 100644 pjlib-util/src/pjstun-client/client_main.c delete mode 100644 pjlib-util/src/pjstun-srv-test/bind_usage.c delete mode 100644 pjlib-util/src/pjstun-srv-test/main.c delete mode 100644 pjlib-util/src/pjstun-srv-test/server.c delete mode 100644 pjlib-util/src/pjstun-srv-test/server.h delete mode 100644 pjlib-util/src/pjstun-srv-test/turn_usage.c delete mode 100644 pjlib-util/src/pjstun-srv-test/usage.c create mode 100644 pjnath/build/pjnath.dsw create mode 100644 pjnath/build/pjstun_client.dsp create mode 100644 pjnath/build/pjstun_srv_test.dsp create mode 100644 pjnath/include/pjnath/stun_auth.h create mode 100644 pjnath/include/pjnath/stun_doc.h create mode 100644 pjnath/include/pjnath/stun_endpoint.h create mode 100644 pjnath/include/pjnath/stun_msg.h create mode 100644 pjnath/include/pjnath/stun_session.h create mode 100644 pjnath/include/pjnath/stun_transaction.h create mode 100644 pjnath/include/pjnath/turn_client.h create mode 100644 pjnath/src/pjnath/stun_auth.c create mode 100644 pjnath/src/pjnath/stun_endpoint.c create mode 100644 pjnath/src/pjnath/stun_msg.c create mode 100644 pjnath/src/pjnath/stun_msg_dump.c create mode 100644 pjnath/src/pjnath/stun_session.c create mode 100644 pjnath/src/pjnath/stun_transaction.c create mode 100644 pjnath/src/pjstun-client/client_main.c create mode 100644 pjnath/src/pjstun-srv-test/bind_usage.c create mode 100644 pjnath/src/pjstun-srv-test/main.c create mode 100644 pjnath/src/pjstun-srv-test/server.c create mode 100644 pjnath/src/pjstun-srv-test/server.h create mode 100644 pjnath/src/pjstun-srv-test/turn_usage.c create mode 100644 pjnath/src/pjstun-srv-test/usage.c diff --git a/pjlib-util/build/pjlib_util.dsp b/pjlib-util/build/pjlib_util.dsp index fea3d258..b637dfac 100644 --- a/pjlib-util/build/pjlib_util.dsp +++ b/pjlib-util/build/pjlib_util.dsp @@ -145,26 +145,6 @@ SOURCE="..\src\pjlib-util\string.c" # End Source File # Begin Source File -SOURCE="..\src\pjlib-util\stun_auth.c" -# End Source File -# Begin Source File - -SOURCE="..\src\pjlib-util\stun_endpoint.c" -# End Source File -# Begin Source File - -SOURCE="..\src\pjlib-util\stun_msg.c" -# End Source File -# Begin Source File - -SOURCE="..\src\pjlib-util\stun_msg_dump.c" -# End Source File -# Begin Source File - -SOURCE="..\src\pjlib-util\stun_session.c" -# End Source File -# Begin Source File - SOURCE="..\src\pjlib-util\stun_simple.c" # End Source File # Begin Source File @@ -173,10 +153,6 @@ SOURCE="..\src\pjlib-util\stun_simple_client.c" # End Source File # Begin Source File -SOURCE="..\src\pjlib-util\stun_transaction.c" -# End Source File -# Begin Source File - SOURCE="..\src\pjlib-util\symbols.c" # End Source File # Begin Source File @@ -249,38 +225,10 @@ SOURCE="..\include\pjlib-util\string.h" # End Source File # Begin Source File -SOURCE="..\include\pjlib-util\stun_auth.h" -# End Source File -# Begin Source File - -SOURCE="..\include\pjlib-util\stun_doc.h" -# End Source File -# Begin Source File - -SOURCE="..\include\pjlib-util\stun_endpoint.h" -# End Source File -# Begin Source File - -SOURCE="..\include\pjlib-util\stun_msg.h" -# End Source File -# Begin Source File - -SOURCE="..\include\pjlib-util\stun_session.h" -# End Source File -# Begin Source File - SOURCE="..\include\pjlib-util\stun_simple.h" # End Source File # Begin Source File -SOURCE="..\include\pjlib-util\stun_transaction.h" -# End Source File -# Begin Source File - -SOURCE="..\include\pjlib-util\turn_client.h" -# End Source File -# Begin Source File - SOURCE="..\include\pjlib-util\types.h" # End Source File # Begin Source File diff --git a/pjlib-util/build/pjlib_util.dsw b/pjlib-util/build/pjlib_util.dsw index fe5108d9..085e524f 100644 --- a/pjlib-util/build/pjlib_util.dsw +++ b/pjlib-util/build/pjlib_util.dsw @@ -57,42 +57,6 @@ Package=<4> ############################################################################### -Project: "pjstun_client"=".\pjstun_client.dsp" - Package Owner=<4> - -Package=<5> -{{{ -}}} - -Package=<4> -{{{ - Begin Project Dependency - Project_Dep_Name pjlib - End Project Dependency - Begin Project Dependency - Project_Dep_Name pjlib_util - End Project Dependency -}}} - -############################################################################### - -Project: "pjstun_srv_test"=".\pjstun_srv_test.dsp" - Package Owner=<4> - -Package=<5> -{{{ -}}} - -Package=<4> -{{{ - Begin Project Dependency - Project_Dep_Name pjlib - End Project Dependency - Begin Project Dependency - Project_Dep_Name pjlib_util - End Project Dependency -}}} - -############################################################################### - Global: Package=<5> diff --git a/pjlib-util/build/pjlib_util.vcproj b/pjlib-util/build/pjlib_util.vcproj index 53a9e617..e91e0587 100644 --- a/pjlib-util/build/pjlib_util.vcproj +++ b/pjlib-util/build/pjlib_util.vcproj @@ -4,6 +4,7 @@ Version="8.00" Name="pjlib_util" ProjectGUID="{FE07F272-AE7F-4549-9E9F-EF9B80CB1693}" + RootNamespace="pjlib_util" > - - - - - - - - - - @@ -442,10 +423,6 @@ RelativePath="..\src\pjlib-util\stun_simple_client.c" > - - @@ -555,34 +532,10 @@ RelativePath="..\include\pjlib-util\string.h" > - - - - - - - - - - - - diff --git a/pjlib-util/build/pjstun_client.dsp b/pjlib-util/build/pjstun_client.dsp deleted file mode 100644 index 2d5705b7..00000000 --- a/pjlib-util/build/pjstun_client.dsp +++ /dev/null @@ -1,102 +0,0 @@ -# Microsoft Developer Studio Project File - Name="pjstun_client" - Package Owner=<4> -# Microsoft Developer Studio Generated Build File, Format Version 6.00 -# ** DO NOT EDIT ** - -# TARGTYPE "Win32 (x86) Console Application" 0x0103 - -CFG=pjstun_client - Win32 Debug -!MESSAGE This is not a valid makefile. To build this project using NMAKE, -!MESSAGE use the Export Makefile command and run -!MESSAGE -!MESSAGE NMAKE /f "pjstun_client.mak". -!MESSAGE -!MESSAGE You can specify a configuration when running NMAKE -!MESSAGE by defining the macro CFG on the command line. For example: -!MESSAGE -!MESSAGE NMAKE /f "pjstun_client.mak" CFG="pjstun_client - Win32 Debug" -!MESSAGE -!MESSAGE Possible choices for configuration are: -!MESSAGE -!MESSAGE "pjstun_client - Win32 Release" (based on "Win32 (x86) Console Application") -!MESSAGE "pjstun_client - Win32 Debug" (based on "Win32 (x86) Console Application") -!MESSAGE - -# Begin Project -# PROP AllowPerConfigDependencies 0 -# PROP Scc_ProjName "" -# PROP Scc_LocalPath "" -CPP=cl.exe -RSC=rc.exe - -!IF "$(CFG)" == "pjstun_client - Win32 Release" - -# PROP BASE Use_MFC 0 -# PROP BASE Use_Debug_Libraries 0 -# PROP BASE Output_Dir "./output/pjstun-client-i386-win32-vc6-release" -# PROP BASE Intermediate_Dir "./output/pjstun-client-i386-win32-vc6-release" -# PROP BASE Target_Dir "" -# PROP Use_MFC 0 -# PROP Use_Debug_Libraries 0 -# PROP Output_Dir "./output/pjstun-client-i386-win32-vc6-release" -# PROP Intermediate_Dir "./output/pjstun-client-i386-win32-vc6-release" -# PROP Ignore_Export_Lib 0 -# PROP Target_Dir "" -# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c -# ADD CPP /nologo /MD /W3 /GX /O2 /I "../include" /I "../../pjlib/include" /D "NDEBUG" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /D PJ_WIN32=1 /D PJ_M_I386=1 /FR /YX /FD /c -# ADD BASE RSC /l 0x409 /d "NDEBUG" -# ADD RSC /l 0x409 /d "NDEBUG" -BSC32=bscmake.exe -# ADD BASE BSC32 /nologo -# ADD BSC32 /nologo -LINK32=link.exe -# 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 -# 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" - -!ELSEIF "$(CFG)" == "pjstun_client - Win32 Debug" - -# PROP BASE Use_MFC 0 -# PROP BASE Use_Debug_Libraries 1 -# PROP BASE Output_Dir "./output/pjstun-client-i386-win32-vc6-debug" -# PROP BASE Intermediate_Dir "./output/pjstun-client-i386-win32-vc6-debug" -# PROP BASE Target_Dir "" -# PROP Use_MFC 0 -# PROP Use_Debug_Libraries 1 -# PROP Output_Dir "./output/pjstun-client-i386-win32-vc6-debug" -# PROP Intermediate_Dir "./output/pjstun-client-i386-win32-vc6-debug" -# PROP Ignore_Export_Lib 0 -# PROP Target_Dir "" -# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c -# ADD CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /I "../include" /I "../../pjlib/include" /D "_DEBUG" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /D PJ_WIN32=1 /D PJ_M_I386=1 /FR /YX /FD /GZ /c -# ADD BASE RSC /l 0x409 /d "_DEBUG" -# ADD RSC /l 0x409 /d "_DEBUG" -BSC32=bscmake.exe -# ADD BASE BSC32 /nologo -# ADD BSC32 /nologo -LINK32=link.exe -# 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 -# 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 - -!ENDIF - -# Begin Target - -# Name "pjstun_client - Win32 Release" -# Name "pjstun_client - Win32 Debug" -# Begin Group "Source Files" - -# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" -# Begin Source File - -SOURCE="..\src\pjstun-client\client_main.c" -# End Source File -# End Group -# Begin Group "Header Files" - -# PROP Default_Filter "h;hpp;hxx;hm;inl" -# End Group -# Begin Group "Resource Files" - -# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe" -# End Group -# End Target -# End Project diff --git a/pjlib-util/build/pjstun_srv_test.dsp b/pjlib-util/build/pjstun_srv_test.dsp deleted file mode 100644 index fa1a5656..00000000 --- a/pjlib-util/build/pjstun_srv_test.dsp +++ /dev/null @@ -1,122 +0,0 @@ -# Microsoft Developer Studio Project File - Name="pjstun_srv_test" - Package Owner=<4> -# Microsoft Developer Studio Generated Build File, Format Version 6.00 -# ** DO NOT EDIT ** - -# TARGTYPE "Win32 (x86) Console Application" 0x0103 - -CFG=pjstun_srv_test - Win32 Debug -!MESSAGE This is not a valid makefile. To build this project using NMAKE, -!MESSAGE use the Export Makefile command and run -!MESSAGE -!MESSAGE NMAKE /f "pjstun_srv_test.mak". -!MESSAGE -!MESSAGE You can specify a configuration when running NMAKE -!MESSAGE by defining the macro CFG on the command line. For example: -!MESSAGE -!MESSAGE NMAKE /f "pjstun_srv_test.mak" CFG="pjstun_srv_test - Win32 Debug" -!MESSAGE -!MESSAGE Possible choices for configuration are: -!MESSAGE -!MESSAGE "pjstun_srv_test - Win32 Release" (based on "Win32 (x86) Console Application") -!MESSAGE "pjstun_srv_test - Win32 Debug" (based on "Win32 (x86) Console Application") -!MESSAGE - -# Begin Project -# PROP AllowPerConfigDependencies 0 -# PROP Scc_ProjName "" -# PROP Scc_LocalPath "" -CPP=cl.exe -RSC=rc.exe - -!IF "$(CFG)" == "pjstun_srv_test - Win32 Release" - -# PROP BASE Use_MFC 0 -# PROP BASE Use_Debug_Libraries 0 -# PROP BASE Output_Dir "./output/pjstun-srv-test-i386-win32-vc6-release" -# PROP BASE Intermediate_Dir "./output/pjstun-srv-test-i386-win32-vc6-release" -# PROP BASE Target_Dir "" -# PROP Use_MFC 0 -# PROP Use_Debug_Libraries 0 -# PROP Output_Dir "./output/pjstun-srv-test-i386-win32-vc6-release" -# PROP Intermediate_Dir "./output/pjstun-srv-test-i386-win32-vc6-release" -# PROP Ignore_Export_Lib 0 -# PROP Target_Dir "" -# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c -# ADD CPP /nologo /MD /W4 /GX /O2 /I "../include" /I "../../pjlib/include" /D "NDEBUG" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /D PJ_WIN32=1 /D PJ_M_I386=1 /FR /YX /FD /c -# ADD BASE RSC /l 0x409 /d "NDEBUG" -# ADD RSC /l 0x409 /d "NDEBUG" -BSC32=bscmake.exe -# ADD BASE BSC32 /nologo -# ADD BSC32 /nologo -LINK32=link.exe -# 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 -# 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-srv-test-i386-win32-vc6-release.exe" - -!ELSEIF "$(CFG)" == "pjstun_srv_test - Win32 Debug" - -# PROP BASE Use_MFC 0 -# PROP BASE Use_Debug_Libraries 1 -# PROP BASE Output_Dir "./output/pjstun-srv-test-i386-win32-vc6-debug" -# PROP BASE Intermediate_Dir "./output/pjstun-srv-test-i386-win32-vc6-debug" -# PROP BASE Target_Dir "" -# PROP Use_MFC 0 -# PROP Use_Debug_Libraries 1 -# PROP Output_Dir "./output/pjstun-srv-test-i386-win32-vc6-debug" -# PROP Intermediate_Dir "./output/pjstun-srv-test-i386-win32-vc6-debug" -# PROP Ignore_Export_Lib 0 -# PROP Target_Dir "" -# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c -# ADD CPP /nologo /MTd /W4 /Gm /GX /ZI /Od /I "../include" /I "../../pjlib/include" /D "_DEBUG" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /D PJ_WIN32=1 /D PJ_M_I386=1 /FR /YX /FD /GZ /c -# ADD BASE RSC /l 0x409 /d "_DEBUG" -# ADD RSC /l 0x409 /d "_DEBUG" -BSC32=bscmake.exe -# ADD BASE BSC32 /nologo -# ADD BSC32 /nologo -LINK32=link.exe -# 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 -# 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-srv-test-i386-win32-vc6-debug.exe" /pdbtype:sept - -!ENDIF - -# Begin Target - -# Name "pjstun_srv_test - Win32 Release" -# Name "pjstun_srv_test - Win32 Debug" -# Begin Group "Source Files" - -# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" -# Begin Source File - -SOURCE="..\src\pjstun-srv-test\bind_usage.c" -# End Source File -# Begin Source File - -SOURCE="..\src\pjstun-srv-test\main.c" -# End Source File -# Begin Source File - -SOURCE="..\src\pjstun-srv-test\server.c" -# End Source File -# Begin Source File - -SOURCE="..\src\pjstun-srv-test\turn_usage.c" -# End Source File -# Begin Source File - -SOURCE="..\src\pjstun-srv-test\usage.c" -# End Source File -# End Group -# Begin Group "Header Files" - -# PROP Default_Filter "h;hpp;hxx;hm;inl" -# Begin Source File - -SOURCE="..\src\pjstun-srv-test\server.h" -# End Source File -# End Group -# Begin Group "Resource Files" - -# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe" -# End Group -# End Target -# End Project diff --git a/pjlib-util/build/wince-evc4/pjlib_util_wince.vcp b/pjlib-util/build/wince-evc4/pjlib_util_wince.vcp index d0a44f04..13d59901 100644 --- a/pjlib-util/build/wince-evc4/pjlib_util_wince.vcp +++ b/pjlib-util/build/wince-evc4/pjlib_util_wince.vcp @@ -363,7 +363,9 @@ DEP_CPP_CRC32=\ "..\..\..\pjlib\include\pj\config_site.h"\ "..\..\..\pjlib\include\pj\config_site_sample.h"\ "..\..\..\pjlib\include\pj\types.h"\ + "..\..\include\pjlib-util\config.h"\ "..\..\include\pjlib-util\crc32.h"\ + "..\..\include\pjlib-util\types.h"\ !ELSEIF "$(CFG)" == "pjlib_util_wince - Win32 (WCE ARMV4I) Release" @@ -6105,7 +6107,7 @@ DEP_CPP_STRIN=\ # End Source File # Begin Source File -SOURCE="..\..\src\pjlib-util\stun_endpoint.c" +SOURCE="..\..\src\pjlib-util\stun_simple.c" !IF "$(CFG)" == "pjlib_util_wince - Win32 (WCE emulator) Release" @@ -6165,8 +6167,7 @@ DEP_CPP_STUN_=\ "..\..\..\pjlib\include\pjlib.h"\ "..\..\include\pjlib-util\config.h"\ "..\..\include\pjlib-util\errno.h"\ - "..\..\include\pjlib-util\stun_endpoint.h"\ - "..\..\include\pjlib-util\stun_msg.h"\ + "..\..\include\pjlib-util\stun_simple.h"\ "..\..\include\pjlib-util\types.h"\ @@ -6228,8 +6229,7 @@ DEP_CPP_STUN_=\ "..\..\..\pjlib\include\pjlib.h"\ "..\..\include\pjlib-util\config.h"\ "..\..\include\pjlib-util\errno.h"\ - "..\..\include\pjlib-util\stun_endpoint.h"\ - "..\..\include\pjlib-util\stun_msg.h"\ + "..\..\include\pjlib-util\stun_simple.h"\ "..\..\include\pjlib-util\types.h"\ @@ -6291,8 +6291,7 @@ DEP_CPP_STUN_=\ "..\..\..\pjlib\include\pjlib.h"\ "..\..\include\pjlib-util\config.h"\ "..\..\include\pjlib-util\errno.h"\ - "..\..\include\pjlib-util\stun_endpoint.h"\ - "..\..\include\pjlib-util\stun_msg.h"\ + "..\..\include\pjlib-util\stun_simple.h"\ "..\..\include\pjlib-util\types.h"\ @@ -6354,8 +6353,7 @@ DEP_CPP_STUN_=\ "..\..\..\pjlib\include\pjlib.h"\ "..\..\include\pjlib-util\config.h"\ "..\..\include\pjlib-util\errno.h"\ - "..\..\include\pjlib-util\stun_endpoint.h"\ - "..\..\include\pjlib-util\stun_msg.h"\ + "..\..\include\pjlib-util\stun_simple.h"\ "..\..\include\pjlib-util\types.h"\ @@ -6417,8 +6415,7 @@ DEP_CPP_STUN_=\ "..\..\..\pjlib\include\pjlib.h"\ "..\..\include\pjlib-util\config.h"\ "..\..\include\pjlib-util\errno.h"\ - "..\..\include\pjlib-util\stun_endpoint.h"\ - "..\..\include\pjlib-util\stun_msg.h"\ + "..\..\include\pjlib-util\stun_simple.h"\ "..\..\include\pjlib-util\types.h"\ @@ -6480,8 +6477,7 @@ DEP_CPP_STUN_=\ "..\..\..\pjlib\include\pjlib.h"\ "..\..\include\pjlib-util\config.h"\ "..\..\include\pjlib-util\errno.h"\ - "..\..\include\pjlib-util\stun_endpoint.h"\ - "..\..\include\pjlib-util\stun_msg.h"\ + "..\..\include\pjlib-util\stun_simple.h"\ "..\..\include\pjlib-util\types.h"\ @@ -6543,8 +6539,7 @@ DEP_CPP_STUN_=\ "..\..\..\pjlib\include\pjlib.h"\ "..\..\include\pjlib-util\config.h"\ "..\..\include\pjlib-util\errno.h"\ - "..\..\include\pjlib-util\stun_endpoint.h"\ - "..\..\include\pjlib-util\stun_msg.h"\ + "..\..\include\pjlib-util\stun_simple.h"\ "..\..\include\pjlib-util\types.h"\ @@ -6606,8 +6601,7 @@ DEP_CPP_STUN_=\ "..\..\..\pjlib\include\pjlib.h"\ "..\..\include\pjlib-util\config.h"\ "..\..\include\pjlib-util\errno.h"\ - "..\..\include\pjlib-util\stun_endpoint.h"\ - "..\..\include\pjlib-util\stun_msg.h"\ + "..\..\include\pjlib-util\stun_simple.h"\ "..\..\include\pjlib-util\types.h"\ @@ -6669,8 +6663,7 @@ DEP_CPP_STUN_=\ "..\..\..\pjlib\include\pjlib.h"\ "..\..\include\pjlib-util\config.h"\ "..\..\include\pjlib-util\errno.h"\ - "..\..\include\pjlib-util\stun_endpoint.h"\ - "..\..\include\pjlib-util\stun_msg.h"\ + "..\..\include\pjlib-util\stun_simple.h"\ "..\..\include\pjlib-util\types.h"\ @@ -6732,8 +6725,7 @@ DEP_CPP_STUN_=\ "..\..\..\pjlib\include\pjlib.h"\ "..\..\include\pjlib-util\config.h"\ "..\..\include\pjlib-util\errno.h"\ - "..\..\include\pjlib-util\stun_endpoint.h"\ - "..\..\include\pjlib-util\stun_msg.h"\ + "..\..\include\pjlib-util\stun_simple.h"\ "..\..\include\pjlib-util\types.h"\ @@ -6742,11 +6734,11 @@ DEP_CPP_STUN_=\ # End Source File # Begin Source File -SOURCE="..\..\src\pjlib-util\stun_msg.c" +SOURCE="..\..\src\pjlib-util\stun_simple_client.c" !IF "$(CFG)" == "pjlib_util_wince - Win32 (WCE emulator) Release" -DEP_CPP_STUN_M=\ +DEP_CPP_STUN_S=\ "..\..\..\pjlib\include\pj\addr_resolv.h"\ "..\..\..\pjlib\include\pj\array.h"\ "..\..\..\pjlib\include\pj\assert.h"\ @@ -6802,13 +6794,13 @@ DEP_CPP_STUN_M=\ "..\..\..\pjlib\include\pjlib.h"\ "..\..\include\pjlib-util\config.h"\ "..\..\include\pjlib-util\errno.h"\ - "..\..\include\pjlib-util\stun_msg.h"\ + "..\..\include\pjlib-util\stun_simple.h"\ "..\..\include\pjlib-util\types.h"\ !ELSEIF "$(CFG)" == "pjlib_util_wince - Win32 (WCE emulator) Debug" -DEP_CPP_STUN_M=\ +DEP_CPP_STUN_S=\ "..\..\..\pjlib\include\pj\addr_resolv.h"\ "..\..\..\pjlib\include\pj\array.h"\ "..\..\..\pjlib\include\pj\assert.h"\ @@ -6863,17 +6855,14 @@ DEP_CPP_STUN_M=\ "..\..\..\pjlib\include\pj\unicode.h"\ "..\..\..\pjlib\include\pjlib.h"\ "..\..\include\pjlib-util\config.h"\ - "..\..\include\pjlib-util\crc32.h"\ "..\..\include\pjlib-util\errno.h"\ - "..\..\include\pjlib-util\hmac_sha1.h"\ - "..\..\include\pjlib-util\md5.h"\ - "..\..\include\pjlib-util\stun_msg.h"\ + "..\..\include\pjlib-util\stun_simple.h"\ "..\..\include\pjlib-util\types.h"\ !ELSEIF "$(CFG)" == "pjlib_util_wince - Win32 (WCE ARMV4I) Release" -DEP_CPP_STUN_M=\ +DEP_CPP_STUN_S=\ "..\..\..\pjlib\include\pj\addr_resolv.h"\ "..\..\..\pjlib\include\pj\array.h"\ "..\..\..\pjlib\include\pj\assert.h"\ @@ -6929,13 +6918,13 @@ DEP_CPP_STUN_M=\ "..\..\..\pjlib\include\pjlib.h"\ "..\..\include\pjlib-util\config.h"\ "..\..\include\pjlib-util\errno.h"\ - "..\..\include\pjlib-util\stun_msg.h"\ + "..\..\include\pjlib-util\stun_simple.h"\ "..\..\include\pjlib-util\types.h"\ !ELSEIF "$(CFG)" == "pjlib_util_wince - Win32 (WCE ARMV4I) Debug" -DEP_CPP_STUN_M=\ +DEP_CPP_STUN_S=\ "..\..\..\pjlib\include\pj\addr_resolv.h"\ "..\..\..\pjlib\include\pj\array.h"\ "..\..\..\pjlib\include\pj\assert.h"\ @@ -6991,13 +6980,13 @@ DEP_CPP_STUN_M=\ "..\..\..\pjlib\include\pjlib.h"\ "..\..\include\pjlib-util\config.h"\ "..\..\include\pjlib-util\errno.h"\ - "..\..\include\pjlib-util\stun_msg.h"\ + "..\..\include\pjlib-util\stun_simple.h"\ "..\..\include\pjlib-util\types.h"\ !ELSEIF "$(CFG)" == "pjlib_util_wince - Win32 (WCE ARMV4) Release" -DEP_CPP_STUN_M=\ +DEP_CPP_STUN_S=\ "..\..\..\pjlib\include\pj\addr_resolv.h"\ "..\..\..\pjlib\include\pj\array.h"\ "..\..\..\pjlib\include\pj\assert.h"\ @@ -7053,13 +7042,13 @@ DEP_CPP_STUN_M=\ "..\..\..\pjlib\include\pjlib.h"\ "..\..\include\pjlib-util\config.h"\ "..\..\include\pjlib-util\errno.h"\ - "..\..\include\pjlib-util\stun_msg.h"\ + "..\..\include\pjlib-util\stun_simple.h"\ "..\..\include\pjlib-util\types.h"\ !ELSEIF "$(CFG)" == "pjlib_util_wince - Win32 (WCE ARMV4) Debug" -DEP_CPP_STUN_M=\ +DEP_CPP_STUN_S=\ "..\..\..\pjlib\include\pj\addr_resolv.h"\ "..\..\..\pjlib\include\pj\array.h"\ "..\..\..\pjlib\include\pj\assert.h"\ @@ -7115,13 +7104,13 @@ DEP_CPP_STUN_M=\ "..\..\..\pjlib\include\pjlib.h"\ "..\..\include\pjlib-util\config.h"\ "..\..\include\pjlib-util\errno.h"\ - "..\..\include\pjlib-util\stun_msg.h"\ + "..\..\include\pjlib-util\stun_simple.h"\ "..\..\include\pjlib-util\types.h"\ !ELSEIF "$(CFG)" == "pjlib_util_wince - Win32 (WCE ARMV4T) Release" -DEP_CPP_STUN_M=\ +DEP_CPP_STUN_S=\ "..\..\..\pjlib\include\pj\addr_resolv.h"\ "..\..\..\pjlib\include\pj\array.h"\ "..\..\..\pjlib\include\pj\assert.h"\ @@ -7177,13 +7166,13 @@ DEP_CPP_STUN_M=\ "..\..\..\pjlib\include\pjlib.h"\ "..\..\include\pjlib-util\config.h"\ "..\..\include\pjlib-util\errno.h"\ - "..\..\include\pjlib-util\stun_msg.h"\ + "..\..\include\pjlib-util\stun_simple.h"\ "..\..\include\pjlib-util\types.h"\ !ELSEIF "$(CFG)" == "pjlib_util_wince - Win32 (WCE ARMV4T) Debug" -DEP_CPP_STUN_M=\ +DEP_CPP_STUN_S=\ "..\..\..\pjlib\include\pj\addr_resolv.h"\ "..\..\..\pjlib\include\pj\array.h"\ "..\..\..\pjlib\include\pj\assert.h"\ @@ -7239,13 +7228,13 @@ DEP_CPP_STUN_M=\ "..\..\..\pjlib\include\pjlib.h"\ "..\..\include\pjlib-util\config.h"\ "..\..\include\pjlib-util\errno.h"\ - "..\..\include\pjlib-util\stun_msg.h"\ + "..\..\include\pjlib-util\stun_simple.h"\ "..\..\include\pjlib-util\types.h"\ !ELSEIF "$(CFG)" == "pjlib_util_wince - Win32 (WCE x86) Release" -DEP_CPP_STUN_M=\ +DEP_CPP_STUN_S=\ "..\..\..\pjlib\include\pj\addr_resolv.h"\ "..\..\..\pjlib\include\pj\array.h"\ "..\..\..\pjlib\include\pj\assert.h"\ @@ -7301,13 +7290,13 @@ DEP_CPP_STUN_M=\ "..\..\..\pjlib\include\pjlib.h"\ "..\..\include\pjlib-util\config.h"\ "..\..\include\pjlib-util\errno.h"\ - "..\..\include\pjlib-util\stun_msg.h"\ + "..\..\include\pjlib-util\stun_simple.h"\ "..\..\include\pjlib-util\types.h"\ !ELSEIF "$(CFG)" == "pjlib_util_wince - Win32 (WCE x86) Debug" -DEP_CPP_STUN_M=\ +DEP_CPP_STUN_S=\ "..\..\..\pjlib\include\pj\addr_resolv.h"\ "..\..\..\pjlib\include\pj\array.h"\ "..\..\..\pjlib\include\pj\assert.h"\ @@ -7363,7 +7352,7 @@ DEP_CPP_STUN_M=\ "..\..\..\pjlib\include\pjlib.h"\ "..\..\include\pjlib-util\config.h"\ "..\..\include\pjlib-util\errno.h"\ - "..\..\include\pjlib-util\stun_msg.h"\ + "..\..\include\pjlib-util\stun_simple.h"\ "..\..\include\pjlib-util\types.h"\ @@ -7372,27 +7361,20 @@ DEP_CPP_STUN_M=\ # End Source File # Begin Source File -SOURCE="..\..\src\pjlib-util\stun_msg_dump.c" +SOURCE="..\..\src\pjlib-util\xml.c" !IF "$(CFG)" == "pjlib_util_wince - Win32 (WCE emulator) Release" -DEP_CPP_STUN_MS=\ - "..\..\..\pjlib\include\pj\addr_resolv.h"\ - "..\..\..\pjlib\include\pj\array.h"\ - "..\..\..\pjlib\include\pj\assert.h"\ - "..\..\..\pjlib\include\pj\compat\assert.h"\ +DEP_CPP_XML_C=\ "..\..\..\pjlib\include\pj\compat\cc_gcc.h"\ "..\..\..\pjlib\include\pj\compat\cc_msvc.h"\ - "..\..\..\pjlib\include\pj\compat\ctype.h"\ - "..\..\..\pjlib\include\pj\compat\errno.h"\ - "..\..\..\pjlib\include\pj\compat\high_precision.h"\ - "..\..\..\pjlib\include\pj\compat\m_auto.h"\ - "..\..\..\pjlib\include\pj\compat\os_auto.h"\ - "..\..\..\pjlib\include\pj\compat\os_darwinos.h"\ + "..\..\..\pjlib\include\pj\compat\m_alpha.h"\ + "..\..\..\pjlib\include\pj\compat\m_i386.h"\ + "..\..\..\pjlib\include\pj\compat\m_m68k.h"\ + "..\..\..\pjlib\include\pj\compat\m_sparc.h"\ "..\..\..\pjlib\include\pj\compat\os_linux.h"\ "..\..\..\pjlib\include\pj\compat\os_linux_kernel.h"\ "..\..\..\pjlib\include\pj\compat\os_palmos.h"\ - "..\..\..\pjlib\include\pj\compat\os_rtems.h"\ "..\..\..\pjlib\include\pj\compat\os_sunos.h"\ "..\..\..\pjlib\include\pj\compat\os_win32.h"\ "..\..\..\pjlib\include\pj\compat\os_win32_wince.h"\ @@ -7401,44 +7383,30 @@ DEP_CPP_STUN_MS=\ "..\..\..\pjlib\include\pj\compat\string.h"\ "..\..\..\pjlib\include\pj\config.h"\ "..\..\..\pjlib\include\pj\config_site.h"\ - "..\..\..\pjlib\include\pj\config_site_sample.h"\ - "..\..\..\pjlib\include\pj\ctype.h"\ - "..\..\..\pjlib\include\pj\errno.h"\ "..\..\..\pjlib\include\pj\except.h"\ - "..\..\..\pjlib\include\pj\fifobuf.h"\ - "..\..\..\pjlib\include\pj\file_access.h"\ - "..\..\..\pjlib\include\pj\file_io.h"\ - "..\..\..\pjlib\include\pj\guid.h"\ - "..\..\..\pjlib\include\pj\hash.h"\ - "..\..\..\pjlib\include\pj\ioqueue.h"\ "..\..\..\pjlib\include\pj\list.h"\ "..\..\..\pjlib\include\pj\list_i.h"\ - "..\..\..\pjlib\include\pj\lock.h"\ "..\..\..\pjlib\include\pj\log.h"\ "..\..\..\pjlib\include\pj\os.h"\ "..\..\..\pjlib\include\pj\pool.h"\ - "..\..\..\pjlib\include\pj\pool_alt.h"\ - "..\..\..\pjlib\include\pj\pool_buf.h"\ "..\..\..\pjlib\include\pj\pool_i.h"\ - "..\..\..\pjlib\include\pj\rand.h"\ - "..\..\..\pjlib\include\pj\rbtree.h"\ - "..\..\..\pjlib\include\pj\sock.h"\ - "..\..\..\pjlib\include\pj\sock_select.h"\ "..\..\..\pjlib\include\pj\string.h"\ "..\..\..\pjlib\include\pj\string_i.h"\ - "..\..\..\pjlib\include\pj\timer.h"\ "..\..\..\pjlib\include\pj\types.h"\ - "..\..\..\pjlib\include\pj\unicode.h"\ - "..\..\..\pjlib\include\pjlib.h"\ - "..\..\include\pjlib-util\config.h"\ - "..\..\include\pjlib-util\errno.h"\ - "..\..\include\pjlib-util\stun_msg.h"\ - "..\..\include\pjlib-util\types.h"\ + "..\..\include\pjlib-util\scanner.h"\ + "..\..\include\pjlib-util\scanner_cis_bitwise.h"\ + "..\..\include\pjlib-util\scanner_cis_uint.h"\ + "..\..\include\pjlib-util\xml.h"\ + +NODEP_CPP_XML_C=\ + "..\..\..\pjlib\include\pj\compat\m_arm.h"\ + "..\..\..\pjlib\include\pj\compat\sprintf.h"\ + "..\..\..\pjlib\include\pj\compat\vsprintf.h"\ !ELSEIF "$(CFG)" == "pjlib_util_wince - Win32 (WCE emulator) Debug" -DEP_CPP_STUN_MS=\ +DEP_CPP_XML_C=\ "..\..\..\pjlib\include\pj\addr_resolv.h"\ "..\..\..\pjlib\include\pj\array.h"\ "..\..\..\pjlib\include\pj\assert.h"\ @@ -7493,30 +7461,25 @@ DEP_CPP_STUN_MS=\ "..\..\..\pjlib\include\pj\unicode.h"\ "..\..\..\pjlib\include\pjlib.h"\ "..\..\include\pjlib-util\config.h"\ - "..\..\include\pjlib-util\errno.h"\ - "..\..\include\pjlib-util\stun_msg.h"\ + "..\..\include\pjlib-util\scanner.h"\ + "..\..\include\pjlib-util\scanner_cis_bitwise.h"\ + "..\..\include\pjlib-util\scanner_cis_uint.h"\ "..\..\include\pjlib-util\types.h"\ + "..\..\include\pjlib-util\xml.h"\ !ELSEIF "$(CFG)" == "pjlib_util_wince - Win32 (WCE ARMV4I) Release" -DEP_CPP_STUN_MS=\ - "..\..\..\pjlib\include\pj\addr_resolv.h"\ - "..\..\..\pjlib\include\pj\array.h"\ - "..\..\..\pjlib\include\pj\assert.h"\ - "..\..\..\pjlib\include\pj\compat\assert.h"\ +DEP_CPP_XML_C=\ "..\..\..\pjlib\include\pj\compat\cc_gcc.h"\ "..\..\..\pjlib\include\pj\compat\cc_msvc.h"\ - "..\..\..\pjlib\include\pj\compat\ctype.h"\ - "..\..\..\pjlib\include\pj\compat\errno.h"\ - "..\..\..\pjlib\include\pj\compat\high_precision.h"\ - "..\..\..\pjlib\include\pj\compat\m_auto.h"\ - "..\..\..\pjlib\include\pj\compat\os_auto.h"\ - "..\..\..\pjlib\include\pj\compat\os_darwinos.h"\ + "..\..\..\pjlib\include\pj\compat\m_alpha.h"\ + "..\..\..\pjlib\include\pj\compat\m_i386.h"\ + "..\..\..\pjlib\include\pj\compat\m_m68k.h"\ + "..\..\..\pjlib\include\pj\compat\m_sparc.h"\ "..\..\..\pjlib\include\pj\compat\os_linux.h"\ "..\..\..\pjlib\include\pj\compat\os_linux_kernel.h"\ "..\..\..\pjlib\include\pj\compat\os_palmos.h"\ - "..\..\..\pjlib\include\pj\compat\os_rtems.h"\ "..\..\..\pjlib\include\pj\compat\os_sunos.h"\ "..\..\..\pjlib\include\pj\compat\os_win32.h"\ "..\..\..\pjlib\include\pj\compat\os_win32_wince.h"\ @@ -7525,60 +7488,39 @@ DEP_CPP_STUN_MS=\ "..\..\..\pjlib\include\pj\compat\string.h"\ "..\..\..\pjlib\include\pj\config.h"\ "..\..\..\pjlib\include\pj\config_site.h"\ - "..\..\..\pjlib\include\pj\config_site_sample.h"\ - "..\..\..\pjlib\include\pj\ctype.h"\ - "..\..\..\pjlib\include\pj\errno.h"\ "..\..\..\pjlib\include\pj\except.h"\ - "..\..\..\pjlib\include\pj\fifobuf.h"\ - "..\..\..\pjlib\include\pj\file_access.h"\ - "..\..\..\pjlib\include\pj\file_io.h"\ - "..\..\..\pjlib\include\pj\guid.h"\ - "..\..\..\pjlib\include\pj\hash.h"\ - "..\..\..\pjlib\include\pj\ioqueue.h"\ "..\..\..\pjlib\include\pj\list.h"\ "..\..\..\pjlib\include\pj\list_i.h"\ - "..\..\..\pjlib\include\pj\lock.h"\ "..\..\..\pjlib\include\pj\log.h"\ "..\..\..\pjlib\include\pj\os.h"\ "..\..\..\pjlib\include\pj\pool.h"\ - "..\..\..\pjlib\include\pj\pool_alt.h"\ - "..\..\..\pjlib\include\pj\pool_buf.h"\ "..\..\..\pjlib\include\pj\pool_i.h"\ - "..\..\..\pjlib\include\pj\rand.h"\ - "..\..\..\pjlib\include\pj\rbtree.h"\ - "..\..\..\pjlib\include\pj\sock.h"\ - "..\..\..\pjlib\include\pj\sock_select.h"\ "..\..\..\pjlib\include\pj\string.h"\ "..\..\..\pjlib\include\pj\string_i.h"\ - "..\..\..\pjlib\include\pj\timer.h"\ "..\..\..\pjlib\include\pj\types.h"\ - "..\..\..\pjlib\include\pj\unicode.h"\ - "..\..\..\pjlib\include\pjlib.h"\ - "..\..\include\pjlib-util\config.h"\ - "..\..\include\pjlib-util\errno.h"\ - "..\..\include\pjlib-util\stun_msg.h"\ - "..\..\include\pjlib-util\types.h"\ + "..\..\include\pjlib-util\scanner.h"\ + "..\..\include\pjlib-util\scanner_cis_bitwise.h"\ + "..\..\include\pjlib-util\scanner_cis_uint.h"\ + "..\..\include\pjlib-util\xml.h"\ + +NODEP_CPP_XML_C=\ + "..\..\..\pjlib\include\pj\compat\m_arm.h"\ + "..\..\..\pjlib\include\pj\compat\sprintf.h"\ + "..\..\..\pjlib\include\pj\compat\vsprintf.h"\ !ELSEIF "$(CFG)" == "pjlib_util_wince - Win32 (WCE ARMV4I) Debug" -DEP_CPP_STUN_MS=\ - "..\..\..\pjlib\include\pj\addr_resolv.h"\ - "..\..\..\pjlib\include\pj\array.h"\ - "..\..\..\pjlib\include\pj\assert.h"\ - "..\..\..\pjlib\include\pj\compat\assert.h"\ +DEP_CPP_XML_C=\ "..\..\..\pjlib\include\pj\compat\cc_gcc.h"\ "..\..\..\pjlib\include\pj\compat\cc_msvc.h"\ - "..\..\..\pjlib\include\pj\compat\ctype.h"\ - "..\..\..\pjlib\include\pj\compat\errno.h"\ - "..\..\..\pjlib\include\pj\compat\high_precision.h"\ - "..\..\..\pjlib\include\pj\compat\m_auto.h"\ - "..\..\..\pjlib\include\pj\compat\os_auto.h"\ - "..\..\..\pjlib\include\pj\compat\os_darwinos.h"\ + "..\..\..\pjlib\include\pj\compat\m_alpha.h"\ + "..\..\..\pjlib\include\pj\compat\m_i386.h"\ + "..\..\..\pjlib\include\pj\compat\m_m68k.h"\ + "..\..\..\pjlib\include\pj\compat\m_sparc.h"\ "..\..\..\pjlib\include\pj\compat\os_linux.h"\ "..\..\..\pjlib\include\pj\compat\os_linux_kernel.h"\ "..\..\..\pjlib\include\pj\compat\os_palmos.h"\ - "..\..\..\pjlib\include\pj\compat\os_rtems.h"\ "..\..\..\pjlib\include\pj\compat\os_sunos.h"\ "..\..\..\pjlib\include\pj\compat\os_win32.h"\ "..\..\..\pjlib\include\pj\compat\os_win32_wince.h"\ @@ -7587,44 +7529,30 @@ DEP_CPP_STUN_MS=\ "..\..\..\pjlib\include\pj\compat\string.h"\ "..\..\..\pjlib\include\pj\config.h"\ "..\..\..\pjlib\include\pj\config_site.h"\ - "..\..\..\pjlib\include\pj\config_site_sample.h"\ - "..\..\..\pjlib\include\pj\ctype.h"\ - "..\..\..\pjlib\include\pj\errno.h"\ "..\..\..\pjlib\include\pj\except.h"\ - "..\..\..\pjlib\include\pj\fifobuf.h"\ - "..\..\..\pjlib\include\pj\file_access.h"\ - "..\..\..\pjlib\include\pj\file_io.h"\ - "..\..\..\pjlib\include\pj\guid.h"\ - "..\..\..\pjlib\include\pj\hash.h"\ - "..\..\..\pjlib\include\pj\ioqueue.h"\ "..\..\..\pjlib\include\pj\list.h"\ "..\..\..\pjlib\include\pj\list_i.h"\ - "..\..\..\pjlib\include\pj\lock.h"\ "..\..\..\pjlib\include\pj\log.h"\ "..\..\..\pjlib\include\pj\os.h"\ "..\..\..\pjlib\include\pj\pool.h"\ - "..\..\..\pjlib\include\pj\pool_alt.h"\ - "..\..\..\pjlib\include\pj\pool_buf.h"\ "..\..\..\pjlib\include\pj\pool_i.h"\ - "..\..\..\pjlib\include\pj\rand.h"\ - "..\..\..\pjlib\include\pj\rbtree.h"\ - "..\..\..\pjlib\include\pj\sock.h"\ - "..\..\..\pjlib\include\pj\sock_select.h"\ "..\..\..\pjlib\include\pj\string.h"\ "..\..\..\pjlib\include\pj\string_i.h"\ - "..\..\..\pjlib\include\pj\timer.h"\ "..\..\..\pjlib\include\pj\types.h"\ - "..\..\..\pjlib\include\pj\unicode.h"\ - "..\..\..\pjlib\include\pjlib.h"\ - "..\..\include\pjlib-util\config.h"\ - "..\..\include\pjlib-util\errno.h"\ - "..\..\include\pjlib-util\stun_msg.h"\ - "..\..\include\pjlib-util\types.h"\ + "..\..\include\pjlib-util\scanner.h"\ + "..\..\include\pjlib-util\scanner_cis_bitwise.h"\ + "..\..\include\pjlib-util\scanner_cis_uint.h"\ + "..\..\include\pjlib-util\xml.h"\ + +NODEP_CPP_XML_C=\ + "..\..\..\pjlib\include\pj\compat\m_arm.h"\ + "..\..\..\pjlib\include\pj\compat\sprintf.h"\ + "..\..\..\pjlib\include\pj\compat\vsprintf.h"\ !ELSEIF "$(CFG)" == "pjlib_util_wince - Win32 (WCE ARMV4) Release" -DEP_CPP_STUN_MS=\ +DEP_CPP_XML_C=\ "..\..\..\pjlib\include\pj\addr_resolv.h"\ "..\..\..\pjlib\include\pj\array.h"\ "..\..\..\pjlib\include\pj\assert.h"\ @@ -7678,31 +7606,24 @@ DEP_CPP_STUN_MS=\ "..\..\..\pjlib\include\pj\types.h"\ "..\..\..\pjlib\include\pj\unicode.h"\ "..\..\..\pjlib\include\pjlib.h"\ - "..\..\include\pjlib-util\config.h"\ - "..\..\include\pjlib-util\errno.h"\ - "..\..\include\pjlib-util\stun_msg.h"\ - "..\..\include\pjlib-util\types.h"\ + "..\..\include\pjlib-util\scanner.h"\ + "..\..\include\pjlib-util\scanner_cis_bitwise.h"\ + "..\..\include\pjlib-util\scanner_cis_uint.h"\ + "..\..\include\pjlib-util\xml.h"\ !ELSEIF "$(CFG)" == "pjlib_util_wince - Win32 (WCE ARMV4) Debug" -DEP_CPP_STUN_MS=\ - "..\..\..\pjlib\include\pj\addr_resolv.h"\ - "..\..\..\pjlib\include\pj\array.h"\ - "..\..\..\pjlib\include\pj\assert.h"\ - "..\..\..\pjlib\include\pj\compat\assert.h"\ +DEP_CPP_XML_C=\ "..\..\..\pjlib\include\pj\compat\cc_gcc.h"\ "..\..\..\pjlib\include\pj\compat\cc_msvc.h"\ - "..\..\..\pjlib\include\pj\compat\ctype.h"\ - "..\..\..\pjlib\include\pj\compat\errno.h"\ - "..\..\..\pjlib\include\pj\compat\high_precision.h"\ - "..\..\..\pjlib\include\pj\compat\m_auto.h"\ - "..\..\..\pjlib\include\pj\compat\os_auto.h"\ - "..\..\..\pjlib\include\pj\compat\os_darwinos.h"\ + "..\..\..\pjlib\include\pj\compat\m_alpha.h"\ + "..\..\..\pjlib\include\pj\compat\m_i386.h"\ + "..\..\..\pjlib\include\pj\compat\m_m68k.h"\ + "..\..\..\pjlib\include\pj\compat\m_sparc.h"\ "..\..\..\pjlib\include\pj\compat\os_linux.h"\ "..\..\..\pjlib\include\pj\compat\os_linux_kernel.h"\ "..\..\..\pjlib\include\pj\compat\os_palmos.h"\ - "..\..\..\pjlib\include\pj\compat\os_rtems.h"\ "..\..\..\pjlib\include\pj\compat\os_sunos.h"\ "..\..\..\pjlib\include\pj\compat\os_win32.h"\ "..\..\..\pjlib\include\pj\compat\os_win32_wince.h"\ @@ -7711,3143 +7632,36 @@ DEP_CPP_STUN_MS=\ "..\..\..\pjlib\include\pj\compat\string.h"\ "..\..\..\pjlib\include\pj\config.h"\ "..\..\..\pjlib\include\pj\config_site.h"\ - "..\..\..\pjlib\include\pj\config_site_sample.h"\ - "..\..\..\pjlib\include\pj\ctype.h"\ - "..\..\..\pjlib\include\pj\errno.h"\ "..\..\..\pjlib\include\pj\except.h"\ - "..\..\..\pjlib\include\pj\fifobuf.h"\ - "..\..\..\pjlib\include\pj\file_access.h"\ - "..\..\..\pjlib\include\pj\file_io.h"\ - "..\..\..\pjlib\include\pj\guid.h"\ - "..\..\..\pjlib\include\pj\hash.h"\ - "..\..\..\pjlib\include\pj\ioqueue.h"\ "..\..\..\pjlib\include\pj\list.h"\ "..\..\..\pjlib\include\pj\list_i.h"\ - "..\..\..\pjlib\include\pj\lock.h"\ "..\..\..\pjlib\include\pj\log.h"\ "..\..\..\pjlib\include\pj\os.h"\ "..\..\..\pjlib\include\pj\pool.h"\ - "..\..\..\pjlib\include\pj\pool_alt.h"\ - "..\..\..\pjlib\include\pj\pool_buf.h"\ "..\..\..\pjlib\include\pj\pool_i.h"\ - "..\..\..\pjlib\include\pj\rand.h"\ - "..\..\..\pjlib\include\pj\rbtree.h"\ - "..\..\..\pjlib\include\pj\sock.h"\ - "..\..\..\pjlib\include\pj\sock_select.h"\ "..\..\..\pjlib\include\pj\string.h"\ "..\..\..\pjlib\include\pj\string_i.h"\ - "..\..\..\pjlib\include\pj\timer.h"\ "..\..\..\pjlib\include\pj\types.h"\ - "..\..\..\pjlib\include\pj\unicode.h"\ - "..\..\..\pjlib\include\pjlib.h"\ - "..\..\include\pjlib-util\config.h"\ - "..\..\include\pjlib-util\errno.h"\ - "..\..\include\pjlib-util\stun_msg.h"\ - "..\..\include\pjlib-util\types.h"\ + "..\..\include\pjlib-util\scanner.h"\ + "..\..\include\pjlib-util\scanner_cis_bitwise.h"\ + "..\..\include\pjlib-util\scanner_cis_uint.h"\ + "..\..\include\pjlib-util\xml.h"\ + +NODEP_CPP_XML_C=\ + "..\..\..\pjlib\include\pj\compat\m_arm.h"\ + "..\..\..\pjlib\include\pj\compat\sprintf.h"\ + "..\..\..\pjlib\include\pj\compat\vsprintf.h"\ !ELSEIF "$(CFG)" == "pjlib_util_wince - Win32 (WCE ARMV4T) Release" -DEP_CPP_STUN_MS=\ - "..\..\..\pjlib\include\pj\addr_resolv.h"\ - "..\..\..\pjlib\include\pj\array.h"\ - "..\..\..\pjlib\include\pj\assert.h"\ - "..\..\..\pjlib\include\pj\compat\assert.h"\ +DEP_CPP_XML_C=\ "..\..\..\pjlib\include\pj\compat\cc_gcc.h"\ "..\..\..\pjlib\include\pj\compat\cc_msvc.h"\ - "..\..\..\pjlib\include\pj\compat\ctype.h"\ - "..\..\..\pjlib\include\pj\compat\errno.h"\ - "..\..\..\pjlib\include\pj\compat\high_precision.h"\ - "..\..\..\pjlib\include\pj\compat\m_auto.h"\ - "..\..\..\pjlib\include\pj\compat\os_auto.h"\ - "..\..\..\pjlib\include\pj\compat\os_darwinos.h"\ - "..\..\..\pjlib\include\pj\compat\os_linux.h"\ - "..\..\..\pjlib\include\pj\compat\os_linux_kernel.h"\ - "..\..\..\pjlib\include\pj\compat\os_palmos.h"\ - "..\..\..\pjlib\include\pj\compat\os_rtems.h"\ - "..\..\..\pjlib\include\pj\compat\os_sunos.h"\ - "..\..\..\pjlib\include\pj\compat\os_win32.h"\ - "..\..\..\pjlib\include\pj\compat\os_win32_wince.h"\ - "..\..\..\pjlib\include\pj\compat\setjmp.h"\ - "..\..\..\pjlib\include\pj\compat\size_t.h"\ - "..\..\..\pjlib\include\pj\compat\string.h"\ - "..\..\..\pjlib\include\pj\config.h"\ - "..\..\..\pjlib\include\pj\config_site.h"\ - "..\..\..\pjlib\include\pj\config_site_sample.h"\ - "..\..\..\pjlib\include\pj\ctype.h"\ - "..\..\..\pjlib\include\pj\errno.h"\ - "..\..\..\pjlib\include\pj\except.h"\ - "..\..\..\pjlib\include\pj\fifobuf.h"\ - "..\..\..\pjlib\include\pj\file_access.h"\ - "..\..\..\pjlib\include\pj\file_io.h"\ - "..\..\..\pjlib\include\pj\guid.h"\ - "..\..\..\pjlib\include\pj\hash.h"\ - "..\..\..\pjlib\include\pj\ioqueue.h"\ - "..\..\..\pjlib\include\pj\list.h"\ - "..\..\..\pjlib\include\pj\list_i.h"\ - "..\..\..\pjlib\include\pj\lock.h"\ - "..\..\..\pjlib\include\pj\log.h"\ - "..\..\..\pjlib\include\pj\os.h"\ - "..\..\..\pjlib\include\pj\pool.h"\ - "..\..\..\pjlib\include\pj\pool_alt.h"\ - "..\..\..\pjlib\include\pj\pool_buf.h"\ - "..\..\..\pjlib\include\pj\pool_i.h"\ - "..\..\..\pjlib\include\pj\rand.h"\ - "..\..\..\pjlib\include\pj\rbtree.h"\ - "..\..\..\pjlib\include\pj\sock.h"\ - "..\..\..\pjlib\include\pj\sock_select.h"\ - "..\..\..\pjlib\include\pj\string.h"\ - "..\..\..\pjlib\include\pj\string_i.h"\ - "..\..\..\pjlib\include\pj\timer.h"\ - "..\..\..\pjlib\include\pj\types.h"\ - "..\..\..\pjlib\include\pj\unicode.h"\ - "..\..\..\pjlib\include\pjlib.h"\ - "..\..\include\pjlib-util\config.h"\ - "..\..\include\pjlib-util\errno.h"\ - "..\..\include\pjlib-util\stun_msg.h"\ - "..\..\include\pjlib-util\types.h"\ - - -!ELSEIF "$(CFG)" == "pjlib_util_wince - Win32 (WCE ARMV4T) Debug" - -DEP_CPP_STUN_MS=\ - "..\..\..\pjlib\include\pj\addr_resolv.h"\ - "..\..\..\pjlib\include\pj\array.h"\ - "..\..\..\pjlib\include\pj\assert.h"\ - "..\..\..\pjlib\include\pj\compat\assert.h"\ - "..\..\..\pjlib\include\pj\compat\cc_gcc.h"\ - "..\..\..\pjlib\include\pj\compat\cc_msvc.h"\ - "..\..\..\pjlib\include\pj\compat\ctype.h"\ - "..\..\..\pjlib\include\pj\compat\errno.h"\ - "..\..\..\pjlib\include\pj\compat\high_precision.h"\ - "..\..\..\pjlib\include\pj\compat\m_auto.h"\ - "..\..\..\pjlib\include\pj\compat\os_auto.h"\ - "..\..\..\pjlib\include\pj\compat\os_darwinos.h"\ - "..\..\..\pjlib\include\pj\compat\os_linux.h"\ - "..\..\..\pjlib\include\pj\compat\os_linux_kernel.h"\ - "..\..\..\pjlib\include\pj\compat\os_palmos.h"\ - "..\..\..\pjlib\include\pj\compat\os_rtems.h"\ - "..\..\..\pjlib\include\pj\compat\os_sunos.h"\ - "..\..\..\pjlib\include\pj\compat\os_win32.h"\ - "..\..\..\pjlib\include\pj\compat\os_win32_wince.h"\ - "..\..\..\pjlib\include\pj\compat\setjmp.h"\ - "..\..\..\pjlib\include\pj\compat\size_t.h"\ - "..\..\..\pjlib\include\pj\compat\string.h"\ - "..\..\..\pjlib\include\pj\config.h"\ - "..\..\..\pjlib\include\pj\config_site.h"\ - "..\..\..\pjlib\include\pj\config_site_sample.h"\ - "..\..\..\pjlib\include\pj\ctype.h"\ - "..\..\..\pjlib\include\pj\errno.h"\ - "..\..\..\pjlib\include\pj\except.h"\ - "..\..\..\pjlib\include\pj\fifobuf.h"\ - "..\..\..\pjlib\include\pj\file_access.h"\ - "..\..\..\pjlib\include\pj\file_io.h"\ - "..\..\..\pjlib\include\pj\guid.h"\ - "..\..\..\pjlib\include\pj\hash.h"\ - "..\..\..\pjlib\include\pj\ioqueue.h"\ - "..\..\..\pjlib\include\pj\list.h"\ - "..\..\..\pjlib\include\pj\list_i.h"\ - "..\..\..\pjlib\include\pj\lock.h"\ - "..\..\..\pjlib\include\pj\log.h"\ - "..\..\..\pjlib\include\pj\os.h"\ - "..\..\..\pjlib\include\pj\pool.h"\ - "..\..\..\pjlib\include\pj\pool_alt.h"\ - "..\..\..\pjlib\include\pj\pool_buf.h"\ - "..\..\..\pjlib\include\pj\pool_i.h"\ - "..\..\..\pjlib\include\pj\rand.h"\ - "..\..\..\pjlib\include\pj\rbtree.h"\ - "..\..\..\pjlib\include\pj\sock.h"\ - "..\..\..\pjlib\include\pj\sock_select.h"\ - "..\..\..\pjlib\include\pj\string.h"\ - "..\..\..\pjlib\include\pj\string_i.h"\ - "..\..\..\pjlib\include\pj\timer.h"\ - "..\..\..\pjlib\include\pj\types.h"\ - "..\..\..\pjlib\include\pj\unicode.h"\ - "..\..\..\pjlib\include\pjlib.h"\ - "..\..\include\pjlib-util\config.h"\ - "..\..\include\pjlib-util\errno.h"\ - "..\..\include\pjlib-util\stun_msg.h"\ - "..\..\include\pjlib-util\types.h"\ - - -!ELSEIF "$(CFG)" == "pjlib_util_wince - Win32 (WCE x86) Release" - -DEP_CPP_STUN_MS=\ - "..\..\..\pjlib\include\pj\addr_resolv.h"\ - "..\..\..\pjlib\include\pj\array.h"\ - "..\..\..\pjlib\include\pj\assert.h"\ - "..\..\..\pjlib\include\pj\compat\assert.h"\ - "..\..\..\pjlib\include\pj\compat\cc_gcc.h"\ - "..\..\..\pjlib\include\pj\compat\cc_msvc.h"\ - "..\..\..\pjlib\include\pj\compat\ctype.h"\ - "..\..\..\pjlib\include\pj\compat\errno.h"\ - "..\..\..\pjlib\include\pj\compat\high_precision.h"\ - "..\..\..\pjlib\include\pj\compat\m_auto.h"\ - "..\..\..\pjlib\include\pj\compat\os_auto.h"\ - "..\..\..\pjlib\include\pj\compat\os_darwinos.h"\ - "..\..\..\pjlib\include\pj\compat\os_linux.h"\ - "..\..\..\pjlib\include\pj\compat\os_linux_kernel.h"\ - "..\..\..\pjlib\include\pj\compat\os_palmos.h"\ - "..\..\..\pjlib\include\pj\compat\os_rtems.h"\ - "..\..\..\pjlib\include\pj\compat\os_sunos.h"\ - "..\..\..\pjlib\include\pj\compat\os_win32.h"\ - "..\..\..\pjlib\include\pj\compat\os_win32_wince.h"\ - "..\..\..\pjlib\include\pj\compat\setjmp.h"\ - "..\..\..\pjlib\include\pj\compat\size_t.h"\ - "..\..\..\pjlib\include\pj\compat\string.h"\ - "..\..\..\pjlib\include\pj\config.h"\ - "..\..\..\pjlib\include\pj\config_site.h"\ - "..\..\..\pjlib\include\pj\config_site_sample.h"\ - "..\..\..\pjlib\include\pj\ctype.h"\ - "..\..\..\pjlib\include\pj\errno.h"\ - "..\..\..\pjlib\include\pj\except.h"\ - "..\..\..\pjlib\include\pj\fifobuf.h"\ - "..\..\..\pjlib\include\pj\file_access.h"\ - "..\..\..\pjlib\include\pj\file_io.h"\ - "..\..\..\pjlib\include\pj\guid.h"\ - "..\..\..\pjlib\include\pj\hash.h"\ - "..\..\..\pjlib\include\pj\ioqueue.h"\ - "..\..\..\pjlib\include\pj\list.h"\ - "..\..\..\pjlib\include\pj\list_i.h"\ - "..\..\..\pjlib\include\pj\lock.h"\ - "..\..\..\pjlib\include\pj\log.h"\ - "..\..\..\pjlib\include\pj\os.h"\ - "..\..\..\pjlib\include\pj\pool.h"\ - "..\..\..\pjlib\include\pj\pool_alt.h"\ - "..\..\..\pjlib\include\pj\pool_buf.h"\ - "..\..\..\pjlib\include\pj\pool_i.h"\ - "..\..\..\pjlib\include\pj\rand.h"\ - "..\..\..\pjlib\include\pj\rbtree.h"\ - "..\..\..\pjlib\include\pj\sock.h"\ - "..\..\..\pjlib\include\pj\sock_select.h"\ - "..\..\..\pjlib\include\pj\string.h"\ - "..\..\..\pjlib\include\pj\string_i.h"\ - "..\..\..\pjlib\include\pj\timer.h"\ - "..\..\..\pjlib\include\pj\types.h"\ - "..\..\..\pjlib\include\pj\unicode.h"\ - "..\..\..\pjlib\include\pjlib.h"\ - "..\..\include\pjlib-util\config.h"\ - "..\..\include\pjlib-util\errno.h"\ - "..\..\include\pjlib-util\stun_msg.h"\ - "..\..\include\pjlib-util\types.h"\ - - -!ELSEIF "$(CFG)" == "pjlib_util_wince - Win32 (WCE x86) Debug" - -DEP_CPP_STUN_MS=\ - "..\..\..\pjlib\include\pj\addr_resolv.h"\ - "..\..\..\pjlib\include\pj\array.h"\ - "..\..\..\pjlib\include\pj\assert.h"\ - "..\..\..\pjlib\include\pj\compat\assert.h"\ - "..\..\..\pjlib\include\pj\compat\cc_gcc.h"\ - "..\..\..\pjlib\include\pj\compat\cc_msvc.h"\ - "..\..\..\pjlib\include\pj\compat\ctype.h"\ - "..\..\..\pjlib\include\pj\compat\errno.h"\ - "..\..\..\pjlib\include\pj\compat\high_precision.h"\ - "..\..\..\pjlib\include\pj\compat\m_auto.h"\ - "..\..\..\pjlib\include\pj\compat\os_auto.h"\ - "..\..\..\pjlib\include\pj\compat\os_darwinos.h"\ - "..\..\..\pjlib\include\pj\compat\os_linux.h"\ - "..\..\..\pjlib\include\pj\compat\os_linux_kernel.h"\ - "..\..\..\pjlib\include\pj\compat\os_palmos.h"\ - "..\..\..\pjlib\include\pj\compat\os_rtems.h"\ - "..\..\..\pjlib\include\pj\compat\os_sunos.h"\ - "..\..\..\pjlib\include\pj\compat\os_win32.h"\ - "..\..\..\pjlib\include\pj\compat\os_win32_wince.h"\ - "..\..\..\pjlib\include\pj\compat\setjmp.h"\ - "..\..\..\pjlib\include\pj\compat\size_t.h"\ - "..\..\..\pjlib\include\pj\compat\string.h"\ - "..\..\..\pjlib\include\pj\config.h"\ - "..\..\..\pjlib\include\pj\config_site.h"\ - "..\..\..\pjlib\include\pj\config_site_sample.h"\ - "..\..\..\pjlib\include\pj\ctype.h"\ - "..\..\..\pjlib\include\pj\errno.h"\ - "..\..\..\pjlib\include\pj\except.h"\ - "..\..\..\pjlib\include\pj\fifobuf.h"\ - "..\..\..\pjlib\include\pj\file_access.h"\ - "..\..\..\pjlib\include\pj\file_io.h"\ - "..\..\..\pjlib\include\pj\guid.h"\ - "..\..\..\pjlib\include\pj\hash.h"\ - "..\..\..\pjlib\include\pj\ioqueue.h"\ - "..\..\..\pjlib\include\pj\list.h"\ - "..\..\..\pjlib\include\pj\list_i.h"\ - "..\..\..\pjlib\include\pj\lock.h"\ - "..\..\..\pjlib\include\pj\log.h"\ - "..\..\..\pjlib\include\pj\os.h"\ - "..\..\..\pjlib\include\pj\pool.h"\ - "..\..\..\pjlib\include\pj\pool_alt.h"\ - "..\..\..\pjlib\include\pj\pool_buf.h"\ - "..\..\..\pjlib\include\pj\pool_i.h"\ - "..\..\..\pjlib\include\pj\rand.h"\ - "..\..\..\pjlib\include\pj\rbtree.h"\ - "..\..\..\pjlib\include\pj\sock.h"\ - "..\..\..\pjlib\include\pj\sock_select.h"\ - "..\..\..\pjlib\include\pj\string.h"\ - "..\..\..\pjlib\include\pj\string_i.h"\ - "..\..\..\pjlib\include\pj\timer.h"\ - "..\..\..\pjlib\include\pj\types.h"\ - "..\..\..\pjlib\include\pj\unicode.h"\ - "..\..\..\pjlib\include\pjlib.h"\ - "..\..\include\pjlib-util\config.h"\ - "..\..\include\pjlib-util\errno.h"\ - "..\..\include\pjlib-util\stun_msg.h"\ - "..\..\include\pjlib-util\types.h"\ - - -!ENDIF - -# End Source File -# Begin Source File - -SOURCE="..\..\src\pjlib-util\stun_server.c" - -!IF "$(CFG)" == "pjlib_util_wince - Win32 (WCE emulator) Release" - -DEP_CPP_STUN_S=\ - "..\..\..\pjlib\include\pj\addr_resolv.h"\ - "..\..\..\pjlib\include\pj\array.h"\ - "..\..\..\pjlib\include\pj\assert.h"\ - "..\..\..\pjlib\include\pj\compat\assert.h"\ - "..\..\..\pjlib\include\pj\compat\cc_gcc.h"\ - "..\..\..\pjlib\include\pj\compat\cc_msvc.h"\ - "..\..\..\pjlib\include\pj\compat\ctype.h"\ - "..\..\..\pjlib\include\pj\compat\errno.h"\ - "..\..\..\pjlib\include\pj\compat\high_precision.h"\ - "..\..\..\pjlib\include\pj\compat\m_auto.h"\ - "..\..\..\pjlib\include\pj\compat\os_auto.h"\ - "..\..\..\pjlib\include\pj\compat\os_darwinos.h"\ - "..\..\..\pjlib\include\pj\compat\os_linux.h"\ - "..\..\..\pjlib\include\pj\compat\os_linux_kernel.h"\ - "..\..\..\pjlib\include\pj\compat\os_palmos.h"\ - "..\..\..\pjlib\include\pj\compat\os_rtems.h"\ - "..\..\..\pjlib\include\pj\compat\os_sunos.h"\ - "..\..\..\pjlib\include\pj\compat\os_win32.h"\ - "..\..\..\pjlib\include\pj\compat\os_win32_wince.h"\ - "..\..\..\pjlib\include\pj\compat\setjmp.h"\ - "..\..\..\pjlib\include\pj\compat\size_t.h"\ - "..\..\..\pjlib\include\pj\compat\string.h"\ - "..\..\..\pjlib\include\pj\config.h"\ - "..\..\..\pjlib\include\pj\config_site.h"\ - "..\..\..\pjlib\include\pj\config_site_sample.h"\ - "..\..\..\pjlib\include\pj\ctype.h"\ - "..\..\..\pjlib\include\pj\errno.h"\ - "..\..\..\pjlib\include\pj\except.h"\ - "..\..\..\pjlib\include\pj\fifobuf.h"\ - "..\..\..\pjlib\include\pj\file_access.h"\ - "..\..\..\pjlib\include\pj\file_io.h"\ - "..\..\..\pjlib\include\pj\guid.h"\ - "..\..\..\pjlib\include\pj\hash.h"\ - "..\..\..\pjlib\include\pj\ioqueue.h"\ - "..\..\..\pjlib\include\pj\list.h"\ - "..\..\..\pjlib\include\pj\list_i.h"\ - "..\..\..\pjlib\include\pj\lock.h"\ - "..\..\..\pjlib\include\pj\log.h"\ - "..\..\..\pjlib\include\pj\os.h"\ - "..\..\..\pjlib\include\pj\pool.h"\ - "..\..\..\pjlib\include\pj\pool_alt.h"\ - "..\..\..\pjlib\include\pj\pool_buf.h"\ - "..\..\..\pjlib\include\pj\pool_i.h"\ - "..\..\..\pjlib\include\pj\rand.h"\ - "..\..\..\pjlib\include\pj\rbtree.h"\ - "..\..\..\pjlib\include\pj\sock.h"\ - "..\..\..\pjlib\include\pj\sock_select.h"\ - "..\..\..\pjlib\include\pj\string.h"\ - "..\..\..\pjlib\include\pj\string_i.h"\ - "..\..\..\pjlib\include\pj\timer.h"\ - "..\..\..\pjlib\include\pj\types.h"\ - "..\..\..\pjlib\include\pj\unicode.h"\ - "..\..\..\pjlib\include\pjlib.h"\ - "..\..\include\pjlib-util\config.h"\ - "..\..\include\pjlib-util\errno.h"\ - "..\..\include\pjlib-util\stun_endpoint.h"\ - "..\..\include\pjlib-util\stun_msg.h"\ - "..\..\include\pjlib-util\stun_server.h"\ - "..\..\include\pjlib-util\types.h"\ - - -!ELSEIF "$(CFG)" == "pjlib_util_wince - Win32 (WCE emulator) Debug" - -DEP_CPP_STUN_S=\ - "..\..\..\pjlib\include\pj\addr_resolv.h"\ - "..\..\..\pjlib\include\pj\array.h"\ - "..\..\..\pjlib\include\pj\assert.h"\ - "..\..\..\pjlib\include\pj\compat\assert.h"\ - "..\..\..\pjlib\include\pj\compat\cc_gcc.h"\ - "..\..\..\pjlib\include\pj\compat\cc_msvc.h"\ - "..\..\..\pjlib\include\pj\compat\ctype.h"\ - "..\..\..\pjlib\include\pj\compat\errno.h"\ - "..\..\..\pjlib\include\pj\compat\high_precision.h"\ - "..\..\..\pjlib\include\pj\compat\m_auto.h"\ - "..\..\..\pjlib\include\pj\compat\os_auto.h"\ - "..\..\..\pjlib\include\pj\compat\os_darwinos.h"\ - "..\..\..\pjlib\include\pj\compat\os_linux.h"\ - "..\..\..\pjlib\include\pj\compat\os_linux_kernel.h"\ - "..\..\..\pjlib\include\pj\compat\os_palmos.h"\ - "..\..\..\pjlib\include\pj\compat\os_rtems.h"\ - "..\..\..\pjlib\include\pj\compat\os_sunos.h"\ - "..\..\..\pjlib\include\pj\compat\os_win32.h"\ - "..\..\..\pjlib\include\pj\compat\os_win32_wince.h"\ - "..\..\..\pjlib\include\pj\compat\setjmp.h"\ - "..\..\..\pjlib\include\pj\compat\size_t.h"\ - "..\..\..\pjlib\include\pj\compat\string.h"\ - "..\..\..\pjlib\include\pj\config.h"\ - "..\..\..\pjlib\include\pj\config_site.h"\ - "..\..\..\pjlib\include\pj\config_site_sample.h"\ - "..\..\..\pjlib\include\pj\ctype.h"\ - "..\..\..\pjlib\include\pj\errno.h"\ - "..\..\..\pjlib\include\pj\except.h"\ - "..\..\..\pjlib\include\pj\fifobuf.h"\ - "..\..\..\pjlib\include\pj\file_access.h"\ - "..\..\..\pjlib\include\pj\file_io.h"\ - "..\..\..\pjlib\include\pj\guid.h"\ - "..\..\..\pjlib\include\pj\hash.h"\ - "..\..\..\pjlib\include\pj\ioqueue.h"\ - "..\..\..\pjlib\include\pj\list.h"\ - "..\..\..\pjlib\include\pj\list_i.h"\ - "..\..\..\pjlib\include\pj\lock.h"\ - "..\..\..\pjlib\include\pj\log.h"\ - "..\..\..\pjlib\include\pj\os.h"\ - "..\..\..\pjlib\include\pj\pool.h"\ - "..\..\..\pjlib\include\pj\pool_alt.h"\ - "..\..\..\pjlib\include\pj\pool_buf.h"\ - "..\..\..\pjlib\include\pj\pool_i.h"\ - "..\..\..\pjlib\include\pj\rand.h"\ - "..\..\..\pjlib\include\pj\rbtree.h"\ - "..\..\..\pjlib\include\pj\sock.h"\ - "..\..\..\pjlib\include\pj\sock_select.h"\ - "..\..\..\pjlib\include\pj\string.h"\ - "..\..\..\pjlib\include\pj\string_i.h"\ - "..\..\..\pjlib\include\pj\timer.h"\ - "..\..\..\pjlib\include\pj\types.h"\ - "..\..\..\pjlib\include\pj\unicode.h"\ - "..\..\..\pjlib\include\pjlib.h"\ - "..\..\include\pjlib-util\config.h"\ - "..\..\include\pjlib-util\errno.h"\ - "..\..\include\pjlib-util\stun_endpoint.h"\ - "..\..\include\pjlib-util\stun_msg.h"\ - "..\..\include\pjlib-util\stun_server.h"\ - "..\..\include\pjlib-util\types.h"\ - - -!ELSEIF "$(CFG)" == "pjlib_util_wince - Win32 (WCE ARMV4I) Release" - -DEP_CPP_STUN_S=\ - "..\..\..\pjlib\include\pj\addr_resolv.h"\ - "..\..\..\pjlib\include\pj\array.h"\ - "..\..\..\pjlib\include\pj\assert.h"\ - "..\..\..\pjlib\include\pj\compat\assert.h"\ - "..\..\..\pjlib\include\pj\compat\cc_gcc.h"\ - "..\..\..\pjlib\include\pj\compat\cc_msvc.h"\ - "..\..\..\pjlib\include\pj\compat\ctype.h"\ - "..\..\..\pjlib\include\pj\compat\errno.h"\ - "..\..\..\pjlib\include\pj\compat\high_precision.h"\ - "..\..\..\pjlib\include\pj\compat\m_auto.h"\ - "..\..\..\pjlib\include\pj\compat\os_auto.h"\ - "..\..\..\pjlib\include\pj\compat\os_darwinos.h"\ - "..\..\..\pjlib\include\pj\compat\os_linux.h"\ - "..\..\..\pjlib\include\pj\compat\os_linux_kernel.h"\ - "..\..\..\pjlib\include\pj\compat\os_palmos.h"\ - "..\..\..\pjlib\include\pj\compat\os_rtems.h"\ - "..\..\..\pjlib\include\pj\compat\os_sunos.h"\ - "..\..\..\pjlib\include\pj\compat\os_win32.h"\ - "..\..\..\pjlib\include\pj\compat\os_win32_wince.h"\ - "..\..\..\pjlib\include\pj\compat\setjmp.h"\ - "..\..\..\pjlib\include\pj\compat\size_t.h"\ - "..\..\..\pjlib\include\pj\compat\string.h"\ - "..\..\..\pjlib\include\pj\config.h"\ - "..\..\..\pjlib\include\pj\config_site.h"\ - "..\..\..\pjlib\include\pj\config_site_sample.h"\ - "..\..\..\pjlib\include\pj\ctype.h"\ - "..\..\..\pjlib\include\pj\errno.h"\ - "..\..\..\pjlib\include\pj\except.h"\ - "..\..\..\pjlib\include\pj\fifobuf.h"\ - "..\..\..\pjlib\include\pj\file_access.h"\ - "..\..\..\pjlib\include\pj\file_io.h"\ - "..\..\..\pjlib\include\pj\guid.h"\ - "..\..\..\pjlib\include\pj\hash.h"\ - "..\..\..\pjlib\include\pj\ioqueue.h"\ - "..\..\..\pjlib\include\pj\list.h"\ - "..\..\..\pjlib\include\pj\list_i.h"\ - "..\..\..\pjlib\include\pj\lock.h"\ - "..\..\..\pjlib\include\pj\log.h"\ - "..\..\..\pjlib\include\pj\os.h"\ - "..\..\..\pjlib\include\pj\pool.h"\ - "..\..\..\pjlib\include\pj\pool_alt.h"\ - "..\..\..\pjlib\include\pj\pool_buf.h"\ - "..\..\..\pjlib\include\pj\pool_i.h"\ - "..\..\..\pjlib\include\pj\rand.h"\ - "..\..\..\pjlib\include\pj\rbtree.h"\ - "..\..\..\pjlib\include\pj\sock.h"\ - "..\..\..\pjlib\include\pj\sock_select.h"\ - "..\..\..\pjlib\include\pj\string.h"\ - "..\..\..\pjlib\include\pj\string_i.h"\ - "..\..\..\pjlib\include\pj\timer.h"\ - "..\..\..\pjlib\include\pj\types.h"\ - "..\..\..\pjlib\include\pj\unicode.h"\ - "..\..\..\pjlib\include\pjlib.h"\ - "..\..\include\pjlib-util\config.h"\ - "..\..\include\pjlib-util\errno.h"\ - "..\..\include\pjlib-util\stun_endpoint.h"\ - "..\..\include\pjlib-util\stun_msg.h"\ - "..\..\include\pjlib-util\stun_server.h"\ - "..\..\include\pjlib-util\types.h"\ - - -!ELSEIF "$(CFG)" == "pjlib_util_wince - Win32 (WCE ARMV4I) Debug" - -DEP_CPP_STUN_S=\ - "..\..\..\pjlib\include\pj\addr_resolv.h"\ - "..\..\..\pjlib\include\pj\array.h"\ - "..\..\..\pjlib\include\pj\assert.h"\ - "..\..\..\pjlib\include\pj\compat\assert.h"\ - "..\..\..\pjlib\include\pj\compat\cc_gcc.h"\ - "..\..\..\pjlib\include\pj\compat\cc_msvc.h"\ - "..\..\..\pjlib\include\pj\compat\ctype.h"\ - "..\..\..\pjlib\include\pj\compat\errno.h"\ - "..\..\..\pjlib\include\pj\compat\high_precision.h"\ - "..\..\..\pjlib\include\pj\compat\m_auto.h"\ - "..\..\..\pjlib\include\pj\compat\os_auto.h"\ - "..\..\..\pjlib\include\pj\compat\os_darwinos.h"\ - "..\..\..\pjlib\include\pj\compat\os_linux.h"\ - "..\..\..\pjlib\include\pj\compat\os_linux_kernel.h"\ - "..\..\..\pjlib\include\pj\compat\os_palmos.h"\ - "..\..\..\pjlib\include\pj\compat\os_rtems.h"\ - "..\..\..\pjlib\include\pj\compat\os_sunos.h"\ - "..\..\..\pjlib\include\pj\compat\os_win32.h"\ - "..\..\..\pjlib\include\pj\compat\os_win32_wince.h"\ - "..\..\..\pjlib\include\pj\compat\setjmp.h"\ - "..\..\..\pjlib\include\pj\compat\size_t.h"\ - "..\..\..\pjlib\include\pj\compat\string.h"\ - "..\..\..\pjlib\include\pj\config.h"\ - "..\..\..\pjlib\include\pj\config_site.h"\ - "..\..\..\pjlib\include\pj\config_site_sample.h"\ - "..\..\..\pjlib\include\pj\ctype.h"\ - "..\..\..\pjlib\include\pj\errno.h"\ - "..\..\..\pjlib\include\pj\except.h"\ - "..\..\..\pjlib\include\pj\fifobuf.h"\ - "..\..\..\pjlib\include\pj\file_access.h"\ - "..\..\..\pjlib\include\pj\file_io.h"\ - "..\..\..\pjlib\include\pj\guid.h"\ - "..\..\..\pjlib\include\pj\hash.h"\ - "..\..\..\pjlib\include\pj\ioqueue.h"\ - "..\..\..\pjlib\include\pj\list.h"\ - "..\..\..\pjlib\include\pj\list_i.h"\ - "..\..\..\pjlib\include\pj\lock.h"\ - "..\..\..\pjlib\include\pj\log.h"\ - "..\..\..\pjlib\include\pj\os.h"\ - "..\..\..\pjlib\include\pj\pool.h"\ - "..\..\..\pjlib\include\pj\pool_alt.h"\ - "..\..\..\pjlib\include\pj\pool_buf.h"\ - "..\..\..\pjlib\include\pj\pool_i.h"\ - "..\..\..\pjlib\include\pj\rand.h"\ - "..\..\..\pjlib\include\pj\rbtree.h"\ - "..\..\..\pjlib\include\pj\sock.h"\ - "..\..\..\pjlib\include\pj\sock_select.h"\ - "..\..\..\pjlib\include\pj\string.h"\ - "..\..\..\pjlib\include\pj\string_i.h"\ - "..\..\..\pjlib\include\pj\timer.h"\ - "..\..\..\pjlib\include\pj\types.h"\ - "..\..\..\pjlib\include\pj\unicode.h"\ - "..\..\..\pjlib\include\pjlib.h"\ - "..\..\include\pjlib-util\config.h"\ - "..\..\include\pjlib-util\errno.h"\ - "..\..\include\pjlib-util\stun_endpoint.h"\ - "..\..\include\pjlib-util\stun_msg.h"\ - "..\..\include\pjlib-util\stun_server.h"\ - "..\..\include\pjlib-util\types.h"\ - - -!ELSEIF "$(CFG)" == "pjlib_util_wince - Win32 (WCE ARMV4) Release" - -DEP_CPP_STUN_S=\ - "..\..\..\pjlib\include\pj\addr_resolv.h"\ - "..\..\..\pjlib\include\pj\array.h"\ - "..\..\..\pjlib\include\pj\assert.h"\ - "..\..\..\pjlib\include\pj\compat\assert.h"\ - "..\..\..\pjlib\include\pj\compat\cc_gcc.h"\ - "..\..\..\pjlib\include\pj\compat\cc_msvc.h"\ - "..\..\..\pjlib\include\pj\compat\ctype.h"\ - "..\..\..\pjlib\include\pj\compat\errno.h"\ - "..\..\..\pjlib\include\pj\compat\high_precision.h"\ - "..\..\..\pjlib\include\pj\compat\m_auto.h"\ - "..\..\..\pjlib\include\pj\compat\os_auto.h"\ - "..\..\..\pjlib\include\pj\compat\os_darwinos.h"\ - "..\..\..\pjlib\include\pj\compat\os_linux.h"\ - "..\..\..\pjlib\include\pj\compat\os_linux_kernel.h"\ - "..\..\..\pjlib\include\pj\compat\os_palmos.h"\ - "..\..\..\pjlib\include\pj\compat\os_rtems.h"\ - "..\..\..\pjlib\include\pj\compat\os_sunos.h"\ - "..\..\..\pjlib\include\pj\compat\os_win32.h"\ - "..\..\..\pjlib\include\pj\compat\os_win32_wince.h"\ - "..\..\..\pjlib\include\pj\compat\setjmp.h"\ - "..\..\..\pjlib\include\pj\compat\size_t.h"\ - "..\..\..\pjlib\include\pj\compat\string.h"\ - "..\..\..\pjlib\include\pj\config.h"\ - "..\..\..\pjlib\include\pj\config_site.h"\ - "..\..\..\pjlib\include\pj\config_site_sample.h"\ - "..\..\..\pjlib\include\pj\ctype.h"\ - "..\..\..\pjlib\include\pj\errno.h"\ - "..\..\..\pjlib\include\pj\except.h"\ - "..\..\..\pjlib\include\pj\fifobuf.h"\ - "..\..\..\pjlib\include\pj\file_access.h"\ - "..\..\..\pjlib\include\pj\file_io.h"\ - "..\..\..\pjlib\include\pj\guid.h"\ - "..\..\..\pjlib\include\pj\hash.h"\ - "..\..\..\pjlib\include\pj\ioqueue.h"\ - "..\..\..\pjlib\include\pj\list.h"\ - "..\..\..\pjlib\include\pj\list_i.h"\ - "..\..\..\pjlib\include\pj\lock.h"\ - "..\..\..\pjlib\include\pj\log.h"\ - "..\..\..\pjlib\include\pj\os.h"\ - "..\..\..\pjlib\include\pj\pool.h"\ - "..\..\..\pjlib\include\pj\pool_alt.h"\ - "..\..\..\pjlib\include\pj\pool_buf.h"\ - "..\..\..\pjlib\include\pj\pool_i.h"\ - "..\..\..\pjlib\include\pj\rand.h"\ - "..\..\..\pjlib\include\pj\rbtree.h"\ - "..\..\..\pjlib\include\pj\sock.h"\ - "..\..\..\pjlib\include\pj\sock_select.h"\ - "..\..\..\pjlib\include\pj\string.h"\ - "..\..\..\pjlib\include\pj\string_i.h"\ - "..\..\..\pjlib\include\pj\timer.h"\ - "..\..\..\pjlib\include\pj\types.h"\ - "..\..\..\pjlib\include\pj\unicode.h"\ - "..\..\..\pjlib\include\pjlib.h"\ - "..\..\include\pjlib-util\config.h"\ - "..\..\include\pjlib-util\errno.h"\ - "..\..\include\pjlib-util\stun_endpoint.h"\ - "..\..\include\pjlib-util\stun_msg.h"\ - "..\..\include\pjlib-util\stun_server.h"\ - "..\..\include\pjlib-util\types.h"\ - - -!ELSEIF "$(CFG)" == "pjlib_util_wince - Win32 (WCE ARMV4) Debug" - -DEP_CPP_STUN_S=\ - "..\..\..\pjlib\include\pj\addr_resolv.h"\ - "..\..\..\pjlib\include\pj\array.h"\ - "..\..\..\pjlib\include\pj\assert.h"\ - "..\..\..\pjlib\include\pj\compat\assert.h"\ - "..\..\..\pjlib\include\pj\compat\cc_gcc.h"\ - "..\..\..\pjlib\include\pj\compat\cc_msvc.h"\ - "..\..\..\pjlib\include\pj\compat\ctype.h"\ - "..\..\..\pjlib\include\pj\compat\errno.h"\ - "..\..\..\pjlib\include\pj\compat\high_precision.h"\ - "..\..\..\pjlib\include\pj\compat\m_auto.h"\ - "..\..\..\pjlib\include\pj\compat\os_auto.h"\ - "..\..\..\pjlib\include\pj\compat\os_darwinos.h"\ - "..\..\..\pjlib\include\pj\compat\os_linux.h"\ - "..\..\..\pjlib\include\pj\compat\os_linux_kernel.h"\ - "..\..\..\pjlib\include\pj\compat\os_palmos.h"\ - "..\..\..\pjlib\include\pj\compat\os_rtems.h"\ - "..\..\..\pjlib\include\pj\compat\os_sunos.h"\ - "..\..\..\pjlib\include\pj\compat\os_win32.h"\ - "..\..\..\pjlib\include\pj\compat\os_win32_wince.h"\ - "..\..\..\pjlib\include\pj\compat\setjmp.h"\ - "..\..\..\pjlib\include\pj\compat\size_t.h"\ - "..\..\..\pjlib\include\pj\compat\string.h"\ - "..\..\..\pjlib\include\pj\config.h"\ - "..\..\..\pjlib\include\pj\config_site.h"\ - "..\..\..\pjlib\include\pj\config_site_sample.h"\ - "..\..\..\pjlib\include\pj\ctype.h"\ - "..\..\..\pjlib\include\pj\errno.h"\ - "..\..\..\pjlib\include\pj\except.h"\ - "..\..\..\pjlib\include\pj\fifobuf.h"\ - "..\..\..\pjlib\include\pj\file_access.h"\ - "..\..\..\pjlib\include\pj\file_io.h"\ - "..\..\..\pjlib\include\pj\guid.h"\ - "..\..\..\pjlib\include\pj\hash.h"\ - "..\..\..\pjlib\include\pj\ioqueue.h"\ - "..\..\..\pjlib\include\pj\list.h"\ - "..\..\..\pjlib\include\pj\list_i.h"\ - "..\..\..\pjlib\include\pj\lock.h"\ - "..\..\..\pjlib\include\pj\log.h"\ - "..\..\..\pjlib\include\pj\os.h"\ - "..\..\..\pjlib\include\pj\pool.h"\ - "..\..\..\pjlib\include\pj\pool_alt.h"\ - "..\..\..\pjlib\include\pj\pool_buf.h"\ - "..\..\..\pjlib\include\pj\pool_i.h"\ - "..\..\..\pjlib\include\pj\rand.h"\ - "..\..\..\pjlib\include\pj\rbtree.h"\ - "..\..\..\pjlib\include\pj\sock.h"\ - "..\..\..\pjlib\include\pj\sock_select.h"\ - "..\..\..\pjlib\include\pj\string.h"\ - "..\..\..\pjlib\include\pj\string_i.h"\ - "..\..\..\pjlib\include\pj\timer.h"\ - "..\..\..\pjlib\include\pj\types.h"\ - "..\..\..\pjlib\include\pj\unicode.h"\ - "..\..\..\pjlib\include\pjlib.h"\ - "..\..\include\pjlib-util\config.h"\ - "..\..\include\pjlib-util\errno.h"\ - "..\..\include\pjlib-util\stun_endpoint.h"\ - "..\..\include\pjlib-util\stun_msg.h"\ - "..\..\include\pjlib-util\stun_server.h"\ - "..\..\include\pjlib-util\types.h"\ - - -!ELSEIF "$(CFG)" == "pjlib_util_wince - Win32 (WCE ARMV4T) Release" - -DEP_CPP_STUN_S=\ - "..\..\..\pjlib\include\pj\addr_resolv.h"\ - "..\..\..\pjlib\include\pj\array.h"\ - "..\..\..\pjlib\include\pj\assert.h"\ - "..\..\..\pjlib\include\pj\compat\assert.h"\ - "..\..\..\pjlib\include\pj\compat\cc_gcc.h"\ - "..\..\..\pjlib\include\pj\compat\cc_msvc.h"\ - "..\..\..\pjlib\include\pj\compat\ctype.h"\ - "..\..\..\pjlib\include\pj\compat\errno.h"\ - "..\..\..\pjlib\include\pj\compat\high_precision.h"\ - "..\..\..\pjlib\include\pj\compat\m_auto.h"\ - "..\..\..\pjlib\include\pj\compat\os_auto.h"\ - "..\..\..\pjlib\include\pj\compat\os_darwinos.h"\ - "..\..\..\pjlib\include\pj\compat\os_linux.h"\ - "..\..\..\pjlib\include\pj\compat\os_linux_kernel.h"\ - "..\..\..\pjlib\include\pj\compat\os_palmos.h"\ - "..\..\..\pjlib\include\pj\compat\os_rtems.h"\ - "..\..\..\pjlib\include\pj\compat\os_sunos.h"\ - "..\..\..\pjlib\include\pj\compat\os_win32.h"\ - "..\..\..\pjlib\include\pj\compat\os_win32_wince.h"\ - "..\..\..\pjlib\include\pj\compat\setjmp.h"\ - "..\..\..\pjlib\include\pj\compat\size_t.h"\ - "..\..\..\pjlib\include\pj\compat\string.h"\ - "..\..\..\pjlib\include\pj\config.h"\ - "..\..\..\pjlib\include\pj\config_site.h"\ - "..\..\..\pjlib\include\pj\config_site_sample.h"\ - "..\..\..\pjlib\include\pj\ctype.h"\ - "..\..\..\pjlib\include\pj\errno.h"\ - "..\..\..\pjlib\include\pj\except.h"\ - "..\..\..\pjlib\include\pj\fifobuf.h"\ - "..\..\..\pjlib\include\pj\file_access.h"\ - "..\..\..\pjlib\include\pj\file_io.h"\ - "..\..\..\pjlib\include\pj\guid.h"\ - "..\..\..\pjlib\include\pj\hash.h"\ - "..\..\..\pjlib\include\pj\ioqueue.h"\ - "..\..\..\pjlib\include\pj\list.h"\ - "..\..\..\pjlib\include\pj\list_i.h"\ - "..\..\..\pjlib\include\pj\lock.h"\ - "..\..\..\pjlib\include\pj\log.h"\ - "..\..\..\pjlib\include\pj\os.h"\ - "..\..\..\pjlib\include\pj\pool.h"\ - "..\..\..\pjlib\include\pj\pool_alt.h"\ - "..\..\..\pjlib\include\pj\pool_buf.h"\ - "..\..\..\pjlib\include\pj\pool_i.h"\ - "..\..\..\pjlib\include\pj\rand.h"\ - "..\..\..\pjlib\include\pj\rbtree.h"\ - "..\..\..\pjlib\include\pj\sock.h"\ - "..\..\..\pjlib\include\pj\sock_select.h"\ - "..\..\..\pjlib\include\pj\string.h"\ - "..\..\..\pjlib\include\pj\string_i.h"\ - "..\..\..\pjlib\include\pj\timer.h"\ - "..\..\..\pjlib\include\pj\types.h"\ - "..\..\..\pjlib\include\pj\unicode.h"\ - "..\..\..\pjlib\include\pjlib.h"\ - "..\..\include\pjlib-util\config.h"\ - "..\..\include\pjlib-util\errno.h"\ - "..\..\include\pjlib-util\stun_endpoint.h"\ - "..\..\include\pjlib-util\stun_msg.h"\ - "..\..\include\pjlib-util\stun_server.h"\ - "..\..\include\pjlib-util\types.h"\ - - -!ELSEIF "$(CFG)" == "pjlib_util_wince - Win32 (WCE ARMV4T) Debug" - -DEP_CPP_STUN_S=\ - "..\..\..\pjlib\include\pj\addr_resolv.h"\ - "..\..\..\pjlib\include\pj\array.h"\ - "..\..\..\pjlib\include\pj\assert.h"\ - "..\..\..\pjlib\include\pj\compat\assert.h"\ - "..\..\..\pjlib\include\pj\compat\cc_gcc.h"\ - "..\..\..\pjlib\include\pj\compat\cc_msvc.h"\ - "..\..\..\pjlib\include\pj\compat\ctype.h"\ - "..\..\..\pjlib\include\pj\compat\errno.h"\ - "..\..\..\pjlib\include\pj\compat\high_precision.h"\ - "..\..\..\pjlib\include\pj\compat\m_auto.h"\ - "..\..\..\pjlib\include\pj\compat\os_auto.h"\ - "..\..\..\pjlib\include\pj\compat\os_darwinos.h"\ - "..\..\..\pjlib\include\pj\compat\os_linux.h"\ - "..\..\..\pjlib\include\pj\compat\os_linux_kernel.h"\ - "..\..\..\pjlib\include\pj\compat\os_palmos.h"\ - "..\..\..\pjlib\include\pj\compat\os_rtems.h"\ - "..\..\..\pjlib\include\pj\compat\os_sunos.h"\ - "..\..\..\pjlib\include\pj\compat\os_win32.h"\ - "..\..\..\pjlib\include\pj\compat\os_win32_wince.h"\ - "..\..\..\pjlib\include\pj\compat\setjmp.h"\ - "..\..\..\pjlib\include\pj\compat\size_t.h"\ - "..\..\..\pjlib\include\pj\compat\string.h"\ - "..\..\..\pjlib\include\pj\config.h"\ - "..\..\..\pjlib\include\pj\config_site.h"\ - "..\..\..\pjlib\include\pj\config_site_sample.h"\ - "..\..\..\pjlib\include\pj\ctype.h"\ - "..\..\..\pjlib\include\pj\errno.h"\ - "..\..\..\pjlib\include\pj\except.h"\ - "..\..\..\pjlib\include\pj\fifobuf.h"\ - "..\..\..\pjlib\include\pj\file_access.h"\ - "..\..\..\pjlib\include\pj\file_io.h"\ - "..\..\..\pjlib\include\pj\guid.h"\ - "..\..\..\pjlib\include\pj\hash.h"\ - "..\..\..\pjlib\include\pj\ioqueue.h"\ - "..\..\..\pjlib\include\pj\list.h"\ - "..\..\..\pjlib\include\pj\list_i.h"\ - "..\..\..\pjlib\include\pj\lock.h"\ - "..\..\..\pjlib\include\pj\log.h"\ - "..\..\..\pjlib\include\pj\os.h"\ - "..\..\..\pjlib\include\pj\pool.h"\ - "..\..\..\pjlib\include\pj\pool_alt.h"\ - "..\..\..\pjlib\include\pj\pool_buf.h"\ - "..\..\..\pjlib\include\pj\pool_i.h"\ - "..\..\..\pjlib\include\pj\rand.h"\ - "..\..\..\pjlib\include\pj\rbtree.h"\ - "..\..\..\pjlib\include\pj\sock.h"\ - "..\..\..\pjlib\include\pj\sock_select.h"\ - "..\..\..\pjlib\include\pj\string.h"\ - "..\..\..\pjlib\include\pj\string_i.h"\ - "..\..\..\pjlib\include\pj\timer.h"\ - "..\..\..\pjlib\include\pj\types.h"\ - "..\..\..\pjlib\include\pj\unicode.h"\ - "..\..\..\pjlib\include\pjlib.h"\ - "..\..\include\pjlib-util\config.h"\ - "..\..\include\pjlib-util\errno.h"\ - "..\..\include\pjlib-util\stun_endpoint.h"\ - "..\..\include\pjlib-util\stun_msg.h"\ - "..\..\include\pjlib-util\stun_server.h"\ - "..\..\include\pjlib-util\types.h"\ - - -!ELSEIF "$(CFG)" == "pjlib_util_wince - Win32 (WCE x86) Release" - -DEP_CPP_STUN_S=\ - "..\..\..\pjlib\include\pj\addr_resolv.h"\ - "..\..\..\pjlib\include\pj\array.h"\ - "..\..\..\pjlib\include\pj\assert.h"\ - "..\..\..\pjlib\include\pj\compat\assert.h"\ - "..\..\..\pjlib\include\pj\compat\cc_gcc.h"\ - "..\..\..\pjlib\include\pj\compat\cc_msvc.h"\ - "..\..\..\pjlib\include\pj\compat\ctype.h"\ - "..\..\..\pjlib\include\pj\compat\errno.h"\ - "..\..\..\pjlib\include\pj\compat\high_precision.h"\ - "..\..\..\pjlib\include\pj\compat\m_auto.h"\ - "..\..\..\pjlib\include\pj\compat\os_auto.h"\ - "..\..\..\pjlib\include\pj\compat\os_darwinos.h"\ - "..\..\..\pjlib\include\pj\compat\os_linux.h"\ - "..\..\..\pjlib\include\pj\compat\os_linux_kernel.h"\ - "..\..\..\pjlib\include\pj\compat\os_palmos.h"\ - "..\..\..\pjlib\include\pj\compat\os_rtems.h"\ - "..\..\..\pjlib\include\pj\compat\os_sunos.h"\ - "..\..\..\pjlib\include\pj\compat\os_win32.h"\ - "..\..\..\pjlib\include\pj\compat\os_win32_wince.h"\ - "..\..\..\pjlib\include\pj\compat\setjmp.h"\ - "..\..\..\pjlib\include\pj\compat\size_t.h"\ - "..\..\..\pjlib\include\pj\compat\string.h"\ - "..\..\..\pjlib\include\pj\config.h"\ - "..\..\..\pjlib\include\pj\config_site.h"\ - "..\..\..\pjlib\include\pj\config_site_sample.h"\ - "..\..\..\pjlib\include\pj\ctype.h"\ - "..\..\..\pjlib\include\pj\errno.h"\ - "..\..\..\pjlib\include\pj\except.h"\ - "..\..\..\pjlib\include\pj\fifobuf.h"\ - "..\..\..\pjlib\include\pj\file_access.h"\ - "..\..\..\pjlib\include\pj\file_io.h"\ - "..\..\..\pjlib\include\pj\guid.h"\ - "..\..\..\pjlib\include\pj\hash.h"\ - "..\..\..\pjlib\include\pj\ioqueue.h"\ - "..\..\..\pjlib\include\pj\list.h"\ - "..\..\..\pjlib\include\pj\list_i.h"\ - "..\..\..\pjlib\include\pj\lock.h"\ - "..\..\..\pjlib\include\pj\log.h"\ - "..\..\..\pjlib\include\pj\os.h"\ - "..\..\..\pjlib\include\pj\pool.h"\ - "..\..\..\pjlib\include\pj\pool_alt.h"\ - "..\..\..\pjlib\include\pj\pool_buf.h"\ - "..\..\..\pjlib\include\pj\pool_i.h"\ - "..\..\..\pjlib\include\pj\rand.h"\ - "..\..\..\pjlib\include\pj\rbtree.h"\ - "..\..\..\pjlib\include\pj\sock.h"\ - "..\..\..\pjlib\include\pj\sock_select.h"\ - "..\..\..\pjlib\include\pj\string.h"\ - "..\..\..\pjlib\include\pj\string_i.h"\ - "..\..\..\pjlib\include\pj\timer.h"\ - "..\..\..\pjlib\include\pj\types.h"\ - "..\..\..\pjlib\include\pj\unicode.h"\ - "..\..\..\pjlib\include\pjlib.h"\ - "..\..\include\pjlib-util\config.h"\ - "..\..\include\pjlib-util\errno.h"\ - "..\..\include\pjlib-util\stun_endpoint.h"\ - "..\..\include\pjlib-util\stun_msg.h"\ - "..\..\include\pjlib-util\stun_server.h"\ - "..\..\include\pjlib-util\types.h"\ - - -!ELSEIF "$(CFG)" == "pjlib_util_wince - Win32 (WCE x86) Debug" - -DEP_CPP_STUN_S=\ - "..\..\..\pjlib\include\pj\addr_resolv.h"\ - "..\..\..\pjlib\include\pj\array.h"\ - "..\..\..\pjlib\include\pj\assert.h"\ - "..\..\..\pjlib\include\pj\compat\assert.h"\ - "..\..\..\pjlib\include\pj\compat\cc_gcc.h"\ - "..\..\..\pjlib\include\pj\compat\cc_msvc.h"\ - "..\..\..\pjlib\include\pj\compat\ctype.h"\ - "..\..\..\pjlib\include\pj\compat\errno.h"\ - "..\..\..\pjlib\include\pj\compat\high_precision.h"\ - "..\..\..\pjlib\include\pj\compat\m_auto.h"\ - "..\..\..\pjlib\include\pj\compat\os_auto.h"\ - "..\..\..\pjlib\include\pj\compat\os_darwinos.h"\ - "..\..\..\pjlib\include\pj\compat\os_linux.h"\ - "..\..\..\pjlib\include\pj\compat\os_linux_kernel.h"\ - "..\..\..\pjlib\include\pj\compat\os_palmos.h"\ - "..\..\..\pjlib\include\pj\compat\os_rtems.h"\ - "..\..\..\pjlib\include\pj\compat\os_sunos.h"\ - "..\..\..\pjlib\include\pj\compat\os_win32.h"\ - "..\..\..\pjlib\include\pj\compat\os_win32_wince.h"\ - "..\..\..\pjlib\include\pj\compat\setjmp.h"\ - "..\..\..\pjlib\include\pj\compat\size_t.h"\ - "..\..\..\pjlib\include\pj\compat\string.h"\ - "..\..\..\pjlib\include\pj\config.h"\ - "..\..\..\pjlib\include\pj\config_site.h"\ - "..\..\..\pjlib\include\pj\config_site_sample.h"\ - "..\..\..\pjlib\include\pj\ctype.h"\ - "..\..\..\pjlib\include\pj\errno.h"\ - "..\..\..\pjlib\include\pj\except.h"\ - "..\..\..\pjlib\include\pj\fifobuf.h"\ - "..\..\..\pjlib\include\pj\file_access.h"\ - "..\..\..\pjlib\include\pj\file_io.h"\ - "..\..\..\pjlib\include\pj\guid.h"\ - "..\..\..\pjlib\include\pj\hash.h"\ - "..\..\..\pjlib\include\pj\ioqueue.h"\ - "..\..\..\pjlib\include\pj\list.h"\ - "..\..\..\pjlib\include\pj\list_i.h"\ - "..\..\..\pjlib\include\pj\lock.h"\ - "..\..\..\pjlib\include\pj\log.h"\ - "..\..\..\pjlib\include\pj\os.h"\ - "..\..\..\pjlib\include\pj\pool.h"\ - "..\..\..\pjlib\include\pj\pool_alt.h"\ - "..\..\..\pjlib\include\pj\pool_buf.h"\ - "..\..\..\pjlib\include\pj\pool_i.h"\ - "..\..\..\pjlib\include\pj\rand.h"\ - "..\..\..\pjlib\include\pj\rbtree.h"\ - "..\..\..\pjlib\include\pj\sock.h"\ - "..\..\..\pjlib\include\pj\sock_select.h"\ - "..\..\..\pjlib\include\pj\string.h"\ - "..\..\..\pjlib\include\pj\string_i.h"\ - "..\..\..\pjlib\include\pj\timer.h"\ - "..\..\..\pjlib\include\pj\types.h"\ - "..\..\..\pjlib\include\pj\unicode.h"\ - "..\..\..\pjlib\include\pjlib.h"\ - "..\..\include\pjlib-util\config.h"\ - "..\..\include\pjlib-util\errno.h"\ - "..\..\include\pjlib-util\stun_endpoint.h"\ - "..\..\include\pjlib-util\stun_msg.h"\ - "..\..\include\pjlib-util\stun_server.h"\ - "..\..\include\pjlib-util\types.h"\ - - -!ENDIF - -# End Source File -# Begin Source File - -SOURCE="..\..\src\pjlib-util\stun_simple.c" - -!IF "$(CFG)" == "pjlib_util_wince - Win32 (WCE emulator) Release" - -DEP_CPP_STUN_SI=\ - "..\..\..\pjlib\include\pj\addr_resolv.h"\ - "..\..\..\pjlib\include\pj\array.h"\ - "..\..\..\pjlib\include\pj\assert.h"\ - "..\..\..\pjlib\include\pj\compat\assert.h"\ - "..\..\..\pjlib\include\pj\compat\cc_gcc.h"\ - "..\..\..\pjlib\include\pj\compat\cc_msvc.h"\ - "..\..\..\pjlib\include\pj\compat\ctype.h"\ - "..\..\..\pjlib\include\pj\compat\errno.h"\ - "..\..\..\pjlib\include\pj\compat\high_precision.h"\ - "..\..\..\pjlib\include\pj\compat\m_auto.h"\ - "..\..\..\pjlib\include\pj\compat\os_auto.h"\ - "..\..\..\pjlib\include\pj\compat\os_darwinos.h"\ - "..\..\..\pjlib\include\pj\compat\os_linux.h"\ - "..\..\..\pjlib\include\pj\compat\os_linux_kernel.h"\ - "..\..\..\pjlib\include\pj\compat\os_palmos.h"\ - "..\..\..\pjlib\include\pj\compat\os_rtems.h"\ - "..\..\..\pjlib\include\pj\compat\os_sunos.h"\ - "..\..\..\pjlib\include\pj\compat\os_win32.h"\ - "..\..\..\pjlib\include\pj\compat\os_win32_wince.h"\ - "..\..\..\pjlib\include\pj\compat\setjmp.h"\ - "..\..\..\pjlib\include\pj\compat\size_t.h"\ - "..\..\..\pjlib\include\pj\compat\string.h"\ - "..\..\..\pjlib\include\pj\config.h"\ - "..\..\..\pjlib\include\pj\config_site.h"\ - "..\..\..\pjlib\include\pj\config_site_sample.h"\ - "..\..\..\pjlib\include\pj\ctype.h"\ - "..\..\..\pjlib\include\pj\errno.h"\ - "..\..\..\pjlib\include\pj\except.h"\ - "..\..\..\pjlib\include\pj\fifobuf.h"\ - "..\..\..\pjlib\include\pj\file_access.h"\ - "..\..\..\pjlib\include\pj\file_io.h"\ - "..\..\..\pjlib\include\pj\guid.h"\ - "..\..\..\pjlib\include\pj\hash.h"\ - "..\..\..\pjlib\include\pj\ioqueue.h"\ - "..\..\..\pjlib\include\pj\list.h"\ - "..\..\..\pjlib\include\pj\list_i.h"\ - "..\..\..\pjlib\include\pj\lock.h"\ - "..\..\..\pjlib\include\pj\log.h"\ - "..\..\..\pjlib\include\pj\os.h"\ - "..\..\..\pjlib\include\pj\pool.h"\ - "..\..\..\pjlib\include\pj\pool_alt.h"\ - "..\..\..\pjlib\include\pj\pool_buf.h"\ - "..\..\..\pjlib\include\pj\pool_i.h"\ - "..\..\..\pjlib\include\pj\rand.h"\ - "..\..\..\pjlib\include\pj\rbtree.h"\ - "..\..\..\pjlib\include\pj\sock.h"\ - "..\..\..\pjlib\include\pj\sock_select.h"\ - "..\..\..\pjlib\include\pj\string.h"\ - "..\..\..\pjlib\include\pj\string_i.h"\ - "..\..\..\pjlib\include\pj\timer.h"\ - "..\..\..\pjlib\include\pj\types.h"\ - "..\..\..\pjlib\include\pj\unicode.h"\ - "..\..\..\pjlib\include\pjlib.h"\ - "..\..\include\pjlib-util\config.h"\ - "..\..\include\pjlib-util\errno.h"\ - "..\..\include\pjlib-util\stun_simple.h"\ - "..\..\include\pjlib-util\types.h"\ - - -!ELSEIF "$(CFG)" == "pjlib_util_wince - Win32 (WCE emulator) Debug" - -DEP_CPP_STUN_SI=\ - "..\..\..\pjlib\include\pj\addr_resolv.h"\ - "..\..\..\pjlib\include\pj\array.h"\ - "..\..\..\pjlib\include\pj\assert.h"\ - "..\..\..\pjlib\include\pj\compat\assert.h"\ - "..\..\..\pjlib\include\pj\compat\cc_gcc.h"\ - "..\..\..\pjlib\include\pj\compat\cc_msvc.h"\ - "..\..\..\pjlib\include\pj\compat\ctype.h"\ - "..\..\..\pjlib\include\pj\compat\errno.h"\ - "..\..\..\pjlib\include\pj\compat\high_precision.h"\ - "..\..\..\pjlib\include\pj\compat\m_auto.h"\ - "..\..\..\pjlib\include\pj\compat\os_auto.h"\ - "..\..\..\pjlib\include\pj\compat\os_darwinos.h"\ - "..\..\..\pjlib\include\pj\compat\os_linux.h"\ - "..\..\..\pjlib\include\pj\compat\os_linux_kernel.h"\ - "..\..\..\pjlib\include\pj\compat\os_palmos.h"\ - "..\..\..\pjlib\include\pj\compat\os_rtems.h"\ - "..\..\..\pjlib\include\pj\compat\os_sunos.h"\ - "..\..\..\pjlib\include\pj\compat\os_win32.h"\ - "..\..\..\pjlib\include\pj\compat\os_win32_wince.h"\ - "..\..\..\pjlib\include\pj\compat\setjmp.h"\ - "..\..\..\pjlib\include\pj\compat\size_t.h"\ - "..\..\..\pjlib\include\pj\compat\string.h"\ - "..\..\..\pjlib\include\pj\config.h"\ - "..\..\..\pjlib\include\pj\config_site.h"\ - "..\..\..\pjlib\include\pj\config_site_sample.h"\ - "..\..\..\pjlib\include\pj\ctype.h"\ - "..\..\..\pjlib\include\pj\errno.h"\ - "..\..\..\pjlib\include\pj\except.h"\ - "..\..\..\pjlib\include\pj\fifobuf.h"\ - "..\..\..\pjlib\include\pj\file_access.h"\ - "..\..\..\pjlib\include\pj\file_io.h"\ - "..\..\..\pjlib\include\pj\guid.h"\ - "..\..\..\pjlib\include\pj\hash.h"\ - "..\..\..\pjlib\include\pj\ioqueue.h"\ - "..\..\..\pjlib\include\pj\list.h"\ - "..\..\..\pjlib\include\pj\list_i.h"\ - "..\..\..\pjlib\include\pj\lock.h"\ - "..\..\..\pjlib\include\pj\log.h"\ - "..\..\..\pjlib\include\pj\os.h"\ - "..\..\..\pjlib\include\pj\pool.h"\ - "..\..\..\pjlib\include\pj\pool_alt.h"\ - "..\..\..\pjlib\include\pj\pool_buf.h"\ - "..\..\..\pjlib\include\pj\pool_i.h"\ - "..\..\..\pjlib\include\pj\rand.h"\ - "..\..\..\pjlib\include\pj\rbtree.h"\ - "..\..\..\pjlib\include\pj\sock.h"\ - "..\..\..\pjlib\include\pj\sock_select.h"\ - "..\..\..\pjlib\include\pj\string.h"\ - "..\..\..\pjlib\include\pj\string_i.h"\ - "..\..\..\pjlib\include\pj\timer.h"\ - "..\..\..\pjlib\include\pj\types.h"\ - "..\..\..\pjlib\include\pj\unicode.h"\ - "..\..\..\pjlib\include\pjlib.h"\ - "..\..\include\pjlib-util\config.h"\ - "..\..\include\pjlib-util\errno.h"\ - "..\..\include\pjlib-util\stun_simple.h"\ - "..\..\include\pjlib-util\types.h"\ - - -!ELSEIF "$(CFG)" == "pjlib_util_wince - Win32 (WCE ARMV4I) Release" - -DEP_CPP_STUN_SI=\ - "..\..\..\pjlib\include\pj\addr_resolv.h"\ - "..\..\..\pjlib\include\pj\array.h"\ - "..\..\..\pjlib\include\pj\assert.h"\ - "..\..\..\pjlib\include\pj\compat\assert.h"\ - "..\..\..\pjlib\include\pj\compat\cc_gcc.h"\ - "..\..\..\pjlib\include\pj\compat\cc_msvc.h"\ - "..\..\..\pjlib\include\pj\compat\ctype.h"\ - "..\..\..\pjlib\include\pj\compat\errno.h"\ - "..\..\..\pjlib\include\pj\compat\high_precision.h"\ - "..\..\..\pjlib\include\pj\compat\m_auto.h"\ - "..\..\..\pjlib\include\pj\compat\os_auto.h"\ - "..\..\..\pjlib\include\pj\compat\os_darwinos.h"\ - "..\..\..\pjlib\include\pj\compat\os_linux.h"\ - "..\..\..\pjlib\include\pj\compat\os_linux_kernel.h"\ - "..\..\..\pjlib\include\pj\compat\os_palmos.h"\ - "..\..\..\pjlib\include\pj\compat\os_rtems.h"\ - "..\..\..\pjlib\include\pj\compat\os_sunos.h"\ - "..\..\..\pjlib\include\pj\compat\os_win32.h"\ - "..\..\..\pjlib\include\pj\compat\os_win32_wince.h"\ - "..\..\..\pjlib\include\pj\compat\setjmp.h"\ - "..\..\..\pjlib\include\pj\compat\size_t.h"\ - "..\..\..\pjlib\include\pj\compat\string.h"\ - "..\..\..\pjlib\include\pj\config.h"\ - "..\..\..\pjlib\include\pj\config_site.h"\ - "..\..\..\pjlib\include\pj\config_site_sample.h"\ - "..\..\..\pjlib\include\pj\ctype.h"\ - "..\..\..\pjlib\include\pj\errno.h"\ - "..\..\..\pjlib\include\pj\except.h"\ - "..\..\..\pjlib\include\pj\fifobuf.h"\ - "..\..\..\pjlib\include\pj\file_access.h"\ - "..\..\..\pjlib\include\pj\file_io.h"\ - "..\..\..\pjlib\include\pj\guid.h"\ - "..\..\..\pjlib\include\pj\hash.h"\ - "..\..\..\pjlib\include\pj\ioqueue.h"\ - "..\..\..\pjlib\include\pj\list.h"\ - "..\..\..\pjlib\include\pj\list_i.h"\ - "..\..\..\pjlib\include\pj\lock.h"\ - "..\..\..\pjlib\include\pj\log.h"\ - "..\..\..\pjlib\include\pj\os.h"\ - "..\..\..\pjlib\include\pj\pool.h"\ - "..\..\..\pjlib\include\pj\pool_alt.h"\ - "..\..\..\pjlib\include\pj\pool_buf.h"\ - "..\..\..\pjlib\include\pj\pool_i.h"\ - "..\..\..\pjlib\include\pj\rand.h"\ - "..\..\..\pjlib\include\pj\rbtree.h"\ - "..\..\..\pjlib\include\pj\sock.h"\ - "..\..\..\pjlib\include\pj\sock_select.h"\ - "..\..\..\pjlib\include\pj\string.h"\ - "..\..\..\pjlib\include\pj\string_i.h"\ - "..\..\..\pjlib\include\pj\timer.h"\ - "..\..\..\pjlib\include\pj\types.h"\ - "..\..\..\pjlib\include\pj\unicode.h"\ - "..\..\..\pjlib\include\pjlib.h"\ - "..\..\include\pjlib-util\config.h"\ - "..\..\include\pjlib-util\errno.h"\ - "..\..\include\pjlib-util\stun_simple.h"\ - "..\..\include\pjlib-util\types.h"\ - - -!ELSEIF "$(CFG)" == "pjlib_util_wince - Win32 (WCE ARMV4I) Debug" - -DEP_CPP_STUN_SI=\ - "..\..\..\pjlib\include\pj\addr_resolv.h"\ - "..\..\..\pjlib\include\pj\array.h"\ - "..\..\..\pjlib\include\pj\assert.h"\ - "..\..\..\pjlib\include\pj\compat\assert.h"\ - "..\..\..\pjlib\include\pj\compat\cc_gcc.h"\ - "..\..\..\pjlib\include\pj\compat\cc_msvc.h"\ - "..\..\..\pjlib\include\pj\compat\ctype.h"\ - "..\..\..\pjlib\include\pj\compat\errno.h"\ - "..\..\..\pjlib\include\pj\compat\high_precision.h"\ - "..\..\..\pjlib\include\pj\compat\m_auto.h"\ - "..\..\..\pjlib\include\pj\compat\os_auto.h"\ - "..\..\..\pjlib\include\pj\compat\os_darwinos.h"\ - "..\..\..\pjlib\include\pj\compat\os_linux.h"\ - "..\..\..\pjlib\include\pj\compat\os_linux_kernel.h"\ - "..\..\..\pjlib\include\pj\compat\os_palmos.h"\ - "..\..\..\pjlib\include\pj\compat\os_rtems.h"\ - "..\..\..\pjlib\include\pj\compat\os_sunos.h"\ - "..\..\..\pjlib\include\pj\compat\os_win32.h"\ - "..\..\..\pjlib\include\pj\compat\os_win32_wince.h"\ - "..\..\..\pjlib\include\pj\compat\setjmp.h"\ - "..\..\..\pjlib\include\pj\compat\size_t.h"\ - "..\..\..\pjlib\include\pj\compat\string.h"\ - "..\..\..\pjlib\include\pj\config.h"\ - "..\..\..\pjlib\include\pj\config_site.h"\ - "..\..\..\pjlib\include\pj\config_site_sample.h"\ - "..\..\..\pjlib\include\pj\ctype.h"\ - "..\..\..\pjlib\include\pj\errno.h"\ - "..\..\..\pjlib\include\pj\except.h"\ - "..\..\..\pjlib\include\pj\fifobuf.h"\ - "..\..\..\pjlib\include\pj\file_access.h"\ - "..\..\..\pjlib\include\pj\file_io.h"\ - "..\..\..\pjlib\include\pj\guid.h"\ - "..\..\..\pjlib\include\pj\hash.h"\ - "..\..\..\pjlib\include\pj\ioqueue.h"\ - "..\..\..\pjlib\include\pj\list.h"\ - "..\..\..\pjlib\include\pj\list_i.h"\ - "..\..\..\pjlib\include\pj\lock.h"\ - "..\..\..\pjlib\include\pj\log.h"\ - "..\..\..\pjlib\include\pj\os.h"\ - "..\..\..\pjlib\include\pj\pool.h"\ - "..\..\..\pjlib\include\pj\pool_alt.h"\ - "..\..\..\pjlib\include\pj\pool_buf.h"\ - "..\..\..\pjlib\include\pj\pool_i.h"\ - "..\..\..\pjlib\include\pj\rand.h"\ - "..\..\..\pjlib\include\pj\rbtree.h"\ - "..\..\..\pjlib\include\pj\sock.h"\ - "..\..\..\pjlib\include\pj\sock_select.h"\ - "..\..\..\pjlib\include\pj\string.h"\ - "..\..\..\pjlib\include\pj\string_i.h"\ - "..\..\..\pjlib\include\pj\timer.h"\ - "..\..\..\pjlib\include\pj\types.h"\ - "..\..\..\pjlib\include\pj\unicode.h"\ - "..\..\..\pjlib\include\pjlib.h"\ - "..\..\include\pjlib-util\config.h"\ - "..\..\include\pjlib-util\errno.h"\ - "..\..\include\pjlib-util\stun_simple.h"\ - "..\..\include\pjlib-util\types.h"\ - - -!ELSEIF "$(CFG)" == "pjlib_util_wince - Win32 (WCE ARMV4) Release" - -DEP_CPP_STUN_SI=\ - "..\..\..\pjlib\include\pj\addr_resolv.h"\ - "..\..\..\pjlib\include\pj\array.h"\ - "..\..\..\pjlib\include\pj\assert.h"\ - "..\..\..\pjlib\include\pj\compat\assert.h"\ - "..\..\..\pjlib\include\pj\compat\cc_gcc.h"\ - "..\..\..\pjlib\include\pj\compat\cc_msvc.h"\ - "..\..\..\pjlib\include\pj\compat\ctype.h"\ - "..\..\..\pjlib\include\pj\compat\errno.h"\ - "..\..\..\pjlib\include\pj\compat\high_precision.h"\ - "..\..\..\pjlib\include\pj\compat\m_auto.h"\ - "..\..\..\pjlib\include\pj\compat\os_auto.h"\ - "..\..\..\pjlib\include\pj\compat\os_darwinos.h"\ - "..\..\..\pjlib\include\pj\compat\os_linux.h"\ - "..\..\..\pjlib\include\pj\compat\os_linux_kernel.h"\ - "..\..\..\pjlib\include\pj\compat\os_palmos.h"\ - "..\..\..\pjlib\include\pj\compat\os_rtems.h"\ - "..\..\..\pjlib\include\pj\compat\os_sunos.h"\ - "..\..\..\pjlib\include\pj\compat\os_win32.h"\ - "..\..\..\pjlib\include\pj\compat\os_win32_wince.h"\ - "..\..\..\pjlib\include\pj\compat\setjmp.h"\ - "..\..\..\pjlib\include\pj\compat\size_t.h"\ - "..\..\..\pjlib\include\pj\compat\string.h"\ - "..\..\..\pjlib\include\pj\config.h"\ - "..\..\..\pjlib\include\pj\config_site.h"\ - "..\..\..\pjlib\include\pj\config_site_sample.h"\ - "..\..\..\pjlib\include\pj\ctype.h"\ - "..\..\..\pjlib\include\pj\errno.h"\ - "..\..\..\pjlib\include\pj\except.h"\ - "..\..\..\pjlib\include\pj\fifobuf.h"\ - "..\..\..\pjlib\include\pj\file_access.h"\ - "..\..\..\pjlib\include\pj\file_io.h"\ - "..\..\..\pjlib\include\pj\guid.h"\ - "..\..\..\pjlib\include\pj\hash.h"\ - "..\..\..\pjlib\include\pj\ioqueue.h"\ - "..\..\..\pjlib\include\pj\list.h"\ - "..\..\..\pjlib\include\pj\list_i.h"\ - "..\..\..\pjlib\include\pj\lock.h"\ - "..\..\..\pjlib\include\pj\log.h"\ - "..\..\..\pjlib\include\pj\os.h"\ - "..\..\..\pjlib\include\pj\pool.h"\ - "..\..\..\pjlib\include\pj\pool_alt.h"\ - "..\..\..\pjlib\include\pj\pool_buf.h"\ - "..\..\..\pjlib\include\pj\pool_i.h"\ - "..\..\..\pjlib\include\pj\rand.h"\ - "..\..\..\pjlib\include\pj\rbtree.h"\ - "..\..\..\pjlib\include\pj\sock.h"\ - "..\..\..\pjlib\include\pj\sock_select.h"\ - "..\..\..\pjlib\include\pj\string.h"\ - "..\..\..\pjlib\include\pj\string_i.h"\ - "..\..\..\pjlib\include\pj\timer.h"\ - "..\..\..\pjlib\include\pj\types.h"\ - "..\..\..\pjlib\include\pj\unicode.h"\ - "..\..\..\pjlib\include\pjlib.h"\ - "..\..\include\pjlib-util\config.h"\ - "..\..\include\pjlib-util\errno.h"\ - "..\..\include\pjlib-util\stun_simple.h"\ - "..\..\include\pjlib-util\types.h"\ - - -!ELSEIF "$(CFG)" == "pjlib_util_wince - Win32 (WCE ARMV4) Debug" - -DEP_CPP_STUN_SI=\ - "..\..\..\pjlib\include\pj\addr_resolv.h"\ - "..\..\..\pjlib\include\pj\array.h"\ - "..\..\..\pjlib\include\pj\assert.h"\ - "..\..\..\pjlib\include\pj\compat\assert.h"\ - "..\..\..\pjlib\include\pj\compat\cc_gcc.h"\ - "..\..\..\pjlib\include\pj\compat\cc_msvc.h"\ - "..\..\..\pjlib\include\pj\compat\ctype.h"\ - "..\..\..\pjlib\include\pj\compat\errno.h"\ - "..\..\..\pjlib\include\pj\compat\high_precision.h"\ - "..\..\..\pjlib\include\pj\compat\m_auto.h"\ - "..\..\..\pjlib\include\pj\compat\os_auto.h"\ - "..\..\..\pjlib\include\pj\compat\os_darwinos.h"\ - "..\..\..\pjlib\include\pj\compat\os_linux.h"\ - "..\..\..\pjlib\include\pj\compat\os_linux_kernel.h"\ - "..\..\..\pjlib\include\pj\compat\os_palmos.h"\ - "..\..\..\pjlib\include\pj\compat\os_rtems.h"\ - "..\..\..\pjlib\include\pj\compat\os_sunos.h"\ - "..\..\..\pjlib\include\pj\compat\os_win32.h"\ - "..\..\..\pjlib\include\pj\compat\os_win32_wince.h"\ - "..\..\..\pjlib\include\pj\compat\setjmp.h"\ - "..\..\..\pjlib\include\pj\compat\size_t.h"\ - "..\..\..\pjlib\include\pj\compat\string.h"\ - "..\..\..\pjlib\include\pj\config.h"\ - "..\..\..\pjlib\include\pj\config_site.h"\ - "..\..\..\pjlib\include\pj\config_site_sample.h"\ - "..\..\..\pjlib\include\pj\ctype.h"\ - "..\..\..\pjlib\include\pj\errno.h"\ - "..\..\..\pjlib\include\pj\except.h"\ - "..\..\..\pjlib\include\pj\fifobuf.h"\ - "..\..\..\pjlib\include\pj\file_access.h"\ - "..\..\..\pjlib\include\pj\file_io.h"\ - "..\..\..\pjlib\include\pj\guid.h"\ - "..\..\..\pjlib\include\pj\hash.h"\ - "..\..\..\pjlib\include\pj\ioqueue.h"\ - "..\..\..\pjlib\include\pj\list.h"\ - "..\..\..\pjlib\include\pj\list_i.h"\ - "..\..\..\pjlib\include\pj\lock.h"\ - "..\..\..\pjlib\include\pj\log.h"\ - "..\..\..\pjlib\include\pj\os.h"\ - "..\..\..\pjlib\include\pj\pool.h"\ - "..\..\..\pjlib\include\pj\pool_alt.h"\ - "..\..\..\pjlib\include\pj\pool_buf.h"\ - "..\..\..\pjlib\include\pj\pool_i.h"\ - "..\..\..\pjlib\include\pj\rand.h"\ - "..\..\..\pjlib\include\pj\rbtree.h"\ - "..\..\..\pjlib\include\pj\sock.h"\ - "..\..\..\pjlib\include\pj\sock_select.h"\ - "..\..\..\pjlib\include\pj\string.h"\ - "..\..\..\pjlib\include\pj\string_i.h"\ - "..\..\..\pjlib\include\pj\timer.h"\ - "..\..\..\pjlib\include\pj\types.h"\ - "..\..\..\pjlib\include\pj\unicode.h"\ - "..\..\..\pjlib\include\pjlib.h"\ - "..\..\include\pjlib-util\config.h"\ - "..\..\include\pjlib-util\errno.h"\ - "..\..\include\pjlib-util\stun_simple.h"\ - "..\..\include\pjlib-util\types.h"\ - - -!ELSEIF "$(CFG)" == "pjlib_util_wince - Win32 (WCE ARMV4T) Release" - -DEP_CPP_STUN_SI=\ - "..\..\..\pjlib\include\pj\addr_resolv.h"\ - "..\..\..\pjlib\include\pj\array.h"\ - "..\..\..\pjlib\include\pj\assert.h"\ - "..\..\..\pjlib\include\pj\compat\assert.h"\ - "..\..\..\pjlib\include\pj\compat\cc_gcc.h"\ - "..\..\..\pjlib\include\pj\compat\cc_msvc.h"\ - "..\..\..\pjlib\include\pj\compat\ctype.h"\ - "..\..\..\pjlib\include\pj\compat\errno.h"\ - "..\..\..\pjlib\include\pj\compat\high_precision.h"\ - "..\..\..\pjlib\include\pj\compat\m_auto.h"\ - "..\..\..\pjlib\include\pj\compat\os_auto.h"\ - "..\..\..\pjlib\include\pj\compat\os_darwinos.h"\ - "..\..\..\pjlib\include\pj\compat\os_linux.h"\ - "..\..\..\pjlib\include\pj\compat\os_linux_kernel.h"\ - "..\..\..\pjlib\include\pj\compat\os_palmos.h"\ - "..\..\..\pjlib\include\pj\compat\os_rtems.h"\ - "..\..\..\pjlib\include\pj\compat\os_sunos.h"\ - "..\..\..\pjlib\include\pj\compat\os_win32.h"\ - "..\..\..\pjlib\include\pj\compat\os_win32_wince.h"\ - "..\..\..\pjlib\include\pj\compat\setjmp.h"\ - "..\..\..\pjlib\include\pj\compat\size_t.h"\ - "..\..\..\pjlib\include\pj\compat\string.h"\ - "..\..\..\pjlib\include\pj\config.h"\ - "..\..\..\pjlib\include\pj\config_site.h"\ - "..\..\..\pjlib\include\pj\config_site_sample.h"\ - "..\..\..\pjlib\include\pj\ctype.h"\ - "..\..\..\pjlib\include\pj\errno.h"\ - "..\..\..\pjlib\include\pj\except.h"\ - "..\..\..\pjlib\include\pj\fifobuf.h"\ - "..\..\..\pjlib\include\pj\file_access.h"\ - "..\..\..\pjlib\include\pj\file_io.h"\ - "..\..\..\pjlib\include\pj\guid.h"\ - "..\..\..\pjlib\include\pj\hash.h"\ - "..\..\..\pjlib\include\pj\ioqueue.h"\ - "..\..\..\pjlib\include\pj\list.h"\ - "..\..\..\pjlib\include\pj\list_i.h"\ - "..\..\..\pjlib\include\pj\lock.h"\ - "..\..\..\pjlib\include\pj\log.h"\ - "..\..\..\pjlib\include\pj\os.h"\ - "..\..\..\pjlib\include\pj\pool.h"\ - "..\..\..\pjlib\include\pj\pool_alt.h"\ - "..\..\..\pjlib\include\pj\pool_buf.h"\ - "..\..\..\pjlib\include\pj\pool_i.h"\ - "..\..\..\pjlib\include\pj\rand.h"\ - "..\..\..\pjlib\include\pj\rbtree.h"\ - "..\..\..\pjlib\include\pj\sock.h"\ - "..\..\..\pjlib\include\pj\sock_select.h"\ - "..\..\..\pjlib\include\pj\string.h"\ - "..\..\..\pjlib\include\pj\string_i.h"\ - "..\..\..\pjlib\include\pj\timer.h"\ - "..\..\..\pjlib\include\pj\types.h"\ - "..\..\..\pjlib\include\pj\unicode.h"\ - "..\..\..\pjlib\include\pjlib.h"\ - "..\..\include\pjlib-util\config.h"\ - "..\..\include\pjlib-util\errno.h"\ - "..\..\include\pjlib-util\stun_simple.h"\ - "..\..\include\pjlib-util\types.h"\ - - -!ELSEIF "$(CFG)" == "pjlib_util_wince - Win32 (WCE ARMV4T) Debug" - -DEP_CPP_STUN_SI=\ - "..\..\..\pjlib\include\pj\addr_resolv.h"\ - "..\..\..\pjlib\include\pj\array.h"\ - "..\..\..\pjlib\include\pj\assert.h"\ - "..\..\..\pjlib\include\pj\compat\assert.h"\ - "..\..\..\pjlib\include\pj\compat\cc_gcc.h"\ - "..\..\..\pjlib\include\pj\compat\cc_msvc.h"\ - "..\..\..\pjlib\include\pj\compat\ctype.h"\ - "..\..\..\pjlib\include\pj\compat\errno.h"\ - "..\..\..\pjlib\include\pj\compat\high_precision.h"\ - "..\..\..\pjlib\include\pj\compat\m_auto.h"\ - "..\..\..\pjlib\include\pj\compat\os_auto.h"\ - "..\..\..\pjlib\include\pj\compat\os_darwinos.h"\ - "..\..\..\pjlib\include\pj\compat\os_linux.h"\ - "..\..\..\pjlib\include\pj\compat\os_linux_kernel.h"\ - "..\..\..\pjlib\include\pj\compat\os_palmos.h"\ - "..\..\..\pjlib\include\pj\compat\os_rtems.h"\ - "..\..\..\pjlib\include\pj\compat\os_sunos.h"\ - "..\..\..\pjlib\include\pj\compat\os_win32.h"\ - "..\..\..\pjlib\include\pj\compat\os_win32_wince.h"\ - "..\..\..\pjlib\include\pj\compat\setjmp.h"\ - "..\..\..\pjlib\include\pj\compat\size_t.h"\ - "..\..\..\pjlib\include\pj\compat\string.h"\ - "..\..\..\pjlib\include\pj\config.h"\ - "..\..\..\pjlib\include\pj\config_site.h"\ - "..\..\..\pjlib\include\pj\config_site_sample.h"\ - "..\..\..\pjlib\include\pj\ctype.h"\ - "..\..\..\pjlib\include\pj\errno.h"\ - "..\..\..\pjlib\include\pj\except.h"\ - "..\..\..\pjlib\include\pj\fifobuf.h"\ - "..\..\..\pjlib\include\pj\file_access.h"\ - "..\..\..\pjlib\include\pj\file_io.h"\ - "..\..\..\pjlib\include\pj\guid.h"\ - "..\..\..\pjlib\include\pj\hash.h"\ - "..\..\..\pjlib\include\pj\ioqueue.h"\ - "..\..\..\pjlib\include\pj\list.h"\ - "..\..\..\pjlib\include\pj\list_i.h"\ - "..\..\..\pjlib\include\pj\lock.h"\ - "..\..\..\pjlib\include\pj\log.h"\ - "..\..\..\pjlib\include\pj\os.h"\ - "..\..\..\pjlib\include\pj\pool.h"\ - "..\..\..\pjlib\include\pj\pool_alt.h"\ - "..\..\..\pjlib\include\pj\pool_buf.h"\ - "..\..\..\pjlib\include\pj\pool_i.h"\ - "..\..\..\pjlib\include\pj\rand.h"\ - "..\..\..\pjlib\include\pj\rbtree.h"\ - "..\..\..\pjlib\include\pj\sock.h"\ - "..\..\..\pjlib\include\pj\sock_select.h"\ - "..\..\..\pjlib\include\pj\string.h"\ - "..\..\..\pjlib\include\pj\string_i.h"\ - "..\..\..\pjlib\include\pj\timer.h"\ - "..\..\..\pjlib\include\pj\types.h"\ - "..\..\..\pjlib\include\pj\unicode.h"\ - "..\..\..\pjlib\include\pjlib.h"\ - "..\..\include\pjlib-util\config.h"\ - "..\..\include\pjlib-util\errno.h"\ - "..\..\include\pjlib-util\stun_simple.h"\ - "..\..\include\pjlib-util\types.h"\ - - -!ELSEIF "$(CFG)" == "pjlib_util_wince - Win32 (WCE x86) Release" - -DEP_CPP_STUN_SI=\ - "..\..\..\pjlib\include\pj\addr_resolv.h"\ - "..\..\..\pjlib\include\pj\array.h"\ - "..\..\..\pjlib\include\pj\assert.h"\ - "..\..\..\pjlib\include\pj\compat\assert.h"\ - "..\..\..\pjlib\include\pj\compat\cc_gcc.h"\ - "..\..\..\pjlib\include\pj\compat\cc_msvc.h"\ - "..\..\..\pjlib\include\pj\compat\ctype.h"\ - "..\..\..\pjlib\include\pj\compat\errno.h"\ - "..\..\..\pjlib\include\pj\compat\high_precision.h"\ - "..\..\..\pjlib\include\pj\compat\m_auto.h"\ - "..\..\..\pjlib\include\pj\compat\os_auto.h"\ - "..\..\..\pjlib\include\pj\compat\os_darwinos.h"\ - "..\..\..\pjlib\include\pj\compat\os_linux.h"\ - "..\..\..\pjlib\include\pj\compat\os_linux_kernel.h"\ - "..\..\..\pjlib\include\pj\compat\os_palmos.h"\ - "..\..\..\pjlib\include\pj\compat\os_rtems.h"\ - "..\..\..\pjlib\include\pj\compat\os_sunos.h"\ - "..\..\..\pjlib\include\pj\compat\os_win32.h"\ - "..\..\..\pjlib\include\pj\compat\os_win32_wince.h"\ - "..\..\..\pjlib\include\pj\compat\setjmp.h"\ - "..\..\..\pjlib\include\pj\compat\size_t.h"\ - "..\..\..\pjlib\include\pj\compat\string.h"\ - "..\..\..\pjlib\include\pj\config.h"\ - "..\..\..\pjlib\include\pj\config_site.h"\ - "..\..\..\pjlib\include\pj\config_site_sample.h"\ - "..\..\..\pjlib\include\pj\ctype.h"\ - "..\..\..\pjlib\include\pj\errno.h"\ - "..\..\..\pjlib\include\pj\except.h"\ - "..\..\..\pjlib\include\pj\fifobuf.h"\ - "..\..\..\pjlib\include\pj\file_access.h"\ - "..\..\..\pjlib\include\pj\file_io.h"\ - "..\..\..\pjlib\include\pj\guid.h"\ - "..\..\..\pjlib\include\pj\hash.h"\ - "..\..\..\pjlib\include\pj\ioqueue.h"\ - "..\..\..\pjlib\include\pj\list.h"\ - "..\..\..\pjlib\include\pj\list_i.h"\ - "..\..\..\pjlib\include\pj\lock.h"\ - "..\..\..\pjlib\include\pj\log.h"\ - "..\..\..\pjlib\include\pj\os.h"\ - "..\..\..\pjlib\include\pj\pool.h"\ - "..\..\..\pjlib\include\pj\pool_alt.h"\ - "..\..\..\pjlib\include\pj\pool_buf.h"\ - "..\..\..\pjlib\include\pj\pool_i.h"\ - "..\..\..\pjlib\include\pj\rand.h"\ - "..\..\..\pjlib\include\pj\rbtree.h"\ - "..\..\..\pjlib\include\pj\sock.h"\ - "..\..\..\pjlib\include\pj\sock_select.h"\ - "..\..\..\pjlib\include\pj\string.h"\ - "..\..\..\pjlib\include\pj\string_i.h"\ - "..\..\..\pjlib\include\pj\timer.h"\ - "..\..\..\pjlib\include\pj\types.h"\ - "..\..\..\pjlib\include\pj\unicode.h"\ - "..\..\..\pjlib\include\pjlib.h"\ - "..\..\include\pjlib-util\config.h"\ - "..\..\include\pjlib-util\errno.h"\ - "..\..\include\pjlib-util\stun_simple.h"\ - "..\..\include\pjlib-util\types.h"\ - - -!ELSEIF "$(CFG)" == "pjlib_util_wince - Win32 (WCE x86) Debug" - -DEP_CPP_STUN_SI=\ - "..\..\..\pjlib\include\pj\addr_resolv.h"\ - "..\..\..\pjlib\include\pj\array.h"\ - "..\..\..\pjlib\include\pj\assert.h"\ - "..\..\..\pjlib\include\pj\compat\assert.h"\ - "..\..\..\pjlib\include\pj\compat\cc_gcc.h"\ - "..\..\..\pjlib\include\pj\compat\cc_msvc.h"\ - "..\..\..\pjlib\include\pj\compat\ctype.h"\ - "..\..\..\pjlib\include\pj\compat\errno.h"\ - "..\..\..\pjlib\include\pj\compat\high_precision.h"\ - "..\..\..\pjlib\include\pj\compat\m_auto.h"\ - "..\..\..\pjlib\include\pj\compat\os_auto.h"\ - "..\..\..\pjlib\include\pj\compat\os_darwinos.h"\ - "..\..\..\pjlib\include\pj\compat\os_linux.h"\ - "..\..\..\pjlib\include\pj\compat\os_linux_kernel.h"\ - "..\..\..\pjlib\include\pj\compat\os_palmos.h"\ - "..\..\..\pjlib\include\pj\compat\os_rtems.h"\ - "..\..\..\pjlib\include\pj\compat\os_sunos.h"\ - "..\..\..\pjlib\include\pj\compat\os_win32.h"\ - "..\..\..\pjlib\include\pj\compat\os_win32_wince.h"\ - "..\..\..\pjlib\include\pj\compat\setjmp.h"\ - "..\..\..\pjlib\include\pj\compat\size_t.h"\ - "..\..\..\pjlib\include\pj\compat\string.h"\ - "..\..\..\pjlib\include\pj\config.h"\ - "..\..\..\pjlib\include\pj\config_site.h"\ - "..\..\..\pjlib\include\pj\config_site_sample.h"\ - "..\..\..\pjlib\include\pj\ctype.h"\ - "..\..\..\pjlib\include\pj\errno.h"\ - "..\..\..\pjlib\include\pj\except.h"\ - "..\..\..\pjlib\include\pj\fifobuf.h"\ - "..\..\..\pjlib\include\pj\file_access.h"\ - "..\..\..\pjlib\include\pj\file_io.h"\ - "..\..\..\pjlib\include\pj\guid.h"\ - "..\..\..\pjlib\include\pj\hash.h"\ - "..\..\..\pjlib\include\pj\ioqueue.h"\ - "..\..\..\pjlib\include\pj\list.h"\ - "..\..\..\pjlib\include\pj\list_i.h"\ - "..\..\..\pjlib\include\pj\lock.h"\ - "..\..\..\pjlib\include\pj\log.h"\ - "..\..\..\pjlib\include\pj\os.h"\ - "..\..\..\pjlib\include\pj\pool.h"\ - "..\..\..\pjlib\include\pj\pool_alt.h"\ - "..\..\..\pjlib\include\pj\pool_buf.h"\ - "..\..\..\pjlib\include\pj\pool_i.h"\ - "..\..\..\pjlib\include\pj\rand.h"\ - "..\..\..\pjlib\include\pj\rbtree.h"\ - "..\..\..\pjlib\include\pj\sock.h"\ - "..\..\..\pjlib\include\pj\sock_select.h"\ - "..\..\..\pjlib\include\pj\string.h"\ - "..\..\..\pjlib\include\pj\string_i.h"\ - "..\..\..\pjlib\include\pj\timer.h"\ - "..\..\..\pjlib\include\pj\types.h"\ - "..\..\..\pjlib\include\pj\unicode.h"\ - "..\..\..\pjlib\include\pjlib.h"\ - "..\..\include\pjlib-util\config.h"\ - "..\..\include\pjlib-util\errno.h"\ - "..\..\include\pjlib-util\stun_simple.h"\ - "..\..\include\pjlib-util\types.h"\ - - -!ENDIF - -# End Source File -# Begin Source File - -SOURCE="..\..\src\pjlib-util\stun_simple_client.c" - -!IF "$(CFG)" == "pjlib_util_wince - Win32 (WCE emulator) Release" - -DEP_CPP_STUN_SIM=\ - "..\..\..\pjlib\include\pj\addr_resolv.h"\ - "..\..\..\pjlib\include\pj\array.h"\ - "..\..\..\pjlib\include\pj\assert.h"\ - "..\..\..\pjlib\include\pj\compat\assert.h"\ - "..\..\..\pjlib\include\pj\compat\cc_gcc.h"\ - "..\..\..\pjlib\include\pj\compat\cc_msvc.h"\ - "..\..\..\pjlib\include\pj\compat\ctype.h"\ - "..\..\..\pjlib\include\pj\compat\errno.h"\ - "..\..\..\pjlib\include\pj\compat\high_precision.h"\ - "..\..\..\pjlib\include\pj\compat\m_auto.h"\ - "..\..\..\pjlib\include\pj\compat\os_auto.h"\ - "..\..\..\pjlib\include\pj\compat\os_darwinos.h"\ - "..\..\..\pjlib\include\pj\compat\os_linux.h"\ - "..\..\..\pjlib\include\pj\compat\os_linux_kernel.h"\ - "..\..\..\pjlib\include\pj\compat\os_palmos.h"\ - "..\..\..\pjlib\include\pj\compat\os_rtems.h"\ - "..\..\..\pjlib\include\pj\compat\os_sunos.h"\ - "..\..\..\pjlib\include\pj\compat\os_win32.h"\ - "..\..\..\pjlib\include\pj\compat\os_win32_wince.h"\ - "..\..\..\pjlib\include\pj\compat\setjmp.h"\ - "..\..\..\pjlib\include\pj\compat\size_t.h"\ - "..\..\..\pjlib\include\pj\compat\string.h"\ - "..\..\..\pjlib\include\pj\config.h"\ - "..\..\..\pjlib\include\pj\config_site.h"\ - "..\..\..\pjlib\include\pj\config_site_sample.h"\ - "..\..\..\pjlib\include\pj\ctype.h"\ - "..\..\..\pjlib\include\pj\errno.h"\ - "..\..\..\pjlib\include\pj\except.h"\ - "..\..\..\pjlib\include\pj\fifobuf.h"\ - "..\..\..\pjlib\include\pj\file_access.h"\ - "..\..\..\pjlib\include\pj\file_io.h"\ - "..\..\..\pjlib\include\pj\guid.h"\ - "..\..\..\pjlib\include\pj\hash.h"\ - "..\..\..\pjlib\include\pj\ioqueue.h"\ - "..\..\..\pjlib\include\pj\list.h"\ - "..\..\..\pjlib\include\pj\list_i.h"\ - "..\..\..\pjlib\include\pj\lock.h"\ - "..\..\..\pjlib\include\pj\log.h"\ - "..\..\..\pjlib\include\pj\os.h"\ - "..\..\..\pjlib\include\pj\pool.h"\ - "..\..\..\pjlib\include\pj\pool_alt.h"\ - "..\..\..\pjlib\include\pj\pool_buf.h"\ - "..\..\..\pjlib\include\pj\pool_i.h"\ - "..\..\..\pjlib\include\pj\rand.h"\ - "..\..\..\pjlib\include\pj\rbtree.h"\ - "..\..\..\pjlib\include\pj\sock.h"\ - "..\..\..\pjlib\include\pj\sock_select.h"\ - "..\..\..\pjlib\include\pj\string.h"\ - "..\..\..\pjlib\include\pj\string_i.h"\ - "..\..\..\pjlib\include\pj\timer.h"\ - "..\..\..\pjlib\include\pj\types.h"\ - "..\..\..\pjlib\include\pj\unicode.h"\ - "..\..\..\pjlib\include\pjlib.h"\ - "..\..\include\pjlib-util\config.h"\ - "..\..\include\pjlib-util\errno.h"\ - "..\..\include\pjlib-util\stun_simple.h"\ - "..\..\include\pjlib-util\types.h"\ - - -!ELSEIF "$(CFG)" == "pjlib_util_wince - Win32 (WCE emulator) Debug" - -DEP_CPP_STUN_SIM=\ - "..\..\..\pjlib\include\pj\addr_resolv.h"\ - "..\..\..\pjlib\include\pj\array.h"\ - "..\..\..\pjlib\include\pj\assert.h"\ - "..\..\..\pjlib\include\pj\compat\assert.h"\ - "..\..\..\pjlib\include\pj\compat\cc_gcc.h"\ - "..\..\..\pjlib\include\pj\compat\cc_msvc.h"\ - "..\..\..\pjlib\include\pj\compat\ctype.h"\ - "..\..\..\pjlib\include\pj\compat\errno.h"\ - "..\..\..\pjlib\include\pj\compat\high_precision.h"\ - "..\..\..\pjlib\include\pj\compat\m_auto.h"\ - "..\..\..\pjlib\include\pj\compat\os_auto.h"\ - "..\..\..\pjlib\include\pj\compat\os_darwinos.h"\ - "..\..\..\pjlib\include\pj\compat\os_linux.h"\ - "..\..\..\pjlib\include\pj\compat\os_linux_kernel.h"\ - "..\..\..\pjlib\include\pj\compat\os_palmos.h"\ - "..\..\..\pjlib\include\pj\compat\os_rtems.h"\ - "..\..\..\pjlib\include\pj\compat\os_sunos.h"\ - "..\..\..\pjlib\include\pj\compat\os_win32.h"\ - "..\..\..\pjlib\include\pj\compat\os_win32_wince.h"\ - "..\..\..\pjlib\include\pj\compat\setjmp.h"\ - "..\..\..\pjlib\include\pj\compat\size_t.h"\ - "..\..\..\pjlib\include\pj\compat\string.h"\ - "..\..\..\pjlib\include\pj\config.h"\ - "..\..\..\pjlib\include\pj\config_site.h"\ - "..\..\..\pjlib\include\pj\config_site_sample.h"\ - "..\..\..\pjlib\include\pj\ctype.h"\ - "..\..\..\pjlib\include\pj\errno.h"\ - "..\..\..\pjlib\include\pj\except.h"\ - "..\..\..\pjlib\include\pj\fifobuf.h"\ - "..\..\..\pjlib\include\pj\file_access.h"\ - "..\..\..\pjlib\include\pj\file_io.h"\ - "..\..\..\pjlib\include\pj\guid.h"\ - "..\..\..\pjlib\include\pj\hash.h"\ - "..\..\..\pjlib\include\pj\ioqueue.h"\ - "..\..\..\pjlib\include\pj\list.h"\ - "..\..\..\pjlib\include\pj\list_i.h"\ - "..\..\..\pjlib\include\pj\lock.h"\ - "..\..\..\pjlib\include\pj\log.h"\ - "..\..\..\pjlib\include\pj\os.h"\ - "..\..\..\pjlib\include\pj\pool.h"\ - "..\..\..\pjlib\include\pj\pool_alt.h"\ - "..\..\..\pjlib\include\pj\pool_buf.h"\ - "..\..\..\pjlib\include\pj\pool_i.h"\ - "..\..\..\pjlib\include\pj\rand.h"\ - "..\..\..\pjlib\include\pj\rbtree.h"\ - "..\..\..\pjlib\include\pj\sock.h"\ - "..\..\..\pjlib\include\pj\sock_select.h"\ - "..\..\..\pjlib\include\pj\string.h"\ - "..\..\..\pjlib\include\pj\string_i.h"\ - "..\..\..\pjlib\include\pj\timer.h"\ - "..\..\..\pjlib\include\pj\types.h"\ - "..\..\..\pjlib\include\pj\unicode.h"\ - "..\..\..\pjlib\include\pjlib.h"\ - "..\..\include\pjlib-util\config.h"\ - "..\..\include\pjlib-util\errno.h"\ - "..\..\include\pjlib-util\stun_simple.h"\ - "..\..\include\pjlib-util\types.h"\ - - -!ELSEIF "$(CFG)" == "pjlib_util_wince - Win32 (WCE ARMV4I) Release" - -DEP_CPP_STUN_SIM=\ - "..\..\..\pjlib\include\pj\addr_resolv.h"\ - "..\..\..\pjlib\include\pj\array.h"\ - "..\..\..\pjlib\include\pj\assert.h"\ - "..\..\..\pjlib\include\pj\compat\assert.h"\ - "..\..\..\pjlib\include\pj\compat\cc_gcc.h"\ - "..\..\..\pjlib\include\pj\compat\cc_msvc.h"\ - "..\..\..\pjlib\include\pj\compat\ctype.h"\ - "..\..\..\pjlib\include\pj\compat\errno.h"\ - "..\..\..\pjlib\include\pj\compat\high_precision.h"\ - "..\..\..\pjlib\include\pj\compat\m_auto.h"\ - "..\..\..\pjlib\include\pj\compat\os_auto.h"\ - "..\..\..\pjlib\include\pj\compat\os_darwinos.h"\ - "..\..\..\pjlib\include\pj\compat\os_linux.h"\ - "..\..\..\pjlib\include\pj\compat\os_linux_kernel.h"\ - "..\..\..\pjlib\include\pj\compat\os_palmos.h"\ - "..\..\..\pjlib\include\pj\compat\os_rtems.h"\ - "..\..\..\pjlib\include\pj\compat\os_sunos.h"\ - "..\..\..\pjlib\include\pj\compat\os_win32.h"\ - "..\..\..\pjlib\include\pj\compat\os_win32_wince.h"\ - "..\..\..\pjlib\include\pj\compat\setjmp.h"\ - "..\..\..\pjlib\include\pj\compat\size_t.h"\ - "..\..\..\pjlib\include\pj\compat\string.h"\ - "..\..\..\pjlib\include\pj\config.h"\ - "..\..\..\pjlib\include\pj\config_site.h"\ - "..\..\..\pjlib\include\pj\config_site_sample.h"\ - "..\..\..\pjlib\include\pj\ctype.h"\ - "..\..\..\pjlib\include\pj\errno.h"\ - "..\..\..\pjlib\include\pj\except.h"\ - "..\..\..\pjlib\include\pj\fifobuf.h"\ - "..\..\..\pjlib\include\pj\file_access.h"\ - "..\..\..\pjlib\include\pj\file_io.h"\ - "..\..\..\pjlib\include\pj\guid.h"\ - "..\..\..\pjlib\include\pj\hash.h"\ - "..\..\..\pjlib\include\pj\ioqueue.h"\ - "..\..\..\pjlib\include\pj\list.h"\ - "..\..\..\pjlib\include\pj\list_i.h"\ - "..\..\..\pjlib\include\pj\lock.h"\ - "..\..\..\pjlib\include\pj\log.h"\ - "..\..\..\pjlib\include\pj\os.h"\ - "..\..\..\pjlib\include\pj\pool.h"\ - "..\..\..\pjlib\include\pj\pool_alt.h"\ - "..\..\..\pjlib\include\pj\pool_buf.h"\ - "..\..\..\pjlib\include\pj\pool_i.h"\ - "..\..\..\pjlib\include\pj\rand.h"\ - "..\..\..\pjlib\include\pj\rbtree.h"\ - "..\..\..\pjlib\include\pj\sock.h"\ - "..\..\..\pjlib\include\pj\sock_select.h"\ - "..\..\..\pjlib\include\pj\string.h"\ - "..\..\..\pjlib\include\pj\string_i.h"\ - "..\..\..\pjlib\include\pj\timer.h"\ - "..\..\..\pjlib\include\pj\types.h"\ - "..\..\..\pjlib\include\pj\unicode.h"\ - "..\..\..\pjlib\include\pjlib.h"\ - "..\..\include\pjlib-util\config.h"\ - "..\..\include\pjlib-util\errno.h"\ - "..\..\include\pjlib-util\stun_simple.h"\ - "..\..\include\pjlib-util\types.h"\ - - -!ELSEIF "$(CFG)" == "pjlib_util_wince - Win32 (WCE ARMV4I) Debug" - -DEP_CPP_STUN_SIM=\ - "..\..\..\pjlib\include\pj\addr_resolv.h"\ - "..\..\..\pjlib\include\pj\array.h"\ - "..\..\..\pjlib\include\pj\assert.h"\ - "..\..\..\pjlib\include\pj\compat\assert.h"\ - "..\..\..\pjlib\include\pj\compat\cc_gcc.h"\ - "..\..\..\pjlib\include\pj\compat\cc_msvc.h"\ - "..\..\..\pjlib\include\pj\compat\ctype.h"\ - "..\..\..\pjlib\include\pj\compat\errno.h"\ - "..\..\..\pjlib\include\pj\compat\high_precision.h"\ - "..\..\..\pjlib\include\pj\compat\m_auto.h"\ - "..\..\..\pjlib\include\pj\compat\os_auto.h"\ - "..\..\..\pjlib\include\pj\compat\os_darwinos.h"\ - "..\..\..\pjlib\include\pj\compat\os_linux.h"\ - "..\..\..\pjlib\include\pj\compat\os_linux_kernel.h"\ - "..\..\..\pjlib\include\pj\compat\os_palmos.h"\ - "..\..\..\pjlib\include\pj\compat\os_rtems.h"\ - "..\..\..\pjlib\include\pj\compat\os_sunos.h"\ - "..\..\..\pjlib\include\pj\compat\os_win32.h"\ - "..\..\..\pjlib\include\pj\compat\os_win32_wince.h"\ - "..\..\..\pjlib\include\pj\compat\setjmp.h"\ - "..\..\..\pjlib\include\pj\compat\size_t.h"\ - "..\..\..\pjlib\include\pj\compat\string.h"\ - "..\..\..\pjlib\include\pj\config.h"\ - "..\..\..\pjlib\include\pj\config_site.h"\ - "..\..\..\pjlib\include\pj\config_site_sample.h"\ - "..\..\..\pjlib\include\pj\ctype.h"\ - "..\..\..\pjlib\include\pj\errno.h"\ - "..\..\..\pjlib\include\pj\except.h"\ - "..\..\..\pjlib\include\pj\fifobuf.h"\ - "..\..\..\pjlib\include\pj\file_access.h"\ - "..\..\..\pjlib\include\pj\file_io.h"\ - "..\..\..\pjlib\include\pj\guid.h"\ - "..\..\..\pjlib\include\pj\hash.h"\ - "..\..\..\pjlib\include\pj\ioqueue.h"\ - "..\..\..\pjlib\include\pj\list.h"\ - "..\..\..\pjlib\include\pj\list_i.h"\ - "..\..\..\pjlib\include\pj\lock.h"\ - "..\..\..\pjlib\include\pj\log.h"\ - "..\..\..\pjlib\include\pj\os.h"\ - "..\..\..\pjlib\include\pj\pool.h"\ - "..\..\..\pjlib\include\pj\pool_alt.h"\ - "..\..\..\pjlib\include\pj\pool_buf.h"\ - "..\..\..\pjlib\include\pj\pool_i.h"\ - "..\..\..\pjlib\include\pj\rand.h"\ - "..\..\..\pjlib\include\pj\rbtree.h"\ - "..\..\..\pjlib\include\pj\sock.h"\ - "..\..\..\pjlib\include\pj\sock_select.h"\ - "..\..\..\pjlib\include\pj\string.h"\ - "..\..\..\pjlib\include\pj\string_i.h"\ - "..\..\..\pjlib\include\pj\timer.h"\ - "..\..\..\pjlib\include\pj\types.h"\ - "..\..\..\pjlib\include\pj\unicode.h"\ - "..\..\..\pjlib\include\pjlib.h"\ - "..\..\include\pjlib-util\config.h"\ - "..\..\include\pjlib-util\errno.h"\ - "..\..\include\pjlib-util\stun_simple.h"\ - "..\..\include\pjlib-util\types.h"\ - - -!ELSEIF "$(CFG)" == "pjlib_util_wince - Win32 (WCE ARMV4) Release" - -DEP_CPP_STUN_SIM=\ - "..\..\..\pjlib\include\pj\addr_resolv.h"\ - "..\..\..\pjlib\include\pj\array.h"\ - "..\..\..\pjlib\include\pj\assert.h"\ - "..\..\..\pjlib\include\pj\compat\assert.h"\ - "..\..\..\pjlib\include\pj\compat\cc_gcc.h"\ - "..\..\..\pjlib\include\pj\compat\cc_msvc.h"\ - "..\..\..\pjlib\include\pj\compat\ctype.h"\ - "..\..\..\pjlib\include\pj\compat\errno.h"\ - "..\..\..\pjlib\include\pj\compat\high_precision.h"\ - "..\..\..\pjlib\include\pj\compat\m_auto.h"\ - "..\..\..\pjlib\include\pj\compat\os_auto.h"\ - "..\..\..\pjlib\include\pj\compat\os_darwinos.h"\ - "..\..\..\pjlib\include\pj\compat\os_linux.h"\ - "..\..\..\pjlib\include\pj\compat\os_linux_kernel.h"\ - "..\..\..\pjlib\include\pj\compat\os_palmos.h"\ - "..\..\..\pjlib\include\pj\compat\os_rtems.h"\ - "..\..\..\pjlib\include\pj\compat\os_sunos.h"\ - "..\..\..\pjlib\include\pj\compat\os_win32.h"\ - "..\..\..\pjlib\include\pj\compat\os_win32_wince.h"\ - "..\..\..\pjlib\include\pj\compat\setjmp.h"\ - "..\..\..\pjlib\include\pj\compat\size_t.h"\ - "..\..\..\pjlib\include\pj\compat\string.h"\ - "..\..\..\pjlib\include\pj\config.h"\ - "..\..\..\pjlib\include\pj\config_site.h"\ - "..\..\..\pjlib\include\pj\config_site_sample.h"\ - "..\..\..\pjlib\include\pj\ctype.h"\ - "..\..\..\pjlib\include\pj\errno.h"\ - "..\..\..\pjlib\include\pj\except.h"\ - "..\..\..\pjlib\include\pj\fifobuf.h"\ - "..\..\..\pjlib\include\pj\file_access.h"\ - "..\..\..\pjlib\include\pj\file_io.h"\ - "..\..\..\pjlib\include\pj\guid.h"\ - "..\..\..\pjlib\include\pj\hash.h"\ - "..\..\..\pjlib\include\pj\ioqueue.h"\ - "..\..\..\pjlib\include\pj\list.h"\ - "..\..\..\pjlib\include\pj\list_i.h"\ - "..\..\..\pjlib\include\pj\lock.h"\ - "..\..\..\pjlib\include\pj\log.h"\ - "..\..\..\pjlib\include\pj\os.h"\ - "..\..\..\pjlib\include\pj\pool.h"\ - "..\..\..\pjlib\include\pj\pool_alt.h"\ - "..\..\..\pjlib\include\pj\pool_buf.h"\ - "..\..\..\pjlib\include\pj\pool_i.h"\ - "..\..\..\pjlib\include\pj\rand.h"\ - "..\..\..\pjlib\include\pj\rbtree.h"\ - "..\..\..\pjlib\include\pj\sock.h"\ - "..\..\..\pjlib\include\pj\sock_select.h"\ - "..\..\..\pjlib\include\pj\string.h"\ - "..\..\..\pjlib\include\pj\string_i.h"\ - "..\..\..\pjlib\include\pj\timer.h"\ - "..\..\..\pjlib\include\pj\types.h"\ - "..\..\..\pjlib\include\pj\unicode.h"\ - "..\..\..\pjlib\include\pjlib.h"\ - "..\..\include\pjlib-util\config.h"\ - "..\..\include\pjlib-util\errno.h"\ - "..\..\include\pjlib-util\stun_simple.h"\ - "..\..\include\pjlib-util\types.h"\ - - -!ELSEIF "$(CFG)" == "pjlib_util_wince - Win32 (WCE ARMV4) Debug" - -DEP_CPP_STUN_SIM=\ - "..\..\..\pjlib\include\pj\addr_resolv.h"\ - "..\..\..\pjlib\include\pj\array.h"\ - "..\..\..\pjlib\include\pj\assert.h"\ - "..\..\..\pjlib\include\pj\compat\assert.h"\ - "..\..\..\pjlib\include\pj\compat\cc_gcc.h"\ - "..\..\..\pjlib\include\pj\compat\cc_msvc.h"\ - "..\..\..\pjlib\include\pj\compat\ctype.h"\ - "..\..\..\pjlib\include\pj\compat\errno.h"\ - "..\..\..\pjlib\include\pj\compat\high_precision.h"\ - "..\..\..\pjlib\include\pj\compat\m_auto.h"\ - "..\..\..\pjlib\include\pj\compat\os_auto.h"\ - "..\..\..\pjlib\include\pj\compat\os_darwinos.h"\ - "..\..\..\pjlib\include\pj\compat\os_linux.h"\ - "..\..\..\pjlib\include\pj\compat\os_linux_kernel.h"\ - "..\..\..\pjlib\include\pj\compat\os_palmos.h"\ - "..\..\..\pjlib\include\pj\compat\os_rtems.h"\ - "..\..\..\pjlib\include\pj\compat\os_sunos.h"\ - "..\..\..\pjlib\include\pj\compat\os_win32.h"\ - "..\..\..\pjlib\include\pj\compat\os_win32_wince.h"\ - "..\..\..\pjlib\include\pj\compat\setjmp.h"\ - "..\..\..\pjlib\include\pj\compat\size_t.h"\ - "..\..\..\pjlib\include\pj\compat\string.h"\ - "..\..\..\pjlib\include\pj\config.h"\ - "..\..\..\pjlib\include\pj\config_site.h"\ - "..\..\..\pjlib\include\pj\config_site_sample.h"\ - "..\..\..\pjlib\include\pj\ctype.h"\ - "..\..\..\pjlib\include\pj\errno.h"\ - "..\..\..\pjlib\include\pj\except.h"\ - "..\..\..\pjlib\include\pj\fifobuf.h"\ - "..\..\..\pjlib\include\pj\file_access.h"\ - "..\..\..\pjlib\include\pj\file_io.h"\ - "..\..\..\pjlib\include\pj\guid.h"\ - "..\..\..\pjlib\include\pj\hash.h"\ - "..\..\..\pjlib\include\pj\ioqueue.h"\ - "..\..\..\pjlib\include\pj\list.h"\ - "..\..\..\pjlib\include\pj\list_i.h"\ - "..\..\..\pjlib\include\pj\lock.h"\ - "..\..\..\pjlib\include\pj\log.h"\ - "..\..\..\pjlib\include\pj\os.h"\ - "..\..\..\pjlib\include\pj\pool.h"\ - "..\..\..\pjlib\include\pj\pool_alt.h"\ - "..\..\..\pjlib\include\pj\pool_buf.h"\ - "..\..\..\pjlib\include\pj\pool_i.h"\ - "..\..\..\pjlib\include\pj\rand.h"\ - "..\..\..\pjlib\include\pj\rbtree.h"\ - "..\..\..\pjlib\include\pj\sock.h"\ - "..\..\..\pjlib\include\pj\sock_select.h"\ - "..\..\..\pjlib\include\pj\string.h"\ - "..\..\..\pjlib\include\pj\string_i.h"\ - "..\..\..\pjlib\include\pj\timer.h"\ - "..\..\..\pjlib\include\pj\types.h"\ - "..\..\..\pjlib\include\pj\unicode.h"\ - "..\..\..\pjlib\include\pjlib.h"\ - "..\..\include\pjlib-util\config.h"\ - "..\..\include\pjlib-util\errno.h"\ - "..\..\include\pjlib-util\stun_simple.h"\ - "..\..\include\pjlib-util\types.h"\ - - -!ELSEIF "$(CFG)" == "pjlib_util_wince - Win32 (WCE ARMV4T) Release" - -DEP_CPP_STUN_SIM=\ - "..\..\..\pjlib\include\pj\addr_resolv.h"\ - "..\..\..\pjlib\include\pj\array.h"\ - "..\..\..\pjlib\include\pj\assert.h"\ - "..\..\..\pjlib\include\pj\compat\assert.h"\ - "..\..\..\pjlib\include\pj\compat\cc_gcc.h"\ - "..\..\..\pjlib\include\pj\compat\cc_msvc.h"\ - "..\..\..\pjlib\include\pj\compat\ctype.h"\ - "..\..\..\pjlib\include\pj\compat\errno.h"\ - "..\..\..\pjlib\include\pj\compat\high_precision.h"\ - "..\..\..\pjlib\include\pj\compat\m_auto.h"\ - "..\..\..\pjlib\include\pj\compat\os_auto.h"\ - "..\..\..\pjlib\include\pj\compat\os_darwinos.h"\ - "..\..\..\pjlib\include\pj\compat\os_linux.h"\ - "..\..\..\pjlib\include\pj\compat\os_linux_kernel.h"\ - "..\..\..\pjlib\include\pj\compat\os_palmos.h"\ - "..\..\..\pjlib\include\pj\compat\os_rtems.h"\ - "..\..\..\pjlib\include\pj\compat\os_sunos.h"\ - "..\..\..\pjlib\include\pj\compat\os_win32.h"\ - "..\..\..\pjlib\include\pj\compat\os_win32_wince.h"\ - "..\..\..\pjlib\include\pj\compat\setjmp.h"\ - "..\..\..\pjlib\include\pj\compat\size_t.h"\ - "..\..\..\pjlib\include\pj\compat\string.h"\ - "..\..\..\pjlib\include\pj\config.h"\ - "..\..\..\pjlib\include\pj\config_site.h"\ - "..\..\..\pjlib\include\pj\config_site_sample.h"\ - "..\..\..\pjlib\include\pj\ctype.h"\ - "..\..\..\pjlib\include\pj\errno.h"\ - "..\..\..\pjlib\include\pj\except.h"\ - "..\..\..\pjlib\include\pj\fifobuf.h"\ - "..\..\..\pjlib\include\pj\file_access.h"\ - "..\..\..\pjlib\include\pj\file_io.h"\ - "..\..\..\pjlib\include\pj\guid.h"\ - "..\..\..\pjlib\include\pj\hash.h"\ - "..\..\..\pjlib\include\pj\ioqueue.h"\ - "..\..\..\pjlib\include\pj\list.h"\ - "..\..\..\pjlib\include\pj\list_i.h"\ - "..\..\..\pjlib\include\pj\lock.h"\ - "..\..\..\pjlib\include\pj\log.h"\ - "..\..\..\pjlib\include\pj\os.h"\ - "..\..\..\pjlib\include\pj\pool.h"\ - "..\..\..\pjlib\include\pj\pool_alt.h"\ - "..\..\..\pjlib\include\pj\pool_buf.h"\ - "..\..\..\pjlib\include\pj\pool_i.h"\ - "..\..\..\pjlib\include\pj\rand.h"\ - "..\..\..\pjlib\include\pj\rbtree.h"\ - "..\..\..\pjlib\include\pj\sock.h"\ - "..\..\..\pjlib\include\pj\sock_select.h"\ - "..\..\..\pjlib\include\pj\string.h"\ - "..\..\..\pjlib\include\pj\string_i.h"\ - "..\..\..\pjlib\include\pj\timer.h"\ - "..\..\..\pjlib\include\pj\types.h"\ - "..\..\..\pjlib\include\pj\unicode.h"\ - "..\..\..\pjlib\include\pjlib.h"\ - "..\..\include\pjlib-util\config.h"\ - "..\..\include\pjlib-util\errno.h"\ - "..\..\include\pjlib-util\stun_simple.h"\ - "..\..\include\pjlib-util\types.h"\ - - -!ELSEIF "$(CFG)" == "pjlib_util_wince - Win32 (WCE ARMV4T) Debug" - -DEP_CPP_STUN_SIM=\ - "..\..\..\pjlib\include\pj\addr_resolv.h"\ - "..\..\..\pjlib\include\pj\array.h"\ - "..\..\..\pjlib\include\pj\assert.h"\ - "..\..\..\pjlib\include\pj\compat\assert.h"\ - "..\..\..\pjlib\include\pj\compat\cc_gcc.h"\ - "..\..\..\pjlib\include\pj\compat\cc_msvc.h"\ - "..\..\..\pjlib\include\pj\compat\ctype.h"\ - "..\..\..\pjlib\include\pj\compat\errno.h"\ - "..\..\..\pjlib\include\pj\compat\high_precision.h"\ - "..\..\..\pjlib\include\pj\compat\m_auto.h"\ - "..\..\..\pjlib\include\pj\compat\os_auto.h"\ - "..\..\..\pjlib\include\pj\compat\os_darwinos.h"\ - "..\..\..\pjlib\include\pj\compat\os_linux.h"\ - "..\..\..\pjlib\include\pj\compat\os_linux_kernel.h"\ - "..\..\..\pjlib\include\pj\compat\os_palmos.h"\ - "..\..\..\pjlib\include\pj\compat\os_rtems.h"\ - "..\..\..\pjlib\include\pj\compat\os_sunos.h"\ - "..\..\..\pjlib\include\pj\compat\os_win32.h"\ - "..\..\..\pjlib\include\pj\compat\os_win32_wince.h"\ - "..\..\..\pjlib\include\pj\compat\setjmp.h"\ - "..\..\..\pjlib\include\pj\compat\size_t.h"\ - "..\..\..\pjlib\include\pj\compat\string.h"\ - "..\..\..\pjlib\include\pj\config.h"\ - "..\..\..\pjlib\include\pj\config_site.h"\ - "..\..\..\pjlib\include\pj\config_site_sample.h"\ - "..\..\..\pjlib\include\pj\ctype.h"\ - "..\..\..\pjlib\include\pj\errno.h"\ - "..\..\..\pjlib\include\pj\except.h"\ - "..\..\..\pjlib\include\pj\fifobuf.h"\ - "..\..\..\pjlib\include\pj\file_access.h"\ - "..\..\..\pjlib\include\pj\file_io.h"\ - "..\..\..\pjlib\include\pj\guid.h"\ - "..\..\..\pjlib\include\pj\hash.h"\ - "..\..\..\pjlib\include\pj\ioqueue.h"\ - "..\..\..\pjlib\include\pj\list.h"\ - "..\..\..\pjlib\include\pj\list_i.h"\ - "..\..\..\pjlib\include\pj\lock.h"\ - "..\..\..\pjlib\include\pj\log.h"\ - "..\..\..\pjlib\include\pj\os.h"\ - "..\..\..\pjlib\include\pj\pool.h"\ - "..\..\..\pjlib\include\pj\pool_alt.h"\ - "..\..\..\pjlib\include\pj\pool_buf.h"\ - "..\..\..\pjlib\include\pj\pool_i.h"\ - "..\..\..\pjlib\include\pj\rand.h"\ - "..\..\..\pjlib\include\pj\rbtree.h"\ - "..\..\..\pjlib\include\pj\sock.h"\ - "..\..\..\pjlib\include\pj\sock_select.h"\ - "..\..\..\pjlib\include\pj\string.h"\ - "..\..\..\pjlib\include\pj\string_i.h"\ - "..\..\..\pjlib\include\pj\timer.h"\ - "..\..\..\pjlib\include\pj\types.h"\ - "..\..\..\pjlib\include\pj\unicode.h"\ - "..\..\..\pjlib\include\pjlib.h"\ - "..\..\include\pjlib-util\config.h"\ - "..\..\include\pjlib-util\errno.h"\ - "..\..\include\pjlib-util\stun_simple.h"\ - "..\..\include\pjlib-util\types.h"\ - - -!ELSEIF "$(CFG)" == "pjlib_util_wince - Win32 (WCE x86) Release" - -DEP_CPP_STUN_SIM=\ - "..\..\..\pjlib\include\pj\addr_resolv.h"\ - "..\..\..\pjlib\include\pj\array.h"\ - "..\..\..\pjlib\include\pj\assert.h"\ - "..\..\..\pjlib\include\pj\compat\assert.h"\ - "..\..\..\pjlib\include\pj\compat\cc_gcc.h"\ - "..\..\..\pjlib\include\pj\compat\cc_msvc.h"\ - "..\..\..\pjlib\include\pj\compat\ctype.h"\ - "..\..\..\pjlib\include\pj\compat\errno.h"\ - "..\..\..\pjlib\include\pj\compat\high_precision.h"\ - "..\..\..\pjlib\include\pj\compat\m_auto.h"\ - "..\..\..\pjlib\include\pj\compat\os_auto.h"\ - "..\..\..\pjlib\include\pj\compat\os_darwinos.h"\ - "..\..\..\pjlib\include\pj\compat\os_linux.h"\ - "..\..\..\pjlib\include\pj\compat\os_linux_kernel.h"\ - "..\..\..\pjlib\include\pj\compat\os_palmos.h"\ - "..\..\..\pjlib\include\pj\compat\os_rtems.h"\ - "..\..\..\pjlib\include\pj\compat\os_sunos.h"\ - "..\..\..\pjlib\include\pj\compat\os_win32.h"\ - "..\..\..\pjlib\include\pj\compat\os_win32_wince.h"\ - "..\..\..\pjlib\include\pj\compat\setjmp.h"\ - "..\..\..\pjlib\include\pj\compat\size_t.h"\ - "..\..\..\pjlib\include\pj\compat\string.h"\ - "..\..\..\pjlib\include\pj\config.h"\ - "..\..\..\pjlib\include\pj\config_site.h"\ - "..\..\..\pjlib\include\pj\config_site_sample.h"\ - "..\..\..\pjlib\include\pj\ctype.h"\ - "..\..\..\pjlib\include\pj\errno.h"\ - "..\..\..\pjlib\include\pj\except.h"\ - "..\..\..\pjlib\include\pj\fifobuf.h"\ - "..\..\..\pjlib\include\pj\file_access.h"\ - "..\..\..\pjlib\include\pj\file_io.h"\ - "..\..\..\pjlib\include\pj\guid.h"\ - "..\..\..\pjlib\include\pj\hash.h"\ - "..\..\..\pjlib\include\pj\ioqueue.h"\ - "..\..\..\pjlib\include\pj\list.h"\ - "..\..\..\pjlib\include\pj\list_i.h"\ - "..\..\..\pjlib\include\pj\lock.h"\ - "..\..\..\pjlib\include\pj\log.h"\ - "..\..\..\pjlib\include\pj\os.h"\ - "..\..\..\pjlib\include\pj\pool.h"\ - "..\..\..\pjlib\include\pj\pool_alt.h"\ - "..\..\..\pjlib\include\pj\pool_buf.h"\ - "..\..\..\pjlib\include\pj\pool_i.h"\ - "..\..\..\pjlib\include\pj\rand.h"\ - "..\..\..\pjlib\include\pj\rbtree.h"\ - "..\..\..\pjlib\include\pj\sock.h"\ - "..\..\..\pjlib\include\pj\sock_select.h"\ - "..\..\..\pjlib\include\pj\string.h"\ - "..\..\..\pjlib\include\pj\string_i.h"\ - "..\..\..\pjlib\include\pj\timer.h"\ - "..\..\..\pjlib\include\pj\types.h"\ - "..\..\..\pjlib\include\pj\unicode.h"\ - "..\..\..\pjlib\include\pjlib.h"\ - "..\..\include\pjlib-util\config.h"\ - "..\..\include\pjlib-util\errno.h"\ - "..\..\include\pjlib-util\stun_simple.h"\ - "..\..\include\pjlib-util\types.h"\ - - -!ELSEIF "$(CFG)" == "pjlib_util_wince - Win32 (WCE x86) Debug" - -DEP_CPP_STUN_SIM=\ - "..\..\..\pjlib\include\pj\addr_resolv.h"\ - "..\..\..\pjlib\include\pj\array.h"\ - "..\..\..\pjlib\include\pj\assert.h"\ - "..\..\..\pjlib\include\pj\compat\assert.h"\ - "..\..\..\pjlib\include\pj\compat\cc_gcc.h"\ - "..\..\..\pjlib\include\pj\compat\cc_msvc.h"\ - "..\..\..\pjlib\include\pj\compat\ctype.h"\ - "..\..\..\pjlib\include\pj\compat\errno.h"\ - "..\..\..\pjlib\include\pj\compat\high_precision.h"\ - "..\..\..\pjlib\include\pj\compat\m_auto.h"\ - "..\..\..\pjlib\include\pj\compat\os_auto.h"\ - "..\..\..\pjlib\include\pj\compat\os_darwinos.h"\ - "..\..\..\pjlib\include\pj\compat\os_linux.h"\ - "..\..\..\pjlib\include\pj\compat\os_linux_kernel.h"\ - "..\..\..\pjlib\include\pj\compat\os_palmos.h"\ - "..\..\..\pjlib\include\pj\compat\os_rtems.h"\ - "..\..\..\pjlib\include\pj\compat\os_sunos.h"\ - "..\..\..\pjlib\include\pj\compat\os_win32.h"\ - "..\..\..\pjlib\include\pj\compat\os_win32_wince.h"\ - "..\..\..\pjlib\include\pj\compat\setjmp.h"\ - "..\..\..\pjlib\include\pj\compat\size_t.h"\ - "..\..\..\pjlib\include\pj\compat\string.h"\ - "..\..\..\pjlib\include\pj\config.h"\ - "..\..\..\pjlib\include\pj\config_site.h"\ - "..\..\..\pjlib\include\pj\config_site_sample.h"\ - "..\..\..\pjlib\include\pj\ctype.h"\ - "..\..\..\pjlib\include\pj\errno.h"\ - "..\..\..\pjlib\include\pj\except.h"\ - "..\..\..\pjlib\include\pj\fifobuf.h"\ - "..\..\..\pjlib\include\pj\file_access.h"\ - "..\..\..\pjlib\include\pj\file_io.h"\ - "..\..\..\pjlib\include\pj\guid.h"\ - "..\..\..\pjlib\include\pj\hash.h"\ - "..\..\..\pjlib\include\pj\ioqueue.h"\ - "..\..\..\pjlib\include\pj\list.h"\ - "..\..\..\pjlib\include\pj\list_i.h"\ - "..\..\..\pjlib\include\pj\lock.h"\ - "..\..\..\pjlib\include\pj\log.h"\ - "..\..\..\pjlib\include\pj\os.h"\ - "..\..\..\pjlib\include\pj\pool.h"\ - "..\..\..\pjlib\include\pj\pool_alt.h"\ - "..\..\..\pjlib\include\pj\pool_buf.h"\ - "..\..\..\pjlib\include\pj\pool_i.h"\ - "..\..\..\pjlib\include\pj\rand.h"\ - "..\..\..\pjlib\include\pj\rbtree.h"\ - "..\..\..\pjlib\include\pj\sock.h"\ - "..\..\..\pjlib\include\pj\sock_select.h"\ - "..\..\..\pjlib\include\pj\string.h"\ - "..\..\..\pjlib\include\pj\string_i.h"\ - "..\..\..\pjlib\include\pj\timer.h"\ - "..\..\..\pjlib\include\pj\types.h"\ - "..\..\..\pjlib\include\pj\unicode.h"\ - "..\..\..\pjlib\include\pjlib.h"\ - "..\..\include\pjlib-util\config.h"\ - "..\..\include\pjlib-util\errno.h"\ - "..\..\include\pjlib-util\stun_simple.h"\ - "..\..\include\pjlib-util\types.h"\ - - -!ENDIF - -# End Source File -# Begin Source File - -SOURCE="..\..\src\pjlib-util\stun_transaction.c" - -!IF "$(CFG)" == "pjlib_util_wince - Win32 (WCE emulator) Release" - -DEP_CPP_STUN_T=\ - "..\..\..\pjlib\include\pj\addr_resolv.h"\ - "..\..\..\pjlib\include\pj\array.h"\ - "..\..\..\pjlib\include\pj\assert.h"\ - "..\..\..\pjlib\include\pj\compat\assert.h"\ - "..\..\..\pjlib\include\pj\compat\cc_gcc.h"\ - "..\..\..\pjlib\include\pj\compat\cc_msvc.h"\ - "..\..\..\pjlib\include\pj\compat\ctype.h"\ - "..\..\..\pjlib\include\pj\compat\errno.h"\ - "..\..\..\pjlib\include\pj\compat\high_precision.h"\ - "..\..\..\pjlib\include\pj\compat\m_auto.h"\ - "..\..\..\pjlib\include\pj\compat\os_auto.h"\ - "..\..\..\pjlib\include\pj\compat\os_darwinos.h"\ - "..\..\..\pjlib\include\pj\compat\os_linux.h"\ - "..\..\..\pjlib\include\pj\compat\os_linux_kernel.h"\ - "..\..\..\pjlib\include\pj\compat\os_palmos.h"\ - "..\..\..\pjlib\include\pj\compat\os_rtems.h"\ - "..\..\..\pjlib\include\pj\compat\os_sunos.h"\ - "..\..\..\pjlib\include\pj\compat\os_win32.h"\ - "..\..\..\pjlib\include\pj\compat\os_win32_wince.h"\ - "..\..\..\pjlib\include\pj\compat\setjmp.h"\ - "..\..\..\pjlib\include\pj\compat\size_t.h"\ - "..\..\..\pjlib\include\pj\compat\string.h"\ - "..\..\..\pjlib\include\pj\config.h"\ - "..\..\..\pjlib\include\pj\config_site.h"\ - "..\..\..\pjlib\include\pj\config_site_sample.h"\ - "..\..\..\pjlib\include\pj\ctype.h"\ - "..\..\..\pjlib\include\pj\errno.h"\ - "..\..\..\pjlib\include\pj\except.h"\ - "..\..\..\pjlib\include\pj\fifobuf.h"\ - "..\..\..\pjlib\include\pj\file_access.h"\ - "..\..\..\pjlib\include\pj\file_io.h"\ - "..\..\..\pjlib\include\pj\guid.h"\ - "..\..\..\pjlib\include\pj\hash.h"\ - "..\..\..\pjlib\include\pj\ioqueue.h"\ - "..\..\..\pjlib\include\pj\list.h"\ - "..\..\..\pjlib\include\pj\list_i.h"\ - "..\..\..\pjlib\include\pj\lock.h"\ - "..\..\..\pjlib\include\pj\log.h"\ - "..\..\..\pjlib\include\pj\os.h"\ - "..\..\..\pjlib\include\pj\pool.h"\ - "..\..\..\pjlib\include\pj\pool_alt.h"\ - "..\..\..\pjlib\include\pj\pool_buf.h"\ - "..\..\..\pjlib\include\pj\pool_i.h"\ - "..\..\..\pjlib\include\pj\rand.h"\ - "..\..\..\pjlib\include\pj\rbtree.h"\ - "..\..\..\pjlib\include\pj\sock.h"\ - "..\..\..\pjlib\include\pj\sock_select.h"\ - "..\..\..\pjlib\include\pj\string.h"\ - "..\..\..\pjlib\include\pj\string_i.h"\ - "..\..\..\pjlib\include\pj\timer.h"\ - "..\..\..\pjlib\include\pj\types.h"\ - "..\..\..\pjlib\include\pj\unicode.h"\ - "..\..\..\pjlib\include\pjlib.h"\ - "..\..\include\pjlib-util\config.h"\ - "..\..\include\pjlib-util\errno.h"\ - "..\..\include\pjlib-util\stun_endpoint.h"\ - "..\..\include\pjlib-util\stun_msg.h"\ - "..\..\include\pjlib-util\stun_transaction.h"\ - "..\..\include\pjlib-util\types.h"\ - - -!ELSEIF "$(CFG)" == "pjlib_util_wince - Win32 (WCE emulator) Debug" - -DEP_CPP_STUN_T=\ - "..\..\..\pjlib\include\pj\addr_resolv.h"\ - "..\..\..\pjlib\include\pj\array.h"\ - "..\..\..\pjlib\include\pj\assert.h"\ - "..\..\..\pjlib\include\pj\compat\assert.h"\ - "..\..\..\pjlib\include\pj\compat\cc_gcc.h"\ - "..\..\..\pjlib\include\pj\compat\cc_msvc.h"\ - "..\..\..\pjlib\include\pj\compat\ctype.h"\ - "..\..\..\pjlib\include\pj\compat\errno.h"\ - "..\..\..\pjlib\include\pj\compat\high_precision.h"\ - "..\..\..\pjlib\include\pj\compat\m_auto.h"\ - "..\..\..\pjlib\include\pj\compat\os_auto.h"\ - "..\..\..\pjlib\include\pj\compat\os_darwinos.h"\ - "..\..\..\pjlib\include\pj\compat\os_linux.h"\ - "..\..\..\pjlib\include\pj\compat\os_linux_kernel.h"\ - "..\..\..\pjlib\include\pj\compat\os_palmos.h"\ - "..\..\..\pjlib\include\pj\compat\os_rtems.h"\ - "..\..\..\pjlib\include\pj\compat\os_sunos.h"\ - "..\..\..\pjlib\include\pj\compat\os_win32.h"\ - "..\..\..\pjlib\include\pj\compat\os_win32_wince.h"\ - "..\..\..\pjlib\include\pj\compat\setjmp.h"\ - "..\..\..\pjlib\include\pj\compat\size_t.h"\ - "..\..\..\pjlib\include\pj\compat\string.h"\ - "..\..\..\pjlib\include\pj\config.h"\ - "..\..\..\pjlib\include\pj\config_site.h"\ - "..\..\..\pjlib\include\pj\config_site_sample.h"\ - "..\..\..\pjlib\include\pj\ctype.h"\ - "..\..\..\pjlib\include\pj\errno.h"\ - "..\..\..\pjlib\include\pj\except.h"\ - "..\..\..\pjlib\include\pj\fifobuf.h"\ - "..\..\..\pjlib\include\pj\file_access.h"\ - "..\..\..\pjlib\include\pj\file_io.h"\ - "..\..\..\pjlib\include\pj\guid.h"\ - "..\..\..\pjlib\include\pj\hash.h"\ - "..\..\..\pjlib\include\pj\ioqueue.h"\ - "..\..\..\pjlib\include\pj\list.h"\ - "..\..\..\pjlib\include\pj\list_i.h"\ - "..\..\..\pjlib\include\pj\lock.h"\ - "..\..\..\pjlib\include\pj\log.h"\ - "..\..\..\pjlib\include\pj\os.h"\ - "..\..\..\pjlib\include\pj\pool.h"\ - "..\..\..\pjlib\include\pj\pool_alt.h"\ - "..\..\..\pjlib\include\pj\pool_buf.h"\ - "..\..\..\pjlib\include\pj\pool_i.h"\ - "..\..\..\pjlib\include\pj\rand.h"\ - "..\..\..\pjlib\include\pj\rbtree.h"\ - "..\..\..\pjlib\include\pj\sock.h"\ - "..\..\..\pjlib\include\pj\sock_select.h"\ - "..\..\..\pjlib\include\pj\string.h"\ - "..\..\..\pjlib\include\pj\string_i.h"\ - "..\..\..\pjlib\include\pj\timer.h"\ - "..\..\..\pjlib\include\pj\types.h"\ - "..\..\..\pjlib\include\pj\unicode.h"\ - "..\..\..\pjlib\include\pjlib.h"\ - "..\..\include\pjlib-util\config.h"\ - "..\..\include\pjlib-util\errno.h"\ - "..\..\include\pjlib-util\stun_endpoint.h"\ - "..\..\include\pjlib-util\stun_msg.h"\ - "..\..\include\pjlib-util\stun_transaction.h"\ - "..\..\include\pjlib-util\types.h"\ - - -!ELSEIF "$(CFG)" == "pjlib_util_wince - Win32 (WCE ARMV4I) Release" - -DEP_CPP_STUN_T=\ - "..\..\..\pjlib\include\pj\addr_resolv.h"\ - "..\..\..\pjlib\include\pj\array.h"\ - "..\..\..\pjlib\include\pj\assert.h"\ - "..\..\..\pjlib\include\pj\compat\assert.h"\ - "..\..\..\pjlib\include\pj\compat\cc_gcc.h"\ - "..\..\..\pjlib\include\pj\compat\cc_msvc.h"\ - "..\..\..\pjlib\include\pj\compat\ctype.h"\ - "..\..\..\pjlib\include\pj\compat\errno.h"\ - "..\..\..\pjlib\include\pj\compat\high_precision.h"\ - "..\..\..\pjlib\include\pj\compat\m_auto.h"\ - "..\..\..\pjlib\include\pj\compat\os_auto.h"\ - "..\..\..\pjlib\include\pj\compat\os_darwinos.h"\ - "..\..\..\pjlib\include\pj\compat\os_linux.h"\ - "..\..\..\pjlib\include\pj\compat\os_linux_kernel.h"\ - "..\..\..\pjlib\include\pj\compat\os_palmos.h"\ - "..\..\..\pjlib\include\pj\compat\os_rtems.h"\ - "..\..\..\pjlib\include\pj\compat\os_sunos.h"\ - "..\..\..\pjlib\include\pj\compat\os_win32.h"\ - "..\..\..\pjlib\include\pj\compat\os_win32_wince.h"\ - "..\..\..\pjlib\include\pj\compat\setjmp.h"\ - "..\..\..\pjlib\include\pj\compat\size_t.h"\ - "..\..\..\pjlib\include\pj\compat\string.h"\ - "..\..\..\pjlib\include\pj\config.h"\ - "..\..\..\pjlib\include\pj\config_site.h"\ - "..\..\..\pjlib\include\pj\config_site_sample.h"\ - "..\..\..\pjlib\include\pj\ctype.h"\ - "..\..\..\pjlib\include\pj\errno.h"\ - "..\..\..\pjlib\include\pj\except.h"\ - "..\..\..\pjlib\include\pj\fifobuf.h"\ - "..\..\..\pjlib\include\pj\file_access.h"\ - "..\..\..\pjlib\include\pj\file_io.h"\ - "..\..\..\pjlib\include\pj\guid.h"\ - "..\..\..\pjlib\include\pj\hash.h"\ - "..\..\..\pjlib\include\pj\ioqueue.h"\ - "..\..\..\pjlib\include\pj\list.h"\ - "..\..\..\pjlib\include\pj\list_i.h"\ - "..\..\..\pjlib\include\pj\lock.h"\ - "..\..\..\pjlib\include\pj\log.h"\ - "..\..\..\pjlib\include\pj\os.h"\ - "..\..\..\pjlib\include\pj\pool.h"\ - "..\..\..\pjlib\include\pj\pool_alt.h"\ - "..\..\..\pjlib\include\pj\pool_buf.h"\ - "..\..\..\pjlib\include\pj\pool_i.h"\ - "..\..\..\pjlib\include\pj\rand.h"\ - "..\..\..\pjlib\include\pj\rbtree.h"\ - "..\..\..\pjlib\include\pj\sock.h"\ - "..\..\..\pjlib\include\pj\sock_select.h"\ - "..\..\..\pjlib\include\pj\string.h"\ - "..\..\..\pjlib\include\pj\string_i.h"\ - "..\..\..\pjlib\include\pj\timer.h"\ - "..\..\..\pjlib\include\pj\types.h"\ - "..\..\..\pjlib\include\pj\unicode.h"\ - "..\..\..\pjlib\include\pjlib.h"\ - "..\..\include\pjlib-util\config.h"\ - "..\..\include\pjlib-util\errno.h"\ - "..\..\include\pjlib-util\stun_endpoint.h"\ - "..\..\include\pjlib-util\stun_msg.h"\ - "..\..\include\pjlib-util\stun_transaction.h"\ - "..\..\include\pjlib-util\types.h"\ - - -!ELSEIF "$(CFG)" == "pjlib_util_wince - Win32 (WCE ARMV4I) Debug" - -DEP_CPP_STUN_T=\ - "..\..\..\pjlib\include\pj\addr_resolv.h"\ - "..\..\..\pjlib\include\pj\array.h"\ - "..\..\..\pjlib\include\pj\assert.h"\ - "..\..\..\pjlib\include\pj\compat\assert.h"\ - "..\..\..\pjlib\include\pj\compat\cc_gcc.h"\ - "..\..\..\pjlib\include\pj\compat\cc_msvc.h"\ - "..\..\..\pjlib\include\pj\compat\ctype.h"\ - "..\..\..\pjlib\include\pj\compat\errno.h"\ - "..\..\..\pjlib\include\pj\compat\high_precision.h"\ - "..\..\..\pjlib\include\pj\compat\m_auto.h"\ - "..\..\..\pjlib\include\pj\compat\os_auto.h"\ - "..\..\..\pjlib\include\pj\compat\os_darwinos.h"\ - "..\..\..\pjlib\include\pj\compat\os_linux.h"\ - "..\..\..\pjlib\include\pj\compat\os_linux_kernel.h"\ - "..\..\..\pjlib\include\pj\compat\os_palmos.h"\ - "..\..\..\pjlib\include\pj\compat\os_rtems.h"\ - "..\..\..\pjlib\include\pj\compat\os_sunos.h"\ - "..\..\..\pjlib\include\pj\compat\os_win32.h"\ - "..\..\..\pjlib\include\pj\compat\os_win32_wince.h"\ - "..\..\..\pjlib\include\pj\compat\setjmp.h"\ - "..\..\..\pjlib\include\pj\compat\size_t.h"\ - "..\..\..\pjlib\include\pj\compat\string.h"\ - "..\..\..\pjlib\include\pj\config.h"\ - "..\..\..\pjlib\include\pj\config_site.h"\ - "..\..\..\pjlib\include\pj\config_site_sample.h"\ - "..\..\..\pjlib\include\pj\ctype.h"\ - "..\..\..\pjlib\include\pj\errno.h"\ - "..\..\..\pjlib\include\pj\except.h"\ - "..\..\..\pjlib\include\pj\fifobuf.h"\ - "..\..\..\pjlib\include\pj\file_access.h"\ - "..\..\..\pjlib\include\pj\file_io.h"\ - "..\..\..\pjlib\include\pj\guid.h"\ - "..\..\..\pjlib\include\pj\hash.h"\ - "..\..\..\pjlib\include\pj\ioqueue.h"\ - "..\..\..\pjlib\include\pj\list.h"\ - "..\..\..\pjlib\include\pj\list_i.h"\ - "..\..\..\pjlib\include\pj\lock.h"\ - "..\..\..\pjlib\include\pj\log.h"\ - "..\..\..\pjlib\include\pj\os.h"\ - "..\..\..\pjlib\include\pj\pool.h"\ - "..\..\..\pjlib\include\pj\pool_alt.h"\ - "..\..\..\pjlib\include\pj\pool_buf.h"\ - "..\..\..\pjlib\include\pj\pool_i.h"\ - "..\..\..\pjlib\include\pj\rand.h"\ - "..\..\..\pjlib\include\pj\rbtree.h"\ - "..\..\..\pjlib\include\pj\sock.h"\ - "..\..\..\pjlib\include\pj\sock_select.h"\ - "..\..\..\pjlib\include\pj\string.h"\ - "..\..\..\pjlib\include\pj\string_i.h"\ - "..\..\..\pjlib\include\pj\timer.h"\ - "..\..\..\pjlib\include\pj\types.h"\ - "..\..\..\pjlib\include\pj\unicode.h"\ - "..\..\..\pjlib\include\pjlib.h"\ - "..\..\include\pjlib-util\config.h"\ - "..\..\include\pjlib-util\errno.h"\ - "..\..\include\pjlib-util\stun_endpoint.h"\ - "..\..\include\pjlib-util\stun_msg.h"\ - "..\..\include\pjlib-util\stun_transaction.h"\ - "..\..\include\pjlib-util\types.h"\ - - -!ELSEIF "$(CFG)" == "pjlib_util_wince - Win32 (WCE ARMV4) Release" - -DEP_CPP_STUN_T=\ - "..\..\..\pjlib\include\pj\addr_resolv.h"\ - "..\..\..\pjlib\include\pj\array.h"\ - "..\..\..\pjlib\include\pj\assert.h"\ - "..\..\..\pjlib\include\pj\compat\assert.h"\ - "..\..\..\pjlib\include\pj\compat\cc_gcc.h"\ - "..\..\..\pjlib\include\pj\compat\cc_msvc.h"\ - "..\..\..\pjlib\include\pj\compat\ctype.h"\ - "..\..\..\pjlib\include\pj\compat\errno.h"\ - "..\..\..\pjlib\include\pj\compat\high_precision.h"\ - "..\..\..\pjlib\include\pj\compat\m_auto.h"\ - "..\..\..\pjlib\include\pj\compat\os_auto.h"\ - "..\..\..\pjlib\include\pj\compat\os_darwinos.h"\ - "..\..\..\pjlib\include\pj\compat\os_linux.h"\ - "..\..\..\pjlib\include\pj\compat\os_linux_kernel.h"\ - "..\..\..\pjlib\include\pj\compat\os_palmos.h"\ - "..\..\..\pjlib\include\pj\compat\os_rtems.h"\ - "..\..\..\pjlib\include\pj\compat\os_sunos.h"\ - "..\..\..\pjlib\include\pj\compat\os_win32.h"\ - "..\..\..\pjlib\include\pj\compat\os_win32_wince.h"\ - "..\..\..\pjlib\include\pj\compat\setjmp.h"\ - "..\..\..\pjlib\include\pj\compat\size_t.h"\ - "..\..\..\pjlib\include\pj\compat\string.h"\ - "..\..\..\pjlib\include\pj\config.h"\ - "..\..\..\pjlib\include\pj\config_site.h"\ - "..\..\..\pjlib\include\pj\config_site_sample.h"\ - "..\..\..\pjlib\include\pj\ctype.h"\ - "..\..\..\pjlib\include\pj\errno.h"\ - "..\..\..\pjlib\include\pj\except.h"\ - "..\..\..\pjlib\include\pj\fifobuf.h"\ - "..\..\..\pjlib\include\pj\file_access.h"\ - "..\..\..\pjlib\include\pj\file_io.h"\ - "..\..\..\pjlib\include\pj\guid.h"\ - "..\..\..\pjlib\include\pj\hash.h"\ - "..\..\..\pjlib\include\pj\ioqueue.h"\ - "..\..\..\pjlib\include\pj\list.h"\ - "..\..\..\pjlib\include\pj\list_i.h"\ - "..\..\..\pjlib\include\pj\lock.h"\ - "..\..\..\pjlib\include\pj\log.h"\ - "..\..\..\pjlib\include\pj\os.h"\ - "..\..\..\pjlib\include\pj\pool.h"\ - "..\..\..\pjlib\include\pj\pool_alt.h"\ - "..\..\..\pjlib\include\pj\pool_buf.h"\ - "..\..\..\pjlib\include\pj\pool_i.h"\ - "..\..\..\pjlib\include\pj\rand.h"\ - "..\..\..\pjlib\include\pj\rbtree.h"\ - "..\..\..\pjlib\include\pj\sock.h"\ - "..\..\..\pjlib\include\pj\sock_select.h"\ - "..\..\..\pjlib\include\pj\string.h"\ - "..\..\..\pjlib\include\pj\string_i.h"\ - "..\..\..\pjlib\include\pj\timer.h"\ - "..\..\..\pjlib\include\pj\types.h"\ - "..\..\..\pjlib\include\pj\unicode.h"\ - "..\..\..\pjlib\include\pjlib.h"\ - "..\..\include\pjlib-util\config.h"\ - "..\..\include\pjlib-util\errno.h"\ - "..\..\include\pjlib-util\stun_endpoint.h"\ - "..\..\include\pjlib-util\stun_msg.h"\ - "..\..\include\pjlib-util\stun_transaction.h"\ - "..\..\include\pjlib-util\types.h"\ - - -!ELSEIF "$(CFG)" == "pjlib_util_wince - Win32 (WCE ARMV4) Debug" - -DEP_CPP_STUN_T=\ - "..\..\..\pjlib\include\pj\addr_resolv.h"\ - "..\..\..\pjlib\include\pj\array.h"\ - "..\..\..\pjlib\include\pj\assert.h"\ - "..\..\..\pjlib\include\pj\compat\assert.h"\ - "..\..\..\pjlib\include\pj\compat\cc_gcc.h"\ - "..\..\..\pjlib\include\pj\compat\cc_msvc.h"\ - "..\..\..\pjlib\include\pj\compat\ctype.h"\ - "..\..\..\pjlib\include\pj\compat\errno.h"\ - "..\..\..\pjlib\include\pj\compat\high_precision.h"\ - "..\..\..\pjlib\include\pj\compat\m_auto.h"\ - "..\..\..\pjlib\include\pj\compat\os_auto.h"\ - "..\..\..\pjlib\include\pj\compat\os_darwinos.h"\ - "..\..\..\pjlib\include\pj\compat\os_linux.h"\ - "..\..\..\pjlib\include\pj\compat\os_linux_kernel.h"\ - "..\..\..\pjlib\include\pj\compat\os_palmos.h"\ - "..\..\..\pjlib\include\pj\compat\os_rtems.h"\ - "..\..\..\pjlib\include\pj\compat\os_sunos.h"\ - "..\..\..\pjlib\include\pj\compat\os_win32.h"\ - "..\..\..\pjlib\include\pj\compat\os_win32_wince.h"\ - "..\..\..\pjlib\include\pj\compat\setjmp.h"\ - "..\..\..\pjlib\include\pj\compat\size_t.h"\ - "..\..\..\pjlib\include\pj\compat\string.h"\ - "..\..\..\pjlib\include\pj\config.h"\ - "..\..\..\pjlib\include\pj\config_site.h"\ - "..\..\..\pjlib\include\pj\config_site_sample.h"\ - "..\..\..\pjlib\include\pj\ctype.h"\ - "..\..\..\pjlib\include\pj\errno.h"\ - "..\..\..\pjlib\include\pj\except.h"\ - "..\..\..\pjlib\include\pj\fifobuf.h"\ - "..\..\..\pjlib\include\pj\file_access.h"\ - "..\..\..\pjlib\include\pj\file_io.h"\ - "..\..\..\pjlib\include\pj\guid.h"\ - "..\..\..\pjlib\include\pj\hash.h"\ - "..\..\..\pjlib\include\pj\ioqueue.h"\ - "..\..\..\pjlib\include\pj\list.h"\ - "..\..\..\pjlib\include\pj\list_i.h"\ - "..\..\..\pjlib\include\pj\lock.h"\ - "..\..\..\pjlib\include\pj\log.h"\ - "..\..\..\pjlib\include\pj\os.h"\ - "..\..\..\pjlib\include\pj\pool.h"\ - "..\..\..\pjlib\include\pj\pool_alt.h"\ - "..\..\..\pjlib\include\pj\pool_buf.h"\ - "..\..\..\pjlib\include\pj\pool_i.h"\ - "..\..\..\pjlib\include\pj\rand.h"\ - "..\..\..\pjlib\include\pj\rbtree.h"\ - "..\..\..\pjlib\include\pj\sock.h"\ - "..\..\..\pjlib\include\pj\sock_select.h"\ - "..\..\..\pjlib\include\pj\string.h"\ - "..\..\..\pjlib\include\pj\string_i.h"\ - "..\..\..\pjlib\include\pj\timer.h"\ - "..\..\..\pjlib\include\pj\types.h"\ - "..\..\..\pjlib\include\pj\unicode.h"\ - "..\..\..\pjlib\include\pjlib.h"\ - "..\..\include\pjlib-util\config.h"\ - "..\..\include\pjlib-util\errno.h"\ - "..\..\include\pjlib-util\stun_endpoint.h"\ - "..\..\include\pjlib-util\stun_msg.h"\ - "..\..\include\pjlib-util\stun_transaction.h"\ - "..\..\include\pjlib-util\types.h"\ - - -!ELSEIF "$(CFG)" == "pjlib_util_wince - Win32 (WCE ARMV4T) Release" - -DEP_CPP_STUN_T=\ - "..\..\..\pjlib\include\pj\addr_resolv.h"\ - "..\..\..\pjlib\include\pj\array.h"\ - "..\..\..\pjlib\include\pj\assert.h"\ - "..\..\..\pjlib\include\pj\compat\assert.h"\ - "..\..\..\pjlib\include\pj\compat\cc_gcc.h"\ - "..\..\..\pjlib\include\pj\compat\cc_msvc.h"\ - "..\..\..\pjlib\include\pj\compat\ctype.h"\ - "..\..\..\pjlib\include\pj\compat\errno.h"\ - "..\..\..\pjlib\include\pj\compat\high_precision.h"\ - "..\..\..\pjlib\include\pj\compat\m_auto.h"\ - "..\..\..\pjlib\include\pj\compat\os_auto.h"\ - "..\..\..\pjlib\include\pj\compat\os_darwinos.h"\ - "..\..\..\pjlib\include\pj\compat\os_linux.h"\ - "..\..\..\pjlib\include\pj\compat\os_linux_kernel.h"\ - "..\..\..\pjlib\include\pj\compat\os_palmos.h"\ - "..\..\..\pjlib\include\pj\compat\os_rtems.h"\ - "..\..\..\pjlib\include\pj\compat\os_sunos.h"\ - "..\..\..\pjlib\include\pj\compat\os_win32.h"\ - "..\..\..\pjlib\include\pj\compat\os_win32_wince.h"\ - "..\..\..\pjlib\include\pj\compat\setjmp.h"\ - "..\..\..\pjlib\include\pj\compat\size_t.h"\ - "..\..\..\pjlib\include\pj\compat\string.h"\ - "..\..\..\pjlib\include\pj\config.h"\ - "..\..\..\pjlib\include\pj\config_site.h"\ - "..\..\..\pjlib\include\pj\config_site_sample.h"\ - "..\..\..\pjlib\include\pj\ctype.h"\ - "..\..\..\pjlib\include\pj\errno.h"\ - "..\..\..\pjlib\include\pj\except.h"\ - "..\..\..\pjlib\include\pj\fifobuf.h"\ - "..\..\..\pjlib\include\pj\file_access.h"\ - "..\..\..\pjlib\include\pj\file_io.h"\ - "..\..\..\pjlib\include\pj\guid.h"\ - "..\..\..\pjlib\include\pj\hash.h"\ - "..\..\..\pjlib\include\pj\ioqueue.h"\ - "..\..\..\pjlib\include\pj\list.h"\ - "..\..\..\pjlib\include\pj\list_i.h"\ - "..\..\..\pjlib\include\pj\lock.h"\ - "..\..\..\pjlib\include\pj\log.h"\ - "..\..\..\pjlib\include\pj\os.h"\ - "..\..\..\pjlib\include\pj\pool.h"\ - "..\..\..\pjlib\include\pj\pool_alt.h"\ - "..\..\..\pjlib\include\pj\pool_buf.h"\ - "..\..\..\pjlib\include\pj\pool_i.h"\ - "..\..\..\pjlib\include\pj\rand.h"\ - "..\..\..\pjlib\include\pj\rbtree.h"\ - "..\..\..\pjlib\include\pj\sock.h"\ - "..\..\..\pjlib\include\pj\sock_select.h"\ - "..\..\..\pjlib\include\pj\string.h"\ - "..\..\..\pjlib\include\pj\string_i.h"\ - "..\..\..\pjlib\include\pj\timer.h"\ - "..\..\..\pjlib\include\pj\types.h"\ - "..\..\..\pjlib\include\pj\unicode.h"\ - "..\..\..\pjlib\include\pjlib.h"\ - "..\..\include\pjlib-util\config.h"\ - "..\..\include\pjlib-util\errno.h"\ - "..\..\include\pjlib-util\stun_endpoint.h"\ - "..\..\include\pjlib-util\stun_msg.h"\ - "..\..\include\pjlib-util\stun_transaction.h"\ - "..\..\include\pjlib-util\types.h"\ - - -!ELSEIF "$(CFG)" == "pjlib_util_wince - Win32 (WCE ARMV4T) Debug" - -DEP_CPP_STUN_T=\ - "..\..\..\pjlib\include\pj\addr_resolv.h"\ - "..\..\..\pjlib\include\pj\array.h"\ - "..\..\..\pjlib\include\pj\assert.h"\ - "..\..\..\pjlib\include\pj\compat\assert.h"\ - "..\..\..\pjlib\include\pj\compat\cc_gcc.h"\ - "..\..\..\pjlib\include\pj\compat\cc_msvc.h"\ - "..\..\..\pjlib\include\pj\compat\ctype.h"\ - "..\..\..\pjlib\include\pj\compat\errno.h"\ - "..\..\..\pjlib\include\pj\compat\high_precision.h"\ - "..\..\..\pjlib\include\pj\compat\m_auto.h"\ - "..\..\..\pjlib\include\pj\compat\os_auto.h"\ - "..\..\..\pjlib\include\pj\compat\os_darwinos.h"\ - "..\..\..\pjlib\include\pj\compat\os_linux.h"\ - "..\..\..\pjlib\include\pj\compat\os_linux_kernel.h"\ - "..\..\..\pjlib\include\pj\compat\os_palmos.h"\ - "..\..\..\pjlib\include\pj\compat\os_rtems.h"\ - "..\..\..\pjlib\include\pj\compat\os_sunos.h"\ - "..\..\..\pjlib\include\pj\compat\os_win32.h"\ - "..\..\..\pjlib\include\pj\compat\os_win32_wince.h"\ - "..\..\..\pjlib\include\pj\compat\setjmp.h"\ - "..\..\..\pjlib\include\pj\compat\size_t.h"\ - "..\..\..\pjlib\include\pj\compat\string.h"\ - "..\..\..\pjlib\include\pj\config.h"\ - "..\..\..\pjlib\include\pj\config_site.h"\ - "..\..\..\pjlib\include\pj\config_site_sample.h"\ - "..\..\..\pjlib\include\pj\ctype.h"\ - "..\..\..\pjlib\include\pj\errno.h"\ - "..\..\..\pjlib\include\pj\except.h"\ - "..\..\..\pjlib\include\pj\fifobuf.h"\ - "..\..\..\pjlib\include\pj\file_access.h"\ - "..\..\..\pjlib\include\pj\file_io.h"\ - "..\..\..\pjlib\include\pj\guid.h"\ - "..\..\..\pjlib\include\pj\hash.h"\ - "..\..\..\pjlib\include\pj\ioqueue.h"\ - "..\..\..\pjlib\include\pj\list.h"\ - "..\..\..\pjlib\include\pj\list_i.h"\ - "..\..\..\pjlib\include\pj\lock.h"\ - "..\..\..\pjlib\include\pj\log.h"\ - "..\..\..\pjlib\include\pj\os.h"\ - "..\..\..\pjlib\include\pj\pool.h"\ - "..\..\..\pjlib\include\pj\pool_alt.h"\ - "..\..\..\pjlib\include\pj\pool_buf.h"\ - "..\..\..\pjlib\include\pj\pool_i.h"\ - "..\..\..\pjlib\include\pj\rand.h"\ - "..\..\..\pjlib\include\pj\rbtree.h"\ - "..\..\..\pjlib\include\pj\sock.h"\ - "..\..\..\pjlib\include\pj\sock_select.h"\ - "..\..\..\pjlib\include\pj\string.h"\ - "..\..\..\pjlib\include\pj\string_i.h"\ - "..\..\..\pjlib\include\pj\timer.h"\ - "..\..\..\pjlib\include\pj\types.h"\ - "..\..\..\pjlib\include\pj\unicode.h"\ - "..\..\..\pjlib\include\pjlib.h"\ - "..\..\include\pjlib-util\config.h"\ - "..\..\include\pjlib-util\errno.h"\ - "..\..\include\pjlib-util\stun_endpoint.h"\ - "..\..\include\pjlib-util\stun_msg.h"\ - "..\..\include\pjlib-util\stun_transaction.h"\ - "..\..\include\pjlib-util\types.h"\ - - -!ELSEIF "$(CFG)" == "pjlib_util_wince - Win32 (WCE x86) Release" - -DEP_CPP_STUN_T=\ - "..\..\..\pjlib\include\pj\addr_resolv.h"\ - "..\..\..\pjlib\include\pj\array.h"\ - "..\..\..\pjlib\include\pj\assert.h"\ - "..\..\..\pjlib\include\pj\compat\assert.h"\ - "..\..\..\pjlib\include\pj\compat\cc_gcc.h"\ - "..\..\..\pjlib\include\pj\compat\cc_msvc.h"\ - "..\..\..\pjlib\include\pj\compat\ctype.h"\ - "..\..\..\pjlib\include\pj\compat\errno.h"\ - "..\..\..\pjlib\include\pj\compat\high_precision.h"\ - "..\..\..\pjlib\include\pj\compat\m_auto.h"\ - "..\..\..\pjlib\include\pj\compat\os_auto.h"\ - "..\..\..\pjlib\include\pj\compat\os_darwinos.h"\ - "..\..\..\pjlib\include\pj\compat\os_linux.h"\ - "..\..\..\pjlib\include\pj\compat\os_linux_kernel.h"\ - "..\..\..\pjlib\include\pj\compat\os_palmos.h"\ - "..\..\..\pjlib\include\pj\compat\os_rtems.h"\ - "..\..\..\pjlib\include\pj\compat\os_sunos.h"\ - "..\..\..\pjlib\include\pj\compat\os_win32.h"\ - "..\..\..\pjlib\include\pj\compat\os_win32_wince.h"\ - "..\..\..\pjlib\include\pj\compat\setjmp.h"\ - "..\..\..\pjlib\include\pj\compat\size_t.h"\ - "..\..\..\pjlib\include\pj\compat\string.h"\ - "..\..\..\pjlib\include\pj\config.h"\ - "..\..\..\pjlib\include\pj\config_site.h"\ - "..\..\..\pjlib\include\pj\config_site_sample.h"\ - "..\..\..\pjlib\include\pj\ctype.h"\ - "..\..\..\pjlib\include\pj\errno.h"\ - "..\..\..\pjlib\include\pj\except.h"\ - "..\..\..\pjlib\include\pj\fifobuf.h"\ - "..\..\..\pjlib\include\pj\file_access.h"\ - "..\..\..\pjlib\include\pj\file_io.h"\ - "..\..\..\pjlib\include\pj\guid.h"\ - "..\..\..\pjlib\include\pj\hash.h"\ - "..\..\..\pjlib\include\pj\ioqueue.h"\ - "..\..\..\pjlib\include\pj\list.h"\ - "..\..\..\pjlib\include\pj\list_i.h"\ - "..\..\..\pjlib\include\pj\lock.h"\ - "..\..\..\pjlib\include\pj\log.h"\ - "..\..\..\pjlib\include\pj\os.h"\ - "..\..\..\pjlib\include\pj\pool.h"\ - "..\..\..\pjlib\include\pj\pool_alt.h"\ - "..\..\..\pjlib\include\pj\pool_buf.h"\ - "..\..\..\pjlib\include\pj\pool_i.h"\ - "..\..\..\pjlib\include\pj\rand.h"\ - "..\..\..\pjlib\include\pj\rbtree.h"\ - "..\..\..\pjlib\include\pj\sock.h"\ - "..\..\..\pjlib\include\pj\sock_select.h"\ - "..\..\..\pjlib\include\pj\string.h"\ - "..\..\..\pjlib\include\pj\string_i.h"\ - "..\..\..\pjlib\include\pj\timer.h"\ - "..\..\..\pjlib\include\pj\types.h"\ - "..\..\..\pjlib\include\pj\unicode.h"\ - "..\..\..\pjlib\include\pjlib.h"\ - "..\..\include\pjlib-util\config.h"\ - "..\..\include\pjlib-util\errno.h"\ - "..\..\include\pjlib-util\stun_endpoint.h"\ - "..\..\include\pjlib-util\stun_msg.h"\ - "..\..\include\pjlib-util\stun_transaction.h"\ - "..\..\include\pjlib-util\types.h"\ - - -!ELSEIF "$(CFG)" == "pjlib_util_wince - Win32 (WCE x86) Debug" - -DEP_CPP_STUN_T=\ - "..\..\..\pjlib\include\pj\addr_resolv.h"\ - "..\..\..\pjlib\include\pj\array.h"\ - "..\..\..\pjlib\include\pj\assert.h"\ - "..\..\..\pjlib\include\pj\compat\assert.h"\ - "..\..\..\pjlib\include\pj\compat\cc_gcc.h"\ - "..\..\..\pjlib\include\pj\compat\cc_msvc.h"\ - "..\..\..\pjlib\include\pj\compat\ctype.h"\ - "..\..\..\pjlib\include\pj\compat\errno.h"\ - "..\..\..\pjlib\include\pj\compat\high_precision.h"\ - "..\..\..\pjlib\include\pj\compat\m_auto.h"\ - "..\..\..\pjlib\include\pj\compat\os_auto.h"\ - "..\..\..\pjlib\include\pj\compat\os_darwinos.h"\ - "..\..\..\pjlib\include\pj\compat\os_linux.h"\ - "..\..\..\pjlib\include\pj\compat\os_linux_kernel.h"\ - "..\..\..\pjlib\include\pj\compat\os_palmos.h"\ - "..\..\..\pjlib\include\pj\compat\os_rtems.h"\ - "..\..\..\pjlib\include\pj\compat\os_sunos.h"\ - "..\..\..\pjlib\include\pj\compat\os_win32.h"\ - "..\..\..\pjlib\include\pj\compat\os_win32_wince.h"\ - "..\..\..\pjlib\include\pj\compat\setjmp.h"\ - "..\..\..\pjlib\include\pj\compat\size_t.h"\ - "..\..\..\pjlib\include\pj\compat\string.h"\ - "..\..\..\pjlib\include\pj\config.h"\ - "..\..\..\pjlib\include\pj\config_site.h"\ - "..\..\..\pjlib\include\pj\config_site_sample.h"\ - "..\..\..\pjlib\include\pj\ctype.h"\ - "..\..\..\pjlib\include\pj\errno.h"\ - "..\..\..\pjlib\include\pj\except.h"\ - "..\..\..\pjlib\include\pj\fifobuf.h"\ - "..\..\..\pjlib\include\pj\file_access.h"\ - "..\..\..\pjlib\include\pj\file_io.h"\ - "..\..\..\pjlib\include\pj\guid.h"\ - "..\..\..\pjlib\include\pj\hash.h"\ - "..\..\..\pjlib\include\pj\ioqueue.h"\ - "..\..\..\pjlib\include\pj\list.h"\ - "..\..\..\pjlib\include\pj\list_i.h"\ - "..\..\..\pjlib\include\pj\lock.h"\ - "..\..\..\pjlib\include\pj\log.h"\ - "..\..\..\pjlib\include\pj\os.h"\ - "..\..\..\pjlib\include\pj\pool.h"\ - "..\..\..\pjlib\include\pj\pool_alt.h"\ - "..\..\..\pjlib\include\pj\pool_buf.h"\ - "..\..\..\pjlib\include\pj\pool_i.h"\ - "..\..\..\pjlib\include\pj\rand.h"\ - "..\..\..\pjlib\include\pj\rbtree.h"\ - "..\..\..\pjlib\include\pj\sock.h"\ - "..\..\..\pjlib\include\pj\sock_select.h"\ - "..\..\..\pjlib\include\pj\string.h"\ - "..\..\..\pjlib\include\pj\string_i.h"\ - "..\..\..\pjlib\include\pj\timer.h"\ - "..\..\..\pjlib\include\pj\types.h"\ - "..\..\..\pjlib\include\pj\unicode.h"\ - "..\..\..\pjlib\include\pjlib.h"\ - "..\..\include\pjlib-util\config.h"\ - "..\..\include\pjlib-util\errno.h"\ - "..\..\include\pjlib-util\stun_endpoint.h"\ - "..\..\include\pjlib-util\stun_msg.h"\ - "..\..\include\pjlib-util\stun_transaction.h"\ - "..\..\include\pjlib-util\types.h"\ - - -!ENDIF - -# End Source File -# Begin Source File - -SOURCE="..\..\src\pjlib-util\xml.c" - -!IF "$(CFG)" == "pjlib_util_wince - Win32 (WCE emulator) Release" - -DEP_CPP_XML_C=\ - "..\..\..\pjlib\include\pj\compat\cc_gcc.h"\ - "..\..\..\pjlib\include\pj\compat\cc_msvc.h"\ - "..\..\..\pjlib\include\pj\compat\m_alpha.h"\ - "..\..\..\pjlib\include\pj\compat\m_i386.h"\ - "..\..\..\pjlib\include\pj\compat\m_m68k.h"\ - "..\..\..\pjlib\include\pj\compat\m_sparc.h"\ - "..\..\..\pjlib\include\pj\compat\os_linux.h"\ - "..\..\..\pjlib\include\pj\compat\os_linux_kernel.h"\ - "..\..\..\pjlib\include\pj\compat\os_palmos.h"\ - "..\..\..\pjlib\include\pj\compat\os_sunos.h"\ - "..\..\..\pjlib\include\pj\compat\os_win32.h"\ - "..\..\..\pjlib\include\pj\compat\os_win32_wince.h"\ - "..\..\..\pjlib\include\pj\compat\setjmp.h"\ - "..\..\..\pjlib\include\pj\compat\size_t.h"\ - "..\..\..\pjlib\include\pj\compat\string.h"\ - "..\..\..\pjlib\include\pj\config.h"\ - "..\..\..\pjlib\include\pj\config_site.h"\ - "..\..\..\pjlib\include\pj\except.h"\ - "..\..\..\pjlib\include\pj\list.h"\ - "..\..\..\pjlib\include\pj\list_i.h"\ - "..\..\..\pjlib\include\pj\log.h"\ - "..\..\..\pjlib\include\pj\os.h"\ - "..\..\..\pjlib\include\pj\pool.h"\ - "..\..\..\pjlib\include\pj\pool_i.h"\ - "..\..\..\pjlib\include\pj\string.h"\ - "..\..\..\pjlib\include\pj\string_i.h"\ - "..\..\..\pjlib\include\pj\types.h"\ - "..\..\include\pjlib-util\scanner.h"\ - "..\..\include\pjlib-util\scanner_cis_bitwise.h"\ - "..\..\include\pjlib-util\scanner_cis_uint.h"\ - "..\..\include\pjlib-util\xml.h"\ - -NODEP_CPP_XML_C=\ - "..\..\..\pjlib\include\pj\compat\m_arm.h"\ - "..\..\..\pjlib\include\pj\compat\sprintf.h"\ - "..\..\..\pjlib\include\pj\compat\vsprintf.h"\ - - -!ELSEIF "$(CFG)" == "pjlib_util_wince - Win32 (WCE emulator) Debug" - -DEP_CPP_XML_C=\ - "..\..\..\pjlib\include\pj\addr_resolv.h"\ - "..\..\..\pjlib\include\pj\array.h"\ - "..\..\..\pjlib\include\pj\assert.h"\ - "..\..\..\pjlib\include\pj\compat\assert.h"\ - "..\..\..\pjlib\include\pj\compat\cc_gcc.h"\ - "..\..\..\pjlib\include\pj\compat\cc_msvc.h"\ - "..\..\..\pjlib\include\pj\compat\ctype.h"\ - "..\..\..\pjlib\include\pj\compat\errno.h"\ - "..\..\..\pjlib\include\pj\compat\high_precision.h"\ - "..\..\..\pjlib\include\pj\compat\m_auto.h"\ - "..\..\..\pjlib\include\pj\compat\os_auto.h"\ - "..\..\..\pjlib\include\pj\compat\os_darwinos.h"\ - "..\..\..\pjlib\include\pj\compat\os_linux.h"\ - "..\..\..\pjlib\include\pj\compat\os_linux_kernel.h"\ - "..\..\..\pjlib\include\pj\compat\os_palmos.h"\ - "..\..\..\pjlib\include\pj\compat\os_rtems.h"\ - "..\..\..\pjlib\include\pj\compat\os_sunos.h"\ - "..\..\..\pjlib\include\pj\compat\os_win32.h"\ - "..\..\..\pjlib\include\pj\compat\os_win32_wince.h"\ - "..\..\..\pjlib\include\pj\compat\setjmp.h"\ - "..\..\..\pjlib\include\pj\compat\size_t.h"\ - "..\..\..\pjlib\include\pj\compat\string.h"\ - "..\..\..\pjlib\include\pj\config.h"\ - "..\..\..\pjlib\include\pj\config_site.h"\ - "..\..\..\pjlib\include\pj\config_site_sample.h"\ - "..\..\..\pjlib\include\pj\ctype.h"\ - "..\..\..\pjlib\include\pj\errno.h"\ - "..\..\..\pjlib\include\pj\except.h"\ - "..\..\..\pjlib\include\pj\fifobuf.h"\ - "..\..\..\pjlib\include\pj\file_access.h"\ - "..\..\..\pjlib\include\pj\file_io.h"\ - "..\..\..\pjlib\include\pj\guid.h"\ - "..\..\..\pjlib\include\pj\hash.h"\ - "..\..\..\pjlib\include\pj\ioqueue.h"\ - "..\..\..\pjlib\include\pj\list.h"\ - "..\..\..\pjlib\include\pj\list_i.h"\ - "..\..\..\pjlib\include\pj\lock.h"\ - "..\..\..\pjlib\include\pj\log.h"\ - "..\..\..\pjlib\include\pj\os.h"\ - "..\..\..\pjlib\include\pj\pool.h"\ - "..\..\..\pjlib\include\pj\pool_alt.h"\ - "..\..\..\pjlib\include\pj\pool_buf.h"\ - "..\..\..\pjlib\include\pj\pool_i.h"\ - "..\..\..\pjlib\include\pj\rand.h"\ - "..\..\..\pjlib\include\pj\rbtree.h"\ - "..\..\..\pjlib\include\pj\sock.h"\ - "..\..\..\pjlib\include\pj\sock_select.h"\ - "..\..\..\pjlib\include\pj\string.h"\ - "..\..\..\pjlib\include\pj\string_i.h"\ - "..\..\..\pjlib\include\pj\timer.h"\ - "..\..\..\pjlib\include\pj\types.h"\ - "..\..\..\pjlib\include\pj\unicode.h"\ - "..\..\..\pjlib\include\pjlib.h"\ - "..\..\include\pjlib-util\config.h"\ - "..\..\include\pjlib-util\scanner.h"\ - "..\..\include\pjlib-util\scanner_cis_bitwise.h"\ - "..\..\include\pjlib-util\scanner_cis_uint.h"\ - "..\..\include\pjlib-util\types.h"\ - "..\..\include\pjlib-util\xml.h"\ - - -!ELSEIF "$(CFG)" == "pjlib_util_wince - Win32 (WCE ARMV4I) Release" - -DEP_CPP_XML_C=\ - "..\..\..\pjlib\include\pj\compat\cc_gcc.h"\ - "..\..\..\pjlib\include\pj\compat\cc_msvc.h"\ - "..\..\..\pjlib\include\pj\compat\m_alpha.h"\ - "..\..\..\pjlib\include\pj\compat\m_i386.h"\ - "..\..\..\pjlib\include\pj\compat\m_m68k.h"\ - "..\..\..\pjlib\include\pj\compat\m_sparc.h"\ - "..\..\..\pjlib\include\pj\compat\os_linux.h"\ - "..\..\..\pjlib\include\pj\compat\os_linux_kernel.h"\ - "..\..\..\pjlib\include\pj\compat\os_palmos.h"\ - "..\..\..\pjlib\include\pj\compat\os_sunos.h"\ - "..\..\..\pjlib\include\pj\compat\os_win32.h"\ - "..\..\..\pjlib\include\pj\compat\os_win32_wince.h"\ - "..\..\..\pjlib\include\pj\compat\setjmp.h"\ - "..\..\..\pjlib\include\pj\compat\size_t.h"\ - "..\..\..\pjlib\include\pj\compat\string.h"\ - "..\..\..\pjlib\include\pj\config.h"\ - "..\..\..\pjlib\include\pj\config_site.h"\ - "..\..\..\pjlib\include\pj\except.h"\ - "..\..\..\pjlib\include\pj\list.h"\ - "..\..\..\pjlib\include\pj\list_i.h"\ - "..\..\..\pjlib\include\pj\log.h"\ - "..\..\..\pjlib\include\pj\os.h"\ - "..\..\..\pjlib\include\pj\pool.h"\ - "..\..\..\pjlib\include\pj\pool_i.h"\ - "..\..\..\pjlib\include\pj\string.h"\ - "..\..\..\pjlib\include\pj\string_i.h"\ - "..\..\..\pjlib\include\pj\types.h"\ - "..\..\include\pjlib-util\scanner.h"\ - "..\..\include\pjlib-util\scanner_cis_bitwise.h"\ - "..\..\include\pjlib-util\scanner_cis_uint.h"\ - "..\..\include\pjlib-util\xml.h"\ - -NODEP_CPP_XML_C=\ - "..\..\..\pjlib\include\pj\compat\m_arm.h"\ - "..\..\..\pjlib\include\pj\compat\sprintf.h"\ - "..\..\..\pjlib\include\pj\compat\vsprintf.h"\ - - -!ELSEIF "$(CFG)" == "pjlib_util_wince - Win32 (WCE ARMV4I) Debug" - -DEP_CPP_XML_C=\ - "..\..\..\pjlib\include\pj\compat\cc_gcc.h"\ - "..\..\..\pjlib\include\pj\compat\cc_msvc.h"\ - "..\..\..\pjlib\include\pj\compat\m_alpha.h"\ - "..\..\..\pjlib\include\pj\compat\m_i386.h"\ - "..\..\..\pjlib\include\pj\compat\m_m68k.h"\ - "..\..\..\pjlib\include\pj\compat\m_sparc.h"\ - "..\..\..\pjlib\include\pj\compat\os_linux.h"\ - "..\..\..\pjlib\include\pj\compat\os_linux_kernel.h"\ - "..\..\..\pjlib\include\pj\compat\os_palmos.h"\ - "..\..\..\pjlib\include\pj\compat\os_sunos.h"\ - "..\..\..\pjlib\include\pj\compat\os_win32.h"\ - "..\..\..\pjlib\include\pj\compat\os_win32_wince.h"\ - "..\..\..\pjlib\include\pj\compat\setjmp.h"\ - "..\..\..\pjlib\include\pj\compat\size_t.h"\ - "..\..\..\pjlib\include\pj\compat\string.h"\ - "..\..\..\pjlib\include\pj\config.h"\ - "..\..\..\pjlib\include\pj\config_site.h"\ - "..\..\..\pjlib\include\pj\except.h"\ - "..\..\..\pjlib\include\pj\list.h"\ - "..\..\..\pjlib\include\pj\list_i.h"\ - "..\..\..\pjlib\include\pj\log.h"\ - "..\..\..\pjlib\include\pj\os.h"\ - "..\..\..\pjlib\include\pj\pool.h"\ - "..\..\..\pjlib\include\pj\pool_i.h"\ - "..\..\..\pjlib\include\pj\string.h"\ - "..\..\..\pjlib\include\pj\string_i.h"\ - "..\..\..\pjlib\include\pj\types.h"\ - "..\..\include\pjlib-util\scanner.h"\ - "..\..\include\pjlib-util\scanner_cis_bitwise.h"\ - "..\..\include\pjlib-util\scanner_cis_uint.h"\ - "..\..\include\pjlib-util\xml.h"\ - -NODEP_CPP_XML_C=\ - "..\..\..\pjlib\include\pj\compat\m_arm.h"\ - "..\..\..\pjlib\include\pj\compat\sprintf.h"\ - "..\..\..\pjlib\include\pj\compat\vsprintf.h"\ - - -!ELSEIF "$(CFG)" == "pjlib_util_wince - Win32 (WCE ARMV4) Release" - -DEP_CPP_XML_C=\ - "..\..\..\pjlib\include\pj\addr_resolv.h"\ - "..\..\..\pjlib\include\pj\array.h"\ - "..\..\..\pjlib\include\pj\assert.h"\ - "..\..\..\pjlib\include\pj\compat\assert.h"\ - "..\..\..\pjlib\include\pj\compat\cc_gcc.h"\ - "..\..\..\pjlib\include\pj\compat\cc_msvc.h"\ - "..\..\..\pjlib\include\pj\compat\ctype.h"\ - "..\..\..\pjlib\include\pj\compat\errno.h"\ - "..\..\..\pjlib\include\pj\compat\high_precision.h"\ - "..\..\..\pjlib\include\pj\compat\m_auto.h"\ - "..\..\..\pjlib\include\pj\compat\os_auto.h"\ - "..\..\..\pjlib\include\pj\compat\os_darwinos.h"\ - "..\..\..\pjlib\include\pj\compat\os_linux.h"\ - "..\..\..\pjlib\include\pj\compat\os_linux_kernel.h"\ - "..\..\..\pjlib\include\pj\compat\os_palmos.h"\ - "..\..\..\pjlib\include\pj\compat\os_rtems.h"\ - "..\..\..\pjlib\include\pj\compat\os_sunos.h"\ - "..\..\..\pjlib\include\pj\compat\os_win32.h"\ - "..\..\..\pjlib\include\pj\compat\os_win32_wince.h"\ - "..\..\..\pjlib\include\pj\compat\setjmp.h"\ - "..\..\..\pjlib\include\pj\compat\size_t.h"\ - "..\..\..\pjlib\include\pj\compat\string.h"\ - "..\..\..\pjlib\include\pj\config.h"\ - "..\..\..\pjlib\include\pj\config_site.h"\ - "..\..\..\pjlib\include\pj\config_site_sample.h"\ - "..\..\..\pjlib\include\pj\ctype.h"\ - "..\..\..\pjlib\include\pj\errno.h"\ - "..\..\..\pjlib\include\pj\except.h"\ - "..\..\..\pjlib\include\pj\fifobuf.h"\ - "..\..\..\pjlib\include\pj\file_access.h"\ - "..\..\..\pjlib\include\pj\file_io.h"\ - "..\..\..\pjlib\include\pj\guid.h"\ - "..\..\..\pjlib\include\pj\hash.h"\ - "..\..\..\pjlib\include\pj\ioqueue.h"\ - "..\..\..\pjlib\include\pj\list.h"\ - "..\..\..\pjlib\include\pj\list_i.h"\ - "..\..\..\pjlib\include\pj\lock.h"\ - "..\..\..\pjlib\include\pj\log.h"\ - "..\..\..\pjlib\include\pj\os.h"\ - "..\..\..\pjlib\include\pj\pool.h"\ - "..\..\..\pjlib\include\pj\pool_alt.h"\ - "..\..\..\pjlib\include\pj\pool_buf.h"\ - "..\..\..\pjlib\include\pj\pool_i.h"\ - "..\..\..\pjlib\include\pj\rand.h"\ - "..\..\..\pjlib\include\pj\rbtree.h"\ - "..\..\..\pjlib\include\pj\sock.h"\ - "..\..\..\pjlib\include\pj\sock_select.h"\ - "..\..\..\pjlib\include\pj\string.h"\ - "..\..\..\pjlib\include\pj\string_i.h"\ - "..\..\..\pjlib\include\pj\timer.h"\ - "..\..\..\pjlib\include\pj\types.h"\ - "..\..\..\pjlib\include\pj\unicode.h"\ - "..\..\..\pjlib\include\pjlib.h"\ - "..\..\include\pjlib-util\scanner.h"\ - "..\..\include\pjlib-util\scanner_cis_bitwise.h"\ - "..\..\include\pjlib-util\scanner_cis_uint.h"\ - "..\..\include\pjlib-util\xml.h"\ - - -!ELSEIF "$(CFG)" == "pjlib_util_wince - Win32 (WCE ARMV4) Debug" - -DEP_CPP_XML_C=\ - "..\..\..\pjlib\include\pj\compat\cc_gcc.h"\ - "..\..\..\pjlib\include\pj\compat\cc_msvc.h"\ - "..\..\..\pjlib\include\pj\compat\m_alpha.h"\ - "..\..\..\pjlib\include\pj\compat\m_i386.h"\ - "..\..\..\pjlib\include\pj\compat\m_m68k.h"\ - "..\..\..\pjlib\include\pj\compat\m_sparc.h"\ - "..\..\..\pjlib\include\pj\compat\os_linux.h"\ - "..\..\..\pjlib\include\pj\compat\os_linux_kernel.h"\ - "..\..\..\pjlib\include\pj\compat\os_palmos.h"\ - "..\..\..\pjlib\include\pj\compat\os_sunos.h"\ - "..\..\..\pjlib\include\pj\compat\os_win32.h"\ - "..\..\..\pjlib\include\pj\compat\os_win32_wince.h"\ - "..\..\..\pjlib\include\pj\compat\setjmp.h"\ - "..\..\..\pjlib\include\pj\compat\size_t.h"\ - "..\..\..\pjlib\include\pj\compat\string.h"\ - "..\..\..\pjlib\include\pj\config.h"\ - "..\..\..\pjlib\include\pj\config_site.h"\ - "..\..\..\pjlib\include\pj\except.h"\ - "..\..\..\pjlib\include\pj\list.h"\ - "..\..\..\pjlib\include\pj\list_i.h"\ - "..\..\..\pjlib\include\pj\log.h"\ - "..\..\..\pjlib\include\pj\os.h"\ - "..\..\..\pjlib\include\pj\pool.h"\ - "..\..\..\pjlib\include\pj\pool_i.h"\ - "..\..\..\pjlib\include\pj\string.h"\ - "..\..\..\pjlib\include\pj\string_i.h"\ - "..\..\..\pjlib\include\pj\types.h"\ - "..\..\include\pjlib-util\scanner.h"\ - "..\..\include\pjlib-util\scanner_cis_bitwise.h"\ - "..\..\include\pjlib-util\scanner_cis_uint.h"\ - "..\..\include\pjlib-util\xml.h"\ - -NODEP_CPP_XML_C=\ - "..\..\..\pjlib\include\pj\compat\m_arm.h"\ - "..\..\..\pjlib\include\pj\compat\sprintf.h"\ - "..\..\..\pjlib\include\pj\compat\vsprintf.h"\ - - -!ELSEIF "$(CFG)" == "pjlib_util_wince - Win32 (WCE ARMV4T) Release" - -DEP_CPP_XML_C=\ - "..\..\..\pjlib\include\pj\compat\cc_gcc.h"\ - "..\..\..\pjlib\include\pj\compat\cc_msvc.h"\ - "..\..\..\pjlib\include\pj\compat\m_alpha.h"\ - "..\..\..\pjlib\include\pj\compat\m_i386.h"\ - "..\..\..\pjlib\include\pj\compat\m_m68k.h"\ - "..\..\..\pjlib\include\pj\compat\m_sparc.h"\ + "..\..\..\pjlib\include\pj\compat\m_alpha.h"\ + "..\..\..\pjlib\include\pj\compat\m_i386.h"\ + "..\..\..\pjlib\include\pj\compat\m_m68k.h"\ + "..\..\..\pjlib\include\pj\compat\m_sparc.h"\ "..\..\..\pjlib\include\pj\compat\os_linux.h"\ "..\..\..\pjlib\include\pj\compat\os_linux_kernel.h"\ "..\..\..\pjlib\include\pj\compat\os_palmos.h"\ @@ -11073,30 +7887,10 @@ SOURCE="..\..\include\pjlib-util\string.h" # End Source File # Begin Source File -SOURCE="..\..\include\pjlib-util\stun_doc.h" -# End Source File -# Begin Source File - -SOURCE="..\..\include\pjlib-util\stun_endpoint.h" -# End Source File -# Begin Source File - -SOURCE="..\..\include\pjlib-util\stun_msg.h" -# End Source File -# Begin Source File - -SOURCE="..\..\include\pjlib-util\stun_server.h" -# End Source File -# Begin Source File - SOURCE="..\..\include\pjlib-util\stun_simple.h" # End Source File # Begin Source File -SOURCE="..\..\include\pjlib-util\stun_transaction.h" -# End Source File -# Begin Source File - SOURCE="..\..\include\pjlib-util\types.h" # End Source File # Begin Source File diff --git a/pjlib-util/include/pjlib-util.h b/pjlib-util/include/pjlib-util.h index 3ad0c7d1..2a9af380 100644 --- a/pjlib-util/include/pjlib-util.h +++ b/pjlib-util/include/pjlib-util.h @@ -48,14 +48,6 @@ /* XML */ #include -/* New STUN */ -#include -#include -#include -#include -#include -/*#include */ - /* Old STUN */ #include diff --git a/pjlib-util/include/pjlib-util/stun_auth.h b/pjlib-util/include/pjlib-util/stun_auth.h deleted file mode 100644 index 49b2acbb..00000000 --- a/pjlib-util/include/pjlib-util/stun_auth.h +++ /dev/null @@ -1,275 +0,0 @@ -/* $Id$ */ -/* - * Copyright (C) 2003-2005 Benny Prijono - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ -#ifndef __PJLIB_UTIL_STUN_AUTH_H__ -#define __PJLIB_UTIL_STUN_AUTH_H__ - -/** - * @file stun_auth.h - * @brief STUN authentication. - */ - -#include - - -PJ_BEGIN_DECL - - -/* **************************************************************************/ -/** - * @defgroup PJLIB_UTIL_STUN_AUTH STUN Authentication - * @ingroup PJLIB_UTIL_STUN - * @{ - */ - -/** - * Type of authentication data in the credential. - */ -typedef enum pj_stun_auth_cred_type -{ - /** - * The credential data contains a static credential to be matched - * against the credential in the message. A static credential can be - * used as both client side or server side authentication. - */ - PJ_STUN_AUTH_CRED_STATIC, - - /** - * The credential data contains callbacks to be called to verify the - * credential in the message. A dynamic credential is suitable when - * performing server side authentication where server does not know - * in advance the identity of the user requesting authentication. - */ - PJ_STUN_AUTH_CRED_DYNAMIC - -} pj_stun_auth_cred_type; - - -/** - * This structure contains the descriptions needed to perform server side - * authentication. Depending on the \a type set in the structure, application - * may specify a static username/password combination, or to have callbacks - * called by the function to authenticate the credential dynamically. - */ -typedef struct pj_stun_auth_cred -{ - /** - * The type of authentication information in this structure. - */ - pj_stun_auth_cred_type type; - - /** - * This union contains the authentication data. - */ - union - { - /** - * This structure contains static data for performing authentication. - * A non-empty realm indicates whether short term or long term - * credential is used. - */ - struct - { - /** - * If not-empty, it indicates that this is a long term credential. - */ - pj_str_t realm; - - /** - * The username of the credential. - */ - pj_str_t username; - - /** - * Data type to indicate the type of password in the \a data field. - * Value zero indicates that the data contains a plaintext - * password. - */ - int data_type; - - /** - * The data, which depends depends on the value of \a data_type - * field. When \a data_type is zero, this field will contain the - * plaintext password. - */ - pj_str_t data; - - /** - * Optional NONCE. - */ - pj_str_t nonce; - - } static_cred; - - /** - * This structure contains callback to be called by the framework - * to authenticate the incoming message. - */ - struct - { - /** - * User data which will be passed back to callback functions. - */ - void *user_data; - - /** - * This callback is called by pj_stun_verify_credential() when - * server needs to challenge the request with 401 response. - * - * @param user_data The user data as specified in the credential. - * @param pool Pool to allocate memory. - * @param realm On return, the function should fill in with - * realm if application wants to use long term - * credential. Otherwise application should set - * empty string for the realm. - * @param nonce On return, if application wants to use long - * term credential, it MUST fill in the nonce - * with some value. Otherwise if short term - * credential is wanted, it MAY set this value. - * If short term credential is wanted and the - * application doesn't want to include NONCE, - * then it must set this to empty string. - * - * @return The callback should return PJ_SUCCESS, or - * otherwise response message will not be - * created. - */ - pj_status_t (*get_auth)(void *user_data, - pj_pool_t *pool, - pj_str_t *realm, - pj_str_t *nonce); - - /** - * Get the password for the specified username. This function - * is also used to check whether the username is valid. - * - * @param user_data The user data as specified in the credential. - * @param realm The realm as specified in the message. - * @param username The username as specified in the message. - * @param pool Pool to allocate memory when necessary. - * @param data_type On return, application should fill up this - * argument with the type of data (which should - * be zero if data is a plaintext password). - * @param data On return, application should fill up this - * argument with the password according to - * data_type. - * - * @return The callback should return PJ_SUCCESS if - * username has been successfully verified - * and password was obtained. If non-PJ_SUCCESS - * is returned, it is assumed that the - * username is not valid. - */ - pj_status_t (*get_password)(void *user_data, - const pj_str_t *realm, - const pj_str_t *username, - pj_pool_t *pool, - int *data_type, - pj_str_t *data); - - /** - * This callback will be called to verify that the NONCE given - * in the message can be accepted. If this callback returns - * PJ_FALSE, 438 (Stale Nonce) response will be created. - * - * @param user_data The user data as specified in the credential. - * @param realm The realm as specified in the message. - * @param username The username as specified in the message. - * @param nonce The nonce to be verified. - * - * @return The callback MUST return non-zero if the - * NONCE can be accepted. - */ - pj_bool_t (*verify_nonce)(void *user_data, - const pj_str_t *realm, - const pj_str_t *username, - const pj_str_t *nonce); - - } dyn_cred; - - } data; - -} pj_stun_auth_cred; - - -/** - * Duplicate authentication credential. - * - * @param pool Pool to be used to allocate memory. - * @param dst Destination credential. - * @param src Source credential. - */ -PJ_DECL(void) pj_stun_auth_cred_dup(pj_pool_t *pool, - pj_stun_auth_cred *dst, - const pj_stun_auth_cred *src); - - -/** - * Verify credential in the STUN message. Note that before calling this - * function, application must have checked that the message contains - * PJ_STUN_ATTR_MESSAGE_INTEGRITY attribute by calling pj_stun_msg_find_attr() - * function, because this function will reject the message with 401 error - * if it doesn't contain PJ_STUN_ATTR_MESSAGE_INTEGRITY attribute. - * - * @param pkt The original packet which has been parsed into - * the message. This packet MUST NOT have been modified - * after the parsing. - * @param pkt_len The length of the packet. - * @param msg The parsed message to be verified. - * @param cred Pointer to credential to be used to authenticate - * the message. - * @param pool If response is to be created, then memory will - * be allocated from this pool. - * @param p_response Optional pointer to receive the response message - * then the credential in the request fails to - * authenticate. - * - * @return PJ_SUCCESS if credential is verified successfully. - * If the verification fails and \a p_response is not - * NULL, an appropriate response will be returned in - * \a p_response. - */ -PJ_DECL(pj_status_t) pj_stun_verify_credential(const pj_uint8_t *pkt, - unsigned pkt_len, - const pj_stun_msg *msg, - pj_stun_auth_cred *cred, - pj_pool_t *pool, - pj_stun_msg **p_response); - - - - -/** - * @} - */ - - -/* Calculate HMAC-SHA1 key for long term credential, by getting - * MD5 digest of username, realm, and password. - */ -void pj_stun_calc_md5_key(pj_uint8_t digest[16], - const pj_str_t *realm, - const pj_str_t *username, - const pj_str_t *passwd); - - -PJ_END_DECL - - -#endif /* __PJLIB_UTIL_STUN_AUTH_H__ */ - diff --git a/pjlib-util/include/pjlib-util/stun_doc.h b/pjlib-util/include/pjlib-util/stun_doc.h deleted file mode 100644 index 612bf1a7..00000000 --- a/pjlib-util/include/pjlib-util/stun_doc.h +++ /dev/null @@ -1,100 +0,0 @@ -/* $Id$ */ -/* - * Copyright (C) 2003-2005 Benny Prijono - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ -#ifndef __PJ_STUN_SERVER_H__ -#define __PJ_STUN_SERVER_H__ - -/* - * STUN documentation. There is no code here. - */ - -/** - * @defgroup PJLIB_UTIL_STUN STUN and TURN - * @ingroup PJLIB_UTIL - - This is the implementation of STUN/TURN in PJLIB-UTIL library. - - The STUN/TURN implementation in PJLIB-UTIL has the following objectives: - - standard based (of course) - - supports both client and server side STUN/TURN services - - independent (that is, only dependent to pjlib), and general purpose - enough to be used not only by pjsip applications but also by other - types of applications - - must be able to support ICE. - - The STUN/TURN implementation is based on the following standards: - - - draft-ietf-behave-rfc3489bis-05.txt - - - draft-ietf-behave-turn-02.txt - - But as STUN standards are currently defined as work in progress at IETF, - the implementation will be updated as these standards are updated. - - - - @section stun_org_sec Organization - - The implementation consists of the following components. - - @subsection stun_msg_sec Messaging and Parsing - - The lowest layer of the STUN implementation is the @ref PJLIB_UTIL_STUN_MSG - component. This part is responsible for encoding and decoding STUN messages. - - This layer only implements message representation and parsing. In particular, - it does not provide any transport functionalities, therefore it can be used - by different types of applications. - - - - @subsection stun_endpt_sec Endpoint - - The @ref PJLIB_UTIL_STUN_ENDPOINT is used by the library to put together - common settings for all STUN objects. For example, the STUN endpoint has a - reference of timer heap to poll all STUN timers, reference to ioqueue to - poll network events for STUN servers, and some common settings used by - various STUN objects. - - - @subsection stun_clt_tsx_sec Client Transaction - - The @ref PJLIB_UTIL_STUN_TRANSACTION is used to manage outgoing STUN request, - for example to retransmit the request and to notify application about the - completion of the request. - - The @ref PJLIB_UTIL_STUN_TRANSACTION does not use any networking operations, - but instead application must supply the transaction with a callback to - be used by the transaction to send outgoing requests. This way the STUN - transaction is made more generic and can work with different types of - networking codes in application. - - - - @subsection stun_srv_sec Server Components - - The @ref PJLIB_UTIL_STUN_SERVER is used for: - - implementing STUN servers, and/or - - implementing server side STUN handling (for example for ICE). - - */ - - - -#endif /* __PJ_STUN_SERVER_H__ */ - diff --git a/pjlib-util/include/pjlib-util/stun_endpoint.h b/pjlib-util/include/pjlib-util/stun_endpoint.h deleted file mode 100644 index b341309a..00000000 --- a/pjlib-util/include/pjlib-util/stun_endpoint.h +++ /dev/null @@ -1,117 +0,0 @@ -/* $Id$ */ -/* - * Copyright (C) 2003-2005 Benny Prijono - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ -#ifndef __PJLIB_UTIL_STUN_ENDPOINT_H__ -#define __PJLIB_UTIL_STUN_ENDPOINT_H__ - -/** - * @file stun_endpoint.h - * @brief STUN endpoint. - */ - -#include - - -PJ_BEGIN_DECL - - -/* **************************************************************************/ -/** - * @defgroup PJLIB_UTIL_STUN_ENDPOINT STUN Endpoint - * @brief Management of incoming and outgoing STUN transactions. - * @ingroup PJLIB_UTIL_STUN - * @{ - */ - -/** - * Opaque declaration for STUN endpoint. STUN endpoint manages client and - * server STUN transactions, and it needs to be initialized before application - * can send or receive STUN messages. - */ -typedef struct pj_stun_endpoint -{ - /** - * Pool factory to be used by the STUN endpoint and all objects created - * that use this STUN endpoint. - */ - pj_pool_factory *pf; - - /** - * Ioqueue used by this endpoint. - */ - pj_ioqueue_t *ioqueue; - - /** - * Timer heap instance used by this endpoint. - */ - pj_timer_heap_t *timer_heap; - - /** - * Internal pool used by this endpoint. This shouldn't be used by - * application. - */ - pj_pool_t *pool; - - /** - * Options. - */ - unsigned options; - - /** - * The default initial STUN round-trip time estimation in msecs. - * The value normally is PJ_STUN_RTO_VALUE. - */ - unsigned rto_msec; - - /** - * The interval to cache outgoing STUN response in the STUN session, - * in miliseconds. - * - * Default 10000 (10 seconds). - */ - unsigned res_cache_msec; - -} pj_stun_endpoint; - - - -/** - * Create a STUN endpoint instance. - */ -PJ_DECL(pj_status_t) pj_stun_endpoint_create(pj_pool_factory *factory, - unsigned options, - pj_ioqueue_t *ioqueue, - pj_timer_heap_t *timer_heap, - pj_stun_endpoint **p_endpt); - -/** - * Destroy STUN endpoint instance. - */ -PJ_DECL(pj_status_t) pj_stun_endpoint_destroy(pj_stun_endpoint *endpt); - - -/** - * @} - */ - - -PJ_END_DECL - - -#endif /* __PJLIB_UTIL_STUN_ENDPOINT_H__ */ - diff --git a/pjlib-util/include/pjlib-util/stun_msg.h b/pjlib-util/include/pjlib-util/stun_msg.h deleted file mode 100644 index ae66c2d1..00000000 --- a/pjlib-util/include/pjlib-util/stun_msg.h +++ /dev/null @@ -1,1539 +0,0 @@ -/* $Id$ */ -/* - * Copyright (C) 2003-2005 Benny Prijono - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ -#ifndef __PJLIB_UTIL_STUN_MSG_H__ -#define __PJLIB_UTIL_STUN_MSG_H__ - -/** - * @file stun_msg.h - * @brief STUN message components. - */ - -#include -#include - - -PJ_BEGIN_DECL - - -/* **************************************************************************/ -/** - * @defgroup PJLIB_UTIL_STUN_MSG STUN Message Representation and Parsing - * @brief Low-level representation and parsing of STUN messages. - * @ingroup PJLIB_UTIL_STUN - * @{ - */ - - -/** - * The default initial STUN round-trip time estimation (the RTO value - * in RFC 3489-bis), in miliseconds. - * This value is used to control the STUN request - * retransmit time. The initial value of retransmission interval - * would be set to this value, and will be doubled after each - * retransmission. - */ -#ifndef PJ_STUN_RTO_VALUE -# define PJ_STUN_RTO_VALUE 100 -#endif - - -/** - * The STUN transaction timeout value, in miliseconds. - * After the last retransmission is sent and if no response is received - * after this time, the STUN transaction will be considered to have failed. - * - * The default value is 1600 miliseconds (as per RFC 3489-bis). - */ -#ifndef PJ_STUN_TIMEOUT_VALUE -# define PJ_STUN_TIMEOUT_VALUE 1600 -#endif - - -/** - * Maximum number of STUN retransmission count. - * - * Default: 7 (as per RFC 3489-bis) - */ -#ifndef PJ_STUN_MAX_RETRANSMIT_COUNT -# define PJ_STUN_MAX_RETRANSMIT_COUNT 7 -#endif - - -/** - * Maximum size of STUN message. - */ -#ifndef PJ_STUN_MAX_PKT_LEN -# define PJ_STUN_MAX_PKT_LEN 512 -#endif - - -/** - * Default STUN port as defined by RFC 3489. - */ -#define PJ_STUN_PORT 3478 - -/** - * STUN magic cookie. - */ -#define PJ_STUN_MAGIC 0x2112A442 - - -/** - * STUN method constants. - */ -enum pj_stun_method_e -{ - /** - * STUN Binding method as defined by RFC 3489-bis. - */ - PJ_STUN_BINDING_METHOD = 1, - - /** - * STUN Shared Secret method as defined by RFC 3489-bis. - */ - PJ_STUN_SHARED_SECRET_METHOD = 2, - - /** - * STUN/TURN Allocate method as defined by draft-ietf-behave-turn - */ - PJ_STUN_ALLOCATE_METHOD = 3, - - /** - * STUN/TURN Send Indication as defined by draft-ietf-behave-turn - */ - PJ_STUN_SEND_INDICATION_METHOD = 4, - - /** - * STUN/TURN Data Indication as defined by draft-ietf-behave-turn - */ - PJ_STUN_DATA_INDICATION_METHOD = 5, - - /** - * STUN/TURN Set Active Destination as defined by draft-ietf-behave-turn - */ - PJ_STUN_SET_ACTIVE_DESTINATION_METHOD = 6, - - /** - * STUN/TURN Connect method as defined by draft-ietf-behave-turn - */ - PJ_STUN_CONNECT_METHOD = 7, - - /** - * STUN/TURN Connect Status indication method. - */ - PJ_STUN_CONNECT_STATUS_METHOD = 8 -}; - - -/** - * Retrieve the STUN method from the message-type field of the STUN - * message. - */ -#define PJ_STUN_GET_METHOD(msg_type) ((msg_type) & 0xFEEF) - - -/** - * STUN message classes constants. - */ -enum pj_stun_msg_class_e -{ - /** - * This specifies that the message type is a STUN request message. - */ - PJ_STUN_REQUEST_CLASS = 0, - - /** - * This specifies that the message type is a STUN indication message. - */ - PJ_STUN_INDICATION_CLASS = 1, - - /** - * This specifies that the message type is a STUN successful response. - */ - PJ_STUN_SUCCESS_CLASS = 2, - - /** - * This specifies that the message type is a STUN error response. - */ - PJ_STUN_ERROR_CLASS = 3 -}; - - -/** - * Determine if the message type is a request. - */ -#define PJ_STUN_IS_REQUEST(msg_type) (((msg_type) & 0x0110) == 0x0000) - - -/** - * Determine if the message type is a response. - */ -#define PJ_STUN_IS_RESPONSE(msg_type) (((msg_type) & 0x0110) == 0x0100) - - -/** - * The response bit in the message type. - */ -#define PJ_STUN_RESPONSE_BIT (0x0100) - -/** - * Determine if the message type is an error response. - */ -#define PJ_STUN_IS_ERROR_RESPONSE(msg_type) (((msg_type) & 0x0110) == 0x0110) - - -/** - * The error response bit in the message type. - */ -#define PJ_STUN_ERROR_RESPONSE_BIT (0x0110) - - -/** - * Determine if the message type is an indication message. - */ -#define PJ_STUN_IS_INDICATION(msg_type) (((msg_type) & 0x0110) == 0x0010) - - -/** - * The error response bit in the message type. - */ -#define PJ_STUN_INDICATION_BIT (0x0010) - - -/** - * This enumeration describes STUN message types. - */ -typedef enum pj_stun_msg_type -{ - /** - * STUN BINDING request. - */ - PJ_STUN_BINDING_REQUEST = 0x0001, - - /** - * Successful response to STUN BINDING-REQUEST. - */ - PJ_STUN_BINDING_RESPONSE = 0x0101, - - /** - * Error response to STUN BINDING-REQUEST. - */ - PJ_STUN_BINDING_ERROR_RESPONSE = 0x0111, - - /** - * STUN SHARED-SECRET reqeust. - */ - PJ_STUN_SHARED_SECRET_REQUEST = 0x0002, - - /** - * Successful response to STUN SHARED-SECRET reqeust. - */ - PJ_STUN_SHARED_SECRET_RESPONSE = 0x0102, - - /** - * Error response to STUN SHARED-SECRET reqeust. - */ - PJ_STUN_SHARED_SECRET_ERROR_RESPONSE = 0x0112, - - /** - * STUN/TURN Allocate Request - */ - PJ_STUN_ALLOCATE_REQUEST = 0x0003, - - /** - * Successful response to STUN/TURN Allocate Request - */ - PJ_STUN_ALLOCATE_RESPONSE = 0x0103, - - /** - * Failure response to STUN/TURN Allocate Request - */ - PJ_STUN_ALLOCATE_ERROR_RESPONSE = 0x0113, - - /** - * STUN/TURN Send Indication - */ - PJ_STUN_SEND_INDICATION = 0x0014, - - /** - * STUN/TURN Data Indication - */ - PJ_STUN_DATA_INDICATION = 0x0015, - - /** - * STUN/TURN Set Active Destination Request - */ - PJ_STUN_SET_ACTIVE_DESTINATION_REQUEST = 0x0006, - - /** - * STUN/TURN Set Active Destination Response - */ - PJ_STUN_SET_ACTIVE_DESTINATION_RESPONSE = 0x0106, - - /** - * STUN/TURN Set Active Destination Error Response - */ - PJ_STUN_SET_ACTIVE_DESTINATION_ERROR_RESPONSE = 0x0116, - - /** - * STUN/TURN Connect Request - */ - PJ_STUN_CONNECT_REQUEST = 0x0007, - - /** - * STUN/TURN Connect Response - */ - PJ_STUN_CONNECT_RESPONSE = 0x0107, - - /** - * STUN/TURN Connect Error Response - */ - PJ_STUN_CONNECT_ERROR_RESPONSE = 0x0117, - - /** - * STUN/TURN Connect Status Indication - */ - PJ_STUN_CONNECT_STATUS_INDICATION = 0x0018 - - -} pj_stun_msg_type; - - - -/** - * This enumeration describes STUN attribute types. - */ -typedef enum pj_stun_attr_type -{ - PJ_STUN_ATTR_MAPPED_ADDR = 0x0001,/**< MAPPED-ADDRESS. */ - PJ_STUN_ATTR_RESPONSE_ADDR = 0x0002,/**< RESPONSE-ADDRESS (deprcatd)*/ - PJ_STUN_ATTR_CHANGE_REQUEST = 0x0003,/**< CHANGE-REQUEST (deprecated)*/ - PJ_STUN_ATTR_SOURCE_ADDR = 0x0004,/**< SOURCE-ADDRESS (deprecated)*/ - PJ_STUN_ATTR_CHANGED_ADDR = 0x0005,/**< CHANGED-ADDRESS (deprecatd)*/ - PJ_STUN_ATTR_USERNAME = 0x0006,/**< USERNAME attribute. */ - PJ_STUN_ATTR_PASSWORD = 0x0007,/**< PASSWORD attribute. */ - PJ_STUN_ATTR_MESSAGE_INTEGRITY = 0x0008,/**< MESSAGE-INTEGRITY. */ - PJ_STUN_ATTR_ERROR_CODE = 0x0009,/**< ERROR-CODE. */ - PJ_STUN_ATTR_UNKNOWN_ATTRIBUTES = 0x000A,/**< UNKNOWN-ATTRIBUTES. */ - PJ_STUN_ATTR_REFLECTED_FROM = 0x000B,/**< REFLECTED-FROM (deprecatd)*/ - PJ_STUN_ATTR_LIFETIME = 0x000D,/**< LIFETIME attribute. */ - PJ_STUN_ATTR_BANDWIDTH = 0x0010,/**< BANDWIDTH attribute */ - PJ_STUN_ATTR_REMOTE_ADDR = 0x0012,/**< REMOTE-ADDRESS attribute */ - PJ_STUN_ATTR_DATA = 0x0013,/**< DATA attribute. */ - PJ_STUN_ATTR_REALM = 0x0014,/**< REALM attribute. */ - PJ_STUN_ATTR_NONCE = 0x0015,/**< NONCE attribute. */ - PJ_STUN_ATTR_RELAY_ADDR = 0x0016,/**< RELAY-ADDRESS attribute. */ - PJ_STUN_ATTR_REQ_ADDR_TYPE = 0x0017,/**< REQUESTED-ADDRESS-TYPE */ - PJ_STUN_ATTR_REQ_PORT_PROPS = 0x0018,/**< REQUESTED-PORT-PROPS */ - PJ_STUN_ATTR_REQ_TRANSPORT = 0x0019,/**< REQUESTED-TRANSPORT */ - PJ_STUN_ATTR_XOR_MAPPED_ADDR = 0x0020,/**< XOR-MAPPED-ADDRESS */ - PJ_STUN_ATTR_TIMER_VAL = 0x0021,/**< TIMER-VAL attribute. */ - PJ_STUN_ATTR_REQ_IP = 0x0022,/**< REQUESTED-IP attribute */ - PJ_STUN_ATTR_XOR_REFLECTED_FROM = 0x0023,/**< XOR-REFLECTED-FROM */ - PJ_STUN_ATTR_PRIORITY = 0x0024,/**< PRIORITY */ - PJ_STUN_ATTR_USE_CANDIDATE = 0x0025,/**< USE-CANDIDATE */ - PJ_STUN_ATTR_XOR_INTERNAL_ADDR = 0x0026,/**< XOR-INTERNAL-ADDRESS */ - - PJ_STUN_ATTR_END_MANDATORY_ATTR, - - PJ_STUN_ATTR_START_EXTENDED_ATTR= 0x8021, - - PJ_STUN_ATTR_SERVER = 0x8022,/**< SERVER attribute. */ - PJ_STUN_ATTR_ALTERNATE_SERVER = 0x8023,/**< ALTERNATE-SERVER. */ - PJ_STUN_ATTR_REFRESH_INTERVAL = 0x8024,/**< REFRESH-INTERVAL. */ - PJ_STUN_ATTR_FINGERPRINT = 0x8028,/**< FINGERPRINT attribute. */ - - PJ_STUN_ATTR_END_EXTENDED_ATTR - -} pj_stun_attr_type; - - -/** - * STUN error codes, which goes into STUN ERROR-CODE attribute. - */ -typedef enum pj_stun_status -{ - PJ_STUN_SC_TRY_ALTERNATE = 300, /**< Try Alternate */ - PJ_STUN_SC_BAD_REQUEST = 400, /**< Bad Request */ - PJ_STUN_SC_UNAUTHORIZED = 401, /**< Unauthorized */ - PJ_STUN_SC_UNKNOWN_ATTRIBUTE = 420, /**< Unknown Attribute */ - PJ_STUN_SC_STALE_CREDENTIALS = 430, /**< Stale Credentials */ - PJ_STUN_SC_INTEGRITY_CHECK_FAILURE = 431, /**< Integrity Chk Fail */ - PJ_STUN_SC_MISSING_USERNAME = 432, /**< Missing Username */ - PJ_STUN_SC_USE_TLS = 433, /**< Use TLS */ - PJ_STUN_SC_MISSING_REALM = 434, /**< Missing Realm */ - PJ_STUN_SC_MISSING_NONCE = 435, /**< Missing Nonce */ - PJ_STUN_SC_UNKNOWN_USERNAME = 436, /**< Unknown Username */ - PJ_STUN_SC_NO_BINDING = 437, /**< No Binding. */ - PJ_STUN_SC_STALE_NONCE = 438, /**< Stale Nonce */ - PJ_STUN_SC_TRANSITIONING = 439, /**< Transitioning. */ - PJ_STUN_SC_WRONG_USERNAME = 441, /**< Wrong Username. */ - PJ_STUN_SC_UNSUPP_TRANSPORT_PROTO = 442, /**< Unsupported Transport or - Protocol */ - PJ_STUN_SC_INVALID_IP_ADDR = 443, /**< Invalid IP Address */ - PJ_STUN_SC_INVALID_PORT = 444, /**< Invalid Port */ - PJ_STUN_SC_OPER_TCP_ONLY = 445, /**< Operation for TCP Only */ - PJ_STUN_SC_CONNECTION_FAILURE = 446, /**< Connection Failure */ - PJ_STUN_SC_CONNECTION_TIMEOUT = 447, /**< Connection Timeout */ - PJ_STUN_SC_ALLOCATION_QUOTA_REACHED = 486, /**< Allocation Quota Reached - (TURN) */ - PJ_STUN_SC_SERVER_ERROR = 500, /**< Server Error */ - PJ_STUN_SC_INSUFFICIENT_CAPACITY = 507, /**< Insufficient Capacity - (TURN) */ - PJ_STUN_SC_GLOBAL_FAILURE = 600 /**< Global Failure */ -} pj_stun_status; - - -/** - * This structure describes STUN message header. A STUN message has the - * following format: - * - * \verbatim - - 0 1 2 3 - 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - |0 0| STUN Message Type | Message Length | - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - | Magic Cookie | - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - | - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - Transaction ID - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - | - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - - \endverbatim - */ -typedef struct pj_stun_msg_hdr -{ - /** - * STUN message type, which the first two bits must be zeroes. - */ - pj_uint16_t type; - - /** - * The message length is the size, in bytes, of the message not - * including the 20 byte STUN header. - */ - pj_uint16_t length; - - /** - * The magic cookie is a fixed value, 0x2112A442 (PJ_STUN_MAGIC constant). - * In the previous version of this specification [15] this field was part - * of the transaction ID. - */ - pj_uint32_t magic; - - /** - * The transaction ID is a 96 bit identifier. STUN transactions are - * identified by their unique 96-bit transaction ID. For request/ - * response transactions, the transaction ID is chosen by the STUN - * client and MUST be unique for each new STUN transaction generated by - * that STUN client. The transaction ID MUST be uniformly and randomly - * distributed between 0 and 2**96 - 1. - */ - pj_uint8_t tsx_id[12]; - -} pj_stun_msg_hdr; - - -/** - * This structre describes STUN attribute header. Each attribute is - * TLV encoded, with a 16 bit type, 16 bit length, and variable value. - * Each STUN attribute ends on a 32 bit boundary: - * - * \verbatim - - 0 1 2 3 - 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - | Type | Length | - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - | Value .... | - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - - \endverbatim - */ -typedef struct pj_stun_attr_hdr -{ - /** - * STUN attribute type. - */ - pj_uint16_t type; - - /** - * The Length refers to the length of the actual useful content of the - * Value portion of the attribute, measured in bytes. The value - * in the Length field refers to the length of the Value part of the - * attribute prior to padding - i.e., the useful content. - */ - pj_uint16_t length; - -} pj_stun_attr_hdr; - - -/** - * This structure describes STUN generic IP address attribute, used for - * example to represent STUN MAPPED-ADDRESS attribute. - * - * The generic IP address attribute indicates the transport address. - * It consists of an eight bit address family, and a sixteen bit port, - * followed by a fixed length value representing the IP address. If the - * address family is IPv4, the address is 32 bits, in network byte - * order. If the address family is IPv6, the address is 128 bits in - * network byte order. - * - * The format of the generic IP address attribute is: - * - * \verbatim - - 0 1 2 3 - 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - |x x x x x x x x| Family | Port | - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - | Address (variable) - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - - \endverbatim - */ -typedef struct pj_stun_sockaddr_attr -{ - /** - * Standard STUN attribute header. - */ - pj_stun_attr_hdr hdr; - - /** - * Flag to indicate whether this attribute should be sent in XOR-ed - * format, or has been received in XOR-ed format. - */ - pj_bool_t xor_ed; - - /** - * The socket address (as a union) - */ - union { - pj_sockaddr addr; /**< Generic socket address. */ - pj_sockaddr_in ipv4; /**< IPv4 socket address. */ - pj_sockaddr_in6 ipv6; /**< IPv6 socket address. */ - } addr; - -} pj_stun_sockaddr_attr; - - -/** - * This structure represents a generic STUN attributes with no payload, - * and it is used for example by ICE USE-CANDIDATE attribute. - */ -typedef struct pj_stun_empty_attr -{ - /** - * Standard STUN attribute header. - */ - pj_stun_attr_hdr hdr; - -} pj_stun_empty_attr; - - -/** - * This structure represents generic STUN string attributes, such as STUN - * USERNAME, PASSWORD, SERVER, REALM, and NONCE attributes. Note that for REALM and - * NONCE attributes, the text MUST be quoted with. - */ -typedef struct pj_stun_string_attr -{ - /** - * Standard STUN attribute header. - */ - pj_stun_attr_hdr hdr; - - /** - * The string value. - */ - pj_str_t value; - -} pj_stun_string_attr; - - -/** - * This structure represents a generic STUN attributes with 32bit (unsigned) - * integer value, such as STUN FINGERPRINT and REFRESH-INTERVAL attributes. - */ -typedef struct pj_stun_uint_attr -{ - /** - * Standard STUN attribute header. - */ - pj_stun_attr_hdr hdr; - - /** - * The 32bit value. - */ - pj_uint32_t value; - -} pj_stun_uint_attr; - - -/** - * This structure represents generic STUN attributes to hold a raw binary - * data. - */ -typedef struct pj_stun_binary_attr -{ - /** - * Standard STUN attribute header. - */ - pj_stun_attr_hdr hdr; - - /** - * Length of the data. - */ - unsigned length; - - /** - * The raw data. - */ - pj_uint8_t *data; - -} pj_stun_binary_attr; - - -/** - * This structure describes STUN MESSAGE-INTEGRITY attribute. - * The MESSAGE-INTEGRITY attribute contains an HMAC-SHA1 [10] of the - * STUN message. The MESSAGE-INTEGRITY attribute can be present in any - * STUN message type. Since it uses the SHA1 hash, the HMAC will be 20 - * bytes. - */ -typedef struct pj_stun_msgint_attr -{ - /** - * Standard STUN attribute header. - */ - pj_stun_attr_hdr hdr; - - /** - * The 20 bytes hmac value. - */ - pj_uint8_t hmac[20]; - -} pj_stun_msgint_attr; - - -/** - * This structure describes STUN FINGERPRINT attribute. The FINGERPRINT - * attribute can be present in all STUN messages. It is computed as - * the CRC-32 of the STUN message up to (but excluding) the FINGERPRINT - * attribute itself, xor-d with the 32 bit value 0x5354554e - */ -typedef struct pj_stun_uint_attr pj_stun_fingerprint_attr; - - -/** - * This structure represents STUN ERROR-CODE attribute. The ERROR-CODE - * attribute is present in the Binding Error Response and Shared Secret - * Error Response. It is a numeric value in the range of 100 to 699 - * plus a textual reason phrase encoded in UTF-8 - * - * \verbatim - - 0 1 2 3 - 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - | 0 |Class| Number | - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - | Reason Phrase (variable) .. - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - - \endverbatim - */ -typedef struct pj_stun_errcode_attr -{ - /** - * Standard STUN attribute header. - */ - pj_stun_attr_hdr hdr; - - /** - * The value must be zero. - */ - pj_uint16_t zero; - - /** - * Error class (1-6). - */ - pj_uint8_t err_class; - - /** - * Error number is the error number modulo 100. - */ - pj_uint8_t number; - - /** - * The reason phrase. - */ - pj_str_t reason; - -} pj_stun_errcode_attr; - - -/** - * This describes STUN REALM attribute. - * The REALM attribute is present in requests and responses. It - * contains text which meets the grammar for "realm" as described in RFC - * 3261 [11], and will thus contain a quoted string (including the - * quotes). - */ -typedef struct pj_stun_string_attr pj_stun_realm_attr; - - -/** - * This describes STUN NONCE attribute. - * The NONCE attribute is present in requests and in error responses. - * It contains a sequence of qdtext or quoted-pair, which are defined in - * RFC 3261 [11]. See RFC 2617 [7] for guidance on selection of nonce - * values in a server. - */ -typedef struct pj_stun_string_attr pj_stun_nonce_attr; - - -/** - * This describes STUN UNKNOWN-ATTRIBUTES attribute. - * The UNKNOWN-ATTRIBUTES attribute is present only in an error response - * when the response code in the ERROR-CODE attribute is 420. - * The attribute contains a list of 16 bit values, each of which - * represents an attribute type that was not understood by the server. - * If the number of unknown attributes is an odd number, one of the - * attributes MUST be repeated in the list, so that the total length of - * the list is a multiple of 4 bytes. - */ -typedef struct pj_stun_unknown_attr -{ - /** - * Standard STUN attribute header. - */ - pj_stun_attr_hdr hdr; - - /** - * Number of unknown attributes in the array. - */ - unsigned attr_count; - - /** - * Array of unknown attribute IDs. - */ - pj_uint16_t attrs[PJ_STUN_MAX_ATTR]; - -} pj_stun_unknown_attr; - - -/** - * This structure describes STUN MAPPED-ADDRESS attribute. - * The MAPPED-ADDRESS attribute indicates the mapped transport address. - */ -typedef struct pj_stun_sockaddr_attr pj_stun_mapped_addr_attr; - - -/** - * This describes STUN XOR-MAPPED-ADDRESS attribute (which has the same - * format as STUN MAPPED-ADDRESS attribute). - * The XOR-MAPPED-ADDRESS attribute is present in responses. It - * provides the same information that would present in the MAPPED- - * ADDRESS attribute but because the NAT's public IP address is - * obfuscated through the XOR function, STUN messages are able to pass - * through NATs which would otherwise interfere with STUN. - */ -typedef struct pj_stun_sockaddr_attr pj_stun_xor_mapped_addr_attr; - - -/** - * This describes STUN SERVER attribute. - * The server attribute contains a textual description of the software - * being used by the server, including manufacturer and version number. - * The attribute has no impact on operation of the protocol, and serves - * only as a tool for diagnostic and debugging purposes. The value of - * SERVER is variable length. - */ -typedef struct pj_stun_string_attr pj_stun_server_attr; - - -/** - * This describes STUN ALTERNATE-SERVER attribute. - * The alternate server represents an alternate transport address for a - * different STUN server to try. It is encoded in the same way as - * MAPPED-ADDRESS. - */ -typedef struct pj_stun_sockaddr_attr pj_stun_alt_server_attr; - - -/** - * This describes STUN REFRESH-INTERVAL attribute. - * The REFRESH-INTERVAL indicates the number of milliseconds that the - * server suggests the client should use between refreshes of the NAT - * bindings between the client and server. - */ -typedef struct pj_stun_uint_attr pj_stun_refresh_interval_attr; - - -/** - * This structure describes STUN RESPONSE-ADDRESS attribute. - * The RESPONSE-ADDRESS attribute indicates where the response to a - * Binding Request should be sent. Its syntax is identical to MAPPED- - * ADDRESS. - * - * Note that the usage of this attribute has been deprecated by the - * RFC 3489-bis standard. - */ -typedef struct pj_stun_sockaddr_attr pj_stun_response_addr_attr; - - -/** - * This structure describes STUN CHANGED-ADDRESS attribute. - * The CHANGED-ADDRESS attribute indicates the IP address and port where - * responses would have been sent from if the "change IP" and "change - * port" flags had been set in the CHANGE-REQUEST attribute of the - * Binding Request. The attribute is always present in a Binding - * Response, independent of the value of the flags. Its syntax is - * identical to MAPPED-ADDRESS. - * - * Note that the usage of this attribute has been deprecated by the - * RFC 3489-bis standard. - */ -typedef struct pj_stun_sockaddr_attr pj_stun_changed_addr_attr; - - -/** - * This structure describes STUN CHANGE-REQUEST attribute. - * The CHANGE-REQUEST attribute is used by the client to request that - * the server use a different address and/or port when sending the - * response. - * - * Bit 29 of the value is the "change IP" flag. If true, it requests - * the server to send the Binding Response with a different IP address - * than the one the Binding Request was received on. - * - * Bit 30 of the value is the "change port" flag. If true, it requests - * the server to send the Binding Response with a different port than - * the one the Binding Request was received on. - * - * Note that the usage of this attribute has been deprecated by the - * RFC 3489-bis standard. - */ -typedef struct pj_stun_uint_attr pj_stun_change_request_attr; - -/** - * This structure describes STUN SOURCE-ADDRESS attribute. - * The SOURCE-ADDRESS attribute is present in Binding Responses. It - * indicates the source IP address and port that the server is sending - * the response from. Its syntax is identical to that of MAPPED- - * ADDRESS. - * - * Note that the usage of this attribute has been deprecated by the - * RFC 3489-bis standard. - */ -typedef struct pj_stun_sockaddr_attr pj_stun_src_addr_attr; - - -/** - * This describes the STUN REFLECTED-FROM attribute. - * The REFLECTED-FROM attribute is present only in Binding Responses, - * when the Binding Request contained a RESPONSE-ADDRESS attribute. The - * attribute contains the identity (in terms of IP address) of the - * source where the request came from. Its purpose is to provide - * traceability, so that a STUN server cannot be used as a reflector for - * denial-of-service attacks. - */ -typedef struct pj_stun_sockaddr_attr pj_stun_reflected_from_attr; - - -/** - * This describes STUN USERNAME attribute. - * The USERNAME attribute is used for message integrity. It identifies - * the shared secret used in the message integrity check. Consequently, - * the USERNAME MUST be included in any request that contains the - * MESSAGE-INTEGRITY attribute. - */ -typedef struct pj_stun_string_attr pj_stun_username_attr; - - -/** - * This describes STUN PASSWORD attribute. - * If the message type is Shared Secret Response it MUST include the - * PASSWORD attribute. - */ -typedef struct pj_stun_string_attr pj_stun_password_attr; - - -/** - * This describes STUN LIFETIME attribute. - * The lifetime attribute represents the duration for which the server - * will maintain an allocation in the absence of data traffic either - * from or to the client. It is a 32 bit value representing the number - * of seconds remaining until expiration. - */ -typedef struct pj_stun_uint_attr pj_stun_lifetime_attr; - - -/** - * This describes STUN BANDWIDTH attribute. - * The bandwidth attribute represents the peak bandwidth, measured in - * kbits per second, that the client expects to use on the binding. The - * value represents the sum in the receive and send directions. - */ -typedef struct pj_stun_uint_attr pj_stun_bandwidth_attr; - - -/** - * This describes the STUN REMOTE-ADDRESS attribute. - * The REMOTE-ADDRESS specifies the address and port of the peer as seen - * from the STUN relay server. - */ -typedef struct pj_stun_sockaddr_attr pj_stun_remote_addr_attr; - - -/** - * This describes the STUN DATA attribute. - * The DATA attribute is present in Send Indications and Data - * Indications. It contains raw payload data that is to be sent (in the - * case of a Send Request) or was received (in the case of a Data - * Indication).. - */ -typedef struct pj_stun_binary_attr pj_stun_data_attr; - - -/** - * This describes the STUN RELAY-ADDRESS attribute. - * The RELAY-ADDRESS is present in Allocate responses. It specifies the - * address and port that the server allocated to the client. - */ -typedef struct pj_stun_sockaddr_attr pj_stun_relay_addr_attr; - - -/** - * This describes the REQUESTED-ADDRESS-TYPE attribute. - * The REQUESTED-ADDRESS-TYPE attribute is used by clients to request - * the allocation of a specific address type from a server. The - * following is the format of the REQUESTED-ADDRESS-TYPE attribute. - - \verbatim - - 0 1 2 3 - 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - | Family | Reserved | - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - - \endverbatim - */ -typedef struct pj_stun_uint_attr pj_stun_req_addr_type; - -/** - * This describes the STUN REQUESTED-PORT-PROPS attribute. - * This attribute allows the client to request certain properties for - * the port that is allocated by the server. The attribute can be used - * with any transport protocol that has the notion of a 16 bit port - * space (including TCP and UDP). The attribute is 32 bits long. Its - * format is: - - \verbatim - - 0 1 2 3 - 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - | Reserved = 0 |B| A | - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - - \endverbatim - */ -typedef struct pj_stun_uint_attr pj_stun_req_port_props_attr; - - -/** - * This describes the STUN REQUESTED-TRANSPORT attribute. - * This attribute is used by the client to request a specific transport - * protocol for the allocated transport address. It is a 32 bit - * unsigned integer. Its values are: 0x0000 for UDP and 0x0000 for TCP. - */ -typedef struct pj_stun_uint_attr pj_stun_req_transport_attr; - - -/** - * This describes the STUN REQUESTED-IP attribute. - * The REQUESTED-IP attribute is used by the client to request that a - * specific IP address be allocated to it. - */ -typedef struct pj_stun_sockaddr_attr pj_stun_req_ip_attr; - -/** - * This describes the XOR-REFLECTED-FROM attribute, as described by - * draft-macdonald-behave-nat-behavior-discovery-00. - * The XOR-REFLECTED-FROM attribute is used in place of the REFLECTED- - * FROM attribute. It provides the same information, but because the - * NAT's public address is obfuscated through the XOR function, It can - * pass through a NAT that would otherwise attempt to translate it to - * the private network address. XOR-REFLECTED-FROM has identical syntax - * to XOR-MAPPED-ADDRESS. - */ -typedef struct pj_stun_sockaddr_attr pj_stun_xor_reflected_from_attr; - -/** - * This describes the PRIORITY attribute from draft-ietf-mmusic-ice-13. - * The PRIORITY attribute indicates the priority that is to be - * associated with a peer reflexive candidate, should one be discovered - * by this check. It is a 32 bit unsigned integer, and has an attribute - * type of 0x0024. - */ -typedef struct pj_stun_uint_attr pj_stun_priority_attr; - -/** - * This describes the USE-CANDIDATE attribute from draft-ietf-mmusic-ice-13. - * The USE-CANDIDATE attribute indicates that the candidate pair - * resulting from this check should be used for transmission of media. - * The attribute has no content (the Length field of the attribute is - * zero); it serves as a flag. - */ -typedef struct pj_stun_empty_attr pj_stun_use_candidate_attr; - -/** - * This structure describes STUN XOR-INTERNAL-ADDRESS attribute from - * draft-wing-behave-nat-control-stun-usage-00. - * This attribute MUST be present in a Binding Response and may be used - * in other responses as well. This attribute is necessary to allow a - * STUN client to 'walk backwards' and communicate directly with all of - * the STUN-aware NATs along the path. - */ -typedef pj_stun_sockaddr_attr pj_stun_xor_internal_addr_attr; - -/** - * This describes the STUN TIMER-VAL attribute. - * The TIMER-VAL attribute is used only in conjunction with the Set - * Active Destination response. It conveys from the server, to the - * client, the value of the timer used in the server state machine. - */ -typedef struct pj_stun_uint_attr pj_stun_timer_val_attr; - - -/** - * This structure describes a parsed STUN message. All integral fields - * in this structure (including IP addresses) will be in the host - * byte order. - */ -typedef struct pj_stun_msg -{ - /** - * STUN message header. - */ - pj_stun_msg_hdr hdr; - - /** - * Number of attributes in the STUN message. - */ - unsigned attr_count; - - /** - * Array of STUN attributes. - */ - pj_stun_attr_hdr *attr[PJ_STUN_MAX_ATTR]; - -} pj_stun_msg; - - -/** STUN decoding options */ -enum pj_stun_decode_options -{ - /** - * Tell the decoder that the message was received from datagram - * oriented transport (such as UDP). - */ - PJ_STUN_IS_DATAGRAM = 1, - - /** - * Tell pj_stun_msg_decode() to check the validity of the STUN - * message by calling pj_stun_msg_check() before starting to - * decode the packet. - */ - PJ_STUN_CHECK_PACKET = 2 -}; - - -/** - * Get STUN message method name. - * - * @param msg_type The STUN message type (in host byte order) - * - * @return The STUN message method name string. - */ -PJ_DECL(const char*) pj_stun_get_method_name(unsigned msg_type); - - -/** - * Get STUN message class name. - * - * @param msg_type The STUN message type (in host byte order) - * - * @return The STUN message class name string. - */ -PJ_DECL(const char*) pj_stun_get_class_name(unsigned msg_type); - - -/** - * Get STUN attribute name. - * - * @return attr_type The STUN attribute type (in host byte order). - * - * @return The STUN attribute type name string. - */ -PJ_DECL(const char*) pj_stun_get_attr_name(unsigned attr_type); - - -/** - * Get STUN standard reason phrase for the specified error code. - * - * @param err_code The STUN error code. - * - * @return The STUN error reason phrase. - */ -PJ_DECL(pj_str_t) pj_stun_get_err_reason(int err_code); - - -/** - * Create a generic STUN message. - * - * @param pool Pool to create the STUN message. - * @param msg_type The 14bit message type. - * @param magic Magic value to be put to the mesage; for requests, - * the value should be PJ_STUN_MAGIC. - * @param tsx_id Optional transaction ID, or NULL to let the - * function generates a random transaction ID. - * @param p_msg Pointer to receive the message. - * - * @return PJ_SUCCESS on success. - */ -PJ_DECL(pj_status_t) pj_stun_msg_create(pj_pool_t *pool, - unsigned msg_type, - pj_uint32_t magic, - const pj_uint8_t tsx_id[12], - pj_stun_msg **p_msg); - -/** - * Create STUN response message. - * - * @param pool Pool to create the mesage. - * @param req_msg The request message. - * @param err_code STUN error code. If this value is not zero, - * then error response will be created, otherwise - * successful response will be created. - * @param err_msg Optional error message to explain err_code. - * If this value is NULL and err_code is not zero, - * the error string will be taken from the default - * STUN error message. - * @param p_response Pointer to receive the response. - * - * @return PJ_SUCCESS on success, or the appropriate error. - */ -PJ_DECL(pj_status_t) pj_stun_msg_create_response(pj_pool_t *pool, - const pj_stun_msg *req_msg, - unsigned err_code, - const pj_str_t *err_msg, - pj_stun_msg **p_response); - - -/** - * Add STUN attribute to STUN message. - * - * @param msg The STUN message. - * @param attr The STUN attribute to be added to the message. - * - * @return PJ_SUCCESS on success, or PJ_ETOOMANY if there are - * already too many attributes in the message. - */ -PJ_DECL(pj_status_t) pj_stun_msg_add_attr(pj_stun_msg *msg, - pj_stun_attr_hdr *attr); - - -/** - * Print the STUN message structure to a packet buffer, ready to be - * sent to remote destination. This function will take care about - * calculating the MESSAGE-INTEGRITY digest as well as FINGERPRINT - * value. - * - * If MESSAGE-INTEGRITY attribute is present, the function assumes - * that application wants to include credential (short or long term) - * in the message, and this function will calculate the HMAC digest - * from the message using the supplied password in the parameter. - * If REALM attribute is present, the HMAC digest is calculated as - * long term credential, otherwise as short term credential. - * - * If FINGERPRINT attribute is present, this function will calculate - * the FINGERPRINT CRC attribute for the message. - * - * @param msg The STUN message to be printed. Upon return, - * some fields in the header (such as message - * length) will be updated. - * @param pkt_buf The buffer to be filled with the packet. - * @param buf_size Size of the buffer. - * @param options Options, which currently must be zero. - * @param password Password to be used when credential is to be - * included. This parameter MUST be specified when - * the message contains MESSAGE-INTEGRITY attribute. - * @param p_msg_len Upon return, it will be filed with the size of - * the packet in bytes, or negative value on error. - * - * @return PJ_SUCCESS on success or the appropriate error code. - */ -PJ_DECL(pj_status_t) pj_stun_msg_encode(pj_stun_msg *msg, - pj_uint8_t *pkt_buf, - unsigned buf_size, - unsigned options, - const pj_str_t *password, - unsigned *p_msg_len); - -/** - * Check that the PDU is potentially a valid STUN message. This function - * is useful when application needs to multiplex STUN packets with other - * application traffic. When this function returns PJ_SUCCESS, there is a - * big chance that the packet is a STUN packet. - * - * Note that we cannot be sure that the PDU is a really valid STUN message - * until we actually parse the PDU. - * - * @param pdu The packet buffer. - * @param pdu_len The length of the packet buffer. - * @param options Additional options to be applied in the checking, - * which can be taken from pj_stun_decode_options. One - * of the useful option is PJ_STUN_IS_DATAGRAM which - * means that the pdu represents a whole STUN packet. - * - * @return PJ_SUCCESS if the PDU is a potentially valid STUN - * message. - */ -PJ_DECL(pj_status_t) pj_stun_msg_check(const pj_uint8_t *pdu, - unsigned pdu_len, unsigned options); - - -/** - * Decode incoming packet into STUN message. - * - * @param pool Pool to allocate the message. - * @param pdu The incoming packet to be parsed. - * @param pdu_len The length of the incoming packet. - * @param options Parsing flags, according to pj_stun_decode_options. - * @param p_msg Pointer to receive the parsed message. - * @param p_parsed_len Optional pointer to receive how many bytes have - * been parsed for the STUN message. This is useful - * when the packet is received over stream oriented - * transport. - * @param p_response Optional pointer to receive an instance of response - * message, if one can be created. If the packet being - * decoded is a request message, and it contains error, - * and a response can be created, then the STUN - * response message will be returned on this argument. - * - * @return PJ_SUCCESS if a STUN message has been successfully - * decoded. - */ -PJ_DECL(pj_status_t) pj_stun_msg_decode(pj_pool_t *pool, - const pj_uint8_t *pdu, - unsigned pdu_len, - unsigned options, - pj_stun_msg **p_msg, - unsigned *p_parsed_len, - pj_stun_msg **p_response); - -/** - * Dump STUN message to a printable string output. - * - * @param msg The STUN message - * @param buffer Buffer where the printable string output will - * be printed on. - * @param length Specify the maximum length of the buffer. - * @param printed_len Optional pointer, which on output will be filled - * up with the actual length of the output string. - * - * @return The message string output. - */ -PJ_DECL(char*) pj_stun_msg_dump(const pj_stun_msg *msg, - char *buffer, - unsigned length, - unsigned *printed_len); - - -/** - * Find STUN attribute in the STUN message, starting from the specified - * index. - * - * @param msg The STUN message. - * @param attr_type The attribute type to be found, from pj_stun_attr_type. - * @param start_index The start index of the attribute in the message. - * Specify zero to start searching from the first - * attribute. - * - * @return The attribute instance, or NULL if it cannot be - * found. - */ -PJ_DECL(pj_stun_attr_hdr*) pj_stun_msg_find_attr(const pj_stun_msg *msg, - int attr_type, - unsigned start_index); - - -/** - * Create a generic STUN IP address attribute. The \a addr_len and - * \a addr parameters specify whether the address is IPv4 or IPv4 - * address. - * - * @param pool The pool to allocate memory from. - * @param attr_type Attribute type, from #pj_stun_attr_type. - * @param xor_ed If non-zero, the port and address will be XOR-ed - * with magic, to make the XOR-MAPPED-ADDRESS attribute. - * @param addr A pj_sockaddr_in or pj_sockaddr_in6 structure. - * @param addr_len Length of \a addr parameter. - * @param p_attr Pointer to receive the attribute. - * - * @return PJ_SUCCESS on success or the appropriate error code. - */ -PJ_DECL(pj_status_t) pj_stun_sockaddr_attr_create(pj_pool_t *pool, - int attr_type, - pj_bool_t xor_ed, - const pj_sockaddr_t *addr, - unsigned addr_len, - pj_stun_sockaddr_attr **p_attr); - - -/** - * Create and add generic STUN IP address attribute to a STUN message. - * The \a addr_len and \a addr parameters specify whether the address is - * IPv4 or IPv4 address. - * - * @param pool The pool to allocate memory from. - * @param msg The STUN message. - * @param attr_type Attribute type, from #pj_stun_attr_type. - * @param xor_ed If non-zero, the port and address will be XOR-ed - * with magic, to make the XOR-MAPPED-ADDRESS attribute. - * @param addr A pj_sockaddr_in or pj_sockaddr_in6 structure. - * @param addr_len Length of \a addr parameter. - * - * @return PJ_SUCCESS on success or the appropriate error code. - */ -PJ_DECL(pj_status_t) pj_stun_msg_add_sockaddr_attr(pj_pool_t *pool, - pj_stun_msg *msg, - int attr_type, - pj_bool_t xor_ed, - const pj_sockaddr_t *addr, - unsigned addr_len); - -/** - * Create a STUN generic string attribute. - * - * @param pool The pool to allocate memory from. - * @param attr_type Attribute type, from #pj_stun_attr_type. - * @param value The string value to be assigned to the attribute. - * @param p_attr Pointer to receive the attribute. - * - * @return PJ_SUCCESS on success or the appropriate error code. - */ -PJ_DECL(pj_status_t) pj_stun_string_attr_create(pj_pool_t *pool, - int attr_type, - const pj_str_t *value, - pj_stun_string_attr **p_attr); - -/** - * Create and add STUN generic string attribute to the message. - * - * @param pool The pool to allocate memory from. - * @param msg The STUN message. - * @param attr_type Attribute type, from #pj_stun_attr_type. - * @param value The string value to be assigned to the attribute. - * - * @return PJ_SUCCESS on success or the appropriate error code. - */ -PJ_DECL(pj_status_t) pj_stun_msg_add_string_attr(pj_pool_t *pool, - pj_stun_msg *msg, - int attr_type, - const pj_str_t *value); - -/** - * Create a STUN generic 32bit value attribute. - * - * @param pool The pool to allocate memory from. - * @param attr_type Attribute type, from #pj_stun_attr_type. - * @param value The 32bit value to be assigned to the attribute. - * @param p_attr Pointer to receive the attribute. - * - * @return PJ_SUCCESS on success or the appropriate error code. - */ -PJ_DECL(pj_status_t) pj_stun_uint_attr_create(pj_pool_t *pool, - int attr_type, - pj_uint32_t value, - pj_stun_uint_attr **p_attr); - -/** - * Create and add STUN generic 32bit value attribute to the message. - * - * @param pool The pool to allocate memory from. - * @param msg The STUN message - * @param attr_type Attribute type, from #pj_stun_attr_type. - * @param value The 32bit value to be assigned to the attribute. - * - * @return PJ_SUCCESS on success or the appropriate error code. - */ -PJ_DECL(pj_status_t) pj_stun_msg_add_uint_attr(pj_pool_t *pool, - pj_stun_msg *msg, - int attr_type, - pj_uint32_t value); - - -/** - * Create a STUN MESSAGE-INTEGRITY attribute. - * - * @param pool The pool to allocate memory from. - * @param p_attr Pointer to receive the attribute. - * - * @return PJ_SUCCESS on success or the appropriate error code. - */ -PJ_DECL(pj_status_t) pj_stun_msgint_attr_create(pj_pool_t *pool, - pj_stun_msgint_attr **p_attr); - -/** - * Create and add STUN MESSAGE-INTEGRITY attribute. - * - * @param pool The pool to allocate memory from. - * @param msg The STUN message - * - * @return PJ_SUCCESS on success or the appropriate error code. - */ -PJ_DECL(pj_status_t) pj_stun_msg_add_msgint_attr(pj_pool_t *pool, - pj_stun_msg *msg); - -/** - * Create a STUN ERROR-CODE attribute. - * - * @param pool The pool to allocate memory from. - * @param err_code STUN error code. - * @param err_reason Optional STUN error reason. If NULL is given, the - * standard error reason will be given. - * @param p_attr Pointer to receive the attribute. - * - * @return PJ_SUCCESS on success or the appropriate error code. - */ -PJ_DECL(pj_status_t) pj_stun_errcode_attr_create(pj_pool_t *pool, - int err_code, - const pj_str_t *err_reason, - pj_stun_errcode_attr **p_attr); - - -/** - * Create and add STUN ERROR-CODE attribute to the message. - * - * @param pool The pool to allocate memory from. - * @param msg The STUN mesage. - * @param err_code STUN error code. - * @param err_reason Optional STUN error reason. If NULL is given, the - * standard error reason will be given. - * - * @return PJ_SUCCESS on success or the appropriate error code. - */ -PJ_DECL(pj_status_t) pj_stun_msg_add_errcode_attr(pj_pool_t *pool, - pj_stun_msg *msg, - int err_code, - const pj_str_t *err_reason); - -/** - * Create instance of STUN UNKNOWN-ATTRIBUTES attribute and copy the - * unknown attribute array to the attribute. - * - * @param pool The pool to allocate memory from. - * @param attr_cnt Number of attributes in the array (can be zero). - * @param attr Optional array of attributes. - * @param p_attr Pointer to receive the attribute. - * - * @return PJ_SUCCESS on success or the appropriate error code. - */ -PJ_DECL(pj_status_t) pj_stun_unknown_attr_create(pj_pool_t *pool, - unsigned attr_cnt, - const pj_uint16_t attr[], - pj_stun_unknown_attr **p_attr); - -/** - * Create and add STUN UNKNOWN-ATTRIBUTES attribute to the message. - * - * @param pool The pool to allocate memory from. - * @param msg The STUN message. - * @param attr_cnt Number of attributes in the array (can be zero). - * @param attr Optional array of attributes. - * - * @return PJ_SUCCESS on success or the appropriate error code. - */ -PJ_DECL(pj_status_t) pj_stun_msg_add_unknown_attr(pj_pool_t *pool, - pj_stun_msg *msg, - unsigned attr_cnt, - const pj_uint16_t attr[]); - -/** - * Create STUN binary attribute. - * - * @param pool The pool to allocate memory from. - * @param attr_type The attribute type, from #pj_stun_attr_type. - * @param data Data to be coped to the attribute, or NULL - * if no data to be copied now. - * @param length Length of data, or zero if no data is to be - * copied now. - * @param p_attr Pointer to receive the attribute. - * - * @return PJ_SUCCESS on success or the appropriate error code. - */ -PJ_DECL(pj_status_t) pj_stun_binary_attr_create(pj_pool_t *pool, - int attr_type, - const pj_uint8_t *data, - unsigned length, - pj_stun_binary_attr **p_attr); - -/** - * Create STUN binary attribute and add the attribute to the message. - * - * @param pool The pool to allocate memory from. - * @param msg The STUN message. - * @param attr_type The attribute type, from #pj_stun_attr_type. - * @param data Data to be coped to the attribute, or NULL - * if no data to be copied now. - * @param length Length of data, or zero if no data is to be - * copied now. - * @param p_attr Pointer to receive the attribute. - * - * @return PJ_SUCCESS on success or the appropriate error code. - */ -PJ_DECL(pj_status_t) pj_stun_msg_add_binary_attr(pj_pool_t *pool, - pj_stun_msg *msg, - int attr_type, - const pj_uint8_t *data, - unsigned length); - - -/** - * @} - */ - - -PJ_END_DECL - - -#endif /* __PJLIB_UTIL_STUN_MSG_H__ */ - diff --git a/pjlib-util/include/pjlib-util/stun_session.h b/pjlib-util/include/pjlib-util/stun_session.h deleted file mode 100644 index fa18dc3a..00000000 --- a/pjlib-util/include/pjlib-util/stun_session.h +++ /dev/null @@ -1,372 +0,0 @@ -/* $Id$ */ -/* - * Copyright (C) 2003-2005 Benny Prijono - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ -#ifndef __PJLIB_UTIL_STUN_SESSION_H__ -#define __PJLIB_UTIL_STUN_SESSION_H__ - -#include -#include -#include -#include -#include -#include - -PJ_BEGIN_DECL - - -/* **************************************************************************/ -/** - * @defgroup PJLIB_UTIL_STUN_SESSION STUN Client/Server Session - * @brief STUN client and server session - * @ingroup PJLIB_UTIL_STUN - * @{ - */ - - -/** Forward declaration for pj_stun_tx_data */ -typedef struct pj_stun_tx_data pj_stun_tx_data; - -/** Forward declaration for pj_stun_session */ -typedef struct pj_stun_session pj_stun_session; - - -/** - * This is the callback to be registered to pj_stun_session, to send - * outgoing message and to receive various notifications from the STUN - * session. - */ -typedef struct pj_stun_session_cb -{ - /** - * Callback to be called by the STUN session to send outgoing message. - * - * @param sess The STUN session. - * @param pkt Packet to be sent. - * @param pkt_size Size of the packet to be sent. - * @param dst_addr The destination address. - * @param addr_len Length of destination address. - * - * @return The callback should return the status of the - * packet sending. - */ - pj_status_t (*on_send_msg)(pj_stun_session *sess, - const void *pkt, - pj_size_t pkt_size, - const pj_sockaddr_t *dst_addr, - unsigned addr_len); - - /** - * Callback to be called on incoming STUN request message. In the - * callback processing, application MUST create a response by calling - * pj_stun_session_create_response() function and send the response - * with pj_stun_session_send_msg() function, before returning from - * the callback. - * - * @param sess The STUN session. - * @param pkt Pointer to the original STUN packet. - * @param pkt_len Length of the STUN packet. - * @param msg The parsed STUN request. - * @param src_addr Source address of the packet. - * @param src_addr_len Length of the source address. - * - * @return The return value of this callback will be - * returned back to pj_stun_session_on_rx_pkt() - * function. - */ - pj_status_t (*on_rx_request)(pj_stun_session *sess, - const pj_uint8_t *pkt, - unsigned pkt_len, - const pj_stun_msg *msg, - const pj_sockaddr_t *src_addr, - unsigned src_addr_len); - - /** - * Callback to be called when response is received or the transaction - * has timed out. - * - * @param sess The STUN session. - * @param status Status of the request. If the value if not - * PJ_SUCCESS, the transaction has timed-out - * or other error has occurred, and the response - * argument may be NULL. - * @param request The original STUN request. - * @param response The response message, on successful transaction. - */ - void (*on_request_complete)(pj_stun_session *sess, - pj_status_t status, - pj_stun_tx_data *tdata, - const pj_stun_msg *response); - - - /** - * Type of callback to be called on incoming STUN indication. - */ - pj_status_t (*on_rx_indication)(pj_stun_session *sess, - const pj_uint8_t *pkt, - unsigned pkt_len, - const pj_stun_msg *msg, - const pj_sockaddr_t *src_addr, - unsigned src_addr_len); - -} pj_stun_session_cb; - - -/** - * This structure describe the outgoing STUN transmit data to carry the - * message to be sent. - */ -struct pj_stun_tx_data -{ - PJ_DECL_LIST_MEMBER(struct pj_stun_tx_data); - - pj_pool_t *pool; /**< Pool. */ - pj_stun_session *sess; /**< The STUN session. */ - pj_stun_msg *msg; /**< The STUN message. */ - - pj_stun_client_tsx *client_tsx; /**< Client STUN transaction. */ - pj_uint32_t msg_magic; /**< Message magic. */ - pj_uint8_t msg_key[12]; /**< Message/transaction key. */ - - void *pkt; /**< The STUN packet. */ - unsigned max_len; /**< Length of packet buffer. */ - unsigned pkt_size; /**< The actual length of STUN pkt. */ - - unsigned addr_len; /**< Length of destination address. */ - const pj_sockaddr_t *dst_addr; /**< Destination address. */ - - pj_timer_entry res_timer; /**< Response cache timer. */ -}; - - -/** - * Create a STUN session. - * - * @param endpt The STUN endpoint, to be used to register timers etc. - * @param name Optional name to be associated with this instance. The - * name will be used for example for logging purpose. - * @param cb Session callback. - * @param fingerprint Enable message fingerprint for outgoing messages. - * @param p_sess Pointer to receive STUN session instance. - * - * @return PJ_SUCCESS on success, or the appropriate error code. - */ -PJ_DECL(pj_status_t) pj_stun_session_create(pj_stun_endpoint *endpt, - const char *name, - const pj_stun_session_cb *cb, - pj_bool_t fingerprint, - pj_stun_session **p_sess); - -/** - * Destroy the STUN session. - * - * @param sess The STUN session instance. - * - * @return PJ_SUCCESS on success, or the appropriate error code. - */ -PJ_DECL(pj_status_t) pj_stun_session_destroy(pj_stun_session *sess); - -/** - * Associated an arbitrary data with this STUN session. The user data may - * be retrieved later with pj_stun_session_get_user_data() function. - * - * @param sess The STUN session instance. - * - * @return PJ_SUCCESS on success, or the appropriate error code. - */ -PJ_DECL(pj_status_t) pj_stun_session_set_user_data(pj_stun_session *sess, - void *user_data); - -/** - * Retrieve the user data previously associated to this STUN session with - * pj_stun_session_set_user_data(). - * - * @param sess The STUN session instance. - * - * @return The user data associated with this STUN session. - */ -PJ_DECL(void*) pj_stun_session_get_user_data(pj_stun_session *sess); - -/** - * Set server name to be included in all response. - * - * @param sess The STUN session instance. - * @param srv_name Server name string. - * - * @return The user data associated with this STUN session. - */ -PJ_DECL(pj_status_t) pj_stun_session_set_server_name(pj_stun_session *sess, - const pj_str_t *srv_name); - -/** - * Set credential to be used by this session. Once credential is set, all - * outgoing messages will include MESSAGE-INTEGRITY, and all incoming - * message will be authenticated against this credential. - * - * To disable authentication after it has been set, call this function - * again with NULL as the argument. - * - * @param sess The STUN session instance. - * @param cred The credential to be used by this session. If NULL - * is specified, authentication will be disabled. - * - * @return PJ_SUCCESS on success, or the appropriate error code. - */ -PJ_DECL(void) pj_stun_session_set_credential(pj_stun_session *sess, - const pj_stun_auth_cred *cred); - -/** - * Create a STUN request message. After the message has been successfully - * created, application can send the message by calling - * pj_stun_session_send_msg(). - * - * @param sess The STUN session instance. - * @param msg_type The STUN request message type, from pj_stun_method_e or - * from pj_stun_msg_type. - * @param p_tdata Pointer to receive STUN transmit data instance containing - * the request. - * - * @return PJ_SUCCESS on success, or the appropriate error code. - */ -PJ_DECL(pj_status_t) pj_stun_session_create_req(pj_stun_session *sess, - int msg_type, - pj_stun_tx_data **p_tdata); - -/** - * Create a STUN Indication message. After the message has been successfully - * created, application can send the message by calling - * pj_stun_session_send_msg(). - * - * @param sess The STUN session instance. - * @param msg_type The STUN request message type, from pj_stun_method_e or - * from pj_stun_msg_type. This function will add the - * indication bit as necessary. - * @param p_tdata Pointer to receive STUN transmit data instance containing - * the message. - * - * @return PJ_SUCCESS on success, or the appropriate error code. - */ -PJ_DECL(pj_status_t) pj_stun_session_create_ind(pj_stun_session *sess, - int msg_type, - pj_stun_tx_data **p_tdata); - -/** - * Create a STUN response message. After the message has been - * successfully created, application can send the message by calling - * pj_stun_session_send_msg(). - * - * @param sess The STUN session instance. - * @param req The STUN request where the response is to be created. - * @param err_code Error code to be set in the response, if error response - * is to be created, according to pj_stun_status enumeration. - * This argument MUST be zero if successful response is - * to be created. - * @param err_msg Optional pointer for the error message string, when - * creating error response. If the value is NULL and the - * \a err_code is non-zero, then default error message will - * be used. - * @param p_tdata Pointer to receive the response message created. - * - * @return PJ_SUCCESS on success, or the appropriate error code. - */ -PJ_DECL(pj_status_t) pj_stun_session_create_response(pj_stun_session *sess, - const pj_stun_msg *req, - unsigned err_code, - const pj_str_t *err_msg, - pj_stun_tx_data **p_tdata); - - -/** - * Send STUN message to the specified destination. This function will encode - * the pj_stun_msg instance to a packet buffer, and add credential or - * fingerprint if necessary. If the message is a request, the session will - * also create and manage a STUN client transaction to be used to manage the - * retransmission of the request. After the message has been encoded and - * transaction is setup, the \a on_send_msg() callback of pj_stun_session_cb - * (which is registered when the STUN session is created) will be called - * to actually send the message to the wire. - * - * @param sess The STUN session instance. - * @param cache_res If PJ_TRUE then response will be cached. - * @param dst_addr The destination socket address. - * @param addr_len Length of destination address. - * @param tdata The STUN transmit data containing the STUN message to - * be sent. - * - * @return PJ_SUCCESS on success, or the appropriate error code. - */ -PJ_DECL(pj_status_t) pj_stun_session_send_msg(pj_stun_session *sess, - pj_bool_t cache_res, - const pj_sockaddr_t *dst_addr, - unsigned addr_len, - pj_stun_tx_data *tdata); - -/** - * Application must call this function to notify the STUN session about - * the arrival of STUN packet. The STUN packet MUST have been checked - * first with #pj_stun_msg_check() to verify that this is indeed a valid - * STUN packet. - * - * The STUN session will decode the packet into pj_stun_msg, and process - * the message accordingly. If the message is a response, it will search - * through the outstanding STUN client transactions for a matching - * transaction ID and hand over the response to the transaction. - * - * On successful message processing, application will be notified about - * the message via one of the pj_stun_session_cb callback. - * - * @param sess The STUN session instance. - * @param packet The packet containing STUN message. - * @param pkt_size Size of the packet. - * @param options Options, from #pj_stun_decode_options. - * @param parsed_len Optional pointer to receive the size of the parsed - * STUN message (useful if packet is received via a - * stream oriented protocol). - * - * @return PJ_SUCCESS on success, or the appropriate error code. - */ -PJ_DECL(pj_status_t) pj_stun_session_on_rx_pkt(pj_stun_session *sess, - const void *packet, - pj_size_t pkt_size, - unsigned options, - unsigned *parsed_len, - const pj_sockaddr_t *src_addr, - unsigned src_addr_len); - -/** - * Destroy the transmit data. Call this function only when tdata has been - * created but application doesn't want to send the message (perhaps - * because of other error). - * - * @param sess The STUN session. - * @param tdata The transmit data. - * - * @return PJ_SUCCESS on success, or the appropriate error code. - */ -PJ_DECL(void) pj_stun_msg_destroy_tdata(pj_stun_session *sess, - pj_stun_tx_data *tdata); - - -/** - * @} - */ - - -PJ_END_DECL - -#endif /* __PJLIB_UTIL_STUN_SESSION_H__ */ - diff --git a/pjlib-util/include/pjlib-util/stun_transaction.h b/pjlib-util/include/pjlib-util/stun_transaction.h deleted file mode 100644 index c7a5bf93..00000000 --- a/pjlib-util/include/pjlib-util/stun_transaction.h +++ /dev/null @@ -1,217 +0,0 @@ -/* $Id$ */ -/* - * Copyright (C) 2003-2005 Benny Prijono - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ -#ifndef __PJLIB_UTIL_STUN_TRANSACTION_H__ -#define __PJLIB_UTIL_STUN_TRANSACTION_H__ - -/** - * @file stun_transaction.h - * @brief STUN transaction - */ - -#include -#include - - -PJ_BEGIN_DECL - - -/* **************************************************************************/ -/** - * @defgroup PJLIB_UTIL_STUN_TRANSACTION STUN Client Transaction - * @brief STUN client transaction - * @ingroup PJLIB_UTIL_STUN - * @{ - * - The @ref PJLIB_UTIL_STUN_TRANSACTION is used to manage outgoing STUN request, - for example to retransmit the request and to notify application about the - completion of the request. - - The @ref PJLIB_UTIL_STUN_TRANSACTION does not use any networking operations, - but instead application must supply the transaction with a callback to - be used by the transaction to send outgoing requests. This way the STUN - transaction is made more generic and can work with different types of - networking codes in application. - - - */ - -/** - * Opaque declaration of STUN client transaction. - */ -typedef struct pj_stun_client_tsx pj_stun_client_tsx; - -/** - * STUN client transaction callback. - */ -typedef struct pj_stun_tsx_cb -{ - /** - * This callback is called when the STUN transaction completed. - * - * @param tsx The STUN transaction. - * @param status Status of the transaction. Status PJ_SUCCESS - * means that the request has received a successful - * response. - * @param response The STUN response, which value may be NULL if - * \a status is not PJ_SUCCESS. - */ - void (*on_complete)(pj_stun_client_tsx *tsx, - pj_status_t status, - const pj_stun_msg *response); - - /** - * This callback is called by the STUN transaction when it wants to send - * outgoing message. - * - * @param tsx The STUN transaction instance. - * @param stun_pkt The STUN packet to be sent. - * @param pkt_size Size of the STUN packet. - * - * @return If return value of the callback is not PJ_SUCCESS, - * the transaction will fail. - */ - pj_status_t (*on_send_msg)(pj_stun_client_tsx *tsx, - const void *stun_pkt, - pj_size_t pkt_size); - -} pj_stun_tsx_cb; - - - -/** - * Create an instance of STUN client transaction. The STUN client - * transaction is used to transmit outgoing STUN request and to - * ensure the reliability of the request by periodically retransmitting - * the request, if necessary. - * - * @param endpt The STUN endpoint, which will be used to retrieve - * various settings for the transaction. - * @param pool Pool to be used to allocate memory from. - * @param cb Callback structure, to be used by the transaction - * to send message and to notify the application about - * the completion of the transaction. - * @param p_tsx Pointer to receive the transaction instance. - * - * @return PJ_SUCCESS on success, or the appropriate error code. - */ -PJ_DECL(pj_status_t) pj_stun_client_tsx_create( pj_stun_endpoint *endpt, - pj_pool_t *pool, - const pj_stun_tsx_cb *cb, - pj_stun_client_tsx **p_tsx); - -/** - * Destroy a STUN client transaction. - * - * @param tsx The STUN transaction. - * - * @return PJ_SUCCESS on success, or the appropriate error code. - */ -PJ_DECL(pj_status_t) pj_stun_client_tsx_destroy(pj_stun_client_tsx *tsx); - - -/** - * Check if transaction has completed. - * - * @param tsx The STUN transaction. - * - * @return Non-zero if transaction has completed. - */ -PJ_DECL(pj_bool_t) pj_stun_client_tsx_is_complete(pj_stun_client_tsx *tsx); - - -/** - * Associate an arbitrary data with the STUN transaction. This data - * can be then retrieved later from the transaction, by using - * pj_stun_client_tsx_get_data() function. - * - * @param tsx The STUN client transaction. - * @param data Application data to be associated with the - * STUN transaction. - * - * @return PJ_SUCCESS on success. - */ -PJ_DECL(pj_status_t) pj_stun_client_tsx_set_data(pj_stun_client_tsx *tsx, - void *data); - - -/** - * Get the user data that was previously associated with the STUN - * transaction. - * - * @param tsx The STUN client transaction. - * - * @return The user data. - */ -PJ_DECL(void*) pj_stun_client_tsx_get_data(pj_stun_client_tsx *tsx); - - -/** - * Start the STUN client transaction by sending STUN request using - * this transaction. If reliable transport such as TCP or TLS is used, - * the retransmit flag should be set to PJ_FALSE because reliablity - * will be assured by the transport layer. - * - * @param tsx The STUN client transaction. - * @param retransmit Should this message be retransmitted by the - * STUN transaction. - * @param pkt The STUN packet to send. - * @param pkt_len Length of STUN packet. - * - * @return PJ_SUCCESS on success or the appropriate error code. - */ -PJ_DECL(pj_status_t) pj_stun_client_tsx_send_msg(pj_stun_client_tsx *tsx, - pj_bool_t retransmit, - void *pkt, - unsigned pkt_len); - - - -/** - * Notify the STUN transaction about the arrival of STUN response. - * If the STUN response contains a final error (300 and greater), the - * transaction will be terminated and callback will be called. If the - * STUN response contains response code 100-299, retransmission - * will cease, but application must still call this function again - * with a final response later to allow the transaction to complete. - * - * @param tsx The STUN client transaction instance. - * @param packet The incoming packet. - * @param pkt_size Size of the incoming packet. - * @param parsed_len Optional pointer to receive the number of bytes - * that have been parsed from the incoming packet - * for the STUN message. This is useful if the - * STUN transaction is running over stream oriented - * socket such as TCP or TLS. - * - * @return PJ_SUCCESS on success or the appropriate error code. - */ -PJ_DECL(pj_status_t) pj_stun_client_tsx_on_rx_msg(pj_stun_client_tsx *tsx, - const pj_stun_msg *msg); - - -/** - * @} - */ - - -PJ_END_DECL - - -#endif /* __PJLIB_UTIL_STUN_TRANSACTION_H__ */ - diff --git a/pjlib-util/include/pjlib-util/turn_client.h b/pjlib-util/include/pjlib-util/turn_client.h deleted file mode 100644 index 83d8d2d6..00000000 --- a/pjlib-util/include/pjlib-util/turn_client.h +++ /dev/null @@ -1,132 +0,0 @@ -/* $Id$ */ -/* - * Copyright (C) 2003-2005 Benny Prijono - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ -#ifndef __PJLIB_UTIL_TURN_CLIENT_H__ -#define __PJLIB_UTIL_TURN_CLIENT_H__ - -/** - * @file turn_client.h - * @brief TURN client session. - */ - -#include - - -PJ_BEGIN_DECL - - -/** - * @defgroup PJLIB_UTIL_TURN_CLIENT TURN Client Session - * @brief Management of STUN/TURN client session - * @ingroup PJLIB_UTIL_STUN - * @{ - */ - -typedef struct pj_turn_client pj_turn_client; - -/** - * This describes TURN client config. - */ -typedef struct pj_turn_client_cb -{ - /** - * Callback to be called by the TURN session to send outgoing message. - * - * @param client The TURN client session. - * @param pkt Packet to be sent. - * @param pkt_size Size of the packet to be sent. - * @param dst_addr The destination address. - * @param addr_len Length of destination address. - * - * @return The callback should return the status of the - * packet sending. - */ - pj_status_t (*on_send_msg)(pj_turn_client *client, - const void *pkt, - pj_size_t pkt_size, - const pj_sockaddr_t *dst_addr, - unsigned addr_len); - - /** - * Callback to be called by TURN session when its state has changed. - */ - pj_status_t (*on_state_changed)(pj_turn_client *client); - -} pj_turn_client_cb; - - -/** - * Options - */ -typedef struct pj_turn_client_config -{ - int bandwidth; - int lifetime; - int sock_type; - int port; -} pj_turn_client_config; - - -PJ_INLINE(void) pj_turn_client_config_default(pj_turn_client_config *cfg) -{ - pj_bzero(cfg, sizeof(*cfg)); - cfg->bandwidth = -1; - cfg->lifetime = -1; - cfg->sock_type = -1; - cfg->port = -1; -} - - -/** - * This describes the TURN client session. - */ -struct pj_turn_client -{ - pj_pool_t *pool; - pj_stun_session *session; - pj_timer_entry alloc_timer; - pj_sockaddr_in mapped_addr; - pj_sockaddr_in relay_addr; -}; - - - - -/** - * Create the TURN client session. - */ -PJ_DECL(pj_status_t) pj_turn_client_create(pj_stun_endpoint *endpt, - const pj_turn_client_config *cfg, - const pj_turn_client_cb *cb, - pj_turn_client **p_client); - -/** - * Start the TURN client session by sending Allocate request to the server. - */ - - -/** - * @} - */ - - -PJ_END_DECL - - -#endif /* __PJLIB_UTIL_TURN_CLIENT_H__ */ - diff --git a/pjlib-util/src/pjlib-util/stun_auth.c b/pjlib-util/src/pjlib-util/stun_auth.c deleted file mode 100644 index 9a94fe0d..00000000 --- a/pjlib-util/src/pjlib-util/stun_auth.c +++ /dev/null @@ -1,341 +0,0 @@ -/* $Id$ */ -/* - * Copyright (C) 2003-2005 Benny Prijono - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ -#include -#include -#include -#include -#include -#include - - -/* Duplicate credential */ -PJ_DEF(void) pj_stun_auth_cred_dup( pj_pool_t *pool, - pj_stun_auth_cred *dst, - const pj_stun_auth_cred *src) -{ - dst->type = src->type; - - switch (src->type) { - case PJ_STUN_AUTH_CRED_STATIC: - pj_strdup(pool, &dst->data.static_cred.realm, - &src->data.static_cred.realm); - pj_strdup(pool, &dst->data.static_cred.username, - &src->data.static_cred.username); - dst->data.static_cred.data_type = src->data.static_cred.data_type; - pj_strdup(pool, &dst->data.static_cred.data, - &src->data.static_cred.data); - pj_strdup(pool, &dst->data.static_cred.nonce, - &src->data.static_cred.nonce); - break; - case PJ_STUN_AUTH_CRED_DYNAMIC: - pj_memcpy(&dst->data.dyn_cred, &src->data.dyn_cred, - sizeof(src->data.dyn_cred)); - break; - } -} - - -PJ_INLINE(pj_uint16_t) GET_VAL16(const pj_uint8_t *pdu, unsigned pos) -{ - return (pj_uint16_t) ((pdu[pos] << 8) + pdu[pos+1]); -} - - -/* Send 401 response */ -static pj_status_t create_challenge(pj_pool_t *pool, - const pj_stun_msg *msg, - int err_code, - const pj_str_t *err_msg, - const pj_str_t *realm, - const pj_str_t *nonce, - pj_stun_msg **p_response) -{ - pj_stun_msg *response; - pj_str_t tmp_nonce; - pj_status_t rc; - - rc = pj_stun_msg_create_response(pool, msg, - err_code, err_msg, &response); - if (rc != PJ_SUCCESS) - return rc; - - - if (realm && realm->slen) { - rc = pj_stun_msg_add_string_attr(pool, response, - PJ_STUN_ATTR_REALM, - realm); - if (rc != PJ_SUCCESS) - return rc; - - /* long term must include nonce */ - if (!nonce || nonce->slen == 0) { - tmp_nonce = pj_str("pjstun"); - nonce = &tmp_nonce; - } - } - - if (nonce && nonce->slen) { - rc = pj_stun_msg_add_string_attr(pool, response, - PJ_STUN_ATTR_NONCE, - nonce); - if (rc != PJ_SUCCESS) - return rc; - } - - *p_response = response; - - return PJ_SUCCESS; -} - - -/* Verify credential */ -PJ_DEF(pj_status_t) pj_stun_verify_credential( const pj_uint8_t *pkt, - unsigned pkt_len, - const pj_stun_msg *msg, - pj_stun_auth_cred *cred, - pj_pool_t *pool, - pj_stun_msg **p_response) -{ - pj_str_t realm, nonce, password; - const pj_stun_msgint_attr *amsgi; - unsigned amsgi_pos; - const pj_stun_username_attr *auser; - pj_bool_t username_ok; - const pj_stun_realm_attr *arealm; - const pj_stun_realm_attr *anonce; - pj_uint8_t digest[PJ_SHA1_DIGEST_SIZE]; - pj_uint8_t md5_digest[16]; - pj_str_t key; - pj_status_t status; - - /* msg and credential MUST be specified */ - PJ_ASSERT_RETURN(pkt && pkt_len && msg && cred, PJ_EINVAL); - - /* If p_response is specified, pool MUST be specified. */ - PJ_ASSERT_RETURN(!p_response || pool, PJ_EINVAL); - - if (p_response) - *p_response = NULL; - - if (!PJ_STUN_IS_REQUEST(msg->hdr.type)) - p_response = NULL; - - /* Get realm and nonce */ - realm.slen = nonce.slen = 0; - if (cred->type == PJ_STUN_AUTH_CRED_STATIC) { - realm = cred->data.static_cred.realm; - nonce = cred->data.static_cred.nonce; - } else if (cred->type == PJ_STUN_AUTH_CRED_DYNAMIC) { - status = cred->data.dyn_cred.get_auth(cred->data.dyn_cred.user_data, - pool, &realm, &nonce); - if (status != PJ_SUCCESS) - return status; - } else { - pj_assert(!"Unexpected"); - return PJ_EBUG; - } - - /* First check that MESSAGE-INTEGRITY is present */ - amsgi = (const pj_stun_msgint_attr*) - pj_stun_msg_find_attr(msg, PJ_STUN_ATTR_MESSAGE_INTEGRITY, 0); - if (amsgi == NULL) { - if (p_response) { - create_challenge(pool, msg, PJ_STUN_SC_UNAUTHORIZED, NULL, - &realm, &nonce, p_response); - } - return PJLIB_UTIL_ESTUNMSGINT; - } - - /* Next check that USERNAME is present */ - auser = (const pj_stun_username_attr*) - pj_stun_msg_find_attr(msg, PJ_STUN_ATTR_USERNAME, 0); - if (auser == NULL) { - if (p_response) { - create_challenge(pool, msg, PJ_STUN_SC_MISSING_USERNAME, NULL, - &realm, &nonce, p_response); - } - return PJLIB_UTIL_ESTUNNOUSERNAME; - } - - /* Get REALM, if any */ - arealm = (const pj_stun_realm_attr*) - pj_stun_msg_find_attr(msg, PJ_STUN_ATTR_REALM, 0); - - /* Check if username match */ - if (cred->type == PJ_STUN_AUTH_CRED_STATIC) { - username_ok = !pj_strcmp(&auser->value, - &cred->data.static_cred.username); - password = cred->data.static_cred.data; - } else if (cred->type == PJ_STUN_AUTH_CRED_DYNAMIC) { - int data_type = 0; - pj_status_t rc; - rc = cred->data.dyn_cred.get_password(cred->data.dyn_cred.user_data, - (arealm?&arealm->value:NULL), - &auser->value, pool, - &data_type, &password); - username_ok = (rc == PJ_SUCCESS); - } else { - username_ok = PJ_TRUE; - password.slen = 0; - } - - if (!username_ok) { - /* Username mismatch */ - if (p_response) { - create_challenge(pool, msg, PJ_STUN_SC_UNKNOWN_USERNAME, NULL, - &realm, &nonce, p_response); - } - return PJLIB_UTIL_ESTUNUSERNAME; - } - - - /* Get NONCE attribute */ - anonce = (pj_stun_nonce_attr*) - pj_stun_msg_find_attr(msg, PJ_STUN_ATTR_NONCE, 0); - - /* Check for long term/short term requirements. */ - if (realm.slen != 0 && arealm == NULL) { - /* Long term credential is required and REALM is not present */ - if (p_response) { - create_challenge(pool, msg, PJ_STUN_SC_MISSING_REALM, NULL, - &realm, &nonce, p_response); - } - return PJLIB_UTIL_ESTUNNOREALM; - - } else if (realm.slen != 0 && arealm != NULL) { - /* We want long term, and REALM is present */ - - /* NONCE must be present. */ - if (anonce == NULL) { - if (p_response) { - create_challenge(pool, msg, PJ_STUN_SC_MISSING_NONCE, - NULL, &realm, &nonce, p_response); - } - return PJLIB_UTIL_ESTUNNONCE; - } - - /* Verify REALM matches */ - if (pj_stricmp(&arealm->value, &realm)) { - /* REALM doesn't match */ - if (p_response) { - create_challenge(pool, msg, PJ_STUN_SC_MISSING_REALM, - NULL, &realm, &nonce, p_response); - } - return PJLIB_UTIL_ESTUNNOREALM; - } - - /* Valid case, will validate the message integrity later */ - - } else if (realm.slen == 0 && arealm != NULL) { - /* We want to use short term credential, but client uses long - * term credential. The draft doesn't mention anything about - * switching between long term and short term. - */ - - /* For now just accept the credential, anyway it will probably - * cause wrong message integrity value later. - */ - } else if (realm.slen==0 && arealm == NULL) { - /* Short term authentication is wanted, and one is supplied */ - - /* Application MAY request NONCE to be supplied */ - if (nonce.slen != 0) { - if (p_response) { - create_challenge(pool, msg, PJ_STUN_SC_MISSING_NONCE, - NULL, &realm, &nonce, p_response); - } - return PJLIB_UTIL_ESTUNNONCE; - } - } - - /* If NONCE is present, validate it */ - if (anonce) { - pj_bool_t ok; - - if (cred->type == PJ_STUN_AUTH_CRED_DYNAMIC) { - ok=cred->data.dyn_cred.verify_nonce(cred->data.dyn_cred.user_data, - (arealm?&arealm->value:NULL), - &auser->value, - &anonce->value); - } else { - if (nonce.slen) { - ok = !pj_strcmp(&anonce->value, &nonce); - } else { - ok = PJ_TRUE; - } - } - - if (!ok) { - if (p_response) { - create_challenge(pool, msg, PJ_STUN_SC_STALE_NONCE, - NULL, &realm, &nonce, p_response); - } - return PJLIB_UTIL_ESTUNNONCE; - } - } - - /* Get the position of MESSAGE-INTEGRITY in the packet */ - amsgi_pos = 20+msg->hdr.length-24; - if (GET_VAL16(pkt, amsgi_pos) == PJ_STUN_ATTR_MESSAGE_INTEGRITY) { - /* Found MESSAGE-INTEGRITY as the last attribute */ - } else { - amsgi_pos = 0; - } - - if (amsgi_pos==0) { - amsgi_pos = 20+msg->hdr.length-8-24; - if (GET_VAL16(pkt, amsgi_pos) == PJ_STUN_ATTR_MESSAGE_INTEGRITY) { - /* Found MESSAGE-INTEGRITY before FINGERPRINT */ - } else { - amsgi_pos = 0; - } - } - - if (amsgi_pos==0) { - pj_assert(!"Unable to find MESSAGE-INTEGRITY in the message!"); - return PJ_EBUG; - } - - /* Determine which key to use */ - if (realm.slen) { - pj_stun_calc_md5_key(md5_digest, &realm, &auser->value, &password); - key.ptr = (char*)md5_digest; - key.slen = 16; - } else { - key = password; - } - - /* Now calculate HMAC of the message */ - pj_hmac_sha1(pkt, amsgi_pos, (pj_uint8_t*)key.ptr, key.slen, digest); - - /* Compare HMACs */ - if (pj_memcmp(amsgi->hmac, digest, 20)) { - /* HMAC value mismatch */ - if (p_response) { - create_challenge(pool, msg, PJ_STUN_SC_INTEGRITY_CHECK_FAILURE, - NULL, &realm, &nonce, p_response); - } - return PJLIB_UTIL_ESTUNMSGINT; - } - - /* Everything looks okay! */ - return PJ_SUCCESS; -} - - diff --git a/pjlib-util/src/pjlib-util/stun_endpoint.c b/pjlib-util/src/pjlib-util/stun_endpoint.c deleted file mode 100644 index 277e385e..00000000 --- a/pjlib-util/src/pjlib-util/stun_endpoint.c +++ /dev/null @@ -1,69 +0,0 @@ -/* $Id$ */ -/* - * Copyright (C) 2003-2005 Benny Prijono - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ -#include -#include -#include -#include - - -/* - * Create a STUN endpoint instance. - */ -PJ_DEF(pj_status_t) pj_stun_endpoint_create( pj_pool_factory *factory, - unsigned options, - pj_ioqueue_t *ioqueue, - pj_timer_heap_t *timer_heap, - pj_stun_endpoint **p_endpt) -{ - pj_pool_t *pool; - pj_stun_endpoint *endpt; - - PJ_ASSERT_RETURN(factory && p_endpt, PJ_EINVAL); - - pool = pj_pool_create(factory, "stunendpt", 1000, 1000, NULL); - if (!pool) - return PJ_ENOMEM; - - endpt = PJ_POOL_ZALLOC_T(pool, pj_stun_endpoint); - endpt->pool = pool; - endpt->pf = factory; - endpt->options = options; - endpt->ioqueue = ioqueue; - endpt->timer_heap = timer_heap; - endpt->rto_msec = PJ_STUN_RTO_VALUE; - endpt->res_cache_msec = 10000; - - *p_endpt = endpt; - - return PJ_SUCCESS; -} - - -/* - * Destroy STUN endpoint instance. - */ -PJ_DEF(pj_status_t) pj_stun_endpoint_destroy(pj_stun_endpoint *endpt) -{ - PJ_ASSERT_RETURN(endpt, PJ_EINVAL); - - pj_pool_release(endpt->pool); - - return PJ_SUCCESS; -} - diff --git a/pjlib-util/src/pjlib-util/stun_msg.c b/pjlib-util/src/pjlib-util/stun_msg.c deleted file mode 100644 index 1c750d8e..00000000 --- a/pjlib-util/src/pjlib-util/stun_msg.c +++ /dev/null @@ -1,2162 +0,0 @@ -/* $Id$ */ -/* - * Copyright (C) 2003-2005 Benny Prijono - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#define THIS_FILE "stun_msg.c" -#define STUN_XOR_FINGERPRINT 0x5354554eL - -static const char *stun_method_names[] = -{ - "Unknown", /* 0 */ - "Binding", /* 1 */ - "Shared Secret", /* 2 */ - "Allocate", /* 3 */ - "Send", /* 4 */ - "Data", /* 5 */ - "Set Active Destination", /* 6 */ - "Connect", /* 7 */ - "Connect Status" /* 8 */ -}; - -static struct -{ - int err_code; - const char *err_msg; -} stun_err_msg_map[] = -{ - { PJ_STUN_SC_TRY_ALTERNATE, "Try Alternate"}, - { PJ_STUN_SC_BAD_REQUEST, "Bad Request"}, - { PJ_STUN_SC_UNAUTHORIZED, "Unauthorized"}, - { PJ_STUN_SC_UNKNOWN_ATTRIBUTE, "Unknown Attribute"}, - { PJ_STUN_SC_STALE_CREDENTIALS, "Stale Credentials"}, - { PJ_STUN_SC_INTEGRITY_CHECK_FAILURE, "Integrity Check Failure"}, - { PJ_STUN_SC_MISSING_USERNAME, "Missing Username"}, - { PJ_STUN_SC_USE_TLS, "Use TLS"}, - { PJ_STUN_SC_MISSING_REALM, "Missing Realm"}, - { PJ_STUN_SC_MISSING_NONCE, "Missing Nonce"}, - { PJ_STUN_SC_UNKNOWN_USERNAME, "Unknown Username"}, - { PJ_STUN_SC_NO_BINDING, "No Binding"}, - { PJ_STUN_SC_STALE_NONCE, "Stale Nonce"}, - { PJ_STUN_SC_TRANSITIONING, "Active Destination Already Set"}, - { PJ_STUN_SC_WRONG_USERNAME, "Wrong Username"}, - { PJ_STUN_SC_UNSUPP_TRANSPORT_PROTO, "Unsupported Transport Protocol"}, - { PJ_STUN_SC_INVALID_IP_ADDR, "Invalid IP Address"}, - { PJ_STUN_SC_INVALID_PORT, "Invalid Port"}, - { PJ_STUN_SC_OPER_TCP_ONLY, "Operation for TCP Only"}, - { PJ_STUN_SC_CONNECTION_FAILURE, "Connection Failure"}, - { PJ_STUN_SC_CONNECTION_TIMEOUT, "Connection Timeout"}, - { PJ_STUN_SC_ALLOCATION_QUOTA_REACHED, "Allocation Quota Reached"}, - { PJ_STUN_SC_SERVER_ERROR, "Server Error"}, - { PJ_STUN_SC_INSUFFICIENT_CAPACITY, "Insufficient Capacity"}, - { PJ_STUN_SC_GLOBAL_FAILURE, "Global Failure"} -}; - - - -struct attr_desc -{ - const char *name; - pj_status_t (*decode_attr)(pj_pool_t *pool, const pj_uint8_t *buf, - void **p_attr); - pj_status_t (*encode_attr)(const void *a, pj_uint8_t *buf, - unsigned len, unsigned *printed); - -}; - -static pj_status_t decode_sockaddr_attr(pj_pool_t *pool, - const pj_uint8_t *buf, - void **p_attr); -static pj_status_t decode_xored_sockaddr_attr(pj_pool_t *pool, - const pj_uint8_t *buf, - void **p_attr); -static pj_status_t encode_sockaddr_attr(const void *a, pj_uint8_t *buf, - unsigned len, - unsigned *printed); -static pj_status_t decode_string_attr(pj_pool_t *pool, - const pj_uint8_t *buf, - void **p_attr); -static pj_status_t encode_string_attr(const void *a, pj_uint8_t *buf, - unsigned len, unsigned *printed); -static pj_status_t decode_msgint_attr(pj_pool_t *pool, - const pj_uint8_t *buf, - void **p_attr); -static pj_status_t encode_msgint_attr(const void *a, pj_uint8_t *buf, - unsigned len, unsigned *printed); -static pj_status_t decode_errcode_attr(pj_pool_t *pool, - const pj_uint8_t *buf, - void **p_attr); -static pj_status_t encode_errcode_attr(const void *a, pj_uint8_t *buf, - unsigned len, unsigned *printed); -static pj_status_t decode_unknown_attr(pj_pool_t *pool, - const pj_uint8_t *buf, - void **p_attr); -static pj_status_t encode_unknown_attr(const void *a, pj_uint8_t *buf, - unsigned len, unsigned *printed); -static pj_status_t decode_uint_attr(pj_pool_t *pool, - const pj_uint8_t *buf, - void **p_attr); -static pj_status_t encode_uint_attr(const void *a, pj_uint8_t *buf, - unsigned len, unsigned *printed); -static pj_status_t decode_binary_attr(pj_pool_t *pool, - const pj_uint8_t *buf, - void **p_attr); -static pj_status_t encode_binary_attr(const void *a, pj_uint8_t *buf, - unsigned len, unsigned *printed); -static pj_status_t decode_empty_attr(pj_pool_t *pool, - const pj_uint8_t *buf, - void **p_attr); -static pj_status_t encode_empty_attr(const void *a, pj_uint8_t *buf, - unsigned len, unsigned *printed); - - -struct attr_desc mandatory_attr_desc[] = -{ - { - /* type zero */ - NULL, - NULL, - NULL - }, - { - /* PJ_STUN_ATTR_MAPPED_ADDR, */ - "MAPPED-ADDRESS", - &decode_sockaddr_attr, - &encode_sockaddr_attr - }, - { - /* PJ_STUN_ATTR_RESPONSE_ADDR, */ - "RESPONSE-ADDRESS", - &decode_sockaddr_attr, - &encode_sockaddr_attr - }, - { - /* PJ_STUN_ATTR_CHANGE_REQUEST, */ - "CHANGE-REQUEST", - &decode_uint_attr, - &encode_uint_attr - }, - { - /* PJ_STUN_ATTR_SOURCE_ADDR, */ - "SOURCE-ADDRESS", - &decode_sockaddr_attr, - &encode_sockaddr_attr - }, - { - /* PJ_STUN_ATTR_CHANGED_ADDR, */ - "CHANGED-ADDRESS", - &decode_sockaddr_attr, - &encode_sockaddr_attr - }, - { - /* PJ_STUN_ATTR_USERNAME, */ - "USERNAME", - &decode_string_attr, - &encode_string_attr - }, - { - /* PJ_STUN_ATTR_PASSWORD, */ - "PASSWORD", - &decode_string_attr, - &encode_string_attr - }, - { - /* PJ_STUN_ATTR_MESSAGE_INTEGRITY, */ - "MESSAGE-INTEGRITY", - &decode_msgint_attr, - &encode_msgint_attr - }, - { - /* PJ_STUN_ATTR_ERROR_CODE, */ - "ERROR-CODE", - &decode_errcode_attr, - &encode_errcode_attr - }, - { - /* PJ_STUN_ATTR_UNKNOWN_ATTRIBUTES, */ - "UNKNOWN-ATTRIBUTES", - &decode_unknown_attr, - &encode_unknown_attr - }, - { - /* PJ_STUN_ATTR_REFLECTED_FROM, */ - "REFLECTED-FROM", - &decode_sockaddr_attr, - &encode_sockaddr_attr - }, - { - /* ID 0x000C is not assigned */ - NULL, - NULL, - NULL - }, - { - /* PJ_STUN_ATTR_LIFETIME, */ - "LIFETIME", - &decode_uint_attr, - &encode_uint_attr - }, - { - /* ID 0x000E is not assigned */ - NULL, - NULL, - NULL - }, - { - /* ID 0x000F is not assigned */ - NULL, - NULL, - NULL - }, - { - /* PJ_STUN_ATTR_BANDWIDTH, */ - "BANDWIDTH", - &decode_uint_attr, - &encode_uint_attr - }, - { - /* ID 0x0011 is not assigned */ - NULL, - NULL, - NULL - }, - { - /* PJ_STUN_ATTR_REMOTE_ADDRESS, */ - "REMOTE-ADDRESS", - &decode_sockaddr_attr, - &encode_sockaddr_attr - }, - { - /* PJ_STUN_ATTR_DATA, */ - "DATA", - &decode_binary_attr, - &encode_binary_attr - }, - { - /* PJ_STUN_ATTR_REALM, */ - "REALM", - &decode_string_attr, - &encode_string_attr - }, - { - /* PJ_STUN_ATTR_NONCE, */ - "NONCE", - &decode_string_attr, - &encode_string_attr - }, - { - /* PJ_STUN_ATTR_RELAY_ADDRESS, */ - "RELAY-ADDRESS", - &decode_sockaddr_attr, - &encode_sockaddr_attr - }, - { - /* PJ_STUN_ATTR_REQUESTED_ADDR_TYPE, */ - "REQUESTED-ADDRESS-TYPE", - &decode_uint_attr, - &encode_uint_attr - }, - { - /* PJ_STUN_ATTR_REQUESTED_PORT_PROPS, */ - "REQUESTED-PORT-PROPS", - &decode_uint_attr, - &encode_uint_attr - }, - { - /* PJ_STUN_ATTR_REQUESTED_TRANSPORT, */ - "REQUESTED-TRANSPORT", - &decode_uint_attr, - &encode_uint_attr - }, - { - /* ID 0x001A is not assigned */ - NULL, - NULL, - NULL - }, - { - /* ID 0x001B is not assigned */ - NULL, - NULL, - NULL - }, - { - /* ID 0x001C is not assigned */ - NULL, - NULL, - NULL - }, - { - /* ID 0x001D is not assigned */ - NULL, - NULL, - NULL - }, - { - /* ID 0x001E is not assigned */ - NULL, - NULL, - NULL - }, - { - /* ID 0x001F is not assigned */ - NULL, - NULL, - NULL - }, - { - /* PJ_STUN_ATTR_XOR_MAPPED_ADDRESS, */ - "XOR-MAPPED-ADDRESS", - &decode_xored_sockaddr_attr, - &encode_sockaddr_attr - }, - { - /* PJ_STUN_ATTR_TIMER_VAL, */ - "TIMER-VAL", - &decode_uint_attr, - &encode_uint_attr - }, - { - /* PJ_STUN_ATTR_REQUESTED_IP, */ - "REQUESTED-IP", - &decode_sockaddr_attr, - &encode_sockaddr_attr - }, - { - /* PJ_STUN_ATTR_XOR_REFLECTED_FROM, */ - "XOR-REFLECTED-FROM", - &decode_xored_sockaddr_attr, - &encode_sockaddr_attr - }, - { - /* PJ_STUN_ATTR_PRIORITY, */ - "PRIORITY", - &decode_uint_attr, - &encode_uint_attr - }, - { - /* PJ_STUN_ATTR_USE_CANDIDATE, */ - "USE-CANDIDATE", - &decode_empty_attr, - &encode_empty_attr - }, - { - /* PJ_STUN_ATTR_XOR_INTERNAL_ADDR, */ - "XOR-INTERNAL-ADDRESS", - &decode_xored_sockaddr_attr, - &encode_sockaddr_attr - }, - - /* Sentinel */ - { - /* PJ_STUN_ATTR_END_MANDATORY_ATTR */ - NULL, - NULL, - NULL - } -}; - -static struct attr_desc extended_attr_desc[] = -{ - { - /* ID 0x8021 is not assigned */ - NULL, - NULL, - NULL - }, - { - /* PJ_STUN_ATTR_SERVER, */ - "SERVER", - &decode_string_attr, - &encode_string_attr - }, - { - /* PJ_STUN_ATTR_ALTERNATE_SERVER, */ - "ALTERNATE-SERVER", - &decode_sockaddr_attr, - &encode_sockaddr_attr - }, - { - /* PJ_STUN_ATTR_REFRESH_INTERVAL, */ - "REFRESH-INTERVAL", - &decode_uint_attr, - &encode_uint_attr - }, - { - /* ID 0x8025 is not assigned*/ - NULL, - NULL, - NULL - }, - { - /* PADDING, 0x8026 */ - NULL, - NULL, - NULL - }, - { - /* CACHE-TIMEOUT, 0x8027 */ - NULL, - NULL, - NULL - }, - { - /* PJ_STUN_ATTR_FINGERPRINT, */ - "FINGERPRINT", - &decode_uint_attr, - &encode_uint_attr - } -}; - - - -/* - * Get STUN message type name. - */ -PJ_DEF(const char*) pj_stun_get_method_name(unsigned msg_type) -{ - unsigned method = PJ_STUN_GET_METHOD(msg_type); - - if (method >= PJ_ARRAY_SIZE(stun_method_names)) - return "???"; - - return stun_method_names[method]; -} - - -/* - * Get STUN message class name. - */ -PJ_DEF(const char*) pj_stun_get_class_name(unsigned msg_type) -{ - if (PJ_STUN_IS_REQUEST(msg_type)) - return "request"; - else if (PJ_STUN_IS_RESPONSE(msg_type)) - return "success response"; - else if (PJ_STUN_IS_ERROR_RESPONSE(msg_type)) - return "error response"; - else if (PJ_STUN_IS_INDICATION(msg_type)) - return "indication"; - else - return "???"; -} - - -static const struct attr_desc *find_attr_desc(unsigned attr_type) -{ - struct attr_desc *desc; - - /* Check that attr_desc array is valid */ - pj_assert(PJ_ARRAY_SIZE(mandatory_attr_desc)== - PJ_STUN_ATTR_END_MANDATORY_ATTR+1); - pj_assert(mandatory_attr_desc[PJ_STUN_ATTR_END_MANDATORY_ATTR].decode_attr - == NULL); - pj_assert(mandatory_attr_desc[PJ_STUN_ATTR_USE_CANDIDATE].decode_attr - == &decode_empty_attr); - pj_assert(PJ_ARRAY_SIZE(extended_attr_desc) == - PJ_STUN_ATTR_END_EXTENDED_ATTR-PJ_STUN_ATTR_START_EXTENDED_ATTR); - - if (attr_type < PJ_STUN_ATTR_START_EXTENDED_ATTR) - desc = &mandatory_attr_desc[attr_type]; - else if (attr_type >= PJ_STUN_ATTR_START_EXTENDED_ATTR && - attr_type < PJ_STUN_ATTR_END_EXTENDED_ATTR) - desc = &extended_attr_desc[attr_type-PJ_STUN_ATTR_START_EXTENDED_ATTR]; - else - return NULL; - - return desc->decode_attr == NULL ? NULL : desc; -} - - -/* - * Get STUN attribute name. - */ -PJ_DEF(const char*) pj_stun_get_attr_name(unsigned attr_type) -{ - const struct attr_desc *attr_desc; - - attr_desc = find_attr_desc(attr_type); - if (!attr_desc || attr_desc->name==NULL) - return "???"; - - return attr_desc->name; -} - - -/** - * Get STUN standard reason phrase for the specified error code. - */ -PJ_DEF(pj_str_t) pj_stun_get_err_reason(int err_code) -{ - unsigned i; - - for (i=0; ihdr.type=(pj_uint16_t)(t), \ - (a)->hdr.length=(pj_uint16_t)(l) -#define ATTR_HDR_LEN 4 - -#define getval16(p, pos) (pj_uint16_t)(((p)[(pos)] << 8) | \ - ((p)[(pos) + 1] << 0)) - - -////////////////////////////////////////////////////////////////////////////// -/* - * STUN generic IP address container - */ -#define STUN_GENERIC_IP_ADDR_LEN 8 - -/* - * Create a generic STUN IP address attribute for IPv4 address. - */ -PJ_DEF(pj_status_t) -pj_stun_sockaddr_attr_create(pj_pool_t *pool, - int attr_type, - pj_bool_t xor_ed, - const pj_sockaddr_t *addr, - unsigned addr_len, - pj_stun_sockaddr_attr **p_attr) -{ - pj_stun_sockaddr_attr *attr; - - PJ_ASSERT_RETURN(pool && addr_len && addr && p_attr, PJ_EINVAL); - PJ_ASSERT_RETURN(addr_len == sizeof(pj_sockaddr_in) || - addr_len == sizeof(pj_sockaddr_in6), PJ_EINVAL); - - attr = PJ_POOL_ZALLOC_T(pool, pj_stun_sockaddr_attr); - INIT_ATTR(attr, attr_type, STUN_GENERIC_IP_ADDR_LEN); - - pj_memcpy(&attr->addr, addr, addr_len); - attr->xor_ed = xor_ed; - - *p_attr = attr; - - return PJ_SUCCESS; -} - - -/* - * Create and add generic STUN IP address attribute to a STUN message. - */ -PJ_DEF(pj_status_t) -pj_stun_msg_add_sockaddr_attr(pj_pool_t *pool, - pj_stun_msg *msg, - int attr_type, - pj_bool_t xor_ed, - const pj_sockaddr_t *addr, - unsigned addr_len) -{ - pj_stun_sockaddr_attr *attr; - pj_status_t status; - - status = pj_stun_sockaddr_attr_create(pool, attr_type, xor_ed, - addr, addr_len, &attr); - if (status != PJ_SUCCESS) - return status; - - return pj_stun_msg_add_attr(msg, &attr->hdr); -} - -static pj_status_t decode_sockaddr_attr(pj_pool_t *pool, - const pj_uint8_t *buf, - void **p_attr) -{ - pj_stun_sockaddr_attr *attr; - pj_uint32_t val; - - /* Create the attribute */ - attr = PJ_POOL_ZALLOC_T(pool, pj_stun_sockaddr_attr); - pj_memcpy(attr, buf, ATTR_HDR_LEN); - - /* Convert to host byte order */ - attr->hdr.type = pj_ntohs(attr->hdr.type); - attr->hdr.length = pj_ntohs(attr->hdr.length); - - /* Check that the attribute length is valid */ - if (attr->hdr.length != STUN_GENERIC_IP_ADDR_LEN) - return PJLIB_UTIL_ESTUNINATTRLEN; - - /* Check address family */ - val = *(pj_uint8_t*)(buf + ATTR_HDR_LEN + 1); - - /* Check address family is valid (only supports ipv4 for now) */ - if (val != 1) - return PJLIB_UTIL_ESTUNIPV6NOTSUPP; - - /* Get port and address */ - pj_sockaddr_in_init(&attr->addr.ipv4, NULL, 0); - pj_memcpy(&attr->addr.ipv4.sin_port, buf+ATTR_HDR_LEN+2, 2); - pj_memcpy(&attr->addr.ipv4.sin_addr, buf+ATTR_HDR_LEN+4, 4); - - /* Done */ - *p_attr = attr; - - return PJ_SUCCESS; -} - - -static pj_status_t decode_xored_sockaddr_attr(pj_pool_t *pool, - const pj_uint8_t *buf, - void **p_attr) -{ - pj_stun_sockaddr_attr *attr; - pj_uint32_t val; - - /* Create the attribute */ - attr = PJ_POOL_ZALLOC_T(pool, pj_stun_sockaddr_attr); - pj_memcpy(attr, buf, ATTR_HDR_LEN); - - /* Convert to host byte order */ - attr->hdr.type = pj_ntohs(attr->hdr.type); - attr->hdr.length = pj_ntohs(attr->hdr.length); - - /* Check that the attribute length is valid */ - if (attr->hdr.length != STUN_GENERIC_IP_ADDR_LEN) - return PJLIB_UTIL_ESTUNINATTRLEN; - - /* Check address family */ - val = *(pj_uint8_t*)(buf + ATTR_HDR_LEN + 1); - - /* Check address family is valid (only supports ipv4 for now) */ - if (val != 1) - return PJLIB_UTIL_ESTUNIPV6NOTSUPP; - - /* Get port and address */ - pj_sockaddr_in_init(&attr->addr.ipv4, NULL, 0); - pj_memcpy(&attr->addr.ipv4.sin_port, buf+ATTR_HDR_LEN+2, 2); - pj_memcpy(&attr->addr.ipv4.sin_addr, buf+ATTR_HDR_LEN+4, 4); - - attr->addr.ipv4.sin_port ^= 0x2112; - attr->addr.ipv4.sin_addr.s_addr ^= pj_htonl(0x2112A442); - - /* Done */ - *p_attr = attr; - - return PJ_SUCCESS; -} - - -static pj_status_t encode_sockaddr_attr(const void *a, pj_uint8_t *buf, - unsigned len, unsigned *printed) -{ - enum { - ATTR_LEN = ATTR_HDR_LEN + STUN_GENERIC_IP_ADDR_LEN - }; - pj_uint8_t *start_buf = buf; - const pj_stun_sockaddr_attr *ca = - (const pj_stun_sockaddr_attr *)a; - pj_stun_sockaddr_attr *attr; - - if (len < ATTR_LEN) - return PJ_ETOOSMALL; - - /* Copy and convert headers to network byte order */ - pj_memcpy(buf, a, ATTR_HDR_LEN); - attr = (pj_stun_sockaddr_attr*) buf; - attr->hdr.type = pj_htons(attr->hdr.type); - attr->hdr.length = pj_htons((pj_uint16_t)STUN_GENERIC_IP_ADDR_LEN); - buf += ATTR_HDR_LEN; - - /* Ignored */ - *buf++ = '\0'; - - /* Family (IPv4 only for now) */ - PJ_ASSERT_RETURN(ca->addr.addr.sa_family == PJ_AF_INET, PJ_EINVAL); - *buf++ = 1; - - if (ca->xor_ed) { - pj_uint32_t addr; - pj_uint16_t port; - - addr = ca->addr.ipv4.sin_addr.s_addr; - port = ca->addr.ipv4.sin_port; - - port ^= 0x2112; - addr ^= pj_htonl(0x2112A442); - - /* Port */ - pj_memcpy(buf, &port, 2); - buf += 2; - - /* Address */ - pj_memcpy(buf, &addr, 4); - buf += 4; - - } else { - /* Port */ - pj_memcpy(buf, &ca->addr.ipv4.sin_port, 2); - buf += 2; - - /* Address */ - pj_memcpy(buf, &ca->addr.ipv4.sin_addr, 4); - buf += 4; - } - - pj_assert(buf - start_buf == ATTR_LEN); - - /* Done */ - *printed = buf - start_buf; - - return PJ_SUCCESS; -} - - -////////////////////////////////////////////////////////////////////////////// -/* - * STUN generic string attribute - */ - -/* - * Create a STUN generic string attribute. - */ -PJ_DEF(pj_status_t) -pj_stun_string_attr_create(pj_pool_t *pool, - int attr_type, - const pj_str_t *value, - pj_stun_string_attr **p_attr) -{ - pj_stun_string_attr *attr; - - PJ_ASSERT_RETURN(pool && value && p_attr, PJ_EINVAL); - - attr = PJ_POOL_ZALLOC_T(pool, pj_stun_string_attr); - INIT_ATTR(attr, attr_type, value->slen); - pj_strdup(pool, &attr->value, value); - - *p_attr = attr; - - return PJ_SUCCESS; -} - - -/* - * Create and add STUN generic string attribute to the message. - */ -PJ_DEF(pj_status_t) -pj_stun_msg_add_string_attr(pj_pool_t *pool, - pj_stun_msg *msg, - int attr_type, - const pj_str_t *value) -{ - pj_stun_string_attr *attr = NULL; - pj_status_t status; - - status = pj_stun_string_attr_create(pool, attr_type, value, - &attr); - if (status != PJ_SUCCESS) - return status; - - return pj_stun_msg_add_attr(msg, &attr->hdr); -} - - -static pj_status_t decode_string_attr(pj_pool_t *pool, - const pj_uint8_t *buf, - void **p_attr) -{ - pj_stun_string_attr *attr; - pj_str_t value; - - /* Create the attribute */ - attr = PJ_POOL_ZALLOC_T(pool, pj_stun_string_attr); - - /* Copy the header */ - pj_memcpy(attr, buf, ATTR_HDR_LEN); - - /* Convert to host byte order */ - attr->hdr.type = pj_ntohs(attr->hdr.type); - attr->hdr.length = pj_ntohs(attr->hdr.length); - - /* Get pointer to the string in the message */ - value.ptr = ((char*)buf + ATTR_HDR_LEN); - value.slen = attr->hdr.length; - - /* Copy the string to the attribute */ - pj_strdup(pool, &attr->value, &value); - - /* Done */ - *p_attr = attr; - - return PJ_SUCCESS; - -} - - -static pj_status_t encode_string_attr(const void *a, pj_uint8_t *buf, - unsigned len, unsigned *printed) -{ - const pj_stun_string_attr *ca = - (const pj_stun_string_attr*)a; - pj_stun_attr_hdr *attr; - - /* Calculated total attr_len (add padding if necessary) */ - *printed = (ca->value.slen + ATTR_HDR_LEN + 3) & (~3); - if (len < *printed) { - *printed = 0; - return PJ_ETOOSMALL; - } - - /* Copy header */ - pj_memcpy(buf, a, ATTR_HDR_LEN); - attr = (pj_stun_attr_hdr*)buf; - - /* Set the correct length */ - attr->length = (pj_uint16_t) ca->value.slen; - - /* Convert to network byte order */ - attr->type = pj_htons(attr->type); - attr->length = pj_htons(attr->length); - - /* Copy the string */ - pj_memcpy(buf+ATTR_HDR_LEN, ca->value.ptr, ca->value.slen); - - /* Done */ - return PJ_SUCCESS; -} - - -////////////////////////////////////////////////////////////////////////////// -/* - * STUN empty attribute (used by USE-CANDIDATE). - */ - -/* - * Create a STUN empty attribute. - */ -PJ_DEF(pj_status_t) -pj_stun_empty_attr_create(pj_pool_t *pool, - int attr_type, - pj_stun_empty_attr **p_attr) -{ - pj_stun_empty_attr *attr; - - PJ_ASSERT_RETURN(pool && p_attr, PJ_EINVAL); - - attr = PJ_POOL_ZALLOC_T(pool, pj_stun_empty_attr); - INIT_ATTR(attr, attr_type, sizeof(pj_stun_empty_attr)); - - *p_attr = attr; - - return PJ_SUCCESS; -} - - -static pj_status_t decode_empty_attr(pj_pool_t *pool, - const pj_uint8_t *buf, - void **p_attr) -{ - pj_stun_empty_attr *attr; - - /* Check that the struct address is valid */ - pj_assert(sizeof(pj_stun_empty_attr) == ATTR_HDR_LEN); - - /* Create the attribute */ - attr = PJ_POOL_ZALLOC_T(pool, pj_stun_empty_attr); - pj_memcpy(attr, buf, ATTR_HDR_LEN); - - /* Convert to host byte order */ - attr->hdr.type = pj_ntohs(attr->hdr.type); - attr->hdr.length = pj_ntohs(attr->hdr.length); - - /* Check that the attribute length is valid */ - if (attr->hdr.length != ATTR_HDR_LEN) - return PJLIB_UTIL_ESTUNINATTRLEN; - - /* Done */ - *p_attr = attr; - - return PJ_SUCCESS; -} - - -static pj_status_t encode_empty_attr(const void *a, pj_uint8_t *buf, - unsigned len, unsigned *printed) -{ - pj_stun_empty_attr *attr; - - if (len < ATTR_HDR_LEN) - return PJ_ETOOSMALL; - - /* Copy and convert attribute to network byte order */ - pj_memcpy(buf, a, ATTR_HDR_LEN); - attr = (pj_stun_empty_attr*) buf; - attr->hdr.type = pj_htons(attr->hdr.type); - pj_assert(attr->hdr.length == ATTR_HDR_LEN); - attr->hdr.length = pj_htons(ATTR_HDR_LEN); - - /* Done */ - *printed = ATTR_HDR_LEN; - - return PJ_SUCCESS; -} - - -////////////////////////////////////////////////////////////////////////////// -/* - * STUN generic 32bit integer attribute. - */ -#define STUN_UINT_LEN 4 - -/* - * Create a STUN generic 32bit value attribute. - */ -PJ_DEF(pj_status_t) -pj_stun_uint_attr_create(pj_pool_t *pool, - int attr_type, - pj_uint32_t value, - pj_stun_uint_attr **p_attr) -{ - pj_stun_uint_attr *attr; - - PJ_ASSERT_RETURN(pool && p_attr, PJ_EINVAL); - - attr = PJ_POOL_ZALLOC_T(pool, pj_stun_uint_attr); - INIT_ATTR(attr, attr_type, STUN_UINT_LEN); - attr->value = value; - - *p_attr = attr; - - return PJ_SUCCESS; -} - -/* Create and add STUN generic 32bit value attribute to the message. */ -PJ_DEF(pj_status_t) -pj_stun_msg_add_uint_attr(pj_pool_t *pool, - pj_stun_msg *msg, - int attr_type, - pj_uint32_t value) -{ - pj_stun_uint_attr *attr = NULL; - pj_status_t status; - - status = pj_stun_uint_attr_create(pool, attr_type, value, &attr); - if (status != PJ_SUCCESS) - return status; - - return pj_stun_msg_add_attr(msg, &attr->hdr); -} - -static pj_status_t decode_uint_attr(pj_pool_t *pool, - const pj_uint8_t *buf, - void **p_attr) -{ - enum - { - ATTR_LEN = STUN_UINT_LEN + ATTR_HDR_LEN - }; - pj_stun_uint_attr *attr; - - /* Check that the struct address is valid */ - pj_assert(sizeof(pj_stun_uint_attr) == ATTR_LEN); - - /* Create the attribute */ - attr = PJ_POOL_ZALLOC_T(pool, pj_stun_uint_attr); - pj_memcpy(attr, buf, ATTR_LEN); - - /* Convert to host byte order */ - attr->hdr.type = pj_ntohs(attr->hdr.type); - attr->hdr.length = pj_ntohs(attr->hdr.length); - attr->value = pj_ntohl(attr->value); - - /* Check that the attribute length is valid */ - if (attr->hdr.length != STUN_UINT_LEN) - return PJLIB_UTIL_ESTUNINATTRLEN; - - /* Done */ - *p_attr = attr; - - return PJ_SUCCESS; -} - - -static pj_status_t encode_uint_attr(const void *a, pj_uint8_t *buf, - unsigned len, unsigned *printed) -{ - enum - { - ATTR_LEN = STUN_UINT_LEN + ATTR_HDR_LEN - }; - pj_stun_uint_attr *attr; - - if (len < ATTR_LEN) - return PJ_ETOOSMALL; - - /* Copy and convert attribute to network byte order */ - pj_memcpy(buf, a, ATTR_LEN); - attr = (pj_stun_uint_attr*) buf; - attr->hdr.type = pj_htons(attr->hdr.type); - pj_assert(attr->hdr.length == STUN_UINT_LEN); - attr->hdr.length = pj_htons(STUN_UINT_LEN); - attr->value = pj_htonl(attr->value); - - /* Done */ - *printed = ATTR_LEN; - - return PJ_SUCCESS; -} - -////////////////////////////////////////////////////////////////////////////// -/* - * STUN MESSAGE-INTEGRITY attribute. - */ - -#define STUN_MSG_INTEGRITY_LEN 20 - -/* - * Create a STUN MESSAGE-INTEGRITY attribute. - */ -PJ_DEF(pj_status_t) -pj_stun_msgint_attr_create(pj_pool_t *pool, - pj_stun_msgint_attr **p_attr) -{ - pj_stun_msgint_attr *attr; - - PJ_ASSERT_RETURN(pool && p_attr, PJ_EINVAL); - - attr = PJ_POOL_ZALLOC_T(pool, pj_stun_msgint_attr); - INIT_ATTR(attr, PJ_STUN_ATTR_MESSAGE_INTEGRITY, STUN_MSG_INTEGRITY_LEN); - - *p_attr = attr; - - return PJ_SUCCESS; -} - - -PJ_DEF(pj_status_t) pj_stun_msg_add_msgint_attr(pj_pool_t *pool, - pj_stun_msg *msg) -{ - pj_stun_msgint_attr *attr = NULL; - pj_status_t status; - - status = pj_stun_msgint_attr_create(pool, &attr); - if (status != PJ_SUCCESS) - return status; - - return pj_stun_msg_add_attr(msg, &attr->hdr); -} - -static pj_status_t decode_msgint_attr(pj_pool_t *pool, - const pj_uint8_t *buf, - void **p_attr) -{ - enum - { - ATTR_LEN = STUN_MSG_INTEGRITY_LEN + ATTR_HDR_LEN - }; - pj_stun_msgint_attr *attr; - - /* Check that struct size is valid */ - pj_assert(sizeof(pj_stun_msgint_attr)==ATTR_LEN); - - /* Create attribute */ - attr = PJ_POOL_ZALLOC_T(pool, pj_stun_msgint_attr); - pj_memcpy(attr, buf, sizeof(pj_stun_msgint_attr)); - attr->hdr.type = pj_ntohs(attr->hdr.type); - attr->hdr.length = pj_ntohs(attr->hdr.length); - - /* Check that the attribute length is valid */ - if (attr->hdr.length != STUN_MSG_INTEGRITY_LEN) - return PJLIB_UTIL_ESTUNINATTRLEN; - - /* Done */ - *p_attr = attr; - return PJ_SUCCESS; -} - - -static pj_status_t encode_msgint_attr(const void *a, pj_uint8_t *buf, - unsigned len, unsigned *printed) -{ - enum - { - ATTR_LEN = STUN_MSG_INTEGRITY_LEN + ATTR_HDR_LEN - }; - pj_stun_msgint_attr *attr; - - if (len < ATTR_LEN) - return PJ_ETOOSMALL; - - /* Copy and convert attribute to network byte order */ - pj_memcpy(buf, a, ATTR_LEN); - attr = (pj_stun_msgint_attr*) buf; - attr->hdr.type = pj_htons(attr->hdr.type); - pj_assert(attr->hdr.length == STUN_MSG_INTEGRITY_LEN); - attr->hdr.length = pj_htons(STUN_MSG_INTEGRITY_LEN); - - /* Done */ - *printed = ATTR_LEN; - - return PJ_SUCCESS; -} - -////////////////////////////////////////////////////////////////////////////// -/* - * STUN ERROR-CODE - */ - -/* - * Create a STUN ERROR-CODE attribute. - */ -PJ_DEF(pj_status_t) -pj_stun_errcode_attr_create(pj_pool_t *pool, - int err_code, - const pj_str_t *err_reason, - pj_stun_errcode_attr **p_attr) -{ - pj_stun_errcode_attr *attr; - char err_buf[80]; - pj_str_t str; - - PJ_ASSERT_RETURN(pool && err_code && p_attr, PJ_EINVAL); - - if (err_reason == NULL) { - str = pj_stun_get_err_reason(err_code); - if (str.slen == 0) { - str.slen = pj_ansi_snprintf(err_buf, sizeof(err_buf), - "Unknown error %d", err_code); - str.ptr = err_buf; - } - err_reason = &str; - } - - attr = PJ_POOL_ZALLOC_T(pool, pj_stun_errcode_attr); - INIT_ATTR(attr, PJ_STUN_ATTR_ERROR_CODE, 4+err_reason->slen); - attr->err_class = (pj_uint8_t)(err_code / 100); - attr->number = (pj_uint8_t) (err_code % 100); - pj_strdup(pool, &attr->reason, err_reason); - - *p_attr = attr; - - return PJ_SUCCESS; -} - - -PJ_DEF(pj_status_t) pj_stun_msg_add_errcode_attr(pj_pool_t *pool, - pj_stun_msg *msg, - int err_code, - const pj_str_t *err_reason) -{ - pj_stun_errcode_attr *err_attr = NULL; - pj_status_t status; - - status = pj_stun_errcode_attr_create(pool, err_code, err_reason, - &err_attr); - if (status != PJ_SUCCESS) - return status; - - return pj_stun_msg_add_attr(msg, &err_attr->hdr); -} - -static pj_status_t decode_errcode_attr(pj_pool_t *pool, - const pj_uint8_t *buf, - void **p_attr) -{ - pj_stun_errcode_attr *attr; - pj_str_t value; - - /* Create the attribute */ - attr = PJ_POOL_ZALLOC_T(pool, pj_stun_errcode_attr); - - /* Copy the header */ - pj_memcpy(attr, buf, ATTR_HDR_LEN + 4); - - /* Convert to host byte order */ - attr->hdr.type = pj_ntohs(attr->hdr.type); - attr->hdr.length = pj_ntohs(attr->hdr.length); - - /* Get pointer to the string in the message */ - value.ptr = ((char*)buf + ATTR_HDR_LEN + 4); - value.slen = attr->hdr.length - 4; - - /* Copy the string to the attribute */ - pj_strdup(pool, &attr->reason, &value); - - /* Done */ - *p_attr = attr; - - return PJ_SUCCESS; -} - - -static pj_status_t encode_errcode_attr(const void *a, pj_uint8_t *buf, - unsigned len, unsigned *printed) -{ - const pj_stun_errcode_attr *ca = - (const pj_stun_errcode_attr*)a; - pj_stun_errcode_attr *attr; - - if (len < ATTR_HDR_LEN + 4 + (unsigned)ca->reason.slen) - return PJ_ETOOSMALL; - - /* Copy and convert attribute to network byte order */ - pj_memcpy(buf, ca, ATTR_HDR_LEN + 4); - - /* Update length */ - attr = (pj_stun_errcode_attr*) buf; - attr->hdr.length = (pj_uint16_t)(4 + ca->reason.slen); - - /* Convert fiends to network byte order */ - attr->hdr.type = pj_htons(attr->hdr.type); - attr->hdr.length = pj_htons(attr->hdr.length); - - /* Copy error string */ - pj_memcpy(buf + ATTR_HDR_LEN + 4, ca->reason.ptr, ca->reason.slen); - - /* Done */ - *printed = (ATTR_HDR_LEN + 4 + ca->reason.slen + 3) & (~3); - - return PJ_SUCCESS; -} - -////////////////////////////////////////////////////////////////////////////// -/* - * STUN UNKNOWN-ATTRIBUTES attribute - */ - -/* - * Create an empty instance of STUN UNKNOWN-ATTRIBUTES attribute. - * - * @param pool The pool to allocate memory from. - * @param p_attr Pointer to receive the attribute. - * - * @return PJ_SUCCESS on success or the appropriate error code. - */ -PJ_DEF(pj_status_t) -pj_stun_unknown_attr_create(pj_pool_t *pool, - unsigned attr_cnt, - const pj_uint16_t attr_array[], - pj_stun_unknown_attr **p_attr) -{ - pj_stun_unknown_attr *attr; - unsigned i; - - PJ_ASSERT_RETURN(pool && attr_cnt < PJ_STUN_MAX_ATTR && p_attr, PJ_EINVAL); - - attr = PJ_POOL_ZALLOC_T(pool, pj_stun_unknown_attr); - INIT_ATTR(attr, PJ_STUN_ATTR_UNKNOWN_ATTRIBUTES, attr_cnt * 2); - - attr->attr_count = attr_cnt; - for (i=0; iattrs[i] = attr_array[i]; - } - - /* If the number of unknown attributes is an odd number, one of the - * attributes MUST be repeated in the list. - */ - if ((attr_cnt & 0x01)) { - attr->attrs[attr_cnt] = attr_array[attr_cnt-1]; - } - - *p_attr = NULL; - - return PJ_SUCCESS; -} - - -/* Create and add STUN UNKNOWN-ATTRIBUTES attribute to the message. */ -PJ_DEF(pj_status_t) -pj_stun_msg_add_unknown_attr(pj_pool_t *pool, - pj_stun_msg *msg, - unsigned attr_cnt, - const pj_uint16_t attr_types[]) -{ - pj_stun_unknown_attr *attr = NULL; - pj_status_t status; - - status = pj_stun_unknown_attr_create(pool, attr_cnt, attr_types, &attr); - if (status != PJ_SUCCESS) - return status; - - return pj_stun_msg_add_attr(msg, &attr->hdr); -} - -static pj_status_t decode_unknown_attr(pj_pool_t *pool, - const pj_uint8_t *buf, - void **p_attr) -{ - pj_stun_unknown_attr *attr; - const pj_uint16_t *punk_attr; - unsigned i; - - attr = PJ_POOL_ZALLOC_T(pool, pj_stun_unknown_attr); - pj_memcpy(attr, buf, ATTR_HDR_LEN); - - attr->hdr.type = pj_ntohs(attr->hdr.type); - attr->hdr.length = pj_ntohs(attr->hdr.length); - - attr->attr_count = (attr->hdr.length >> 1); - if (attr->attr_count > PJ_STUN_MAX_ATTR) - return PJ_ETOOMANY; - - punk_attr = (const pj_uint16_t*)(buf + ATTR_HDR_LEN); - for (i=0; iattr_count; ++i) { - attr->attrs[i] = pj_ntohs(punk_attr[i]); - } - - /* Done */ - *p_attr = attr; - - return PJ_SUCCESS; -} - - -static pj_status_t encode_unknown_attr(const void *a, pj_uint8_t *buf, - unsigned len, unsigned *printed) -{ - const pj_stun_unknown_attr *ca = (const pj_stun_unknown_attr*) a; - pj_stun_unknown_attr *attr; - pj_uint16_t *dst_unk_attr; - unsigned i; - - /* Check that buffer is enough */ - if (len < ATTR_HDR_LEN + (ca->attr_count << 1)) - return PJ_ETOOSMALL; - - /* Copy to message */ - pj_memcpy(buf, ca, ATTR_HDR_LEN); - - /* Set the correct length */ - attr = (pj_stun_unknown_attr *) buf; - attr->hdr.length = (pj_uint16_t)(ca->attr_count << 1); - - /* Convert to network byte order */ - attr->hdr.type = pj_htons(attr->hdr.type); - attr->hdr.length = pj_htons(attr->hdr.length); - - /* Copy individual attribute */ - dst_unk_attr = (pj_uint16_t*)(buf + ATTR_HDR_LEN); - for (i=0; i < ca->attr_count; ++i, ++dst_unk_attr) { - *dst_unk_attr = pj_htons(attr->attrs[i]); - } - - /* Done */ - *printed = (ATTR_HDR_LEN + (ca->attr_count << 1) + 3) & (~3); - - return PJ_SUCCESS; -} - - -////////////////////////////////////////////////////////////////////////////// -/* - * STUN generic binary attribute - */ - -/* - * Create a blank binary attribute. - */ -PJ_DEF(pj_status_t) -pj_stun_binary_attr_create(pj_pool_t *pool, - int attr_type, - const pj_uint8_t *data, - unsigned length, - pj_stun_binary_attr **p_attr) -{ - pj_stun_binary_attr *attr; - - PJ_ASSERT_RETURN(pool && attr_type && p_attr, PJ_EINVAL); - - attr = PJ_POOL_ZALLOC_T(pool, pj_stun_binary_attr); - INIT_ATTR(attr, attr_type, sizeof(pj_stun_binary_attr)); - - if (data && length) { - attr->length = length; - attr->data = pj_pool_alloc(pool, length); - pj_memcpy(attr->data, data, length); - } - - *p_attr = attr; - - return PJ_SUCCESS; -} - - -/* Create and add binary attr. */ -PJ_DEF(pj_status_t) -pj_stun_msg_add_binary_attr(pj_pool_t *pool, - pj_stun_msg *msg, - int attr_type, - const pj_uint8_t *data, - unsigned length) -{ - pj_stun_binary_attr *attr = NULL; - pj_status_t status; - - status = pj_stun_binary_attr_create(pool, attr_type, - data, length, &attr); - if (status != PJ_SUCCESS) - return status; - - return pj_stun_msg_add_attr(msg, &attr->hdr); -} - - -static pj_status_t decode_binary_attr(pj_pool_t *pool, - const pj_uint8_t *buf, - void **p_attr) -{ - pj_stun_binary_attr *attr; - - /* Create the attribute */ - attr = PJ_POOL_ZALLOC_T(pool, pj_stun_binary_attr); - - /* Copy the header */ - pj_memcpy(attr, buf, ATTR_HDR_LEN); - - /* Convert to host byte order */ - attr->hdr.type = pj_ntohs(attr->hdr.type); - attr->hdr.length = pj_ntohs(attr->hdr.length); - - /* Copy the data to the attribute */ - attr->length = attr->hdr.length; - attr->data = pj_pool_alloc(pool, attr->length); - pj_memcpy(attr->data, buf+ATTR_HDR_LEN, attr->length); - - /* Done */ - *p_attr = attr; - - return PJ_SUCCESS; - -} - - -static pj_status_t encode_binary_attr(const void *a, pj_uint8_t *buf, - unsigned len, unsigned *printed) -{ - const pj_stun_binary_attr *ca = (const pj_stun_binary_attr*)a; - pj_stun_attr_hdr *attr; - - /* Calculated total attr_len (add padding if necessary) */ - *printed = (ca->length + ATTR_HDR_LEN + 3) & (~3); - if (len < *printed) - return PJ_ETOOSMALL; - - /* Copy header */ - pj_memcpy(buf, a, ATTR_HDR_LEN); - - /* Set the correct length */ - attr = (pj_stun_attr_hdr*)buf; - attr->length = (pj_uint16_t) ca->length; - - /* Convert to network byte order */ - attr->type = pj_htons(attr->type); - attr->length = pj_htons(attr->length); - - /* Copy the data */ - pj_memcpy(buf+ATTR_HDR_LEN, ca->data, ca->length); - - /* Done */ - return PJ_SUCCESS; -} - - -////////////////////////////////////////////////////////////////////////////// - -/* - * Create a blank STUN message. - */ -PJ_DEF(pj_status_t) pj_stun_msg_create( pj_pool_t *pool, - unsigned msg_type, - pj_uint32_t magic, - const pj_uint8_t tsx_id[12], - pj_stun_msg **p_msg) -{ - pj_stun_msg *msg; - - PJ_ASSERT_RETURN(pool && msg_type && p_msg, PJ_EINVAL); - - msg = PJ_POOL_ZALLOC_T(pool, pj_stun_msg); - msg->hdr.type = (pj_uint16_t) msg_type; - msg->hdr.magic = magic; - - if (tsx_id) { - pj_memcpy(&msg->hdr.tsx_id, tsx_id, sizeof(msg->hdr.tsx_id)); - } else { - struct transaction_id - { - pj_uint32_t proc_id; - pj_uint32_t random; - pj_uint32_t counter; - } id; - static pj_uint32_t pj_stun_tsx_id_counter; - - id.proc_id = pj_getpid(); - id.random = pj_rand(); - id.counter = pj_stun_tsx_id_counter++; - - pj_memcpy(&msg->hdr.tsx_id, &id, sizeof(msg->hdr.tsx_id)); - } - - *p_msg = msg; - - return PJ_SUCCESS; -} - - -/* - * Add STUN attribute to STUN message. - */ -PJ_DEF(pj_status_t) pj_stun_msg_add_attr(pj_stun_msg *msg, - pj_stun_attr_hdr *attr) -{ - PJ_ASSERT_RETURN(msg && attr, PJ_EINVAL); - PJ_ASSERT_RETURN(msg->attr_count < PJ_STUN_MAX_ATTR, PJ_ETOOMANY); - - msg->attr[msg->attr_count++] = attr; - return PJ_SUCCESS; -} - - -PJ_INLINE(pj_uint16_t) GET_VAL16(const pj_uint8_t *pdu, unsigned pos) -{ - return (pj_uint16_t) ((pdu[pos] << 8) + pdu[pos+1]); -} - -PJ_INLINE(pj_uint32_t) GET_VAL32(const pj_uint8_t *pdu, unsigned pos) -{ - return (pdu[pos+0] << 24) + - (pdu[pos+1] << 16) + - (pdu[pos+2] << 8) + - (pdu[pos+3]); -} - - -/* - * Check that the PDU is potentially a valid STUN message. - */ -PJ_DEF(pj_status_t) pj_stun_msg_check(const pj_uint8_t *pdu, unsigned pdu_len, - unsigned options) -{ - unsigned msg_len; - - PJ_ASSERT_RETURN(pdu, PJ_EINVAL); - - if (pdu_len < sizeof(pj_stun_msg_hdr)) - return PJLIB_UTIL_ESTUNINMSGLEN; - - /* First byte of STUN message is always 0x00 or 0x01. */ - if (*pdu != 0x00 && *pdu != 0x01) - return PJLIB_UTIL_ESTUNINMSGTYPE; - - /* Check the PDU length */ - msg_len = GET_VAL16(pdu, 2); - if ((msg_len + 20 > pdu_len) || - ((options & PJ_STUN_IS_DATAGRAM) && msg_len + 20 != pdu_len)) - { - return PJLIB_UTIL_ESTUNINMSGLEN; - } - - /* If magic is set, then there is great possibility that this is - * a STUN message. - */ - if (GET_VAL32(pdu, 4) == PJ_STUN_MAGIC) { - - /* Check if FINGERPRINT attribute is present */ - if (GET_VAL16(pdu, msg_len + 20) == PJ_STUN_ATTR_FINGERPRINT) { - pj_uint16_t attr_len = GET_VAL16(pdu, msg_len + 22); - pj_uint32_t fingerprint = GET_VAL32(pdu, msg_len + 24); - pj_uint32_t crc; - - if (attr_len != 4) - return PJLIB_UTIL_ESTUNINATTRLEN; - - crc = pj_crc32_calc(pdu, msg_len + 20); - crc ^= STUN_XOR_FINGERPRINT; - - if (crc != fingerprint) - return PJLIB_UTIL_ESTUNFINGERPRINT; - } - } - - /* Could be a STUN message */ - return PJ_SUCCESS; -} - - -/* Create error response */ -PJ_DEF(pj_status_t) pj_stun_msg_create_response(pj_pool_t *pool, - const pj_stun_msg *req_msg, - unsigned err_code, - const pj_str_t *err_msg, - pj_stun_msg **p_response) -{ - unsigned msg_type = req_msg->hdr.type; - pj_stun_msg *response = NULL; - pj_status_t status; - - PJ_ASSERT_RETURN(pool && p_response, PJ_EINVAL); - - PJ_ASSERT_RETURN(PJ_STUN_IS_REQUEST(msg_type), - PJLIB_UTIL_ESTUNINMSGTYPE); - - /* Create response or error response */ - if (err_code) - msg_type |= PJ_STUN_ERROR_RESPONSE_BIT; - else - msg_type |= PJ_STUN_RESPONSE_BIT; - - status = pj_stun_msg_create(pool, msg_type, req_msg->hdr.magic, - req_msg->hdr.tsx_id, &response); - if (status != PJ_SUCCESS) { - return status; - } - - /* Add error code attribute */ - if (err_code) { - status = pj_stun_msg_add_errcode_attr(pool, response, - err_code, err_msg); - if (status != PJ_SUCCESS) { - return status; - } - } - - *p_response = response; - return PJ_SUCCESS; -} - - -/* - * Parse incoming packet into STUN message. - */ -PJ_DEF(pj_status_t) pj_stun_msg_decode(pj_pool_t *pool, - const pj_uint8_t *pdu, - unsigned pdu_len, - unsigned options, - pj_stun_msg **p_msg, - unsigned *p_parsed_len, - pj_stun_msg **p_response) -{ - - pj_stun_msg *msg; - unsigned uattr_cnt; - const pj_uint8_t *start_pdu = pdu; - pj_bool_t has_msg_int = PJ_FALSE; - pj_bool_t has_fingerprint = PJ_FALSE; - pj_status_t status; - - PJ_UNUSED_ARG(options); - - PJ_ASSERT_RETURN(pool && pdu && pdu_len && p_msg, PJ_EINVAL); - PJ_ASSERT_RETURN(sizeof(pj_stun_msg_hdr) == 20, PJ_EBUG); - - if (p_parsed_len) - *p_parsed_len = 0; - if (p_response) - *p_response = NULL; - - /* Check if this is a STUN message, if necessary */ - if (options & PJ_STUN_CHECK_PACKET) { - status = pj_stun_msg_check(pdu, pdu_len, options); - if (status != PJ_SUCCESS) - return status; - } - - /* Create the message, copy the header, and convert to host byte order */ - msg = PJ_POOL_ZALLOC_T(pool, pj_stun_msg); - pj_memcpy(&msg->hdr, pdu, sizeof(pj_stun_msg_hdr)); - msg->hdr.type = pj_ntohs(msg->hdr.type); - msg->hdr.length = pj_ntohs(msg->hdr.length); - msg->hdr.magic = pj_ntohl(msg->hdr.magic); - - pdu += sizeof(pj_stun_msg_hdr); - /* pdu_len -= sizeof(pj_stun_msg_hdr); */ - pdu_len = msg->hdr.length; - - /* No need to create response if this is not a request */ - if (!PJ_STUN_IS_REQUEST(msg->hdr.type)) - p_response = NULL; - - /* Parse attributes */ - uattr_cnt = 0; - while (pdu_len > 0) { - unsigned attr_type, attr_val_len; - const struct attr_desc *adesc; - - /* Get attribute type and length. If length is not aligned - * to 4 bytes boundary, add padding. - */ - attr_type = pj_ntohs(*(pj_uint16_t*)pdu); - attr_val_len = pj_ntohs(*(pj_uint16_t*)(pdu+2)); - attr_val_len = (attr_val_len + 3) & (~3); - - /* Check length */ - if (pdu_len < attr_val_len) { - pj_str_t err_msg; - char err_msg_buf[80]; - - err_msg.ptr = err_msg_buf; - err_msg.slen = pj_ansi_snprintf(err_msg_buf, sizeof(err_msg_buf), - "Attribute %s has invalid length", - pj_stun_get_attr_name(attr_type)); - - PJ_LOG(4,(THIS_FILE, "Error decoding message: %.*s", - (int)err_msg.slen, err_msg.ptr)); - - if (p_response) { - pj_stun_msg_create_response(pool, msg, - PJ_STUN_SC_BAD_REQUEST, - &err_msg, p_response); - } - return PJLIB_UTIL_ESTUNINATTRLEN; - } - - /* Get the attribute descriptor */ - adesc = find_attr_desc(attr_type); - - if (adesc == NULL) { - /* Unrecognized attribute */ - - PJ_LOG(4,(THIS_FILE, "Unrecognized attribute type %d", - attr_type)); - - /* Is this a fatal condition? */ - if (attr_type <= 0x7FFF) { - /* This is a mandatory attribute, we must return error - * if we don't understand the attribute. - */ - if (p_response) { - unsigned err_code = PJ_STUN_SC_UNKNOWN_ATTRIBUTE; - - status = pj_stun_msg_create_response(pool, msg, - err_code, NULL, - p_response); - if (status==PJ_SUCCESS) { - pj_uint16_t d = (pj_uint16_t)attr_type; - pj_stun_msg_add_unknown_attr(pool, *p_response, 1, &d); - } - } - - return PJLIB_UTIL_ESTUNUNKNOWNATTR; - } - - } else { - void *attr; - char err_msg1[PJ_ERR_MSG_SIZE], - err_msg2[PJ_ERR_MSG_SIZE]; - - /* Parse the attribute */ - status = (adesc->decode_attr)(pool, pdu, &attr); - - if (status != PJ_SUCCESS) { - pj_strerror(status, err_msg1, sizeof(err_msg1)); - - if (p_response) { - pj_str_t e; - - e.ptr = err_msg2; - e.slen= pj_ansi_snprintf(err_msg2, sizeof(err_msg2), - "%s in %s", - err_msg1, - pj_stun_get_attr_name(attr_type)); - - pj_stun_msg_create_response(pool, msg, - PJ_STUN_SC_BAD_REQUEST, - &e, p_response); - } - - PJ_LOG(4,(THIS_FILE, - "Error parsing STUN attribute %s: %s", - pj_stun_get_attr_name(attr_type), - err_msg1)); - - return status; - } - - if (attr_type == PJ_STUN_ATTR_MESSAGE_INTEGRITY && - !has_fingerprint) - { - if (has_msg_int) { - /* Already has MESSAGE-INTEGRITY */ - if (p_response) { - pj_str_t e; - e = pj_str("MESSAGE-INTEGRITY already present"); - pj_stun_msg_create_response(pool, msg, - PJ_STUN_SC_BAD_REQUEST, - NULL, p_response); - } - return PJLIB_UTIL_ESTUNDUPATTR; - } - has_msg_int = PJ_TRUE; - - } else if (attr_type == PJ_STUN_ATTR_FINGERPRINT) { - if (has_fingerprint) { - /* Already has FINGERPRINT */ - if (p_response) { - pj_str_t e; - e = pj_str("FINGERPRINT already present"); - pj_stun_msg_create_response(pool, msg, - PJ_STUN_SC_BAD_REQUEST, - NULL, p_response); - } - return PJLIB_UTIL_ESTUNDUPATTR; - } - has_fingerprint = PJ_TRUE; - } else { - if (has_msg_int || has_fingerprint) { - /* Another attribute is found which is not FINGERPRINT - * after FINGERPRINT or MESSAGE-INTEGRITY */ - if (p_response) { - pj_str_t e; - e = pj_str("Invalid attribute order"); - pj_stun_msg_create_response(pool, msg, - PJ_STUN_SC_BAD_REQUEST, - NULL, p_response); - } - return has_fingerprint ? PJLIB_UTIL_ESTUNFINGERPOS : - PJLIB_UTIL_ESTUNMSGINTPOS; - } - } - - /* Make sure we have rooms for the new attribute */ - if (msg->attr_count >= PJ_STUN_MAX_ATTR) { - if (p_response) { - pj_str_t e; - - e = pj_str("Too many attributes"); - pj_stun_msg_create_response(pool, msg, - PJ_STUN_SC_BAD_REQUEST, - &e, p_response); - } - return PJLIB_UTIL_ESTUNTOOMANYATTR; - } - - /* Add the attribute */ - msg->attr[msg->attr_count++] = (pj_stun_attr_hdr*)attr; - } - - pdu += (attr_val_len + 4); - pdu_len -= (attr_val_len + 4); - } - - *p_msg = msg; - - if (p_parsed_len) - *p_parsed_len = (pdu - start_pdu); - - return PJ_SUCCESS; -} - -/* Calculate HMAC-SHA1 key for long term credential, by getting - * MD5 digest of username, realm, and password. - */ -void pj_stun_calc_md5_key(pj_uint8_t digest[16], - const pj_str_t *realm, - const pj_str_t *username, - const pj_str_t *passwd) -{ - /* The 16-byte key for MESSAGE-INTEGRITY HMAC is formed by taking - * the MD5 hash of the result of concatenating the following five - * fields: (1) The username, with any quotes and trailing nulls - * removed, (2) A single colon, (3) The realm, with any quotes and - * trailing nulls removed, (4) A single colon, and (5) The - * password, with any trailing nulls removed. - */ - pj_md5_context ctx; - pj_str_t s; - - pj_md5_init(&ctx); - -#define REMOVE_QUOTE(s) if (s.slen && *s.ptr=='"') \ - s.ptr++, s.slen--; \ - if (s.slen && s.ptr[s.slen-1]=='"') \ - s.slen--; - - /* Add username */ - s = *username; - REMOVE_QUOTE(s); - pj_md5_update(&ctx, (pj_uint8_t*)s.ptr, s.slen); - - /* Add single colon */ - pj_md5_update(&ctx, (pj_uint8_t*)":", 1); - - /* Add realm */ - s = *realm; - REMOVE_QUOTE(s); - pj_md5_update(&ctx, (pj_uint8_t*)s.ptr, s.slen); - -#undef REMOVE_QUOTE - - /* Another colon */ - pj_md5_update(&ctx, (pj_uint8_t*)":", 1); - - /* Add password */ - pj_md5_update(&ctx, (pj_uint8_t*)passwd->ptr, passwd->slen); - - /* Done */ - pj_md5_final(&ctx, digest); -} - - -/* -static char *print_binary(const pj_uint8_t *data, unsigned data_len) -{ - static char static_buffer[1024]; - char *buffer = static_buffer; - unsigned length=sizeof(static_buffer), i; - - if (length < data_len * 2 + 8) - return ""; - - pj_ansi_sprintf(buffer, ", data="); - buffer += 7; - - for (i=0; ihdr, sizeof(pj_stun_msg_hdr)); - hdr = (pj_stun_msg_hdr*) buf; - hdr->magic = pj_htonl(hdr->magic); - hdr->type = pj_htons(hdr->type); - /* We'll fill in the length later */ - - buf += sizeof(pj_stun_msg_hdr); - buf_size -= sizeof(pj_stun_msg_hdr); - - /* Print each attribute */ - for (i=0; iattr_count; ++i) { - const struct attr_desc *adesc; - const pj_stun_attr_hdr *attr_hdr = msg->attr[i]; - - if (attr_hdr->type == PJ_STUN_ATTR_MESSAGE_INTEGRITY) { - pj_assert(amsgint == NULL); - amsgint = (pj_stun_msgint_attr*) attr_hdr; - - /* Stop when encountering MESSAGE-INTEGRITY */ - break; - - } else if (attr_hdr->type == PJ_STUN_ATTR_USERNAME) { - pj_assert(auname == NULL); - auname = (pj_stun_username_attr*) attr_hdr; - - } else if (attr_hdr->type == PJ_STUN_ATTR_REALM) { - pj_assert(arealm == NULL); - arealm = (pj_stun_realm_attr*) attr_hdr; - - } else if (attr_hdr->type == PJ_STUN_ATTR_FINGERPRINT) { - afingerprint = (pj_stun_fingerprint_attr*) attr_hdr; - break; - } - - adesc = find_attr_desc(attr_hdr->type); - PJ_ASSERT_RETURN(adesc != NULL, PJ_EBUG); - - status = adesc->encode_attr(attr_hdr, buf, buf_size, &printed); - if (status != PJ_SUCCESS) - return status; - - buf += printed; - buf_size -= printed; - } - - /* We may have stopped printing attribute because we found - * MESSAGE-INTEGRITY or FINGERPRINT. Scan the rest of the - * attributes. - */ - for ( ++i; iattr_count; ++i) { - const pj_stun_attr_hdr *attr_hdr = msg->attr[i]; - - /* There mustn't any attribute after FINGERPRINT */ - PJ_ASSERT_RETURN(afingerprint == NULL, PJLIB_UTIL_ESTUNFINGERPOS); - - if (attr_hdr->type == PJ_STUN_ATTR_MESSAGE_INTEGRITY) { - /* There mustn't be MESSAGE-INTEGRITY before */ - PJ_ASSERT_RETURN(amsgint == NULL, - PJLIB_UTIL_ESTUNMSGINTPOS); - amsgint = (pj_stun_msgint_attr*) attr_hdr; - - } else if (attr_hdr->type == PJ_STUN_ATTR_FINGERPRINT) { - afingerprint = (pj_stun_fingerprint_attr*) attr_hdr; - } - } - - /* We MUST update the message length in the header NOW before - * calculating MESSAGE-INTEGRITY and FINGERPRINT. - * Note that length is not including the 20 bytes header. - */ - if (amsgint && afingerprint) { - msg->hdr.length = (pj_uint16_t)((buf - start) - 20 + 24 + 8); - } else if (amsgint) { - msg->hdr.length = (pj_uint16_t)((buf - start) - 20 + 24); - } else if (afingerprint) { - msg->hdr.length = (pj_uint16_t)((buf - start) - 20 + 8); - } else { - msg->hdr.length = (pj_uint16_t)((buf - start) - 20); - } - - /* hdr->length = pj_htons(length); */ - start[2] = (pj_uint8_t)((msg->hdr.length >> 8) & 0x00FF); - start[3] = (pj_uint8_t)(msg->hdr.length & 0x00FF); - - /* Calculate message integrity, if present */ - if (amsgint != NULL) { - - pj_uint8_t md5_key_buf[16]; - pj_str_t key; - - /* MESSAGE-INTEGRITY must be the last attribute in the message, or - * the last attribute before FINGERPRINT. - */ - if (i < msg->attr_count-2) { - /* Should not happen for message generated by us */ - pj_assert(PJ_FALSE); - return PJLIB_UTIL_ESTUNMSGINTPOS; - - } else if (i == msg->attr_count-2) { - if (msg->attr[i+1]->type != PJ_STUN_ATTR_FINGERPRINT) { - /* Should not happen for message generated by us */ - pj_assert(PJ_FALSE); - return PJLIB_UTIL_ESTUNMSGINTPOS; - } else { - afingerprint = (pj_stun_fingerprint_attr*) msg->attr[i+1]; - } - } - - /* Must have USERNAME attribute */ - if (auname == NULL) { - /* Should not happen for message generated by us */ - pj_assert(PJ_FALSE); - return PJLIB_UTIL_ESTUNNOUSERNAME; - } - - /* Password must be specified */ - PJ_ASSERT_RETURN(password, PJ_EINVAL); - - /* Get the key to sign the message */ - if (arealm == NULL ) { - /* For short term credential, the key is the password */ - key = *password; - - } else { - pj_stun_calc_md5_key(md5_key_buf, &arealm->value, - &auname->value, password); - key.ptr = (char*) md5_key_buf; - key.slen = 16; - } - - /* Calculate HMAC-SHA1 digest */ - pj_hmac_sha1((pj_uint8_t*)start, buf-start, - (pj_uint8_t*)key.ptr, key.slen, - amsgint->hmac); - - /* Put this attribute in the message */ - status = encode_msgint_attr(amsgint, buf, buf_size, - &printed); - if (status != PJ_SUCCESS) - return status; - - buf += printed; - buf_size -= printed; - } - - /* Calculate FINGERPRINT if present */ - if (afingerprint != NULL) { - afingerprint->value = pj_crc32_calc(start, buf-start); - afingerprint->value ^= STUN_XOR_FINGERPRINT; - - /* Put this attribute in the message */ - status = encode_uint_attr(afingerprint, buf, buf_size, - &printed); - if (status != PJ_SUCCESS) - return status; - - buf += printed; - buf_size -= printed; - } - - /* Done */ - if (p_msg_len) - *p_msg_len = (buf - start); - - return PJ_SUCCESS; -} - - -/* - * Find STUN attribute in the STUN message, starting from the specified - * index. - */ -PJ_DEF(pj_stun_attr_hdr*) pj_stun_msg_find_attr( const pj_stun_msg *msg, - int attr_type, - unsigned index) -{ - PJ_ASSERT_RETURN(msg, NULL); - - for (; index < msg->attr_count; ++index) { - if (msg->attr[index]->type == attr_type) - return (pj_stun_attr_hdr*) msg->attr[index]; - } - - return NULL; -} - diff --git a/pjlib-util/src/pjlib-util/stun_msg_dump.c b/pjlib-util/src/pjlib-util/stun_msg_dump.c deleted file mode 100644 index 0ee0ebe4..00000000 --- a/pjlib-util/src/pjlib-util/stun_msg_dump.c +++ /dev/null @@ -1,250 +0,0 @@ -/* $Id$ */ -/* - * Copyright (C) 2003-2005 Benny Prijono - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ -#include -#include -#include -#include - - -#define APPLY() if (len < 1 || len >= (end-p)) \ - goto on_return; \ - p += len - -static int print_binary(char *buffer, unsigned length, - const pj_uint8_t *data, unsigned data_len) -{ - unsigned i; - - if (length < data_len * 2 + 8) - return -1; - - pj_ansi_sprintf(buffer, ", data="); - buffer += 7; - - for (i=0; itype), - (int)ahdr->length); - APPLY(); - - - switch (ahdr->type) { - case PJ_STUN_ATTR_MAPPED_ADDR: - case PJ_STUN_ATTR_RESPONSE_ADDR: - case PJ_STUN_ATTR_SOURCE_ADDR: - case PJ_STUN_ATTR_CHANGED_ADDR: - case PJ_STUN_ATTR_REFLECTED_FROM: - case PJ_STUN_ATTR_REMOTE_ADDR: - case PJ_STUN_ATTR_RELAY_ADDR: - case PJ_STUN_ATTR_XOR_MAPPED_ADDR: - case PJ_STUN_ATTR_REQ_IP: - case PJ_STUN_ATTR_XOR_REFLECTED_FROM: - case PJ_STUN_ATTR_XOR_INTERNAL_ADDR: - case PJ_STUN_ATTR_ALTERNATE_SERVER: - { - const pj_stun_sockaddr_attr *attr; - - attr = (const pj_stun_sockaddr_attr*)ahdr; - - if (attr->addr.addr.sa_family == PJ_AF_INET) { - len = pj_ansi_snprintf(p, end-p, - ", IPv4 addr=%s:%d\n", - pj_inet_ntoa(attr->addr.ipv4.sin_addr), - pj_ntohs(attr->addr.ipv4.sin_port)); - - } else if (attr->addr.addr.sa_family == PJ_AF_INET6) { - len = pj_ansi_snprintf(p, end-p, - ", IPv6 addr present\n"); - } else { - len = pj_ansi_snprintf(p, end-p, - ", INVALID ADDRESS FAMILY!\n"); - } - } - break; - - case PJ_STUN_ATTR_CHANGE_REQUEST: - case PJ_STUN_ATTR_LIFETIME: - case PJ_STUN_ATTR_BANDWIDTH: - case PJ_STUN_ATTR_REQ_ADDR_TYPE: - case PJ_STUN_ATTR_REQ_PORT_PROPS: - case PJ_STUN_ATTR_REQ_TRANSPORT: - case PJ_STUN_ATTR_TIMER_VAL: - case PJ_STUN_ATTR_PRIORITY: - case PJ_STUN_ATTR_FINGERPRINT: - case PJ_STUN_ATTR_REFRESH_INTERVAL: - { - const pj_stun_uint_attr *attr; - - attr = (const pj_stun_uint_attr*)ahdr; - len = pj_ansi_snprintf(p, end-p, - ", value=%d (0x%x)\n", - (pj_uint32_t)attr->value, - (pj_uint32_t)attr->value); - } - break; - - case PJ_STUN_ATTR_USERNAME: - case PJ_STUN_ATTR_PASSWORD: - case PJ_STUN_ATTR_REALM: - case PJ_STUN_ATTR_NONCE: - case PJ_STUN_ATTR_SERVER: - { - const pj_stun_string_attr *attr; - - attr = (pj_stun_string_attr*)ahdr; - len = pj_ansi_snprintf(p, end-p, - ", value=\"%.*s\"\n", - (int)attr->value.slen, - attr->value.ptr); - } - break; - - case PJ_STUN_ATTR_ERROR_CODE: - { - const pj_stun_errcode_attr *attr; - - attr = (const pj_stun_errcode_attr*) ahdr; - len = pj_ansi_snprintf(p, end-p, - ", err_code=%d, reason=\"%.*s\"\n", - attr->err_class*100 + attr->number, - (int)attr->reason.slen, - attr->reason.ptr); - } - break; - - case PJ_STUN_ATTR_UNKNOWN_ATTRIBUTES: - { - const pj_stun_unknown_attr *attr; - unsigned j; - - attr = (const pj_stun_unknown_attr*) ahdr; - - len = pj_ansi_snprintf(p, end-p, - ", unknown list:"); - APPLY(); - - for (j=0; jattr_count; ++j) { - len = pj_ansi_snprintf(p, end-p, - " %d", - (int)attr->attrs[j]); - APPLY(); - } - } - break; - - case PJ_STUN_ATTR_MESSAGE_INTEGRITY: - { - const pj_stun_msgint_attr *attr; - - attr = (const pj_stun_msgint_attr*) ahdr; - len = print_binary(p, end-p, attr->hmac, 20); - APPLY(); - } - break; - - case PJ_STUN_ATTR_DATA: - { - const pj_stun_binary_attr *attr; - - attr = (const pj_stun_binary_attr*) ahdr; - len = print_binary(p, end-p, attr->data, attr->length); - APPLY(); - } - break; - case PJ_STUN_ATTR_USE_CANDIDATE: - default: - len = pj_ansi_snprintf(p, end-p, "\n"); - - break; - } - - APPLY(); - - return (p-buffer); - -on_return: - return len; -} - - -/* - * Dump STUN message to a printable string output. - */ -PJ_DEF(char*) pj_stun_msg_dump(const pj_stun_msg *msg, - char *buffer, - unsigned length, - unsigned *printed_len) -{ - char *p, *end; - int len; - unsigned i; - - PJ_ASSERT_RETURN(msg && buffer && length, NULL); - - p = buffer; - end = buffer + length; - - len = pj_ansi_snprintf(p, end-p, "STUN %s %s\n", - pj_stun_get_method_name(msg->hdr.type), - pj_stun_get_class_name(msg->hdr.type)); - APPLY(); - - len = pj_ansi_snprintf(p, end-p, - " Hdr: length=%d, magic=%08x, tsx_id=%08x %08x %08x\n" - " Attributes:\n", - msg->hdr.length, - msg->hdr.magic, - *(pj_uint32_t*)&msg->hdr.tsx_id[0], - *(pj_uint32_t*)&msg->hdr.tsx_id[4], - *(pj_uint32_t*)&msg->hdr.tsx_id[8]); - APPLY(); - - for (i=0; iattr_count; ++i) { - len = print_attr(p, end-p, msg->attr[i]); - APPLY(); - } - -on_return: - *p = '\0'; - if (printed_len) - *printed_len = (p-buffer); - return buffer; - -} - - -#undef APPLY diff --git a/pjlib-util/src/pjlib-util/stun_session.c b/pjlib-util/src/pjlib-util/stun_session.c deleted file mode 100644 index b4e7356c..00000000 --- a/pjlib-util/src/pjlib-util/stun_session.c +++ /dev/null @@ -1,903 +0,0 @@ -/* $Id$ */ -/* - * Copyright (C) 2003-2005 Benny Prijono - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ -#include -#include - -struct pj_stun_session -{ - pj_stun_endpoint *endpt; - pj_pool_t *pool; - pj_mutex_t *mutex; - pj_stun_session_cb cb; - void *user_data; - - pj_bool_t use_fingerprint; - pj_stun_auth_cred *cred; - pj_str_t srv_name; - - pj_stun_tx_data pending_request_list; - pj_stun_tx_data cached_response_list; -}; - -#define SNAME(s_) ((s_)->pool->obj_name) - -#if PJ_LOG_MAX_LEVEL >= 5 -# define TRACE_(expr) PJ_LOG(5,expr) -#else -# define TRACE_(expr) -#endif - -#if PJ_LOG_MAX_LEVEL >= 4 -# define LOG_ERR_(sess, title, rc) stun_perror(sess, title, rc) -static void stun_perror(pj_stun_session *sess, const char *title, - pj_status_t status) -{ - char errmsg[PJ_ERR_MSG_SIZE]; - - pj_strerror(status, errmsg, sizeof(errmsg)); - - PJ_LOG(4,(SNAME(sess), "%s: %s", title, errmsg)); -} - -#else -# define LOG_ERR_(sess, title, rc) -#endif - -#define TDATA_POOL_SIZE 1024 -#define TDATA_POOL_INC 1024 - - -static void tsx_on_complete(pj_stun_client_tsx *tsx, - pj_status_t status, - const pj_stun_msg *response); -static pj_status_t tsx_on_send_msg(pj_stun_client_tsx *tsx, - const void *stun_pkt, - pj_size_t pkt_size); - -static pj_stun_tsx_cb tsx_cb = -{ - &tsx_on_complete, - &tsx_on_send_msg -}; - - -static pj_status_t tsx_add(pj_stun_session *sess, - pj_stun_tx_data *tdata) -{ - pj_list_push_back(&sess->pending_request_list, tdata); - return PJ_SUCCESS; -} - -static pj_status_t tsx_erase(pj_stun_session *sess, - pj_stun_tx_data *tdata) -{ - PJ_UNUSED_ARG(sess); - pj_list_erase(tdata); - return PJ_SUCCESS; -} - -static pj_stun_tx_data* tsx_lookup(pj_stun_session *sess, - const pj_stun_msg *msg) -{ - pj_stun_tx_data *tdata; - - tdata = sess->pending_request_list.next; - while (tdata != &sess->pending_request_list) { - pj_assert(sizeof(tdata->msg_key)==sizeof(msg->hdr.tsx_id)); - if (tdata->msg_magic == msg->hdr.magic && - pj_memcmp(tdata->msg_key, msg->hdr.tsx_id, - sizeof(msg->hdr.tsx_id))==0) - { - return tdata; - } - tdata = tdata->next; - } - - return NULL; -} - -static pj_status_t create_tdata(pj_stun_session *sess, - pj_stun_tx_data **p_tdata) -{ - pj_pool_t *pool; - pj_stun_tx_data *tdata; - - /* Create pool and initialize basic tdata attributes */ - pool = pj_pool_create(sess->endpt->pf, "tdata%p", - TDATA_POOL_SIZE, TDATA_POOL_INC, NULL); - PJ_ASSERT_RETURN(pool, PJ_ENOMEM); - - tdata = PJ_POOL_ZALLOC_T(pool, pj_stun_tx_data); - tdata->pool = pool; - tdata->sess = sess; - - *p_tdata = tdata; - - return PJ_SUCCESS; -} - -static pj_status_t create_request_tdata(pj_stun_session *sess, - unsigned msg_type, - pj_stun_tx_data **p_tdata) -{ - pj_status_t status; - pj_stun_tx_data *tdata; - - status = create_tdata(sess, &tdata); - if (status != PJ_SUCCESS) - return status; - - /* Create STUN message */ - status = pj_stun_msg_create(tdata->pool, msg_type, PJ_STUN_MAGIC, - NULL, &tdata->msg); - if (status != PJ_SUCCESS) { - pj_pool_release(tdata->pool); - return status; - } - - /* copy the request's transaction ID as the transaction key. */ - pj_assert(sizeof(tdata->msg_key)==sizeof(tdata->msg->hdr.tsx_id)); - tdata->msg_magic = tdata->msg->hdr.magic; - pj_memcpy(tdata->msg_key, tdata->msg->hdr.tsx_id, - sizeof(tdata->msg->hdr.tsx_id)); - - *p_tdata = tdata; - - return PJ_SUCCESS; -} - -static void destroy_tdata(pj_stun_tx_data *tdata) -{ - if (tdata->client_tsx) { - tsx_erase(tdata->sess, tdata); - pj_stun_client_tsx_destroy(tdata->client_tsx); - tdata->client_tsx = NULL; - } - if (tdata->res_timer.id != PJ_FALSE) { - pj_timer_heap_cancel(tdata->sess->endpt->timer_heap, - &tdata->res_timer); - tdata->res_timer.id = PJ_FALSE; - pj_list_erase(tdata); - } - pj_pool_release(tdata->pool); -} - -/* - * Destroy the transmit data. - */ -PJ_DEF(void) pj_stun_msg_destroy_tdata( pj_stun_session *sess, - pj_stun_tx_data *tdata) -{ - PJ_UNUSED_ARG(sess); - destroy_tdata(tdata); -} - - -/* Timer callback to be called when it's time to destroy response cache */ -static void on_cache_timeout(pj_timer_heap_t *timer_heap, - struct pj_timer_entry *entry) -{ - pj_stun_tx_data *tdata; - - PJ_UNUSED_ARG(timer_heap); - - entry->id = PJ_FALSE; - tdata = (pj_stun_tx_data*) entry->user_data; - - PJ_LOG(5,(SNAME(tdata->sess), "Response cache deleted")); - - pj_list_erase(tdata); - pj_stun_msg_destroy_tdata(tdata->sess, tdata); -} - -static pj_str_t *get_passwd(pj_stun_session *sess) -{ - if (sess->cred == NULL) - return NULL; - else if (sess->cred->type == PJ_STUN_AUTH_CRED_STATIC) - return &sess->cred->data.static_cred.data; - else - return NULL; -} - -static pj_status_t apply_msg_options(pj_stun_session *sess, - pj_pool_t *pool, - pj_stun_msg *msg) -{ - pj_status_t status = 0; - - /* The server SHOULD include a SERVER attribute in all responses */ - if (PJ_STUN_IS_RESPONSE(msg->hdr.type) || - PJ_STUN_IS_ERROR_RESPONSE(msg->hdr.type)) - { - pj_stun_msg_add_string_attr(pool, msg, PJ_STUN_ATTR_SERVER, - &sess->srv_name); - } - - /* From draft-ietf-behave-rfc3489bis-05.txt - * Section 8.3.1. Formulating the Request Message - * - * Note: only put MESSAGE-INTEGRITY in non error response. - */ - if (sess->cred && sess->cred->type == PJ_STUN_AUTH_CRED_STATIC && - !PJ_STUN_IS_ERROR_RESPONSE(msg->hdr.type)) - { - const pj_str_t *username; - - /* Create and add USERNAME attribute */ - username = &sess->cred->data.static_cred.username; - status = pj_stun_msg_add_string_attr(pool, msg, - PJ_STUN_ATTR_USERNAME, - username); - PJ_ASSERT_RETURN(status==PJ_SUCCESS, status); - - /* Add REALM only when long term credential is used */ - if (sess->cred->data.static_cred.realm.slen) { - const pj_str_t *realm = &sess->cred->data.static_cred.realm; - status = pj_stun_msg_add_string_attr(pool, msg, - PJ_STUN_ATTR_REALM, - realm); - } - - /* Add MESSAGE-INTEGRITY attribute */ - status = pj_stun_msg_add_msgint_attr(pool, msg); - PJ_ASSERT_RETURN(status==PJ_SUCCESS, status); - - } - - /* Add FINGERPRINT attribute if necessary */ - if (sess->use_fingerprint) { - status = pj_stun_msg_add_uint_attr(pool, msg, - PJ_STUN_ATTR_FINGERPRINT, 0); - PJ_ASSERT_RETURN(status==PJ_SUCCESS, status); - } - - return PJ_SUCCESS; -} - - -static void tsx_on_complete(pj_stun_client_tsx *tsx, - pj_status_t status, - const pj_stun_msg *response) -{ - pj_stun_tx_data *tdata; - - tdata = (pj_stun_tx_data*) pj_stun_client_tsx_get_data(tsx); - - if (tdata->sess->cb.on_request_complete) { - (*tdata->sess->cb.on_request_complete)(tdata->sess, status, tdata, - response); - } -} - -static pj_status_t tsx_on_send_msg(pj_stun_client_tsx *tsx, - const void *stun_pkt, - pj_size_t pkt_size) -{ - pj_stun_tx_data *tdata; - - tdata = (pj_stun_tx_data*) pj_stun_client_tsx_get_data(tsx); - - return tdata->sess->cb.on_send_msg(tdata->sess, stun_pkt, pkt_size, - tdata->dst_addr, tdata->addr_len); -} - -/* **************************************************************************/ - -PJ_DEF(pj_status_t) pj_stun_session_create( pj_stun_endpoint *endpt, - const char *name, - const pj_stun_session_cb *cb, - pj_bool_t fingerprint, - pj_stun_session **p_sess) -{ - pj_pool_t *pool; - pj_stun_session *sess; - pj_status_t status; - - PJ_ASSERT_RETURN(endpt && cb && p_sess, PJ_EINVAL); - - if (name==NULL) - name = "sess%p"; - - pool = pj_pool_create(endpt->pf, name, 4000, 4000, NULL); - PJ_ASSERT_RETURN(pool, PJ_ENOMEM); - - sess = PJ_POOL_ZALLOC_T(pool, pj_stun_session); - sess->endpt = endpt; - sess->pool = pool; - pj_memcpy(&sess->cb, cb, sizeof(*cb)); - sess->use_fingerprint = fingerprint; - - sess->srv_name.ptr = pj_pool_alloc(pool, 32); - sess->srv_name.slen = pj_ansi_snprintf(sess->srv_name.ptr, 32, - "pj_stun-%s", PJ_VERSION); - - pj_list_init(&sess->pending_request_list); - pj_list_init(&sess->cached_response_list); - - status = pj_mutex_create_recursive(pool, name, &sess->mutex); - if (status != PJ_SUCCESS) { - pj_pool_release(pool); - return status; - } - - *p_sess = sess; - - return PJ_SUCCESS; -} - -PJ_DEF(pj_status_t) pj_stun_session_destroy(pj_stun_session *sess) -{ - PJ_ASSERT_RETURN(sess, PJ_EINVAL); - - pj_mutex_lock(sess->mutex); - while (!pj_list_empty(&sess->pending_request_list)) { - pj_stun_tx_data *tdata = sess->pending_request_list.next; - destroy_tdata(tdata); - } - while (!pj_list_empty(&sess->cached_response_list)) { - pj_stun_tx_data *tdata = sess->cached_response_list.next; - destroy_tdata(tdata); - } - pj_mutex_unlock(sess->mutex); - - pj_mutex_destroy(sess->mutex); - pj_pool_release(sess->pool); - - return PJ_SUCCESS; -} - - -PJ_DEF(pj_status_t) pj_stun_session_set_user_data( pj_stun_session *sess, - void *user_data) -{ - PJ_ASSERT_RETURN(sess, PJ_EINVAL); - pj_mutex_lock(sess->mutex); - sess->user_data = user_data; - pj_mutex_unlock(sess->mutex); - return PJ_SUCCESS; -} - -PJ_DEF(void*) pj_stun_session_get_user_data(pj_stun_session *sess) -{ - PJ_ASSERT_RETURN(sess, NULL); - return sess->user_data; -} - -PJ_DEF(pj_status_t) pj_stun_session_set_server_name(pj_stun_session *sess, - const pj_str_t *srv_name) -{ - PJ_ASSERT_RETURN(sess && srv_name, PJ_EINVAL); - pj_strdup(sess->pool, &sess->srv_name, srv_name); - return PJ_SUCCESS; -} - -PJ_DEF(void) pj_stun_session_set_credential(pj_stun_session *sess, - const pj_stun_auth_cred *cred) -{ - PJ_ASSERT_ON_FAIL(sess, return); - if (cred) { - if (!sess->cred) - sess->cred = pj_pool_alloc(sess->pool, sizeof(pj_stun_auth_cred)); - pj_stun_auth_cred_dup(sess->pool, sess->cred, cred); - } else { - sess->cred = NULL; - } -} - - -PJ_DEF(pj_status_t) pj_stun_session_create_req(pj_stun_session *sess, - int method, - pj_stun_tx_data **p_tdata) -{ - pj_stun_tx_data *tdata = NULL; - pj_status_t status; - - PJ_ASSERT_RETURN(sess && p_tdata, PJ_EINVAL); - - status = create_request_tdata(sess, method, &tdata); - if (status != PJ_SUCCESS) - return status; - - *p_tdata = tdata; - return PJ_SUCCESS; -} - -PJ_DEF(pj_status_t) pj_stun_session_create_ind(pj_stun_session *sess, - int msg_type, - pj_stun_tx_data **p_tdata) -{ - pj_stun_tx_data *tdata = NULL; - pj_status_t status; - - PJ_ASSERT_RETURN(sess && p_tdata, PJ_EINVAL); - - status = create_tdata(sess, &tdata); - if (status != PJ_SUCCESS) - return status; - - /* Create STUN message */ - msg_type |= PJ_STUN_INDICATION_BIT; - status = pj_stun_msg_create(tdata->pool, msg_type, PJ_STUN_MAGIC, - NULL, &tdata->msg); - if (status != PJ_SUCCESS) { - pj_pool_release(tdata->pool); - return status; - } - - *p_tdata = tdata; - return PJ_SUCCESS; -} - -/* - * Create a STUN response message. - */ -PJ_DEF(pj_status_t) pj_stun_session_create_response( pj_stun_session *sess, - const pj_stun_msg *req, - unsigned err_code, - const pj_str_t *err_msg, - pj_stun_tx_data **p_tdata) -{ - pj_status_t status; - pj_stun_tx_data *tdata = NULL; - - status = create_tdata(sess, &tdata); - if (status != PJ_SUCCESS) - return status; - - /* Create STUN response message */ - status = pj_stun_msg_create_response(tdata->pool, req, err_code, err_msg, - &tdata->msg); - if (status != PJ_SUCCESS) { - pj_pool_release(tdata->pool); - return status; - } - - /* copy the request's transaction ID as the transaction key. */ - pj_assert(sizeof(tdata->msg_key)==sizeof(req->hdr.tsx_id)); - tdata->msg_magic = req->hdr.magic; - pj_memcpy(tdata->msg_key, req->hdr.tsx_id, sizeof(req->hdr.tsx_id)); - - *p_tdata = tdata; - - return PJ_SUCCESS; -} - - -/* Print outgoing message to log */ -static void dump_tx_msg(pj_stun_session *sess, const pj_stun_msg *msg, - unsigned pkt_size, const pj_sockaddr_t *addr) -{ - const char *dst_name; - int dst_port; - const pj_sockaddr *dst = (const pj_sockaddr*)addr; - char buf[512]; - - if (dst->sa_family == PJ_AF_INET) { - const pj_sockaddr_in *dst4 = (const pj_sockaddr_in*)dst; - dst_name = pj_inet_ntoa(dst4->sin_addr); - dst_port = pj_ntohs(dst4->sin_port); - } else if (dst->sa_family == PJ_AF_INET6) { - const pj_sockaddr_in6 *dst6 = (const pj_sockaddr_in6*)dst; - dst_name = "IPv6"; - dst_port = pj_ntohs(dst6->sin6_port); - } else { - LOG_ERR_(sess, "Invalid address family", PJ_EINVAL); - return; - } - - PJ_LOG(5,(SNAME(sess), - "TX %d bytes STUN message to %s:%d:\n" - "--- begin STUN message ---\n" - "%s" - "--- end of STUN message ---\n", - pkt_size, dst_name, dst_port, - pj_stun_msg_dump(msg, buf, sizeof(buf), NULL))); - -} - - -PJ_DEF(pj_status_t) pj_stun_session_send_msg( pj_stun_session *sess, - pj_bool_t cache_res, - const pj_sockaddr_t *server, - unsigned addr_len, - pj_stun_tx_data *tdata) -{ - pj_status_t status; - - PJ_ASSERT_RETURN(sess && addr_len && server && tdata, PJ_EINVAL); - - /* Allocate packet */ - tdata->max_len = PJ_STUN_MAX_PKT_LEN; - tdata->pkt = pj_pool_alloc(tdata->pool, tdata->max_len); - - /* Start locking the session now */ - pj_mutex_lock(sess->mutex); - - /* Apply options */ - status = apply_msg_options(sess, tdata->pool, tdata->msg); - if (status != PJ_SUCCESS) { - pj_stun_msg_destroy_tdata(sess, tdata); - pj_mutex_unlock(sess->mutex); - LOG_ERR_(sess, "Error applying options", status); - return status; - } - - /* Encode message */ - status = pj_stun_msg_encode(tdata->msg, tdata->pkt, tdata->max_len, - 0, get_passwd(sess), &tdata->pkt_size); - if (status != PJ_SUCCESS) { - pj_stun_msg_destroy_tdata(sess, tdata); - pj_mutex_unlock(sess->mutex); - LOG_ERR_(sess, "STUN encode() error", status); - return status; - } - - /* Dump packet */ - dump_tx_msg(sess, tdata->msg, tdata->pkt_size, server); - - /* If this is a STUN request message, then send the request with - * a new STUN client transaction. - */ - if (PJ_STUN_IS_REQUEST(tdata->msg->hdr.type)) { - - /* Create STUN client transaction */ - status = pj_stun_client_tsx_create(sess->endpt, tdata->pool, - &tsx_cb, &tdata->client_tsx); - PJ_ASSERT_RETURN(status==PJ_SUCCESS, status); - pj_stun_client_tsx_set_data(tdata->client_tsx, (void*)tdata); - - /* Save the remote address */ - tdata->addr_len = addr_len; - tdata->dst_addr = server; - - /* Send the request! */ - status = pj_stun_client_tsx_send_msg(tdata->client_tsx, PJ_TRUE, - tdata->pkt, tdata->pkt_size); - if (status != PJ_SUCCESS && status != PJ_EPENDING) { - pj_stun_msg_destroy_tdata(sess, tdata); - pj_mutex_unlock(sess->mutex); - LOG_ERR_(sess, "Error sending STUN request", status); - return status; - } - - /* Add to pending request list */ - tsx_add(sess, tdata); - - } else { - if (cache_res && - (PJ_STUN_IS_RESPONSE(tdata->msg->hdr.type) || - PJ_STUN_IS_ERROR_RESPONSE(tdata->msg->hdr.type))) - { - /* Requested to keep the response in the cache */ - pj_time_val timeout; - - pj_memset(&tdata->res_timer, 0, sizeof(tdata->res_timer)); - pj_timer_entry_init(&tdata->res_timer, PJ_TRUE, tdata, - &on_cache_timeout); - - timeout.sec = sess->endpt->res_cache_msec / 1000; - timeout.msec = sess->endpt->res_cache_msec % 1000; - - status = pj_timer_heap_schedule(sess->endpt->timer_heap, - &tdata->res_timer, - &timeout); - if (status != PJ_SUCCESS) { - pj_stun_msg_destroy_tdata(sess, tdata); - pj_mutex_unlock(sess->mutex); - LOG_ERR_(sess, "Error scheduling response timer", status); - return status; - } - - pj_list_push_back(&sess->cached_response_list, tdata); - } - - /* Otherwise for non-request message, send directly to transport. */ - status = sess->cb.on_send_msg(sess, tdata->pkt, tdata->pkt_size, - server, addr_len); - - if (status != PJ_SUCCESS && status != PJ_EPENDING) { - LOG_ERR_(sess, "Error sending STUN request", status); - } - - /* Destroy only when response is not cached*/ - if (tdata->res_timer.id == 0) { - pj_stun_msg_destroy_tdata(sess, tdata); - } - } - - - pj_mutex_unlock(sess->mutex); - return status; -} - - -/* Send response */ -static pj_status_t send_response(pj_stun_session *sess, - pj_pool_t *pool, pj_stun_msg *response, - pj_bool_t retransmission, - const pj_sockaddr_t *addr, unsigned addr_len) -{ - pj_uint8_t *out_pkt; - unsigned out_max_len, out_len; - pj_status_t status; - - /* Alloc packet buffer */ - out_max_len = PJ_STUN_MAX_PKT_LEN; - out_pkt = pj_pool_alloc(pool, out_max_len); - - /* Apply options */ - if (!retransmission) { - apply_msg_options(sess, pool, response); - } - - /* Encode */ - status = pj_stun_msg_encode(response, out_pkt, out_max_len, 0, - get_passwd(sess), &out_len); - if (status != PJ_SUCCESS) { - LOG_ERR_(sess, "Error encoding message", status); - return status; - } - - /* Print log */ - dump_tx_msg(sess, response, out_len, addr); - - /* Send packet */ - status = sess->cb.on_send_msg(sess, out_pkt, out_len, addr, addr_len); - - return status; -} - -/* Authenticate incoming message */ -static pj_status_t authenticate_msg(pj_stun_session *sess, - const pj_uint8_t *pkt, - unsigned pkt_len, - const pj_stun_msg *msg, - pj_pool_t *tmp_pool, - const pj_sockaddr_t *src_addr, - unsigned src_addr_len) -{ - pj_stun_msg *response; - pj_status_t status; - - if (PJ_STUN_IS_ERROR_RESPONSE(msg->hdr.type) || sess->cred == NULL) - return PJ_SUCCESS; - - status = pj_stun_verify_credential(pkt, pkt_len, msg, sess->cred, - tmp_pool, &response); - if (status != PJ_SUCCESS && response != NULL) { - PJ_LOG(5,(SNAME(sess), "Message authentication failed")); - send_response(sess, tmp_pool, response, PJ_FALSE, - src_addr, src_addr_len); - } - - return status; -} - - -/* Handle incoming response */ -static pj_status_t on_incoming_response(pj_stun_session *sess, - pj_stun_msg *msg) -{ - pj_stun_tx_data *tdata; - pj_status_t status; - - /* Lookup pending client transaction */ - tdata = tsx_lookup(sess, msg); - if (tdata == NULL) { - PJ_LOG(4,(SNAME(sess), - "Transaction not found, response silently discarded")); - return PJ_SUCCESS; - } - - /* Pass the response to the transaction. - * If the message is accepted, transaction callback will be called, - * and this will call the session callback too. - */ - status = pj_stun_client_tsx_on_rx_msg(tdata->client_tsx, msg); - if (status != PJ_SUCCESS) { - return status; - } - - /* If transaction has completed, destroy the transmit data. - * This will remove the transaction from the pending list too. - */ - if (pj_stun_client_tsx_is_complete(tdata->client_tsx)) { - pj_stun_msg_destroy_tdata(sess, tdata); - tdata = NULL; - } - - return PJ_SUCCESS; -} - - -/* For requests, check if we cache the response */ -static pj_status_t check_cached_response(pj_stun_session *sess, - pj_pool_t *tmp_pool, - const pj_stun_msg *msg, - const pj_sockaddr_t *src_addr, - unsigned src_addr_len) -{ - pj_stun_tx_data *t; - - /* First lookup response in response cache */ - t = sess->cached_response_list.next; - while (t != &sess->cached_response_list) { - if (t->msg_magic == msg->hdr.magic && - pj_memcmp(t->msg_key, msg->hdr.tsx_id, - sizeof(msg->hdr.tsx_id))==0) - { - break; - } - t = t->next; - } - - if (t != &sess->cached_response_list) { - /* Found response in the cache */ - - PJ_LOG(5,(SNAME(sess), - "Request retransmission, sending cached response")); - - send_response(sess, tmp_pool, t->msg, PJ_TRUE, - src_addr, src_addr_len); - return PJ_SUCCESS; - } - - return PJ_ENOTFOUND; -} - -/* Handle incoming request */ -static pj_status_t on_incoming_request(pj_stun_session *sess, - pj_pool_t *tmp_pool, - const pj_uint8_t *in_pkt, - unsigned in_pkt_len, - const pj_stun_msg *msg, - const pj_sockaddr_t *src_addr, - unsigned src_addr_len) -{ - pj_status_t status; - - /* Distribute to handler, or respond with Bad Request */ - if (sess->cb.on_rx_request) { - status = (*sess->cb.on_rx_request)(sess, in_pkt, in_pkt_len, msg, - src_addr, src_addr_len); - } else { - pj_stun_msg *response; - - status = pj_stun_msg_create_response(tmp_pool, msg, - PJ_STUN_SC_BAD_REQUEST, NULL, - &response); - if (status == PJ_SUCCESS && response) { - status = send_response(sess, tmp_pool, response, - PJ_FALSE, src_addr, src_addr_len); - } - } - - return status; -} - - -/* Handle incoming indication */ -static pj_status_t on_incoming_indication(pj_stun_session *sess, - pj_pool_t *tmp_pool, - const pj_uint8_t *in_pkt, - unsigned in_pkt_len, - const pj_stun_msg *msg, - const pj_sockaddr_t *src_addr, - unsigned src_addr_len) -{ - PJ_UNUSED_ARG(tmp_pool); - - /* Distribute to handler */ - if (sess->cb.on_rx_indication) { - return (*sess->cb.on_rx_indication)(sess, in_pkt, in_pkt_len, msg, - src_addr, src_addr_len); - } else { - return PJ_SUCCESS; - } -} - - -PJ_DEF(pj_status_t) pj_stun_session_on_rx_pkt(pj_stun_session *sess, - const void *packet, - pj_size_t pkt_size, - unsigned options, - unsigned *parsed_len, - const pj_sockaddr_t *src_addr, - unsigned src_addr_len) -{ - pj_stun_msg *msg, *response; - pj_pool_t *tmp_pool; - char *dump; - pj_status_t status; - - PJ_ASSERT_RETURN(sess && packet && pkt_size, PJ_EINVAL); - - tmp_pool = pj_pool_create(sess->endpt->pf, "tmpstun", 1024, 1024, NULL); - if (!tmp_pool) - return PJ_ENOMEM; - - /* Try to parse the message */ - status = pj_stun_msg_decode(tmp_pool, (const pj_uint8_t*)packet, - pkt_size, options, - &msg, parsed_len, &response); - if (status != PJ_SUCCESS) { - LOG_ERR_(sess, "STUN msg_decode() error", status); - if (response) { - send_response(sess, tmp_pool, response, - PJ_FALSE, src_addr, src_addr_len); - } - pj_pool_release(tmp_pool); - return status; - } - - dump = pj_pool_alloc(tmp_pool, PJ_STUN_MAX_PKT_LEN); - - PJ_LOG(5,(SNAME(sess), - "RX STUN message:\n" - "--- begin STUN message ---\n" - "%s" - "--- end of STUN message ---\n", - pj_stun_msg_dump(msg, dump, PJ_STUN_MAX_PKT_LEN, NULL))); - - pj_mutex_lock(sess->mutex); - - /* For requests, check if we have cached response */ - status = check_cached_response(sess, tmp_pool, msg, - src_addr, src_addr_len); - if (status == PJ_SUCCESS) { - goto on_return; - } - - /* Authenticate the message */ - status = authenticate_msg(sess, packet, pkt_size, msg, tmp_pool, - src_addr, src_addr_len); - if (status != PJ_SUCCESS) { - goto on_return; - } - - /* Handle message */ - if (PJ_STUN_IS_RESPONSE(msg->hdr.type) || - PJ_STUN_IS_ERROR_RESPONSE(msg->hdr.type)) - { - status = on_incoming_response(sess, msg); - - } else if (PJ_STUN_IS_REQUEST(msg->hdr.type)) { - - status = on_incoming_request(sess, tmp_pool, packet, pkt_size, msg, - src_addr, src_addr_len); - - } else if (PJ_STUN_IS_INDICATION(msg->hdr.type)) { - - status = on_incoming_indication(sess, tmp_pool, packet, pkt_size, - msg, src_addr, src_addr_len); - - } else { - pj_assert(!"Unexpected!"); - status = PJ_EBUG; - } - -on_return: - pj_mutex_unlock(sess->mutex); - - pj_pool_release(tmp_pool); - return status; -} - - diff --git a/pjlib-util/src/pjlib-util/stun_transaction.c b/pjlib-util/src/pjlib-util/stun_transaction.c deleted file mode 100644 index 0000e3a6..00000000 --- a/pjlib-util/src/pjlib-util/stun_transaction.c +++ /dev/null @@ -1,315 +0,0 @@ -/* $Id$ */ -/* - * Copyright (C) 2003-2005 Benny Prijono - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ -#include -#include -#include -#include -#include -#include -#include - - -#define TIMER_ACTIVE 1 - - -struct pj_stun_client_tsx -{ - char obj_name[PJ_MAX_OBJ_NAME]; - pj_stun_endpoint *endpt; - pj_stun_tsx_cb cb; - void *user_data; - - pj_bool_t complete; - \ - pj_bool_t require_retransmit; - pj_timer_entry timer; - unsigned transmit_count; - pj_time_val retransmit_time; - - void *last_pkt; - unsigned last_pkt_size; -}; - - -static void retransmit_timer_callback(pj_timer_heap_t *timer_heap, - pj_timer_entry *timer); - -static void stun_perror(pj_stun_client_tsx *tsx, const char *title, - pj_status_t status) -{ - char errmsg[PJ_ERR_MSG_SIZE]; - - pj_strerror(status, errmsg, sizeof(errmsg)); - PJ_LOG(4,(tsx->obj_name, "%s: %s", title, errmsg)); -} - - -/* - * Create a STUN client transaction. - */ -PJ_DEF(pj_status_t) pj_stun_client_tsx_create(pj_stun_endpoint *endpt, - pj_pool_t *pool, - const pj_stun_tsx_cb *cb, - pj_stun_client_tsx **p_tsx) -{ - pj_stun_client_tsx *tsx; - - PJ_ASSERT_RETURN(endpt && cb && p_tsx, PJ_EINVAL); - PJ_ASSERT_RETURN(cb->on_send_msg, PJ_EINVAL); - - tsx = PJ_POOL_ZALLOC_T(pool, pj_stun_client_tsx); - tsx->endpt = endpt; - pj_memcpy(&tsx->cb, cb, sizeof(*cb)); - - tsx->timer.cb = &retransmit_timer_callback; - tsx->timer.user_data = tsx; - - pj_ansi_snprintf(tsx->obj_name, sizeof(tsx->obj_name), "stuntsx%p", tsx); - - *p_tsx = tsx; - - PJ_LOG(4,(tsx->obj_name, "STUN client transaction created")); - return PJ_SUCCESS; -} - - -/* - * . - */ -PJ_DEF(pj_status_t) pj_stun_client_tsx_destroy(pj_stun_client_tsx *tsx) -{ - PJ_ASSERT_RETURN(tsx, PJ_EINVAL); - - if (tsx->timer.id != 0) { - pj_timer_heap_cancel(tsx->endpt->timer_heap, &tsx->timer); - tsx->timer.id = 0; - } - return PJ_SUCCESS; -} - - -/* - * Check if transaction has completed. - */ -PJ_DEF(pj_bool_t) pj_stun_client_tsx_is_complete(pj_stun_client_tsx *tsx) -{ - PJ_ASSERT_RETURN(tsx, PJ_FALSE); - return tsx->complete; -} - - -/* - * Set user data. - */ -PJ_DEF(pj_status_t) pj_stun_client_tsx_set_data(pj_stun_client_tsx *tsx, - void *data) -{ - PJ_ASSERT_RETURN(tsx, PJ_EINVAL); - tsx->user_data = data; - return PJ_SUCCESS; -} - - -/* - * Get the user data - */ -PJ_DEF(void*) pj_stun_client_tsx_get_data(pj_stun_client_tsx *tsx) -{ - PJ_ASSERT_RETURN(tsx, NULL); - return tsx->user_data; -} - - -/* - * Transmit message. - */ -static pj_status_t tsx_transmit_msg(pj_stun_client_tsx *tsx) -{ - pj_status_t status; - - PJ_ASSERT_RETURN(tsx->timer.id == 0, PJ_EBUSY); - - if (tsx->require_retransmit) { - /* Calculate retransmit/timeout delay */ - if (tsx->transmit_count == 0) { - tsx->retransmit_time.sec = 0; - tsx->retransmit_time.msec = tsx->endpt->rto_msec; - - } else if (tsx->transmit_count < PJ_STUN_MAX_RETRANSMIT_COUNT-1) { - unsigned msec; - - msec = PJ_TIME_VAL_MSEC(tsx->retransmit_time); - msec = (msec << 1) + 100; - tsx->retransmit_time.sec = msec / 1000; - tsx->retransmit_time.msec = msec % 1000; - - } else { - tsx->retransmit_time.sec = PJ_STUN_TIMEOUT_VALUE / 1000; - tsx->retransmit_time.msec = PJ_STUN_TIMEOUT_VALUE % 1000; - } - - /* Schedule timer first because when send_msg() failed we can - * cancel it (as opposed to when schedule_timer() failed we cannot - * cancel transmission). - */; - status = pj_timer_heap_schedule(tsx->endpt->timer_heap, &tsx->timer, - &tsx->retransmit_time); - if (status != PJ_SUCCESS) { - tsx->timer.id = 0; - return status; - } - tsx->timer.id = TIMER_ACTIVE; - } - - - /* Send message */ - status = tsx->cb.on_send_msg(tsx, tsx->last_pkt, tsx->last_pkt_size); - if (status != PJ_SUCCESS) { - if (tsx->timer.id != 0) { - pj_timer_heap_cancel(tsx->endpt->timer_heap, &tsx->timer); - tsx->timer.id = 0; - } - stun_perror(tsx, "STUN error sending message", status); - return status; - } - - tsx->transmit_count++; - - PJ_LOG(4,(tsx->obj_name, "STUN sending message (transmit count=%d)", - tsx->transmit_count)); - return status; -} - - -/* - * Send outgoing message and start STUN transaction. - */ -PJ_DEF(pj_status_t) pj_stun_client_tsx_send_msg(pj_stun_client_tsx *tsx, - pj_bool_t retransmit, - void *pkt, - unsigned pkt_len) -{ - PJ_ASSERT_RETURN(tsx && pkt && pkt_len, PJ_EINVAL); - PJ_ASSERT_RETURN(tsx->timer.id == 0, PJ_EBUSY); - - /* Encode message */ - tsx->last_pkt = pkt; - tsx->last_pkt_size = pkt_len; - - /* Update STUN retransmit flag */ - tsx->require_retransmit = retransmit; - - /* Send the message */ - return tsx_transmit_msg(tsx); -} - - -/* Retransmit timer callback */ -static void retransmit_timer_callback(pj_timer_heap_t *timer_heap, - pj_timer_entry *timer) -{ - pj_stun_client_tsx *tsx = (pj_stun_client_tsx *) timer->user_data; - pj_status_t status; - - PJ_UNUSED_ARG(timer_heap); - - if (tsx->transmit_count >= PJ_STUN_MAX_RETRANSMIT_COUNT) { - /* Retransmission count exceeded. Transaction has failed */ - tsx->timer.id = 0; - PJ_LOG(4,(tsx->obj_name, "STUN timeout waiting for response")); - tsx->complete = PJ_TRUE; - if (tsx->cb.on_complete) { - tsx->cb.on_complete(tsx, PJLIB_UTIL_ESTUNNOTRESPOND, NULL); - } - return; - } - - tsx->timer.id = 0; - status = tsx_transmit_msg(tsx); - if (status != PJ_SUCCESS) { - tsx->timer.id = 0; - tsx->complete = PJ_TRUE; - if (tsx->cb.on_complete) { - tsx->cb.on_complete(tsx, status, NULL); - } - } -} - - - -/* - * Notify the STUN transaction about the arrival of STUN response. - */ -PJ_DEF(pj_status_t) pj_stun_client_tsx_on_rx_msg(pj_stun_client_tsx *tsx, - const pj_stun_msg *msg) -{ - pj_stun_errcode_attr *err_attr; - pj_status_t status; - - /* Must be STUN response message */ - if (!PJ_STUN_IS_RESPONSE(msg->hdr.type) && - !PJ_STUN_IS_ERROR_RESPONSE(msg->hdr.type)) - { - PJ_LOG(4,(tsx->obj_name, - "STUN rx_msg() error: not response message")); - return PJLIB_UTIL_ESTUNNOTRESPONSE; - } - - - /* We have a response with matching transaction ID. - * We can cancel retransmit timer now. - */ - if (tsx->timer.id) { - pj_timer_heap_cancel(tsx->endpt->timer_heap, &tsx->timer); - tsx->timer.id = 0; - } - - /* Find STUN error code attribute */ - err_attr = (pj_stun_errcode_attr*) - pj_stun_msg_find_attr(msg, PJ_STUN_ATTR_ERROR_CODE, 0); - - if (err_attr && err_attr->err_class <= 2) { - /* draft-ietf-behave-rfc3489bis-05.txt Section 8.3.2: - * Any response between 100 and 299 MUST result in the cessation - * of request retransmissions, but otherwise is discarded. - */ - PJ_LOG(4,(tsx->obj_name, - "STUN rx_msg() error: received provisional %d code (%.*s)", - err_attr->err_class * 100 + err_attr->number, - (int)err_attr->reason.slen, - err_attr->reason.ptr)); - return PJ_SUCCESS; - } - - if (err_attr == NULL) { - status = PJ_SUCCESS; - } else { - status = PJLIB_UTIL_ESTUNTSXFAILED; - } - - /* Call callback */ - tsx->complete = PJ_TRUE; - if (tsx->cb.on_complete) { - tsx->cb.on_complete(tsx, status, msg); - } - - return PJ_SUCCESS; - -} - diff --git a/pjlib-util/src/pjstun-client/client_main.c b/pjlib-util/src/pjstun-client/client_main.c deleted file mode 100644 index be65b516..00000000 --- a/pjlib-util/src/pjstun-client/client_main.c +++ /dev/null @@ -1,680 +0,0 @@ -/* $Id$ */ -/* - * Copyright (C) 2003-2005 Benny Prijono - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ -#include -#include - - -#define THIS_FILE "client_main.c" -#define LOCAL_PORT 1998 -#define BANDWIDTH 64 /* -1 to disable */ -#define LIFETIME 600 /* -1 to disable */ -#define REQ_TRANSPORT -1 /* 0: udp, 1: tcp, -1: disable */ -#define REQ_PORT_PROPS -1 /* -1 to disable */ -#define REQ_IP NULL /* IP address string */ - - -static struct global -{ - pj_stun_endpoint *endpt; - pj_pool_t *pool; - pj_caching_pool cp; - pj_timer_heap_t *th; - pj_stun_session *sess; - pj_sock_t sock; - pj_thread_t *thread; - pj_bool_t quit; - pj_sockaddr_in peer_addr; - pj_sockaddr_in srv_addr; - pj_sockaddr_in relay_addr; - char data_buf[256]; - char *data; -} g; - -static struct options -{ - char *srv_addr; - char *srv_port; - char *realm; - char *user_name; - char *password; - char *nonce; - char *peer_addr; - pj_bool_t use_fingerprint; -} o; - - -static pj_status_t parse_addr(const char *input, pj_sockaddr_in *addr); - - -static my_perror(const char *title, pj_status_t status) -{ - char errmsg[PJ_ERR_MSG_SIZE]; - pj_strerror(status, errmsg, sizeof(errmsg)); - - PJ_LOG(3,(THIS_FILE, "%s: %s", title, errmsg)); -} - -static pj_status_t on_send_msg(pj_stun_session *sess, - const void *pkt, - pj_size_t pkt_size, - const pj_sockaddr_t *srv_addr, - unsigned addr_len) -{ - pj_ssize_t len; - pj_status_t status; - - len = pkt_size; - status = pj_sock_sendto(g.sock, pkt, &len, 0, srv_addr, addr_len); - - if (status != PJ_SUCCESS) - my_perror("Error sending packet", status); - - return status; -} - -static void on_request_complete(pj_stun_session *sess, - pj_status_t status, - pj_stun_tx_data *tdata, - const pj_stun_msg *response) -{ - if (status == PJ_SUCCESS) { - switch (response->hdr.type) { - case PJ_STUN_ALLOCATE_RESPONSE: - { - pj_stun_relay_addr_attr *ar; - - ar = (pj_stun_relay_addr_attr*) - pj_stun_msg_find_attr(response, - PJ_STUN_ATTR_RELAY_ADDR, 0); - if (ar) { - pj_memcpy(&g.relay_addr, &ar->addr.ipv4, - sizeof(pj_sockaddr_in)); - PJ_LOG(3,(THIS_FILE, "Relay address is %s:%d", - pj_inet_ntoa(g.relay_addr.sin_addr), - (int)pj_ntohs(g.relay_addr.sin_port))); - } else { - pj_memset(&g.relay_addr, 0, sizeof(g.relay_addr)); - } - } - break; - } - } else { - my_perror("Client transaction error", status); - } -} - -static int worker_thread(void *unused) -{ - PJ_UNUSED_ARG(unused); - - while (!g.quit) { - pj_time_val timeout = {0, 50}; - pj_fd_set_t readset; - int n; - - pj_timer_heap_poll(g.th, NULL); - - PJ_FD_ZERO(&readset); - PJ_FD_SET(g.sock, &readset); - - n = pj_sock_select(g.sock+1, &readset, NULL, NULL, &timeout); - if (n > 0) { - if (PJ_FD_ISSET(g.sock, &readset)) { - char buffer[512]; - pj_ssize_t len; - pj_sockaddr_in addr; - int addrlen; - pj_status_t rc; - - len = sizeof(buffer); - addrlen = sizeof(addr); - rc = pj_sock_recvfrom(g.sock, buffer, &len, 0, &addr, &addrlen); - if (rc != PJ_SUCCESS || len <= 0) - continue; - - if (pj_stun_msg_check(buffer, len, PJ_STUN_IS_DATAGRAM)==PJ_SUCCESS) { - rc = pj_stun_session_on_rx_pkt(g.sess, buffer, len, - 0, - NULL, &addr, addrlen); - if (rc != PJ_SUCCESS) - my_perror("Error processing packet", rc); - - } else { - buffer[len] = '\0'; - PJ_LOG(3,(THIS_FILE, "Received data: %s", (char*)buffer)); - } - } - } else if (n < 0) - pj_thread_sleep(50); - } - - return 0; -} - -static int init() -{ - pj_sockaddr_in addr; - pj_stun_session_cb stun_cb; - int len; - pj_status_t status; - - g.sock = PJ_INVALID_SOCKET; - - status = pj_init(); - status = pjlib_util_init(); - - pj_caching_pool_init(&g.cp, &pj_pool_factory_default_policy, 0); - - if (o.srv_addr) { - pj_str_t s; - pj_uint16_t port; - - if (o.srv_port) - port = (pj_uint16_t) atoi(o.srv_port); - else - port = PJ_STUN_PORT; - - status = pj_sockaddr_in_init(&g.srv_addr, pj_cstr(&s, o.srv_addr), port); - if (status != PJ_SUCCESS) { - my_perror("Invalid address", status); - return status; - } - - printf("Destination address set to %s:%d\n", o.srv_addr, (int)port); - } else { - printf("Error: address must be specified\n"); - return PJ_EINVAL; - } - - g.pool = pj_pool_create(&g.cp.factory, NULL, 1000, 1000, NULL); - - status = pj_timer_heap_create(g.pool, 1000, &g.th); - pj_assert(status == PJ_SUCCESS); - - status = pj_stun_endpoint_create(&g.cp.factory, 0, NULL, g.th, &g.endpt); - pj_assert(status == PJ_SUCCESS); - - status = pj_sock_socket(PJ_AF_INET, PJ_SOCK_DGRAM, 0, &g.sock); - pj_assert(status == PJ_SUCCESS); - - status = pj_sockaddr_in_init(&addr, NULL, 0); - pj_assert(status == PJ_SUCCESS); - - addr.sin_port = pj_htons((pj_uint16_t)LOCAL_PORT); - status = pj_sock_bind(g.sock, &addr, sizeof(addr)); - pj_assert(status == PJ_SUCCESS); - - len = sizeof(addr); - status = pj_sock_getsockname(g.sock, &addr, &len); - pj_assert(status == PJ_SUCCESS); - - PJ_LOG(3,(THIS_FILE, "Listening on port %d", (int)pj_ntohs(addr.sin_port))); - - pj_memcpy(&g.peer_addr, &addr, sizeof(pj_sockaddr_in)); - if (g.peer_addr.sin_addr.s_addr == 0) - pj_gethostip(&g.peer_addr.sin_addr); - - pj_memset(&stun_cb, 0, sizeof(stun_cb)); - stun_cb.on_send_msg = &on_send_msg; - stun_cb.on_request_complete = &on_request_complete; - - status = pj_stun_session_create(g.endpt, NULL, &stun_cb, - o.use_fingerprint!=0, &g.sess); - pj_assert(status == PJ_SUCCESS); - - if (o.user_name) { - pj_stun_auth_cred cred; - - pj_bzero(&cred, sizeof(cred)); - - cred.type = PJ_STUN_AUTH_CRED_STATIC; - cred.data.static_cred.realm = pj_str(o.realm); - cred.data.static_cred.username = pj_str(o.user_name); - cred.data.static_cred.data_type = 0; - cred.data.static_cred.data = pj_str(o.password); - cred.data.static_cred.nonce = pj_str(o.nonce); - - pj_stun_session_set_credential(g.sess, &cred); - puts("Session credential set"); - } else { - puts("Credential not set"); - } - - if (o.peer_addr) { - if (parse_addr(o.peer_addr, &g.peer_addr)!=PJ_SUCCESS) - return -1; - } - - status = pj_thread_create(g.pool, "stun", &worker_thread, NULL, - 0, 0, &g.thread); - if (status != PJ_SUCCESS) - return status; - - return PJ_SUCCESS; -} - - -static int shutdown() -{ - if (g.thread) { - g.quit = 1; - pj_thread_join(g.thread); - pj_thread_destroy(g.thread); - g.thread = NULL; - } - if (g.sess) - pj_stun_session_destroy(g.sess); - if (g.endpt) - pj_stun_endpoint_destroy(g.endpt); - if (g.sock != PJ_INVALID_SOCKET) - pj_sock_close(g.sock); - if (g.th) - pj_timer_heap_destroy(g.th); - if (g.pool) - pj_pool_release(g.pool); - - pj_pool_factory_dump(&g.cp.factory, PJ_TRUE); - pj_caching_pool_destroy(&g.cp); - - return PJ_SUCCESS; -} - -static void send_bind_request(void) -{ - pj_stun_tx_data *tdata; - pj_status_t rc; - - rc = pj_stun_session_create_req(g.sess, PJ_STUN_BINDING_REQUEST, &tdata); - pj_assert(rc == PJ_SUCCESS); - - rc = pj_stun_session_send_msg(g.sess, PJ_FALSE, - &g.srv_addr, sizeof(g.srv_addr), - tdata); - if (rc != PJ_SUCCESS) - my_perror("Error sending STUN request", rc); -} - -static void send_allocate_request(pj_bool_t allocate) -{ - pj_stun_tx_data *tdata; - pj_status_t rc; - - rc = pj_stun_session_create_req(g.sess, PJ_STUN_ALLOCATE_REQUEST, &tdata); - pj_assert(rc == PJ_SUCCESS); - - - if (BANDWIDTH != -1) { - pj_stun_msg_add_uint_attr(tdata->pool, tdata->msg, - PJ_STUN_ATTR_BANDWIDTH, BANDWIDTH); - } - - if (!allocate) { - pj_stun_msg_add_uint_attr(tdata->pool, tdata->msg, - PJ_STUN_ATTR_LIFETIME, 0); - - } else { - if (LIFETIME != -1) { - pj_stun_msg_add_uint_attr(tdata->pool, tdata->msg, - PJ_STUN_ATTR_LIFETIME, LIFETIME); - } - - if (REQ_TRANSPORT != -1) { - pj_stun_msg_add_uint_attr(tdata->pool, tdata->msg, - PJ_STUN_ATTR_REQ_TRANSPORT, REQ_TRANSPORT); - } - - if (REQ_PORT_PROPS != -1) { - pj_stun_msg_add_uint_attr(tdata->pool, tdata->msg, - PJ_STUN_ATTR_REQ_PORT_PROPS, REQ_PORT_PROPS); - } - - if (REQ_IP != NULL) { - pj_sockaddr_in addr; - pj_str_t tmp; - - pj_sockaddr_in_init(&addr, pj_cstr(&tmp, REQ_IP), 0); - pj_stun_msg_add_sockaddr_attr(tdata->pool, tdata->msg, - PJ_STUN_ATTR_REQ_IP, PJ_FALSE, - &addr, sizeof(addr)); - } - } - - rc = pj_stun_session_send_msg(g.sess, PJ_FALSE, - &g.srv_addr, sizeof(g.srv_addr), - tdata); - pj_assert(rc == PJ_SUCCESS); -} - -static void send_sad_request(pj_bool_t set) -{ - pj_stun_tx_data *tdata; - pj_status_t rc; - - if (g.peer_addr.sin_addr.s_addr == 0 || - g.peer_addr.sin_port == 0) - { - puts("Error: peer address is not set"); - return; - } - - rc = pj_stun_session_create_req(g.sess, PJ_STUN_SET_ACTIVE_DESTINATION_REQUEST, &tdata); - pj_assert(rc == PJ_SUCCESS); - - if (set) { - pj_stun_msg_add_sockaddr_attr(tdata->pool, tdata->msg, - PJ_STUN_ATTR_REMOTE_ADDR, PJ_FALSE, - &g.peer_addr, sizeof(g.peer_addr)); - } - - rc = pj_stun_session_send_msg(g.sess, PJ_FALSE, - &g.srv_addr, sizeof(g.srv_addr), - tdata); - pj_assert(rc == PJ_SUCCESS); -} - -static void send_send_ind(void) -{ - pj_stun_tx_data *tdata; - int len; - pj_status_t rc; - - if (g.peer_addr.sin_addr.s_addr == 0 || - g.peer_addr.sin_port == 0) - { - puts("Error: peer address is not set"); - return; - } - - len = strlen(g.data); - if (len==0) { - puts("Error: data is not set"); - return; - } - - rc = pj_stun_session_create_ind(g.sess, PJ_STUN_SEND_INDICATION, &tdata); - pj_assert(rc == PJ_SUCCESS); - - pj_stun_msg_add_sockaddr_attr(tdata->pool, tdata->msg, - PJ_STUN_ATTR_REMOTE_ADDR, PJ_FALSE, - &g.peer_addr, sizeof(g.peer_addr)); - pj_stun_msg_add_binary_attr(tdata->pool, tdata->msg, - PJ_STUN_ATTR_DATA, g.data, len); - - rc = pj_stun_session_send_msg(g.sess, PJ_FALSE, - &g.srv_addr, sizeof(g.srv_addr), - tdata); - pj_assert(rc == PJ_SUCCESS); - -} - -static void send_raw_data_to_srv(void) -{ - pj_ssize_t len; - - if (g.srv_addr.sin_addr.s_addr == 0 || - g.srv_addr.sin_port == 0) - { - puts("Error: server address is not set"); - return; - } - - len = strlen(g.data); - if (len==0) { - puts("Error: data is not set"); - return; - } - - len = strlen(g.data); - pj_sock_sendto(g.sock, g.data, &len, 0, &g.srv_addr, sizeof(g.srv_addr)); -} - -static void send_raw_data_to_relay(void) -{ - pj_ssize_t len; - - if (g.relay_addr.sin_addr.s_addr == 0 || - g.relay_addr.sin_port == 0) - { - puts("Error: relay address is not set"); - return; - } - - len = strlen(g.data); - if (len==0) { - puts("Error: data is not set"); - return; - } - - len = strlen(g.data); - pj_sock_sendto(g.sock, g.data, &len, 0, &g.relay_addr, sizeof(g.relay_addr)); -} - -static pj_status_t parse_addr(const char *input, - pj_sockaddr_in *addr) -{ - const char *pos; - pj_str_t ip; - pj_uint16_t port; - pj_sockaddr_in tmp_addr; - - pos = pj_ansi_strchr(input, ':'); - if (pos==NULL) { - puts("Invalid format"); - return -1; - } - - ip.ptr = (char*)input; - ip.slen = pos - input; - port = (pj_uint16_t)atoi(pos+1); - - if (port==0) { - puts("Invalid port"); - return -1; - } - - if (pj_sockaddr_in_init(&tmp_addr, &ip, port)!=PJ_SUCCESS) { - puts("Invalid address"); - return -1; - } - - pj_memcpy(addr, &tmp_addr, sizeof(tmp_addr)); - - return PJ_SUCCESS; -} - -static void set_peer_addr(void) -{ - char addr[64]; - - printf("Current peer address: %s:%d\n", - pj_inet_ntoa(g.peer_addr.sin_addr), - pj_ntohs(g.peer_addr.sin_port)); - - printf("Input peer address in IP:PORT format: "); - fflush(stdout); - gets(addr); - - if (parse_addr(addr, &g.peer_addr) != PJ_SUCCESS) { - return; - } - -} - -static void menu(void) -{ - puts("Menu:"); - printf(" pr Set peer address (currently %s:%d)\n", - pj_inet_ntoa(g.peer_addr.sin_addr), pj_ntohs(g.peer_addr.sin_port)); - printf(" dt Set data (currently \"%s\")\n", g.data); - puts(" br Send Bind request"); - puts(" ar Send Allocate request"); - puts(" dr Send de-Allocate request"); - puts(" sr Send Set Active Destination request"); - puts(" cr Send clear Active Destination request"); - puts(" si Send data with Send Indication"); - puts(" rw Send raw data to TURN server"); - puts(" rW Send raw data to relay address"); - puts(" q Quit"); - puts(""); - printf("Choice: "); -} - - -static void console_main(void) -{ - while (!g.quit) { - char input[10]; - - menu(); - - fgets(input, sizeof(input), stdin); - - if (0) { - - } else if (input[0]=='d' && input[1]=='t') { - printf("Input data: "); - gets(g.data); - - } else if (input[0]=='p' && input[1]=='r') { - set_peer_addr(); - - } else if (input[0]=='b' && input[1]=='r') { - send_bind_request(); - - } else if (input[0]=='a' && input[1]=='r') { - send_allocate_request(PJ_TRUE); - - } else if (input[0]=='d' && input[1]=='r') { - send_allocate_request(PJ_FALSE); - - } else if (input[0]=='s' && input[1]=='r') { - send_sad_request(PJ_TRUE); - - } else if (input[0]=='c' && input[1]=='r') { - send_sad_request(PJ_FALSE); - - } else if (input[0]=='s' && input[1]=='i') { - send_send_ind(); - - } else if (input[0]=='r' && input[1]=='w') { - send_raw_data_to_srv(); - - } else if (input[0]=='r' && input[1]=='W') { - send_raw_data_to_relay(); - - } else if (input[0]=='q') { - g.quit = 1; - } - } -} - - -static void usage(void) -{ - puts("Usage: pjstun_client TARGET [OPTIONS]"); - puts(""); - puts("where TARGET is \"host[:port]\""); - puts(""); - puts("and OPTIONS:"); - puts(" --realm, -r Set realm of the credential"); - puts(" --username, -u Set username of the credential"); - puts(" --password, -p Set password of the credential"); - puts(" --nonce, -N Set NONCE"); - puts(" --fingerprint, -F Use fingerprint for outgoing requests"); - puts(" --peer, -P Set peer address (address is in HOST:PORT format)"); - puts(" --data, -D Set data"); - puts(" --help, -h"); -} - -int main(int argc, char *argv[]) -{ - struct pj_getopt_option long_options[] = { - { "realm", 1, 0, 'r'}, - { "username", 1, 0, 'u'}, - { "password", 1, 0, 'p'}, - { "nonce", 1, 0, 'N'}, - { "fingerprint",0, 0, 'F'}, - { "peer", 1, 0, 'P'}, - { "data", 1, 0, 'D'}, - { "help", 0, 0, 'h'} - }; - int c, opt_id; - char *pos; - pj_status_t status; - - g.data = g.data_buf; - - while((c=pj_getopt_long(argc,argv, "r:u:p:hF", long_options, &opt_id))!=-1) { - switch (c) { - case 'r': - o.realm = pj_optarg; - break; - case 'u': - o.user_name = pj_optarg; - break; - case 'p': - o.password = pj_optarg; - break; - case 'N': - o.nonce = pj_optarg; - break; - case 'h': - usage(); - return 0; - case 'F': - o.use_fingerprint = PJ_TRUE; - break; - case 'P': - o.peer_addr = pj_optarg; - break; - case 'D': - g.data = pj_optarg; - break; - - default: - printf("Argument \"%s\" is not valid. Use -h to see help", - argv[pj_optind]); - return 1; - } - } - - if (pj_optind == argc) { - puts("Error: TARGET is needed"); - return 1; - } - - if ((pos=pj_ansi_strchr(argv[pj_optind], ':')) != NULL) { - o.srv_addr = argv[pj_optind]; - *pos = '\0'; - o.srv_port = pos+1; - } else { - o.srv_addr = argv[pj_optind]; - } - - status = init(); - if (status != PJ_SUCCESS) - goto on_return; - - console_main(); - -on_return: - shutdown(); - return status ? 1 : 0; -} - diff --git a/pjlib-util/src/pjstun-srv-test/bind_usage.c b/pjlib-util/src/pjstun-srv-test/bind_usage.c deleted file mode 100644 index fc10fb91..00000000 --- a/pjlib-util/src/pjstun-srv-test/bind_usage.c +++ /dev/null @@ -1,206 +0,0 @@ -/* $Id$ */ -/* - * Copyright (C) 2003-2005 Benny Prijono - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ -#include "server.h" - -#define THIS_FILE "bind_usage.c" - -static void usage_on_rx_data(pj_stun_usage *usage, - void *pkt, - pj_size_t pkt_size, - const pj_sockaddr_t *src_addr, - unsigned src_addr_len); -static void usage_on_destroy(pj_stun_usage *usage); -static pj_status_t sess_on_send_msg(pj_stun_session *sess, - const void *pkt, - pj_size_t pkt_size, - const pj_sockaddr_t *dst_addr, - unsigned addr_len); -static pj_status_t sess_on_rx_request(pj_stun_session *sess, - const pj_uint8_t *pkt, - unsigned pkt_len, - const pj_stun_msg *msg, - const pj_sockaddr_t *src_addr, - unsigned src_addr_len); - -struct bind_usage -{ - pj_pool_t *pool; - pj_stun_usage *usage; - pj_stun_session *session; -}; - - -PJ_DEF(pj_status_t) pj_stun_bind_usage_create(pj_stun_server *srv, - const pj_str_t *ip_addr, - unsigned port, - pj_stun_usage **p_bu) -{ - pj_pool_t *pool; - struct bind_usage *bu; - pj_stun_server_info *si; - pj_stun_usage_cb usage_cb; - pj_stun_session_cb sess_cb; - pj_sockaddr_in local_addr; - pj_status_t status; - - si = pj_stun_server_get_info(srv); - - pool = pj_pool_create(si->pf, "bind%p", 128, 128, NULL); - bu = PJ_POOL_ZALLOC_T(pool, struct bind_usage); - bu->pool = pool; - - status = pj_sockaddr_in_init(&local_addr, ip_addr, (pj_uint16_t)port); - if (status != PJ_SUCCESS) - return status; - - pj_bzero(&usage_cb, sizeof(usage_cb)); - usage_cb.on_rx_data = &usage_on_rx_data; - usage_cb.on_destroy = &usage_on_destroy; - - status = pj_stun_usage_create(srv, "bind%p", &usage_cb, - PJ_AF_INET, PJ_SOCK_DGRAM, 0, - &local_addr, sizeof(local_addr), - &bu->usage); - if (status != PJ_SUCCESS) { - pj_pool_release(pool); - return status; - } - - pj_bzero(&sess_cb, sizeof(sess_cb)); - sess_cb.on_send_msg = &sess_on_send_msg; - sess_cb.on_rx_request = &sess_on_rx_request; - status = pj_stun_session_create(si->endpt, "bind%p", &sess_cb, PJ_FALSE, - &bu->session); - if (status != PJ_SUCCESS) { - pj_stun_usage_destroy(bu->usage); - return status; - } - - pj_stun_usage_set_user_data(bu->usage, bu); - pj_stun_session_set_user_data(bu->session, bu); - - if (p_bu) - *p_bu = bu->usage; - - return PJ_SUCCESS; -} - - -static void usage_on_rx_data(pj_stun_usage *usage, - void *pkt, - pj_size_t pkt_size, - const pj_sockaddr_t *src_addr, - unsigned src_addr_len) -{ - struct bind_usage *bu; - pj_stun_session *session; - pj_status_t status; - - bu = (struct bind_usage*) pj_stun_usage_get_user_data(usage); - session = bu->session; - - /* Handle packet to session */ - status = pj_stun_session_on_rx_pkt(session, (pj_uint8_t*)pkt, pkt_size, - PJ_STUN_IS_DATAGRAM | PJ_STUN_CHECK_PACKET, - NULL, src_addr, src_addr_len); - if (status != PJ_SUCCESS) { - pj_stun_perror(THIS_FILE, "Error handling incoming packet", status); - return; - } -} - - -static pj_status_t sess_on_send_msg(pj_stun_session *sess, - const void *pkt, - pj_size_t pkt_size, - const pj_sockaddr_t *dst_addr, - unsigned addr_len) -{ - struct bind_usage *bu; - pj_stun_usage *usage; - - bu = (struct bind_usage*) pj_stun_session_get_user_data(sess); - usage = bu->usage; - - return pj_stun_usage_sendto(usage, pkt, pkt_size, 0, - dst_addr, addr_len); -} - - -static pj_status_t sess_on_rx_request(pj_stun_session *sess, - const pj_uint8_t *pkt, - unsigned pkt_len, - const pj_stun_msg *msg, - const pj_sockaddr_t *src_addr, - unsigned src_addr_len) -{ - pj_stun_tx_data *tdata; - pj_status_t status; - - PJ_UNUSED_ARG(pkt); - PJ_UNUSED_ARG(pkt_len); - - /* Create response */ - status = pj_stun_session_create_response(sess, msg, 0, NULL, &tdata); - if (status != PJ_SUCCESS) - return status; - - /* Create MAPPED-ADDRESS attribute */ - status = pj_stun_msg_add_sockaddr_attr(tdata->pool, tdata->msg, - PJ_STUN_ATTR_MAPPED_ADDR, - PJ_FALSE, - src_addr, src_addr_len); - if (status != PJ_SUCCESS) { - pj_stun_perror(THIS_FILE, "Error creating response", status); - pj_stun_msg_destroy_tdata(sess, tdata); - return status; - } - - /* On the presence of magic, create XOR-MAPPED-ADDRESS attribute */ - if (msg->hdr.magic == PJ_STUN_MAGIC) { - status = - pj_stun_msg_add_sockaddr_attr(tdata->pool, tdata->msg, - PJ_STUN_ATTR_XOR_MAPPED_ADDR, - PJ_TRUE, - src_addr, src_addr_len); - if (status != PJ_SUCCESS) { - pj_stun_perror(THIS_FILE, "Error creating response", status); - pj_stun_msg_destroy_tdata(sess, tdata); - return status; - } - } - - /* Send */ - status = pj_stun_session_send_msg(sess, PJ_TRUE, - src_addr, src_addr_len, tdata); - return status; - -} - -static void usage_on_destroy(pj_stun_usage *usage) -{ - struct bind_usage *bu; - - bu = (struct bind_usage*) pj_stun_usage_get_user_data(usage); - if (bu==NULL) - return; - - pj_stun_session_destroy(bu->session); - pj_pool_release(bu->pool); -} diff --git a/pjlib-util/src/pjstun-srv-test/main.c b/pjlib-util/src/pjstun-srv-test/main.c deleted file mode 100644 index c462d47e..00000000 --- a/pjlib-util/src/pjstun-srv-test/main.c +++ /dev/null @@ -1,146 +0,0 @@ -/* $Id$ */ -/* - * Copyright (C) 2003-2005 Benny Prijono - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ -#include "server.h" - -#define THIS_FILE "main.c" - -struct options -{ - char *realm; - char *user_name; - char *password; - char *nonce; - pj_bool_t use_fingerprint; -} o; - -static void usage(void) -{ - puts("Usage: pjstun_srv_test [OPTIONS]"); - puts(""); - puts("where OPTIONS:"); - puts(" --realm, -r Set realm of the credential"); - puts(" --username, -u Set username of the credential"); - puts(" --password, -p Set password of the credential"); - puts(" --nonce, -N Set NONCE"); - puts(" --fingerprint, -F Use fingerprint for outgoing requests"); - puts(" --help, -h"); -} - - -static void server_main(pj_stun_server *srv) -{ - int quit = 0; - - while (!quit) { - char line[10]; - - printf("Menu:\n" - " d Dump status\n" - " q Quit\n" - "Choice:"); - - fgets(line, sizeof(line), stdin); - if (line[0] == 'q') { - quit = 1; - } else if (line[0] == 'd') { - pj_stun_server_info *si = pj_stun_server_get_info(srv); - pj_pool_factory_dump(si->pf, PJ_TRUE); - } - } -} - -int main(int argc, char *argv[]) -{ - struct pj_getopt_option long_options[] = { - { "realm", 1, 0, 'r'}, - { "username", 1, 0, 'u'}, - { "password", 1, 0, 'p'}, - { "nonce", 1, 0, 'N'}, - { "fingerprint",0, 0, 'F'}, - { "help", 0, 0, 'h'} - }; - int c, opt_id; - pj_caching_pool cp; - pj_stun_server *srv; - pj_status_t status; - - while((c=pj_getopt_long(argc,argv, "r:u:p:hF", long_options, &opt_id))!=-1) { - switch (c) { - case 'r': - o.realm = pj_optarg; - break; - case 'u': - o.user_name = pj_optarg; - break; - case 'p': - o.password = pj_optarg; - break; - case 'N': - o.nonce = pj_optarg; - break; - case 'h': - usage(); - return 0; - case 'F': - o.use_fingerprint = PJ_TRUE; - break; - default: - printf("Argument \"%s\" is not valid. Use -h to see help", - argv[pj_optind]); - return 1; - } - } - - if (pj_optind != argc) { - puts("Error: invalid arguments"); - return 1; - } - - pj_init(); - pjlib_util_init(); - pj_caching_pool_init(&cp, &pj_pool_factory_default_policy, 0); - - status = pj_stun_server_create(&cp.factory, 1, &srv); - if (status != PJ_SUCCESS) { - pj_stun_perror(THIS_FILE, "Unable to create server", status); - return 1; - } - - /* - status = pj_stun_bind_usage_create(srv, NULL, 3478, NULL); - if (status != PJ_SUCCESS) { - pj_stun_perror(THIS_FILE, "Unable to create bind usage", status); - return 1; - } - */ - - status = pj_stun_turn_usage_create(srv, PJ_SOCK_DGRAM, NULL, - 3478, NULL); - if (status != PJ_SUCCESS) { - pj_stun_perror(THIS_FILE, "Unable to create bind usage", status); - return 1; - } - - server_main(srv); - - pj_stun_server_destroy(srv); - pj_pool_factory_dump(&cp.factory, PJ_TRUE); - pj_shutdown(); - return 0; -} diff --git a/pjlib-util/src/pjstun-srv-test/server.c b/pjlib-util/src/pjstun-srv-test/server.c deleted file mode 100644 index 5fdb233e..00000000 --- a/pjlib-util/src/pjstun-srv-test/server.c +++ /dev/null @@ -1,185 +0,0 @@ -/* $Id$ */ -/* - * Copyright (C) 2003-2005 Benny Prijono - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "server.h" - -#define THIS_FILE "server.c" - -struct pj_stun_server -{ - pj_stun_server_info si; - - pj_pool_t *pool; - - pj_bool_t thread_quit_flag; - pj_thread_t **threads; - - unsigned usage_cnt; - pj_stun_usage *usage[32]; -}; - -PJ_DEF(pj_status_t) pj_stun_perror( const char *sender, - const char *title, - pj_status_t status) -{ - char errmsg[PJ_ERR_MSG_SIZE]; - pj_strerror(status, errmsg, sizeof(errmsg)); - - PJ_LOG(3,(sender, "%s: %s", title, errmsg)); - return status; -} - -static int worker_thread(void *p) -{ - pj_stun_server *srv = (pj_stun_server*)p; - - while (!srv->thread_quit_flag) { - pj_time_val timeout = { 0, 50 }; - pj_timer_heap_poll(srv->si.timer_heap, NULL); - pj_ioqueue_poll(srv->si.ioqueue, &timeout); - } - - return 0; -} - - -PJ_DEF(pj_status_t) pj_stun_server_create(pj_pool_factory *pf, - unsigned thread_cnt, - pj_stun_server **p_srv) -{ - pj_pool_t *pool; - pj_stun_server *srv; - unsigned i; - pj_status_t status; - - pool = pj_pool_create(pf, "server%p", 4000, 4000, NULL); - - srv = PJ_POOL_ZALLOC_T(pool, pj_stun_server); - srv->pool = pool; - srv->si.pf = pf; - - status = pj_ioqueue_create(srv->pool, PJ_IOQUEUE_MAX_HANDLES, - &srv->si.ioqueue); - if (status != PJ_SUCCESS) - goto on_error; - - status = pj_timer_heap_create(srv->pool, 1024, &srv->si.timer_heap); - if (status != PJ_SUCCESS) - goto on_error; - - status = pj_stun_endpoint_create(srv->si.pf, 0, srv->si.ioqueue, - srv->si.timer_heap, &srv->si.endpt); - if (status != PJ_SUCCESS) - goto on_error; - - srv->si.thread_cnt = thread_cnt; - srv->threads = pj_pool_calloc(pool, thread_cnt, sizeof(pj_thread_t*)); - for (i=0; ithreads[i]); - if (status != PJ_SUCCESS) - goto on_error; - } - - *p_srv = srv; - return PJ_SUCCESS; - -on_error: - pj_stun_server_destroy(srv); - return status; -} - - -PJ_DEF(pj_stun_server_info*) pj_stun_server_get_info(pj_stun_server *srv) -{ - return &srv->si; -} - - -pj_status_t pj_stun_server_register_usage(pj_stun_server *srv, - pj_stun_usage *usage) -{ - unsigned i; - - for (i=0; iusage); ++i) { - if (srv->usage[i] == usage) - return PJ_SUCCESS; - } - - for (i=0; iusage); ++i) { - if (srv->usage[i] == NULL) - break; - } - - if (i == PJ_ARRAY_SIZE(srv->usage)) - return PJ_ETOOMANY; - - srv->usage[i] = usage; - ++srv->usage_cnt; - - return PJ_SUCCESS; -} - -pj_status_t pj_stun_server_unregister_usage(pj_stun_server *srv, - pj_stun_usage *usage) -{ - unsigned i; - - for (i=0; iusage); ++i) { - if (srv->usage[i] == usage) - break; - } - - if (i != PJ_ARRAY_SIZE(srv->usage)) { - srv->usage[i] = NULL; - --srv->usage_cnt; - return PJ_SUCCESS; - } - - return PJ_ENOTFOUND; -} - - -PJ_DEF(pj_status_t) pj_stun_server_destroy(pj_stun_server *srv) -{ - unsigned i; - - for (i=0; iusage); ++i) { - if (!srv->usage[i]) - continue; - - pj_stun_usage_destroy(srv->usage[i]); - pj_stun_server_unregister_usage(srv, srv->usage[i]); - } - - srv->thread_quit_flag = PJ_TRUE; - for (i=0; isi.thread_cnt; ++i) { - pj_thread_join(srv->threads[i]); - srv->threads[i] = NULL; - } - - pj_stun_endpoint_destroy(srv->si.endpt); - pj_timer_heap_destroy(srv->si.timer_heap); - pj_ioqueue_destroy(srv->si.ioqueue); - pj_pool_release(srv->pool); - - return PJ_SUCCESS; -} - - diff --git a/pjlib-util/src/pjstun-srv-test/server.h b/pjlib-util/src/pjstun-srv-test/server.h deleted file mode 100644 index a88d87c2..00000000 --- a/pjlib-util/src/pjstun-srv-test/server.h +++ /dev/null @@ -1,135 +0,0 @@ -/* $Id$ */ -/* - * Copyright (C) 2003-2005 Benny Prijono - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ -#ifndef __STUN_SERVER_H__ -#define __STUN_SERVER_H__ - -#include -#include - - -/** Opaque declaration for STUN server instance */ -typedef struct pj_stun_server pj_stun_server; - -/** STUN server info */ -typedef struct pj_stun_server_info -{ - pj_pool_factory *pf; - pj_stun_endpoint *endpt; - pj_ioqueue_t *ioqueue; - pj_timer_heap_t *timer_heap; - unsigned thread_cnt; -} pj_stun_server_info; - -/** STUN usage */ -typedef struct pj_stun_usage pj_stun_usage; - -/** STUN usage callback */ -typedef struct pj_stun_usage_cb -{ - void (*on_rx_data)(pj_stun_usage *usage, - void *pkt, - pj_size_t pkt_size, - const pj_sockaddr_t *src_addr, - unsigned src_addr_len); - void (*on_destroy)(pj_stun_usage *usage); -} pj_stun_usage_cb; - - -PJ_DECL(pj_status_t) pj_stun_perror(const char *sender, - const char *title, - pj_status_t status); - -/** - * Create instance of STUN server. - */ -PJ_DECL(pj_status_t) pj_stun_server_create(pj_pool_factory *pf, - unsigned thread_cnt, - pj_stun_server **p_srv); - -/** - * Get STUN server info. - */ -PJ_DECL(pj_stun_server_info*) pj_stun_server_get_info(pj_stun_server *srv); - - -/** - * Destroy STUN server. - */ -PJ_DECL(pj_status_t) pj_stun_server_destroy(pj_stun_server *srv); - - -/** - * Create STUN usage. - */ -PJ_DECL(pj_status_t) pj_stun_usage_create(pj_stun_server *srv, - const char *name, - const pj_stun_usage_cb *cb, - int family, - int type, - int protocol, - const pj_sockaddr_t *local_addr, - int addr_len, - pj_stun_usage **p_usage); - -/** - * Destroy usage. - */ -PJ_DECL(pj_status_t) pj_stun_usage_destroy(pj_stun_usage *usage); - -/** - * Set user data. - */ -PJ_DECL(pj_status_t) pj_stun_usage_set_user_data(pj_stun_usage *usage, - void *user_data); -/** - * Get user data. - */ -PJ_DECL(void*) pj_stun_usage_get_user_data(pj_stun_usage *usage); - -/** - * Send with the usage. - */ -PJ_DECL(pj_status_t) pj_stun_usage_sendto(pj_stun_usage *usage, - const void *pkt, - pj_size_t pkt_size, - unsigned flags, - const pj_sockaddr_t *dst_addr, - unsigned addr_len); - -PJ_DECL(pj_status_t) pj_stun_bind_usage_create(pj_stun_server *srv, - const pj_str_t *ip_addr, - unsigned port, - pj_stun_usage **p_bu); - -PJ_DECL(pj_status_t) pj_stun_turn_usage_create(pj_stun_server *srv, - int type, - const pj_str_t *ip_addr, - unsigned port, - pj_stun_usage **p_bu); - - -pj_status_t pj_stun_server_register_usage(pj_stun_server *srv, - pj_stun_usage *usage); -pj_status_t pj_stun_server_unregister_usage(pj_stun_server *srv, - pj_stun_usage *usage); - - -#endif /* __STUN_SERVER_H__ */ - - diff --git a/pjlib-util/src/pjstun-srv-test/turn_usage.c b/pjlib-util/src/pjstun-srv-test/turn_usage.c deleted file mode 100644 index e3d2e595..00000000 --- a/pjlib-util/src/pjstun-srv-test/turn_usage.c +++ /dev/null @@ -1,1408 +0,0 @@ -/* $Id$ */ -/* - * Copyright (C) 2003-2005 Benny Prijono - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ -#include "server.h" - -#define THIS_FILE "turn_usage.c" - -#define MAX_CLIENTS 8000 -#define MAX_PEER_PER_CLIENT 16 -#define START_PORT 2000 -#define END_PORT 65530 - -/* - * Forward declarations. - */ -struct turn_usage; -struct turn_client; - -static void tu_on_rx_data(pj_stun_usage *usage, - void *pkt, - pj_size_t pkt_size, - const pj_sockaddr_t *src_addr, - unsigned src_addr_len); -static void tu_on_destroy(pj_stun_usage *usage); -static pj_status_t tu_sess_on_send_msg(pj_stun_session *sess, - const void *pkt, - pj_size_t pkt_size, - const pj_sockaddr_t *dst_addr, - unsigned addr_len); -static pj_status_t tu_sess_on_rx_request(pj_stun_session *sess, - const pj_uint8_t *pkt, - unsigned pkt_len, - const pj_stun_msg *msg, - const pj_sockaddr_t *src_addr, - unsigned src_addr_len); - -static pj_status_t handle_binding_req(pj_stun_session *session, - const pj_stun_msg *msg, - const pj_sockaddr_t *src_addr, - unsigned src_addr_len); - -static pj_status_t client_create(struct turn_usage *tu, - const pj_sockaddr_t *src_addr, - unsigned src_addr_len, - struct turn_client **p_client); -static pj_status_t client_destroy(struct turn_client *client, - pj_status_t reason); -static pj_status_t client_handle_stun_msg(struct turn_client *client, - const pj_stun_msg *msg, - const pj_sockaddr_t *src_addr, - unsigned src_addr_len); - - -struct turn_usage -{ - pj_pool_factory *pf; - pj_stun_endpoint *endpt; - pj_ioqueue_t *ioqueue; - pj_timer_heap_t *timer_heap; - pj_pool_t *pool; - pj_mutex_t *mutex; - pj_stun_usage *usage; - int type; - pj_stun_session *default_session; - pj_hash_table_t *client_htable; - - unsigned max_bw_kbps; - unsigned max_lifetime; - - unsigned next_port; -}; - -struct peer; - -struct turn_client -{ - char obj_name[PJ_MAX_OBJ_NAME]; - struct turn_usage *tu; - pj_pool_t *pool; - pj_stun_session *session; - pj_mutex_t *mutex; - - pj_sockaddr_in client_src_addr; - - /* Socket and socket address of the allocated port */ - int sock_type; - pj_sock_t sock; - pj_ioqueue_key_t *key; - pj_sockaddr_in alloc_addr; - - /* Allocation properties */ - unsigned bw_kbps; - unsigned lifetime; - pj_timer_entry expiry_timer; - - - /* Hash table to keep all peers, key-ed by their address */ - pj_hash_table_t *peer_htable; - - /* Active destination, or sin_addr.s_addr will be zero if - * no active destination is set. - */ - struct peer *active_peer; - - /* Current packet received/sent from/to the allocated port */ - pj_uint8_t pkt[4000]; - pj_sockaddr_in pkt_src_addr; - int pkt_src_addr_len; - pj_ioqueue_op_key_t pkt_read_key; - pj_ioqueue_op_key_t pkt_write_key; -}; - -struct peer -{ - struct turn_client *client; - pj_sockaddr_in addr; -}; - -struct session_data -{ - struct turn_usage *tu; - struct turn_client *client; -}; - - -/* - * This is the only public API, to create and start the TURN usage. - */ -PJ_DEF(pj_status_t) pj_stun_turn_usage_create(pj_stun_server *srv, - int type, - const pj_str_t *ip_addr, - unsigned port, - pj_stun_usage **p_bu) -{ - pj_pool_t *pool; - struct turn_usage *tu; - pj_stun_server_info *si; - pj_stun_usage_cb usage_cb; - pj_stun_session_cb sess_cb; - struct session_data *sd; - pj_sockaddr_in local_addr; - pj_status_t status; - - PJ_ASSERT_RETURN(srv && (type==PJ_SOCK_DGRAM||type==PJ_SOCK_STREAM), - PJ_EINVAL); - si = pj_stun_server_get_info(srv); - - pool = pj_pool_create(si->pf, "turn%p", 4000, 4000, NULL); - tu = PJ_POOL_ZALLOC_T(pool, struct turn_usage); - tu->pool = pool; - tu->type = type; - tu->pf = si->pf; - tu->endpt = si->endpt; - tu->ioqueue = si->ioqueue; - tu->timer_heap = si->timer_heap; - tu->next_port = START_PORT; - tu->max_bw_kbps = 64; - tu->max_lifetime = 10 * 60; - - status = pj_sockaddr_in_init(&local_addr, ip_addr, (pj_uint16_t)port); - if (status != PJ_SUCCESS) - return status; - - /* Create usage */ - pj_bzero(&usage_cb, sizeof(usage_cb)); - usage_cb.on_rx_data = &tu_on_rx_data; - usage_cb.on_destroy = &tu_on_destroy; - status = pj_stun_usage_create(srv, "turn%p", &usage_cb, - PJ_AF_INET, tu->type, 0, - &local_addr, sizeof(local_addr), - &tu->usage); - if (status != PJ_SUCCESS) { - pj_pool_release(pool); - return status; - } - pj_stun_usage_set_user_data(tu->usage, tu); - - /* Init hash tables */ - tu->client_htable = pj_hash_create(tu->pool, MAX_CLIENTS); - - /* Create default session */ - pj_bzero(&sess_cb, sizeof(sess_cb)); - sess_cb.on_send_msg = &tu_sess_on_send_msg; - sess_cb.on_rx_request = &tu_sess_on_rx_request; - status = pj_stun_session_create(si->endpt, "turns%p", &sess_cb, PJ_FALSE, - &tu->default_session); - if (status != PJ_SUCCESS) { - pj_stun_usage_destroy(tu->usage); - return status; - } - - sd = PJ_POOL_ZALLOC_T(pool, struct session_data); - sd->tu = tu; - pj_stun_session_set_user_data(tu->default_session, sd); - - /* Create mutex */ - status = pj_mutex_create_recursive(pool, "turn%p", &tu->mutex); - if (status != PJ_SUCCESS) { - pj_stun_usage_destroy(tu->usage); - return status; - } - - if (p_bu) { - *p_bu = tu->usage; - } - - return PJ_SUCCESS; -} - - -/* - * This is a callback called by usage.c when the particular STUN usage - * is to be destroyed. - */ -static void tu_on_destroy(pj_stun_usage *usage) -{ - struct turn_usage *tu; - pj_hash_iterator_t hit, *it; - - tu = (struct turn_usage*) pj_stun_usage_get_user_data(usage); - - /* Destroy all clients */ - if (tu->client_htable) { - it = pj_hash_first(tu->client_htable, &hit); - while (it) { - struct turn_client *client; - - client = (struct turn_client *)pj_hash_this(tu->client_htable, it); - client_destroy(client, PJ_SUCCESS); - - it = pj_hash_first(tu->client_htable, &hit); - } - } - - pj_stun_session_destroy(tu->default_session); - pj_mutex_destroy(tu->mutex); - pj_pool_release(tu->pool); -} - - -/* - * This is a callback called by the usage.c to notify the TURN usage, - * that incoming packet (may or may not be a STUN packet) is received - * on the port where the TURN usage is listening. - */ -static void tu_on_rx_data(pj_stun_usage *usage, - void *pkt, - pj_size_t pkt_size, - const pj_sockaddr_t *src_addr, - unsigned src_addr_len) -{ - struct turn_usage *tu; - struct turn_client *client; - unsigned flags; - pj_status_t status; - - /* Which usage instance is this */ - tu = (struct turn_usage*) pj_stun_usage_get_user_data(usage); - - /* Lookup client structure based on source address */ - client = (struct turn_client*) pj_hash_get(tu->client_htable, src_addr, - src_addr_len, NULL); - - /* STUN message decoding flag */ - flags = 0; - if (tu->type == PJ_SOCK_DGRAM) - flags |= PJ_STUN_IS_DATAGRAM; - - - if (client) { - status = pj_stun_msg_check(pkt, pkt_size, flags); - - if (status == PJ_SUCCESS) { - /* Received STUN message */ - status = pj_stun_session_on_rx_pkt(client->session, - (pj_uint8_t*)pkt, pkt_size, - flags, NULL, - src_addr, src_addr_len); - } else if (client->active_peer) { - /* Received non-STUN message and client has active destination */ - pj_ssize_t sz = pkt_size; - pj_ioqueue_sendto(client->key, &client->pkt_write_key, - pkt, &sz, 0, - &client->active_peer->addr, - sizeof(client->active_peer->addr)); - } else { - /* Received non-STUN message and client doesn't have active - * destination. - */ - /* Ignore */ - } - - } else { - /* Received packet (could be STUN or no) from new source */ - flags |= PJ_STUN_CHECK_PACKET; - pj_stun_session_on_rx_pkt(tu->default_session, (pj_uint8_t*)pkt, - pkt_size, flags, NULL, - src_addr, src_addr_len); - } -} - - -/* - * This is a utility function provided by TU (Turn Usage) to reserve - * or allocate internal port/socket. The allocation needs to be - * coordinated to minimize bind() collissions. - */ -static pj_status_t tu_alloc_port(struct turn_usage *tu, - int type, - unsigned rpp_bits, - const pj_sockaddr_in *req_addr, - pj_sock_t *p_sock, - int *err_code) -{ - enum { RETRY = 100 }; - pj_sockaddr_in addr; - pj_sock_t sock = PJ_INVALID_SOCKET; - unsigned retry; - pj_status_t status; - - if (req_addr && req_addr->sin_port != 0) { - - *err_code = PJ_STUN_SC_INVALID_PORT; - - /* Allocate specific port */ - status = pj_sock_socket(PJ_AF_INET, type, 0, &sock); - if (status != PJ_SUCCESS) - return status; - - /* Bind */ - status = pj_sock_bind(sock, req_addr, sizeof(pj_sockaddr_in)); - if (status != PJ_SUCCESS) { - pj_sock_close(sock); - return status; - } - - /* Success */ - *p_sock = sock; - return PJ_SUCCESS; - - } else { - status = -1; - *err_code = PJ_STUN_SC_INSUFFICIENT_CAPACITY; - - if (req_addr && req_addr->sin_addr.s_addr) { - *err_code = PJ_STUN_SC_INVALID_IP_ADDR; - pj_memcpy(&addr, req_addr, sizeof(pj_sockaddr_in)); - } else { - pj_sockaddr_in_init(&addr, NULL, 0); - } - - for (retry=0; retrynext_port & 0x01)==0) - tu->next_port++; - break; - case 2: - case 3: - if ((tu->next_port & 0x01)==1) - tu->next_port++; - break; - } - - status = pj_sock_socket(PJ_AF_INET, type, 0, &sock); - if (status != PJ_SUCCESS) - return status; - - addr.sin_port = pj_htons((pj_uint16_t)tu->next_port); - - if (++tu->next_port > END_PORT) - tu->next_port = START_PORT; - - status = pj_sock_bind(sock, &addr, sizeof(addr)); - if (status != PJ_SUCCESS) { - pj_sock_close(sock); - sock = PJ_INVALID_SOCKET; - - /* If client requested specific IP address, assume that - * bind failed because the IP address is not valid. We - * don't want to retry that since it will exhaust our - * port space. - */ - if (req_addr && req_addr->sin_addr.s_addr) - break; - } - } - - if (sock == PJ_INVALID_SOCKET) { - return status; - } - - *p_sock = sock; - return PJ_SUCCESS; - } -} - - -/* - * This callback is called by the TU's STUN session when it receives - * a valid STUN message. This is called from tu_on_rx_data above. - */ -static pj_status_t tu_sess_on_rx_request(pj_stun_session *sess, - const pj_uint8_t *pkt, - unsigned pkt_len, - const pj_stun_msg *msg, - const pj_sockaddr_t *src_addr, - unsigned src_addr_len) -{ - struct session_data *sd; - struct turn_client *client; - pj_stun_tx_data *tdata; - pj_status_t status; - - PJ_UNUSED_ARG(pkt); - PJ_UNUSED_ARG(pkt_len); - - sd = (struct session_data*) pj_stun_session_get_user_data(sess); - - pj_assert(sd->client == NULL); - - if (msg->hdr.type == PJ_STUN_BINDING_REQUEST) { - return handle_binding_req(sess, msg, src_addr, src_addr_len); - - } else if (msg->hdr.type != PJ_STUN_ALLOCATE_REQUEST) { - if (PJ_STUN_IS_REQUEST(msg->hdr.type)) { - status = pj_stun_session_create_response(sess, msg, - PJ_STUN_SC_NO_BINDING, - NULL, &tdata); - if (status==PJ_SUCCESS) { - status = pj_stun_session_send_msg(sess, PJ_FALSE, - src_addr, src_addr_len, - tdata); - } - } else { - PJ_LOG(4,(THIS_FILE, - "Received %s %s without matching Allocation, " - "ignored", pj_stun_get_method_name(msg->hdr.type), - pj_stun_get_class_name(msg->hdr.type))); - } - return PJ_SUCCESS; - } - - status = client_create(sd->tu, src_addr, src_addr_len, &client); - if (status != PJ_SUCCESS) { - pj_stun_perror(THIS_FILE, "Error creating new TURN client", - status); - return status; - } - - - /* Hand over message to client */ - pj_mutex_lock(client->mutex); - status = client_handle_stun_msg(client, msg, src_addr, src_addr_len); - pj_mutex_unlock(client->mutex); - - return status; -} - - -/* - * This callback is called by STUN session when it needs to send packet - * to the network. - */ -static pj_status_t tu_sess_on_send_msg(pj_stun_session *sess, - const void *pkt, - pj_size_t pkt_size, - const pj_sockaddr_t *dst_addr, - unsigned addr_len) -{ - struct session_data *sd; - - sd = (struct session_data*) pj_stun_session_get_user_data(sess); - - if (sd->tu->type == PJ_SOCK_DGRAM) { - return pj_stun_usage_sendto(sd->tu->usage, pkt, pkt_size, 0, - dst_addr, addr_len); - } else { - return PJ_ENOTSUP; - } -} - - -/****************************************************************************/ -/* - * TURN client operations. - */ - -/* Function prototypes */ -static pj_status_t client_create_relay(struct turn_client *client); -static pj_status_t client_destroy_relay(struct turn_client *client); -static void client_on_expired(pj_timer_heap_t *th, pj_timer_entry *e); -static void client_on_read_complete(pj_ioqueue_key_t *key, - pj_ioqueue_op_key_t *op_key, - pj_ssize_t bytes_read); -static pj_status_t client_respond(struct turn_client *client, - const pj_stun_msg *msg, - int err_code, - const char *err_msg, - const pj_sockaddr_t *dst_addr, - int dst_addr_len); -static struct peer* client_get_peer(struct turn_client *client, - const pj_sockaddr_in *peer_addr, - pj_uint32_t *hval); -static struct peer* client_add_peer(struct turn_client *client, - const pj_sockaddr_in *peer_addr, - pj_uint32_t hval); - -static const char *get_tp_type(int type) -{ - if (type==PJ_SOCK_DGRAM) - return "udp"; - else if (type==PJ_SOCK_STREAM) - return "tcp"; - else - return "???"; -} - - -/* - * This callback is called when incoming STUN message is received - * in the TURN usage. This is called from by tu_on_rx_data() when - * the packet is handed over to the client. - */ -static pj_status_t client_sess_on_rx_msg(pj_stun_session *sess, - const pj_uint8_t *pkt, - unsigned pkt_len, - const pj_stun_msg *msg, - const pj_sockaddr_t *src_addr, - unsigned src_addr_len) -{ - struct session_data *sd; - - PJ_UNUSED_ARG(pkt); - PJ_UNUSED_ARG(pkt_len); - - sd = (struct session_data*) pj_stun_session_get_user_data(sess); - pj_assert(sd->client != PJ_SUCCESS); - - return client_handle_stun_msg(sd->client, msg, src_addr, src_addr_len); -} - - -/* - * This callback is called by client's STUN session to send outgoing - * STUN packet. It's called when client calls pj_stun_session_send_msg() - * function. - */ -static pj_status_t client_sess_on_send_msg(pj_stun_session *sess, - const void *pkt, - pj_size_t pkt_size, - const pj_sockaddr_t *dst_addr, - unsigned addr_len) -{ - struct session_data *sd; - - sd = (struct session_data*) pj_stun_session_get_user_data(sess); - - if (sd->tu->type == PJ_SOCK_DGRAM) { - return pj_stun_usage_sendto(sd->tu->usage, pkt, pkt_size, 0, - dst_addr, addr_len); - } else { - return PJ_ENOTSUP; - } -} - - -/* - * Create a new TURN client for the specified source address. - */ -static pj_status_t client_create(struct turn_usage *tu, - const pj_sockaddr_t *src_addr, - unsigned src_addr_len, - struct turn_client **p_client) -{ - pj_pool_t *pool; - struct turn_client *client; - pj_stun_session_cb sess_cb; - struct session_data *sd; - pj_status_t status; - - PJ_ASSERT_RETURN(src_addr_len==sizeof(pj_sockaddr_in), PJ_EINVAL); - - pool = pj_pool_create(tu->pf, "turnc%p", 4000, 4000, NULL); - client = PJ_POOL_ZALLOC_T(pool, struct turn_client); - client->pool = pool; - client->tu = tu; - client->sock = PJ_INVALID_SOCKET; - - pj_memcpy(&client->client_src_addr, src_addr, - sizeof(client->client_src_addr)); - - if (src_addr) { - const pj_sockaddr_in *a4 = (const pj_sockaddr_in *)src_addr; - pj_ansi_snprintf(client->obj_name, sizeof(client->obj_name), - "%s:%s:%d", - get_tp_type(tu->type), - pj_inet_ntoa(a4->sin_addr), - (int)pj_ntohs(a4->sin_port)); - client->obj_name[sizeof(client->obj_name)-1] = '\0'; - } - - /* Create session */ - pj_bzero(&sess_cb, sizeof(sess_cb)); - sess_cb.on_send_msg = &client_sess_on_send_msg; - sess_cb.on_rx_request = &client_sess_on_rx_msg; - sess_cb.on_rx_indication = &client_sess_on_rx_msg; - status = pj_stun_session_create(tu->endpt, client->obj_name, - &sess_cb, PJ_FALSE, - &client->session); - if (status != PJ_SUCCESS) { - pj_pool_release(pool); - return status; - } - - sd = PJ_POOL_ZALLOC_T(pool, struct session_data); - sd->tu = tu; - sd->client = client; - pj_stun_session_set_user_data(client->session, sd); - - /* Mutex */ - status = pj_mutex_create_recursive(client->pool, pool->obj_name, - &client->mutex); - if (status != PJ_SUCCESS) { - client_destroy(client, status); - return status; - } - - /* Create hash table */ - client->peer_htable = pj_hash_create(client->pool, MAX_PEER_PER_CLIENT); - if (client->peer_htable == NULL) { - client_destroy(client, status); - return PJ_ENOMEM; - } - - /* Init timer entry */ - client->expiry_timer.user_data = client; - client->expiry_timer.cb = &client_on_expired; - client->expiry_timer.id = 0; - - /* Register to hash table */ - pj_mutex_lock(tu->mutex); - pj_hash_set(pool, tu->client_htable, src_addr, src_addr_len, 0, client); - pj_mutex_unlock(tu->mutex); - - /* Done */ - *p_client = client; - - PJ_LOG(4,(THIS_FILE, "TURN client %s created", client->obj_name)); - - return PJ_SUCCESS; -} - - -/* - * Destroy TURN client. - */ -static pj_status_t client_destroy(struct turn_client *client, - pj_status_t reason) -{ - struct turn_usage *tu = client->tu; - char name[PJ_MAX_OBJ_NAME]; - - pj_assert(sizeof(name)==sizeof(client->obj_name)); - pj_memcpy(name, client->obj_name, sizeof(name)); - - /* Kill timer if it's active */ - if (client->expiry_timer.id != 0) { - pj_timer_heap_cancel(tu->timer_heap, &client->expiry_timer); - client->expiry_timer.id = PJ_FALSE; - } - - /* Destroy relay */ - client_destroy_relay(client); - - /* Unregister client from hash table */ - pj_mutex_lock(tu->mutex); - pj_hash_set(NULL, tu->client_htable, - &client->client_src_addr, sizeof(client->client_src_addr), - 0, NULL); - pj_mutex_unlock(tu->mutex); - - /* Destroy STUN session */ - if (client->session) { - pj_stun_session_destroy(client->session); - client->session = NULL; - } - - /* Mutex */ - if (client->mutex) { - pj_mutex_destroy(client->mutex); - client->mutex = NULL; - } - - /* Finally destroy pool */ - if (client->pool) { - pj_pool_t *pool = client->pool; - client->pool = NULL; - pj_pool_release(pool); - } - - if (reason == PJ_SUCCESS) { - PJ_LOG(4,(THIS_FILE, "TURN client %s destroyed", name)); - } - - return PJ_SUCCESS; -} - - -/* - * This utility function is used to setup relay (with ioqueue) after - * socket has been allocated for the TURN client. - */ -static pj_status_t client_create_relay(struct turn_client *client) -{ - pj_ioqueue_callback client_ioq_cb; - int addrlen; - pj_status_t status; - - /* Update address */ - addrlen = sizeof(pj_sockaddr_in); - status = pj_sock_getsockname(client->sock, &client->alloc_addr, - &addrlen); - if (status != PJ_SUCCESS) { - pj_sock_close(client->sock); - client->sock = PJ_INVALID_SOCKET; - return status; - } - - if (client->alloc_addr.sin_addr.s_addr == 0) { - status = pj_gethostip(&client->alloc_addr.sin_addr); - if (status != PJ_SUCCESS) { - pj_sock_close(client->sock); - client->sock = PJ_INVALID_SOCKET; - return status; - } - } - - /* Register to ioqueue */ - pj_bzero(&client_ioq_cb, sizeof(client_ioq_cb)); - client_ioq_cb.on_read_complete = &client_on_read_complete; - status = pj_ioqueue_register_sock(client->pool, client->tu->ioqueue, - client->sock, client, - &client_ioq_cb, &client->key); - if (status != PJ_SUCCESS) { - pj_sock_close(client->sock); - client->sock = PJ_INVALID_SOCKET; - return status; - } - - pj_ioqueue_op_key_init(&client->pkt_read_key, - sizeof(client->pkt_read_key)); - pj_ioqueue_op_key_init(&client->pkt_write_key, - sizeof(client->pkt_write_key)); - - /* Trigger the first read */ - client_on_read_complete(client->key, &client->pkt_read_key, 0); - - PJ_LOG(4,(THIS_FILE, "TURN client %s: relay allocated on %s:%s:%d", - client->obj_name, - get_tp_type(client->sock_type), - pj_inet_ntoa(client->alloc_addr.sin_addr), - (int)pj_ntohs(client->alloc_addr.sin_port))); - - return PJ_SUCCESS; -} - - -/* - * This utility function is used to destroy the port allocated for - * the TURN client. - */ -static pj_status_t client_destroy_relay(struct turn_client *client) -{ - /* Close socket */ - if (client->key) { - pj_ioqueue_unregister(client->key); - client->key = NULL; - client->sock = PJ_INVALID_SOCKET; - } else if (client->sock && client->sock != PJ_INVALID_SOCKET) { - pj_sock_close(client->sock); - client->sock = PJ_INVALID_SOCKET; - } - - PJ_LOG(4,(THIS_FILE, "TURN client %s: relay allocation %s:%s:%d destroyed", - client->obj_name, - get_tp_type(client->sock_type), - pj_inet_ntoa(client->alloc_addr.sin_addr), - (int)pj_ntohs(client->alloc_addr.sin_port))); - return PJ_SUCCESS; -} - - -/* - * From the source packet address, get the peer instance from hash table. - */ -static struct peer* client_get_peer(struct turn_client *client, - const pj_sockaddr_in *peer_addr, - pj_uint32_t *hval) -{ - return (struct peer*) - pj_hash_get(client->peer_htable, peer_addr, sizeof(*peer_addr), hval); -} - - -/* - * Add a peer instance to the peer hash table. - */ -static struct peer* client_add_peer(struct turn_client *client, - const pj_sockaddr_in *peer_addr, - unsigned hval) -{ - struct peer *peer; - - peer = PJ_POOL_ZALLOC_T(client->pool, struct peer); - peer->client = client; - pj_memcpy(&peer->addr, peer_addr, sizeof(peer->addr)); - - pj_hash_set(client->pool, client->peer_htable, - &peer->addr, sizeof(peer->addr), hval, peer); - - PJ_LOG(4,(THIS_FILE, "TURN client %s: peer %s:%s:%d added", - client->obj_name, get_tp_type(client->sock_type), - pj_inet_ntoa(peer->addr.sin_addr), - (int)pj_ntohs(peer->addr.sin_port))); - - return peer; -} - - -/* - * Utility to send STUN response message (normally to send error response). - */ -static pj_status_t client_respond(struct turn_client *client, - const pj_stun_msg *msg, - int err_code, - const char *custom_msg, - const pj_sockaddr_t *dst_addr, - int dst_addr_len) -{ - pj_str_t err_msg; - pj_str_t *p_err_msg = NULL; - pj_stun_tx_data *response; - pj_status_t status; - - if (custom_msg) - pj_cstr(&err_msg, custom_msg), p_err_msg = &err_msg; - - status = pj_stun_session_create_response(client->session, msg, - err_code, p_err_msg, - &response); - if (status == PJ_SUCCESS) - status = pj_stun_session_send_msg(client->session, PJ_TRUE, - dst_addr, dst_addr_len, response); - - return status; -} - - -/* - * Handle incoming initial or subsequent Allocate Request. - * This function is called by client_handle_stun_msg() below. - */ -static pj_status_t client_handle_allocate_req(struct turn_client *client, - const pj_stun_msg *msg, - const pj_sockaddr_t *src_addr, - unsigned src_addr_len) -{ - const pj_stun_bandwidth_attr *a_bw; - const pj_stun_lifetime_attr *a_lf; - const pj_stun_req_port_props_attr *a_rpp; - const pj_stun_req_transport_attr *a_rt; - const pj_stun_req_ip_attr *a_rip; - pj_stun_tx_data *response; - pj_sockaddr_in req_addr; - int addr_len; - unsigned req_bw, rpp_bits; - pj_time_val timeout; - pj_status_t status; - - a_bw = (const pj_stun_bandwidth_attr *) - pj_stun_msg_find_attr(msg, PJ_STUN_ATTR_BANDWIDTH, 0); - a_lf = (const pj_stun_lifetime_attr*) - pj_stun_msg_find_attr(msg, PJ_STUN_ATTR_LIFETIME, 0); - a_rpp = (const pj_stun_req_port_props_attr*) - pj_stun_msg_find_attr(msg, PJ_STUN_ATTR_REQ_PORT_PROPS, 0); - a_rt = (const pj_stun_req_transport_attr*) - pj_stun_msg_find_attr(msg, PJ_STUN_ATTR_REQ_TRANSPORT, 0); - a_rip = (const pj_stun_req_ip_attr*) - pj_stun_msg_find_attr(msg, PJ_STUN_ATTR_REQ_IP, 0); - - /* Init requested local address */ - pj_sockaddr_in_init(&req_addr, NULL, 0); - - /* Process BANDWIDTH attribute */ - if (a_bw && a_bw->value > client->tu->max_bw_kbps) { - client_respond(client, msg, PJ_STUN_SC_INSUFFICIENT_CAPACITY, NULL, - src_addr, src_addr_len); - return PJ_SUCCESS; - } else if (a_bw) { - client->bw_kbps = req_bw = a_bw->value; - } else { - req_bw = 0; - client->bw_kbps = client->tu->max_bw_kbps; - } - - /* Process REQUESTED-TRANSPORT attribute */ - if (a_rt && a_rt->value != 0) { - client_respond(client, msg, PJ_STUN_SC_UNSUPP_TRANSPORT_PROTO, NULL, - src_addr, src_addr_len); - return PJ_SUCCESS; - } else if (a_rt) { - client->sock_type = a_rt->value ? PJ_SOCK_STREAM : PJ_SOCK_DGRAM; - } else { - client->sock_type = client->tu->type;; - } - - /* Process REQUESTED-IP attribute */ - if (a_rip && a_rip->addr.addr.sa_family != PJ_AF_INET) { - client_respond(client, msg, PJ_STUN_SC_INVALID_IP_ADDR, NULL, - src_addr, src_addr_len); - return PJ_SUCCESS; - - } else if (a_rip) { - req_addr.sin_addr.s_addr = a_rip->addr.ipv4.sin_addr.s_addr; - } - - /* Process REQUESTED-PORT-PROPS attribute */ - if (a_rpp) { - unsigned port; - - rpp_bits = (a_rpp->value & 0x00030000) >> 16; - port = (a_rpp->value & 0xFFFF); - req_addr.sin_port = pj_htons((pj_uint8_t)port); - } else { - rpp_bits = 0; - } - - /* Process LIFETIME attribute */ - if (a_lf && a_lf->value > client->tu->max_lifetime) { - client->lifetime = client->tu->max_lifetime; - } else if (a_lf) { - client->lifetime = a_lf->value; - } else { - client->lifetime = client->tu->max_lifetime; - } - - /* Allocate socket if we don't have one */ - if (client->key == NULL) { - int err_code; - - PJ_LOG(4,(THIS_FILE, "TURN client %s: received initial Allocate " - "request, requested type:addr:port=%s:%s:%d, rpp " - "bits=%d, bw=%dkbps, lifetime=%d", - client->obj_name, get_tp_type(client->sock_type), - pj_inet_ntoa(req_addr.sin_addr), pj_ntohs(req_addr.sin_port), - rpp_bits, client->bw_kbps, client->lifetime)); - - status = tu_alloc_port(client->tu, client->sock_type, rpp_bits, - &req_addr, &client->sock, &err_code); - if (status != PJ_SUCCESS) { - char errmsg[PJ_ERR_MSG_SIZE]; - - pj_strerror(status, errmsg, sizeof(errmsg)); - PJ_LOG(4,(THIS_FILE, "TURN client %s: error allocating relay port" - ": %s", - client->obj_name, errmsg)); - - client_respond(client, msg, err_code, NULL, - src_addr, src_addr_len); - - return status; - } - - status = client_create_relay(client); - if (status != PJ_SUCCESS) { - client_respond(client, msg, PJ_STUN_SC_SERVER_ERROR, NULL, - src_addr, src_addr_len); - return status; - } - } else { - /* Otherwise check if the port parameter stays the same */ - /* TODO */ - PJ_LOG(4,(THIS_FILE, "TURN client %s: received Allocate refresh, " - "lifetime=%d", - client->obj_name, client->lifetime)); - } - - /* Refresh timer */ - if (client->expiry_timer.id != PJ_FALSE) { - pj_timer_heap_cancel(client->tu->timer_heap, &client->expiry_timer); - client->expiry_timer.id = PJ_FALSE; - } - timeout.sec = client->lifetime; - timeout.msec = 0; - pj_timer_heap_schedule(client->tu->timer_heap, &client->expiry_timer, &timeout); - client->expiry_timer.id = PJ_TRUE; - - /* Done successfully, create and send success response */ - status = pj_stun_session_create_response(client->session, msg, - 0, NULL, &response); - if (status != PJ_SUCCESS) { - return status; - } - - pj_stun_msg_add_uint_attr(response->pool, response->msg, - PJ_STUN_ATTR_BANDWIDTH, client->bw_kbps); - pj_stun_msg_add_uint_attr(response->pool, response->msg, - PJ_STUN_ATTR_LIFETIME, client->lifetime); - pj_stun_msg_add_sockaddr_attr(response->pool, response->msg, - PJ_STUN_ATTR_MAPPED_ADDR, PJ_FALSE, - src_addr, src_addr_len); - pj_stun_msg_add_sockaddr_attr(response->pool, response->msg, - PJ_STUN_ATTR_XOR_MAPPED_ADDR, PJ_TRUE, - src_addr, src_addr_len); - - addr_len = sizeof(req_addr); - pj_sock_getsockname(client->sock, &req_addr, &addr_len); - pj_stun_msg_add_sockaddr_attr(response->pool, response->msg, - PJ_STUN_ATTR_RELAY_ADDR, PJ_FALSE, - &client->alloc_addr, addr_len); - - PJ_LOG(4,(THIS_FILE, "TURN client %s: relay allocated or refreshed, " - "internal address is %s:%s:%d", - client->obj_name, - get_tp_type(client->sock_type), - pj_inet_ntoa(req_addr.sin_addr), - (int)pj_ntohs(req_addr.sin_port))); - - return pj_stun_session_send_msg(client->session, PJ_TRUE, - src_addr, src_addr_len, response); -} - - -/* - * Handle incoming Binding request. - * This function is called by client_handle_stun_msg() below. - */ -static pj_status_t handle_binding_req(pj_stun_session *session, - const pj_stun_msg *msg, - const pj_sockaddr_t *src_addr, - unsigned src_addr_len) -{ - pj_stun_tx_data *tdata; - pj_status_t status; - - /* Create response */ - status = pj_stun_session_create_response(session, msg, 0, NULL, - &tdata); - if (status != PJ_SUCCESS) - return status; - - /* Create MAPPED-ADDRESS attribute */ - pj_stun_msg_add_sockaddr_attr(tdata->pool, tdata->msg, - PJ_STUN_ATTR_MAPPED_ADDR, - PJ_FALSE, - src_addr, src_addr_len); - - /* On the presence of magic, create XOR-MAPPED-ADDRESS attribute */ - if (msg->hdr.magic == PJ_STUN_MAGIC) { - status = - pj_stun_msg_add_sockaddr_attr(tdata->pool, tdata->msg, - PJ_STUN_ATTR_XOR_MAPPED_ADDR, - PJ_TRUE, - src_addr, src_addr_len); - } - - /* Send */ - status = pj_stun_session_send_msg(session, PJ_TRUE, - src_addr, src_addr_len, tdata); - return status; -} - - -/* - * client handling incoming STUN Set Active Destination request - * This function is called by client_handle_stun_msg() below. - */ -static pj_status_t client_handle_sad(struct turn_client *client, - const pj_stun_msg *msg, - const pj_sockaddr_t *src_addr, - unsigned src_addr_len) -{ - pj_stun_remote_addr_attr *a_raddr; - - a_raddr = (pj_stun_remote_addr_attr*) - pj_stun_msg_find_attr(msg, PJ_STUN_ATTR_REMOTE_ADDR, 0); - if (!a_raddr) { - /* Remote active destination needs to be cleared */ - client->active_peer = NULL; - - } else if (a_raddr->addr.addr.sa_family != PJ_AF_INET) { - /* Bad request (not IPv4) */ - client_respond(client, msg, PJ_STUN_SC_BAD_REQUEST, NULL, - src_addr, src_addr_len); - return PJ_SUCCESS; - - } else if (client->active_peer) { - /* Client tries to set new active destination without clearing - * it first. Reject with 439. - */ - client_respond(client, msg, PJ_STUN_SC_TRANSITIONING, NULL, - src_addr, src_addr_len); - return PJ_SUCCESS; - - } else { - struct peer *peer; - pj_uint32_t hval = 0; - - /* Add a new peer/permission if we don't have one for this address */ - peer = client_get_peer(client, &a_raddr->addr.ipv4, &hval); - if (peer==NULL) { - peer = client_add_peer(client, &a_raddr->addr.ipv4, hval); - } - - /* Set active destination */ - client->active_peer = peer; - } - - if (client->active_peer) { - PJ_LOG(4,(THIS_FILE, - "TURN client %s: active destination set to %s:%d", - client->obj_name, - pj_inet_ntoa(client->active_peer->addr.sin_addr), - (int)pj_ntohs(client->active_peer->addr.sin_port))); - } else { - PJ_LOG(4,(THIS_FILE, "TURN client %s: active destination cleared", - client->obj_name)); - } - - /* Respond with successful response */ - client_respond(client, msg, 0, NULL, src_addr, src_addr_len); - - return PJ_SUCCESS; -} - - -/* - * client handling incoming STUN Send Indication - * This function is called by client_handle_stun_msg() below. - */ -static pj_status_t client_handle_send_ind(struct turn_client *client, - const pj_stun_msg *msg) -{ - pj_stun_remote_addr_attr *a_raddr; - pj_stun_data_attr *a_data; - pj_uint32_t hval = 0; - const pj_uint8_t *data; - pj_ssize_t datalen; - - /* Get REMOTE-ADDRESS attribute */ - a_raddr = (pj_stun_remote_addr_attr*) - pj_stun_msg_find_attr(msg, PJ_STUN_ATTR_REMOTE_ADDR, 0); - if (!a_raddr) { - /* REMOTE-ADDRESS not present, discard packet */ - return PJ_SUCCESS; - - } else if (a_raddr->addr.addr.sa_family != PJ_AF_INET) { - /* REMOTE-ADDRESS present but not IPv4, discard packet */ - return PJ_SUCCESS; - - } - - /* Get the DATA attribute */ - a_data = (pj_stun_data_attr*) - pj_stun_msg_find_attr(msg, PJ_STUN_ATTR_DATA, 0); - if (a_data) { - data = (const pj_uint8_t *)a_data->data; - datalen = a_data->length; - - } else if (client->sock_type == PJ_SOCK_STREAM) { - /* Discard if no Data and Allocation type is TCP */ - return PJ_SUCCESS; - - } else { - data = (const pj_uint8_t *)""; - datalen = 0; - } - - /* Add to peer table if necessary */ - if (client_get_peer(client, &a_raddr->addr.ipv4, &hval)==NULL) - client_add_peer(client, &a_raddr->addr.ipv4, hval); - - /* Send the packet */ - pj_ioqueue_sendto(client->key, &client->pkt_write_key, - data, &datalen, 0, - &a_raddr->addr.ipv4, sizeof(a_raddr->addr.ipv4)); - - return PJ_SUCCESS; -} - - -/* - * client handling unknown incoming STUN message. - * This function is called by client_handle_stun_msg() below. - */ -static pj_status_t client_handle_unknown_msg(struct turn_client *client, - const pj_stun_msg *msg, - const pj_sockaddr_t *src_addr, - unsigned src_addr_len) -{ - PJ_LOG(4,(THIS_FILE, "TURN client %s: unhandled %s %s", - client->obj_name, pj_stun_get_method_name(msg->hdr.type), - pj_stun_get_class_name(msg->hdr.type))); - - if (PJ_STUN_IS_REQUEST(msg->hdr.type)) { - return client_respond(client, msg, PJ_STUN_SC_BAD_REQUEST, NULL, - src_addr, src_addr_len); - } else { - /* Ignore */ - return PJ_SUCCESS; - } -} - - -/* - * Main entry for handling STUN messages arriving on the main TURN port, - * for this client - */ -static pj_status_t client_handle_stun_msg(struct turn_client *client, - const pj_stun_msg *msg, - const pj_sockaddr_t *src_addr, - unsigned src_addr_len) -{ - pj_status_t status; - - switch (msg->hdr.type) { - case PJ_STUN_SEND_INDICATION: - status = client_handle_send_ind(client, msg); - break; - - case PJ_STUN_SET_ACTIVE_DESTINATION_REQUEST: - status = client_handle_sad(client, msg, - src_addr, src_addr_len); - break; - - case PJ_STUN_ALLOCATE_REQUEST: - status = client_handle_allocate_req(client, msg, - src_addr, src_addr_len); - break; - - case PJ_STUN_BINDING_REQUEST: - status = handle_binding_req(client->session, msg, - src_addr, src_addr_len); - break; - - default: - status = client_handle_unknown_msg(client, msg, - src_addr, src_addr_len); - break; - } - - return status; -} - - -PJ_INLINE(pj_uint32_t) GET_VAL32(const pj_uint8_t *pdu, unsigned pos) -{ - return (pdu[pos+0] << 24) + - (pdu[pos+1] << 16) + - (pdu[pos+2] << 8) + - (pdu[pos+3]); -} - - -/* - * Handle incoming data from peer - * This function is called by client_on_read_complete() below. - */ -static void client_handle_peer_data(struct turn_client *client, - unsigned bytes_read) -{ - struct peer *peer; - pj_bool_t has_magic_cookie; - pj_status_t status; - - /* Has the sender been registered as peer? */ - peer = client_get_peer(client, &client->pkt_src_addr, NULL); - if (peer == NULL) { - /* Nope. Discard packet */ - PJ_LOG(5,(THIS_FILE, - "TURN client %s: discarded data from %s:%d", - client->obj_name, - pj_inet_ntoa(client->pkt_src_addr.sin_addr), - (int)pj_ntohs(client->pkt_src_addr.sin_port))); - return; - } - - /* Check if packet has STUN magic cookie */ - has_magic_cookie = (GET_VAL32(client->pkt, 4) == PJ_STUN_MAGIC); - - /* If this is the Active Destination and the packet doesn't have - * STUN magic cookie, send the packet to client as is. - */ - if (peer == client->active_peer && !has_magic_cookie) { - pj_stun_usage_sendto(client->tu->usage, client->pkt, bytes_read, 0, - &client->pkt_src_addr, client->pkt_src_addr_len); - } else { - /* Otherwise wrap in Data Indication */ - pj_stun_tx_data *data_ind; - - status = pj_stun_session_create_ind(client->session, - PJ_STUN_DATA_INDICATION, - &data_ind); - if (status != PJ_SUCCESS) - return; - - pj_stun_msg_add_sockaddr_attr(data_ind->pool, data_ind->msg, - PJ_STUN_ATTR_REMOTE_ADDR, PJ_FALSE, - &client->pkt_src_addr, - client->pkt_src_addr_len); - pj_stun_msg_add_binary_attr(data_ind->pool, data_ind->msg, - PJ_STUN_ATTR_DATA, - client->pkt, bytes_read); - - - pj_stun_session_send_msg(client->session, PJ_FALSE, - &client->pkt_src_addr, - client->pkt_src_addr_len, - data_ind); - } -} - - -/* - * This callback is called by the ioqueue when read operation has - * completed on the allocated relay port. - */ -static void client_on_read_complete(pj_ioqueue_key_t *key, - pj_ioqueue_op_key_t *op_key, - pj_ssize_t bytes_read) -{ - enum { MAX_LOOP = 10 }; - struct turn_client *client; - unsigned count; - pj_status_t status; - - PJ_UNUSED_ARG(op_key); - - client = pj_ioqueue_get_user_data(key); - - /* Lock client */ - pj_mutex_lock(client->mutex); - - for (count=0; ; ++count) { - unsigned flags; - - if (bytes_read > 0) { - /* Received data from peer! */ - client_handle_peer_data(client, bytes_read); - - } else if (bytes_read < 0) { - char errmsg[PJ_ERR_MSG_SIZE]; - pj_strerror(-bytes_read, errmsg, sizeof(errmsg)); - PJ_LOG(4,(THIS_FILE, "TURN client %s: error reading data " - "from allocated relay port: %s", - client->obj_name, errmsg)); - } - - bytes_read = sizeof(client->pkt); - flags = (count >= MAX_LOOP) ? PJ_IOQUEUE_ALWAYS_ASYNC : 0; - client->pkt_src_addr_len = sizeof(client->pkt_src_addr); - status = pj_ioqueue_recvfrom(client->key, - &client->pkt_read_key, - client->pkt, &bytes_read, flags, - &client->pkt_src_addr, - &client->pkt_src_addr_len); - if (status == PJ_EPENDING) - break; - } - - /* Unlock client */ - pj_mutex_unlock(client->mutex); -} - - -/* On Allocation timer timeout (i.e. we don't receive new Allocate request - * to refresh the allocation in time) - */ -static void client_on_expired(pj_timer_heap_t *th, pj_timer_entry *e) -{ - struct turn_client *client; - - PJ_UNUSED_ARG(th); - - client = (struct turn_client*) e->user_data; - - PJ_LOG(4,(THIS_FILE, "TURN client %s: allocation timer timeout, " - "destroying client", - client->obj_name)); - client_destroy(client, PJ_SUCCESS); -} - diff --git a/pjlib-util/src/pjstun-srv-test/usage.c b/pjlib-util/src/pjstun-srv-test/usage.c deleted file mode 100644 index a8a5c274..00000000 --- a/pjlib-util/src/pjstun-srv-test/usage.c +++ /dev/null @@ -1,271 +0,0 @@ -/* $Id$ */ -/* - * Copyright (C) 2003-2005 Benny Prijono - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ -#include "server.h" - -struct worker -{ - pj_ioqueue_op_key_t read_key; - unsigned index; - pj_uint8_t readbuf[4000]; - pj_sockaddr src_addr; - int src_addr_len; -}; - -struct pj_stun_usage -{ - pj_pool_t *pool; - pj_stun_server *srv; - pj_mutex_t *mutex; - pj_stun_usage_cb cb; - int type; - pj_sock_t sock; - pj_ioqueue_key_t *key; - unsigned worker_cnt; - struct worker *worker; - - pj_ioqueue_op_key_t *send_key; - unsigned send_count, send_index; - - pj_bool_t quitting; - void *user_data; -}; - - -static void on_read_complete(pj_ioqueue_key_t *key, - pj_ioqueue_op_key_t *op_key, - pj_ssize_t bytes_read); - -/* - * Create STUN usage. - */ -PJ_DEF(pj_status_t) pj_stun_usage_create( pj_stun_server *srv, - const char *name, - const pj_stun_usage_cb *cb, - int family, - int type, - int protocol, - const pj_sockaddr_t *local_addr, - int addr_len, - pj_stun_usage **p_usage) -{ - pj_stun_server_info *si; - pj_pool_t *pool; - pj_stun_usage *usage; - pj_ioqueue_callback ioqueue_cb; - unsigned i; - pj_status_t status; - - si = pj_stun_server_get_info(srv); - - pool = pj_pool_create(si->pf, name, 4000, 4000, NULL); - usage = PJ_POOL_ZALLOC_T(pool, pj_stun_usage); - usage->pool = pool; - usage->srv = srv; - - status = pj_mutex_create_simple(pool, name, &usage->mutex); - if (status != PJ_SUCCESS) - goto on_error; - - usage->type = type; - status = pj_sock_socket(family, type, protocol, &usage->sock); - if (status != PJ_SUCCESS) - goto on_error; - - status = pj_sock_bind(usage->sock, local_addr, addr_len); - if (status != PJ_SUCCESS) - goto on_error; - - pj_bzero(&ioqueue_cb, sizeof(ioqueue_cb)); - ioqueue_cb.on_read_complete = &on_read_complete; - status = pj_ioqueue_register_sock(usage->pool, si->ioqueue, usage->sock, - usage, &ioqueue_cb, &usage->key); - if (status != PJ_SUCCESS) - goto on_error; - - usage->worker_cnt = si->thread_cnt; - usage->worker = pj_pool_calloc(pool, si->thread_cnt, - sizeof(struct worker)); - for (i=0; ithread_cnt; ++i) { - pj_ioqueue_op_key_init(&usage->worker[i].read_key, - sizeof(usage->worker[i].read_key)); - usage->worker[i].index = i; - } - - usage->send_count = usage->worker_cnt * 2; - usage->send_key = pj_pool_calloc(pool, usage->send_count, - sizeof(pj_ioqueue_op_key_t)); - for (i=0; isend_count; ++i) { - pj_ioqueue_op_key_init(&usage->send_key[i], - sizeof(usage->send_key[i])); - } - - for (i=0; ithread_cnt; ++i) { - pj_ssize_t size; - - size = sizeof(usage->worker[i].readbuf); - usage->worker[i].src_addr_len = sizeof(usage->worker[i].src_addr); - status = pj_ioqueue_recvfrom(usage->key, &usage->worker[i].read_key, - usage->worker[i].readbuf, &size, - PJ_IOQUEUE_ALWAYS_ASYNC, - &usage->worker[i].src_addr, - &usage->worker[i].src_addr_len); - if (status != PJ_EPENDING) - goto on_error; - } - - pj_stun_server_register_usage(srv, usage); - - /* Only after everything has been initialized we copy the callback, - * to prevent callback from being called when we encounter error - * during initialiation (decendant would not expect this). - */ - pj_memcpy(&usage->cb, cb, sizeof(*cb)); - - *p_usage = usage; - return PJ_SUCCESS; - -on_error: - pj_stun_usage_destroy(usage); - return status; -} - - -/** - * Destroy usage. - */ -PJ_DEF(pj_status_t) pj_stun_usage_destroy(pj_stun_usage *usage) -{ - pj_stun_server_unregister_usage(usage->srv, usage); - if (usage->cb.on_destroy) - (*usage->cb.on_destroy)(usage); - - if (usage->key) { - pj_ioqueue_unregister(usage->key); - usage->key = NULL; - usage->sock = PJ_INVALID_SOCKET; - } else if (usage->sock != 0 && usage->sock != PJ_INVALID_SOCKET) { - pj_sock_close(usage->sock); - usage->sock = PJ_INVALID_SOCKET; - } - - if (usage->mutex) { - pj_mutex_destroy(usage->mutex); - usage->mutex = NULL; - } - - if (usage->pool) { - pj_pool_t *pool = usage->pool; - usage->pool = NULL; - pj_pool_release(pool); - } - - return PJ_SUCCESS; -} - - -/** - * Set user data. - */ -PJ_DEF(pj_status_t) pj_stun_usage_set_user_data( pj_stun_usage *usage, - void *user_data) -{ - usage->user_data = user_data; - return PJ_SUCCESS; -} - -/** - * Get user data. - */ -PJ_DEF(void*) pj_stun_usage_get_user_data(pj_stun_usage *usage) -{ - return usage->user_data; -} - - -/** - * Send with the usage. - */ -PJ_DEF(pj_status_t) pj_stun_usage_sendto( pj_stun_usage *usage, - const void *pkt, - pj_size_t pkt_size, - unsigned flags, - const pj_sockaddr_t *dst_addr, - unsigned addr_len) -{ - pj_ssize_t size = pkt_size; - unsigned i, count = usage->send_count, index; - - pj_mutex_lock(usage->mutex); - for (i=0, ++usage->send_index; isend_index) { - if (usage->send_index >= usage->send_count) - usage->send_index = 0; - - if (pj_ioqueue_is_pending(usage->key, &usage->send_key[usage->send_index])==0) { - break; - } - } - - if (i==count) { - pj_mutex_unlock(usage->mutex); - return PJ_EBUSY; - } - - index = usage->send_index; - pj_mutex_unlock(usage->mutex); - - return pj_ioqueue_sendto(usage->key, &usage->send_key[index], - pkt, &size, flags, - dst_addr, addr_len); -} - - -static void on_read_complete(pj_ioqueue_key_t *key, - pj_ioqueue_op_key_t *op_key, - pj_ssize_t bytes_read) -{ - enum { MAX_LOOP = 10 }; - pj_stun_usage *usage = pj_ioqueue_get_user_data(key); - struct worker *worker = (struct worker*) op_key; - unsigned count; - pj_status_t status; - - for (count=0; !usage->quitting; ++count) { - unsigned flags; - - if (bytes_read > 0) { - (*usage->cb.on_rx_data)(usage, worker->readbuf, bytes_read, - &worker->src_addr, worker->src_addr_len); - } else if (bytes_read < 0) { - pj_stun_perror(usage->pool->obj_name, "recv() error", -bytes_read); - } - - if (usage->quitting) - break; - - bytes_read = sizeof(worker->readbuf); - flags = (count >= MAX_LOOP) ? PJ_IOQUEUE_ALWAYS_ASYNC : 0; - worker->src_addr_len = sizeof(worker->src_addr); - status = pj_ioqueue_recvfrom(usage->key, &worker->read_key, - worker->readbuf, &bytes_read, flags, - &worker->src_addr, &worker->src_addr_len); - if (status == PJ_EPENDING) - break; - } -} - diff --git a/pjlib/build/wince-evc4/pjlib_wince.vcp b/pjlib/build/wince-evc4/pjlib_wince.vcp index 764d4324..db73c47f 100644 --- a/pjlib/build/wince-evc4/pjlib_wince.vcp +++ b/pjlib/build/wince-evc4/pjlib_wince.vcp @@ -370,6 +370,8 @@ DEP_CPP_ADDR_=\ "..\..\include\pj\compat\ctype.h"\ "..\..\include\pj\compat\errno.h"\ "..\..\include\pj\compat\high_precision.h"\ + "..\..\include\pj\compat\m_auto.h"\ + "..\..\include\pj\compat\os_auto.h"\ "..\..\include\pj\compat\os_darwinos.h"\ "..\..\include\pj\compat\os_linux.h"\ "..\..\include\pj\compat\os_linux_kernel.h"\ @@ -779,6 +781,8 @@ DEP_CPP_ARRAY=\ "..\..\include\pj\compat\ctype.h"\ "..\..\include\pj\compat\errno.h"\ "..\..\include\pj\compat\high_precision.h"\ + "..\..\include\pj\compat\m_auto.h"\ + "..\..\include\pj\compat\os_auto.h"\ "..\..\include\pj\compat\os_darwinos.h"\ "..\..\include\pj\compat\os_linux.h"\ "..\..\include\pj\compat\os_linux_kernel.h"\ @@ -1158,6 +1162,8 @@ DEP_CPP_CONFI=\ DEP_CPP_CONFI=\ "..\..\include\pj\compat\cc_gcc.h"\ "..\..\include\pj\compat\cc_msvc.h"\ + "..\..\include\pj\compat\m_auto.h"\ + "..\..\include\pj\compat\os_auto.h"\ "..\..\include\pj\compat\os_darwinos.h"\ "..\..\include\pj\compat\os_linux.h"\ "..\..\include\pj\compat\os_linux_kernel.h"\ @@ -1404,6 +1410,8 @@ DEP_CPP_CTYPE=\ "..\..\include\pj\compat\cc_gcc.h"\ "..\..\include\pj\compat\cc_msvc.h"\ "..\..\include\pj\compat\ctype.h"\ + "..\..\include\pj\compat\m_auto.h"\ + "..\..\include\pj\compat\os_auto.h"\ "..\..\include\pj\compat\os_darwinos.h"\ "..\..\include\pj\compat\os_linux.h"\ "..\..\include\pj\compat\os_linux_kernel.h"\ @@ -1666,6 +1674,8 @@ DEP_CPP_ERRNO=\ "..\..\include\pj\compat\ctype.h"\ "..\..\include\pj\compat\errno.h"\ "..\..\include\pj\compat\high_precision.h"\ + "..\..\include\pj\compat\m_auto.h"\ + "..\..\include\pj\compat\os_auto.h"\ "..\..\include\pj\compat\os_darwinos.h"\ "..\..\include\pj\compat\os_linux.h"\ "..\..\include\pj\compat\os_linux_kernel.h"\ @@ -2038,6 +2048,8 @@ DEP_CPP_EXCEP=\ "..\..\include\pj\compat\ctype.h"\ "..\..\include\pj\compat\errno.h"\ "..\..\include\pj\compat\high_precision.h"\ + "..\..\include\pj\compat\m_auto.h"\ + "..\..\include\pj\compat\os_auto.h"\ "..\..\include\pj\compat\os_darwinos.h"\ "..\..\include\pj\compat\os_linux.h"\ "..\..\include\pj\compat\os_linux_kernel.h"\ @@ -2371,6 +2383,8 @@ DEP_CPP_FIFOB=\ "..\..\include\pj\compat\assert.h"\ "..\..\include\pj\compat\cc_gcc.h"\ "..\..\include\pj\compat\cc_msvc.h"\ + "..\..\include\pj\compat\m_auto.h"\ + "..\..\include\pj\compat\os_auto.h"\ "..\..\include\pj\compat\os_darwinos.h"\ "..\..\include\pj\compat\os_linux.h"\ "..\..\include\pj\compat\os_linux_kernel.h"\ @@ -2651,6 +2665,8 @@ DEP_CPP_FILE_=\ "..\..\include\pj\compat\ctype.h"\ "..\..\include\pj\compat\errno.h"\ "..\..\include\pj\compat\high_precision.h"\ + "..\..\include\pj\compat\m_auto.h"\ + "..\..\include\pj\compat\os_auto.h"\ "..\..\include\pj\compat\os_darwinos.h"\ "..\..\include\pj\compat\os_linux.h"\ "..\..\include\pj\compat\os_linux_kernel.h"\ @@ -2987,6 +3003,8 @@ DEP_CPP_FILE_I=\ "..\..\include\pj\compat\cc_gcc.h"\ "..\..\include\pj\compat\cc_msvc.h"\ "..\..\include\pj\compat\errno.h"\ + "..\..\include\pj\compat\m_auto.h"\ + "..\..\include\pj\compat\os_auto.h"\ "..\..\include\pj\compat\os_darwinos.h"\ "..\..\include\pj\compat\os_linux.h"\ "..\..\include\pj\compat\os_linux_kernel.h"\ @@ -3277,6 +3295,8 @@ DEP_CPP_GUID_=\ "..\..\include\pj\compat\ctype.h"\ "..\..\include\pj\compat\errno.h"\ "..\..\include\pj\compat\high_precision.h"\ + "..\..\include\pj\compat\m_auto.h"\ + "..\..\include\pj\compat\os_auto.h"\ "..\..\include\pj\compat\os_darwinos.h"\ "..\..\include\pj\compat\os_linux.h"\ "..\..\include\pj\compat\os_linux_kernel.h"\ @@ -3643,6 +3663,8 @@ DEP_CPP_GUID_S=\ "..\..\include\pj\compat\ctype.h"\ "..\..\include\pj\compat\errno.h"\ "..\..\include\pj\compat\high_precision.h"\ + "..\..\include\pj\compat\m_auto.h"\ + "..\..\include\pj\compat\os_auto.h"\ "..\..\include\pj\compat\os_darwinos.h"\ "..\..\include\pj\compat\os_linux.h"\ "..\..\include\pj\compat\os_linux_kernel.h"\ @@ -4027,6 +4049,8 @@ DEP_CPP_HASH_=\ "..\..\include\pj\compat\ctype.h"\ "..\..\include\pj\compat\errno.h"\ "..\..\include\pj\compat\high_precision.h"\ + "..\..\include\pj\compat\m_auto.h"\ + "..\..\include\pj\compat\os_auto.h"\ "..\..\include\pj\compat\os_darwinos.h"\ "..\..\include\pj\compat\os_linux.h"\ "..\..\include\pj\compat\os_linux_kernel.h"\ @@ -4448,6 +4472,8 @@ DEP_CPP_IOQUE=\ "..\..\include\pj\compat\ctype.h"\ "..\..\include\pj\compat\errno.h"\ "..\..\include\pj\compat\high_precision.h"\ + "..\..\include\pj\compat\m_auto.h"\ + "..\..\include\pj\compat\os_auto.h"\ "..\..\include\pj\compat\os_darwinos.h"\ "..\..\include\pj\compat\os_linux.h"\ "..\..\include\pj\compat\os_linux_kernel.h"\ @@ -4894,6 +4920,8 @@ DEP_CPP_LIST_=\ DEP_CPP_LIST_=\ "..\..\include\pj\compat\cc_gcc.h"\ "..\..\include\pj\compat\cc_msvc.h"\ + "..\..\include\pj\compat\m_auto.h"\ + "..\..\include\pj\compat\os_auto.h"\ "..\..\include\pj\compat\os_darwinos.h"\ "..\..\include\pj\compat\os_linux.h"\ "..\..\include\pj\compat\os_linux_kernel.h"\ @@ -5161,6 +5189,8 @@ DEP_CPP_LOCK_=\ "..\..\include\pj\compat\ctype.h"\ "..\..\include\pj\compat\errno.h"\ "..\..\include\pj\compat\high_precision.h"\ + "..\..\include\pj\compat\m_auto.h"\ + "..\..\include\pj\compat\os_auto.h"\ "..\..\include\pj\compat\os_darwinos.h"\ "..\..\include\pj\compat\os_linux.h"\ "..\..\include\pj\compat\os_linux_kernel.h"\ @@ -5567,6 +5597,8 @@ DEP_CPP_LOG_C=\ "..\..\include\pj\compat\ctype.h"\ "..\..\include\pj\compat\errno.h"\ "..\..\include\pj\compat\high_precision.h"\ + "..\..\include\pj\compat\m_auto.h"\ + "..\..\include\pj\compat\os_auto.h"\ "..\..\include\pj\compat\os_darwinos.h"\ "..\..\include\pj\compat\os_linux.h"\ "..\..\include\pj\compat\os_linux_kernel.h"\ @@ -5932,6 +5964,8 @@ DEP_CPP_LOG_W=\ DEP_CPP_LOG_W=\ "..\..\include\pj\compat\cc_gcc.h"\ "..\..\include\pj\compat\cc_msvc.h"\ + "..\..\include\pj\compat\m_auto.h"\ + "..\..\include\pj\compat\os_auto.h"\ "..\..\include\pj\compat\os_darwinos.h"\ "..\..\include\pj\compat\os_linux.h"\ "..\..\include\pj\compat\os_linux_kernel.h"\ @@ -6212,6 +6246,8 @@ DEP_CPP_OS_CO=\ "..\..\include\pj\compat\ctype.h"\ "..\..\include\pj\compat\errno.h"\ "..\..\include\pj\compat\high_precision.h"\ + "..\..\include\pj\compat\m_auto.h"\ + "..\..\include\pj\compat\os_auto.h"\ "..\..\include\pj\compat\os_darwinos.h"\ "..\..\include\pj\compat\os_linux.h"\ "..\..\include\pj\compat\os_linux_kernel.h"\ @@ -6654,6 +6690,8 @@ DEP_CPP_OS_ER=\ "..\..\include\pj\compat\ctype.h"\ "..\..\include\pj\compat\errno.h"\ "..\..\include\pj\compat\high_precision.h"\ + "..\..\include\pj\compat\m_auto.h"\ + "..\..\include\pj\compat\os_auto.h"\ "..\..\include\pj\compat\os_darwinos.h"\ "..\..\include\pj\compat\os_linux.h"\ "..\..\include\pj\compat\os_linux_kernel.h"\ @@ -7042,6 +7080,8 @@ DEP_CPP_OS_TI=\ "..\..\include\pj\compat\ctype.h"\ "..\..\include\pj\compat\errno.h"\ "..\..\include\pj\compat\high_precision.h"\ + "..\..\include\pj\compat\m_auto.h"\ + "..\..\include\pj\compat\os_auto.h"\ "..\..\include\pj\compat\os_darwinos.h"\ "..\..\include\pj\compat\os_linux.h"\ "..\..\include\pj\compat\os_linux_kernel.h"\ @@ -7335,6 +7375,8 @@ DEP_CPP_OS_TIM=\ "..\..\include\pj\compat\cc_gcc.h"\ "..\..\include\pj\compat\cc_msvc.h"\ "..\..\include\pj\compat\high_precision.h"\ + "..\..\include\pj\compat\m_auto.h"\ + "..\..\include\pj\compat\os_auto.h"\ "..\..\include\pj\compat\os_darwinos.h"\ "..\..\include\pj\compat\os_linux.h"\ "..\..\include\pj\compat\os_linux_kernel.h"\ @@ -7583,6 +7625,8 @@ DEP_CPP_OS_TIME=\ "..\..\include\pj\compat\cc_gcc.h"\ "..\..\include\pj\compat\cc_msvc.h"\ "..\..\include\pj\compat\errno.h"\ + "..\..\include\pj\compat\m_auto.h"\ + "..\..\include\pj\compat\os_auto.h"\ "..\..\include\pj\compat\os_darwinos.h"\ "..\..\include\pj\compat\os_linux.h"\ "..\..\include\pj\compat\os_linux_kernel.h"\ @@ -7862,6 +7906,8 @@ DEP_CPP_POOL_=\ "..\..\include\pj\compat\ctype.h"\ "..\..\include\pj\compat\errno.h"\ "..\..\include\pj\compat\high_precision.h"\ + "..\..\include\pj\compat\m_auto.h"\ + "..\..\include\pj\compat\os_auto.h"\ "..\..\include\pj\compat\os_darwinos.h"\ "..\..\include\pj\compat\os_linux.h"\ "..\..\include\pj\compat\os_linux_kernel.h"\ @@ -8289,6 +8335,8 @@ DEP_CPP_POOL_B=\ "..\..\include\pj\compat\ctype.h"\ "..\..\include\pj\compat\errno.h"\ "..\..\include\pj\compat\high_precision.h"\ + "..\..\include\pj\compat\m_auto.h"\ + "..\..\include\pj\compat\os_auto.h"\ "..\..\include\pj\compat\os_darwinos.h"\ "..\..\include\pj\compat\os_linux.h"\ "..\..\include\pj\compat\os_linux_kernel.h"\ @@ -8836,6 +8884,8 @@ DEP_CPP_POOL_C=\ "..\..\include\pj\compat\ctype.h"\ "..\..\include\pj\compat\errno.h"\ "..\..\include\pj\compat\high_precision.h"\ + "..\..\include\pj\compat\m_auto.h"\ + "..\..\include\pj\compat\os_auto.h"\ "..\..\include\pj\compat\os_darwinos.h"\ "..\..\include\pj\compat\os_linux.h"\ "..\..\include\pj\compat\os_linux_kernel.h"\ @@ -9227,7 +9277,9 @@ DEP_CPP_POOL_P=\ "..\..\include\pj\compat\ctype.h"\ "..\..\include\pj\compat\errno.h"\ "..\..\include\pj\compat\high_precision.h"\ + "..\..\include\pj\compat\m_auto.h"\ "..\..\include\pj\compat\malloc.h"\ + "..\..\include\pj\compat\os_auto.h"\ "..\..\include\pj\compat\os_darwinos.h"\ "..\..\include\pj\compat\os_linux.h"\ "..\..\include\pj\compat\os_linux_kernel.h"\ @@ -9600,6 +9652,8 @@ DEP_CPP_RAND_=\ DEP_CPP_RAND_=\ "..\..\include\pj\compat\cc_gcc.h"\ "..\..\include\pj\compat\cc_msvc.h"\ + "..\..\include\pj\compat\m_auto.h"\ + "..\..\include\pj\compat\os_auto.h"\ "..\..\include\pj\compat\os_darwinos.h"\ "..\..\include\pj\compat\os_linux.h"\ "..\..\include\pj\compat\os_linux_kernel.h"\ @@ -9854,6 +9908,8 @@ DEP_CPP_RBTRE=\ DEP_CPP_RBTRE=\ "..\..\include\pj\compat\cc_gcc.h"\ "..\..\include\pj\compat\cc_msvc.h"\ + "..\..\include\pj\compat\m_auto.h"\ + "..\..\include\pj\compat\os_auto.h"\ "..\..\include\pj\compat\os_darwinos.h"\ "..\..\include\pj\compat\os_linux.h"\ "..\..\include\pj\compat\os_linux_kernel.h"\ @@ -10123,6 +10179,8 @@ DEP_CPP_SOCK_=\ "..\..\include\pj\compat\ctype.h"\ "..\..\include\pj\compat\errno.h"\ "..\..\include\pj\compat\high_precision.h"\ + "..\..\include\pj\compat\m_auto.h"\ + "..\..\include\pj\compat\os_auto.h"\ "..\..\include\pj\compat\os_darwinos.h"\ "..\..\include\pj\compat\os_linux.h"\ "..\..\include\pj\compat\os_linux_kernel.h"\ @@ -10535,6 +10593,8 @@ DEP_CPP_SOCK_S=\ "..\..\include\pj\compat\cc_gcc.h"\ "..\..\include\pj\compat\cc_msvc.h"\ "..\..\include\pj\compat\errno.h"\ + "..\..\include\pj\compat\m_auto.h"\ + "..\..\include\pj\compat\os_auto.h"\ "..\..\include\pj\compat\os_darwinos.h"\ "..\..\include\pj\compat\os_linux.h"\ "..\..\include\pj\compat\os_linux_kernel.h"\ @@ -10842,6 +10902,8 @@ DEP_CPP_STRIN=\ "..\..\include\pj\compat\ctype.h"\ "..\..\include\pj\compat\errno.h"\ "..\..\include\pj\compat\high_precision.h"\ + "..\..\include\pj\compat\m_auto.h"\ + "..\..\include\pj\compat\os_auto.h"\ "..\..\include\pj\compat\os_darwinos.h"\ "..\..\include\pj\compat\os_linux.h"\ "..\..\include\pj\compat\os_linux_kernel.h"\ @@ -11236,6 +11298,8 @@ DEP_CPP_TIMER=\ "..\..\include\pj\compat\ctype.h"\ "..\..\include\pj\compat\errno.h"\ "..\..\include\pj\compat\high_precision.h"\ + "..\..\include\pj\compat\m_auto.h"\ + "..\..\include\pj\compat\os_auto.h"\ "..\..\include\pj\compat\os_darwinos.h"\ "..\..\include\pj\compat\os_linux.h"\ "..\..\include\pj\compat\os_linux_kernel.h"\ @@ -11630,6 +11694,8 @@ DEP_CPP_TYPES=\ DEP_CPP_TYPES=\ "..\..\include\pj\compat\cc_gcc.h"\ "..\..\include\pj\compat\cc_msvc.h"\ + "..\..\include\pj\compat\m_auto.h"\ + "..\..\include\pj\compat\os_auto.h"\ "..\..\include\pj\compat\os_darwinos.h"\ "..\..\include\pj\compat\os_linux.h"\ "..\..\include\pj\compat\os_linux_kernel.h"\ @@ -11885,6 +11951,8 @@ DEP_CPP_UNICO=\ "..\..\include\pj\compat\ctype.h"\ "..\..\include\pj\compat\errno.h"\ "..\..\include\pj\compat\high_precision.h"\ + "..\..\include\pj\compat\m_auto.h"\ + "..\..\include\pj\compat\os_auto.h"\ "..\..\include\pj\compat\os_darwinos.h"\ "..\..\include\pj\compat\os_linux.h"\ "..\..\include\pj\compat\os_linux_kernel.h"\ @@ -12325,6 +12393,10 @@ SOURCE=..\..\include\pj\config_site.h # End Source File # Begin Source File +SOURCE=..\..\include\pj\config_site_sample.h +# End Source File +# Begin Source File + SOURCE=..\..\include\pj\ctype.h # End Source File # Begin Source File diff --git a/pjnath/build/pjnath.dsw b/pjnath/build/pjnath.dsw new file mode 100644 index 00000000..2105962e --- /dev/null +++ b/pjnath/build/pjnath.dsw @@ -0,0 +1,89 @@ +Microsoft Developer Studio Workspace File, Format Version 6.00 +# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE! + +############################################################################### + +Project: "pjlib"=..\..\pjlib\build\pjlib.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Project: "pjlib_test"=..\..\pjlib\build\pjlib_test.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Project: "pjlib_util"="..\..\pjlib-util\build\pjlib_util.dsp" - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Project: "pjstun_client"=.\pjstun_client.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ + Begin Project Dependency + Project_Dep_Name pjlib + End Project Dependency + Begin Project Dependency + Project_Dep_Name pjlib_util + End Project Dependency +}}} + +############################################################################### + +Project: "pjstun_srv_test"=.\pjstun_srv_test.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ + Begin Project Dependency + Project_Dep_Name pjlib + End Project Dependency + Begin Project Dependency + Project_Dep_Name pjlib_util + End Project Dependency +}}} + +############################################################################### + +Global: + +Package=<5> +{{{ +}}} + +Package=<3> +{{{ +}}} + +############################################################################### + diff --git a/pjnath/build/pjstun_client.dsp b/pjnath/build/pjstun_client.dsp new file mode 100644 index 00000000..2d5705b7 --- /dev/null +++ b/pjnath/build/pjstun_client.dsp @@ -0,0 +1,102 @@ +# Microsoft Developer Studio Project File - Name="pjstun_client" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Console Application" 0x0103 + +CFG=pjstun_client - Win32 Debug +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "pjstun_client.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "pjstun_client.mak" CFG="pjstun_client - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "pjstun_client - Win32 Release" (based on "Win32 (x86) Console Application") +!MESSAGE "pjstun_client - Win32 Debug" (based on "Win32 (x86) Console Application") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe +RSC=rc.exe + +!IF "$(CFG)" == "pjstun_client - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "./output/pjstun-client-i386-win32-vc6-release" +# PROP BASE Intermediate_Dir "./output/pjstun-client-i386-win32-vc6-release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "./output/pjstun-client-i386-win32-vc6-release" +# PROP Intermediate_Dir "./output/pjstun-client-i386-win32-vc6-release" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c +# ADD CPP /nologo /MD /W3 /GX /O2 /I "../include" /I "../../pjlib/include" /D "NDEBUG" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /D PJ_WIN32=1 /D PJ_M_I386=1 /FR /YX /FD /c +# ADD BASE RSC /l 0x409 /d "NDEBUG" +# ADD RSC /l 0x409 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# 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 +# 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" + +!ELSEIF "$(CFG)" == "pjstun_client - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "./output/pjstun-client-i386-win32-vc6-debug" +# PROP BASE Intermediate_Dir "./output/pjstun-client-i386-win32-vc6-debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "./output/pjstun-client-i386-win32-vc6-debug" +# PROP Intermediate_Dir "./output/pjstun-client-i386-win32-vc6-debug" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c +# ADD CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /I "../include" /I "../../pjlib/include" /D "_DEBUG" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /D PJ_WIN32=1 /D PJ_M_I386=1 /FR /YX /FD /GZ /c +# ADD BASE RSC /l 0x409 /d "_DEBUG" +# ADD RSC /l 0x409 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# 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 +# 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 + +!ENDIF + +# Begin Target + +# Name "pjstun_client - Win32 Release" +# Name "pjstun_client - Win32 Debug" +# Begin Group "Source Files" + +# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" +# Begin Source File + +SOURCE="..\src\pjstun-client\client_main.c" +# End Source File +# End Group +# Begin Group "Header Files" + +# PROP Default_Filter "h;hpp;hxx;hm;inl" +# End Group +# Begin Group "Resource Files" + +# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe" +# End Group +# End Target +# End Project diff --git a/pjnath/build/pjstun_srv_test.dsp b/pjnath/build/pjstun_srv_test.dsp new file mode 100644 index 00000000..fa1a5656 --- /dev/null +++ b/pjnath/build/pjstun_srv_test.dsp @@ -0,0 +1,122 @@ +# Microsoft Developer Studio Project File - Name="pjstun_srv_test" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Console Application" 0x0103 + +CFG=pjstun_srv_test - Win32 Debug +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "pjstun_srv_test.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "pjstun_srv_test.mak" CFG="pjstun_srv_test - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "pjstun_srv_test - Win32 Release" (based on "Win32 (x86) Console Application") +!MESSAGE "pjstun_srv_test - Win32 Debug" (based on "Win32 (x86) Console Application") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe +RSC=rc.exe + +!IF "$(CFG)" == "pjstun_srv_test - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "./output/pjstun-srv-test-i386-win32-vc6-release" +# PROP BASE Intermediate_Dir "./output/pjstun-srv-test-i386-win32-vc6-release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "./output/pjstun-srv-test-i386-win32-vc6-release" +# PROP Intermediate_Dir "./output/pjstun-srv-test-i386-win32-vc6-release" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c +# ADD CPP /nologo /MD /W4 /GX /O2 /I "../include" /I "../../pjlib/include" /D "NDEBUG" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /D PJ_WIN32=1 /D PJ_M_I386=1 /FR /YX /FD /c +# ADD BASE RSC /l 0x409 /d "NDEBUG" +# ADD RSC /l 0x409 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# 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 +# 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-srv-test-i386-win32-vc6-release.exe" + +!ELSEIF "$(CFG)" == "pjstun_srv_test - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "./output/pjstun-srv-test-i386-win32-vc6-debug" +# PROP BASE Intermediate_Dir "./output/pjstun-srv-test-i386-win32-vc6-debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "./output/pjstun-srv-test-i386-win32-vc6-debug" +# PROP Intermediate_Dir "./output/pjstun-srv-test-i386-win32-vc6-debug" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c +# ADD CPP /nologo /MTd /W4 /Gm /GX /ZI /Od /I "../include" /I "../../pjlib/include" /D "_DEBUG" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /D PJ_WIN32=1 /D PJ_M_I386=1 /FR /YX /FD /GZ /c +# ADD BASE RSC /l 0x409 /d "_DEBUG" +# ADD RSC /l 0x409 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# 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 +# 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-srv-test-i386-win32-vc6-debug.exe" /pdbtype:sept + +!ENDIF + +# Begin Target + +# Name "pjstun_srv_test - Win32 Release" +# Name "pjstun_srv_test - Win32 Debug" +# Begin Group "Source Files" + +# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" +# Begin Source File + +SOURCE="..\src\pjstun-srv-test\bind_usage.c" +# End Source File +# Begin Source File + +SOURCE="..\src\pjstun-srv-test\main.c" +# End Source File +# Begin Source File + +SOURCE="..\src\pjstun-srv-test\server.c" +# End Source File +# Begin Source File + +SOURCE="..\src\pjstun-srv-test\turn_usage.c" +# End Source File +# Begin Source File + +SOURCE="..\src\pjstun-srv-test\usage.c" +# End Source File +# End Group +# Begin Group "Header Files" + +# PROP Default_Filter "h;hpp;hxx;hm;inl" +# Begin Source File + +SOURCE="..\src\pjstun-srv-test\server.h" +# End Source File +# End Group +# Begin Group "Resource Files" + +# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe" +# End Group +# End Target +# End Project diff --git a/pjnath/include/pjnath/stun_auth.h b/pjnath/include/pjnath/stun_auth.h new file mode 100644 index 00000000..49b2acbb --- /dev/null +++ b/pjnath/include/pjnath/stun_auth.h @@ -0,0 +1,275 @@ +/* $Id$ */ +/* + * Copyright (C) 2003-2005 Benny Prijono + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +#ifndef __PJLIB_UTIL_STUN_AUTH_H__ +#define __PJLIB_UTIL_STUN_AUTH_H__ + +/** + * @file stun_auth.h + * @brief STUN authentication. + */ + +#include + + +PJ_BEGIN_DECL + + +/* **************************************************************************/ +/** + * @defgroup PJLIB_UTIL_STUN_AUTH STUN Authentication + * @ingroup PJLIB_UTIL_STUN + * @{ + */ + +/** + * Type of authentication data in the credential. + */ +typedef enum pj_stun_auth_cred_type +{ + /** + * The credential data contains a static credential to be matched + * against the credential in the message. A static credential can be + * used as both client side or server side authentication. + */ + PJ_STUN_AUTH_CRED_STATIC, + + /** + * The credential data contains callbacks to be called to verify the + * credential in the message. A dynamic credential is suitable when + * performing server side authentication where server does not know + * in advance the identity of the user requesting authentication. + */ + PJ_STUN_AUTH_CRED_DYNAMIC + +} pj_stun_auth_cred_type; + + +/** + * This structure contains the descriptions needed to perform server side + * authentication. Depending on the \a type set in the structure, application + * may specify a static username/password combination, or to have callbacks + * called by the function to authenticate the credential dynamically. + */ +typedef struct pj_stun_auth_cred +{ + /** + * The type of authentication information in this structure. + */ + pj_stun_auth_cred_type type; + + /** + * This union contains the authentication data. + */ + union + { + /** + * This structure contains static data for performing authentication. + * A non-empty realm indicates whether short term or long term + * credential is used. + */ + struct + { + /** + * If not-empty, it indicates that this is a long term credential. + */ + pj_str_t realm; + + /** + * The username of the credential. + */ + pj_str_t username; + + /** + * Data type to indicate the type of password in the \a data field. + * Value zero indicates that the data contains a plaintext + * password. + */ + int data_type; + + /** + * The data, which depends depends on the value of \a data_type + * field. When \a data_type is zero, this field will contain the + * plaintext password. + */ + pj_str_t data; + + /** + * Optional NONCE. + */ + pj_str_t nonce; + + } static_cred; + + /** + * This structure contains callback to be called by the framework + * to authenticate the incoming message. + */ + struct + { + /** + * User data which will be passed back to callback functions. + */ + void *user_data; + + /** + * This callback is called by pj_stun_verify_credential() when + * server needs to challenge the request with 401 response. + * + * @param user_data The user data as specified in the credential. + * @param pool Pool to allocate memory. + * @param realm On return, the function should fill in with + * realm if application wants to use long term + * credential. Otherwise application should set + * empty string for the realm. + * @param nonce On return, if application wants to use long + * term credential, it MUST fill in the nonce + * with some value. Otherwise if short term + * credential is wanted, it MAY set this value. + * If short term credential is wanted and the + * application doesn't want to include NONCE, + * then it must set this to empty string. + * + * @return The callback should return PJ_SUCCESS, or + * otherwise response message will not be + * created. + */ + pj_status_t (*get_auth)(void *user_data, + pj_pool_t *pool, + pj_str_t *realm, + pj_str_t *nonce); + + /** + * Get the password for the specified username. This function + * is also used to check whether the username is valid. + * + * @param user_data The user data as specified in the credential. + * @param realm The realm as specified in the message. + * @param username The username as specified in the message. + * @param pool Pool to allocate memory when necessary. + * @param data_type On return, application should fill up this + * argument with the type of data (which should + * be zero if data is a plaintext password). + * @param data On return, application should fill up this + * argument with the password according to + * data_type. + * + * @return The callback should return PJ_SUCCESS if + * username has been successfully verified + * and password was obtained. If non-PJ_SUCCESS + * is returned, it is assumed that the + * username is not valid. + */ + pj_status_t (*get_password)(void *user_data, + const pj_str_t *realm, + const pj_str_t *username, + pj_pool_t *pool, + int *data_type, + pj_str_t *data); + + /** + * This callback will be called to verify that the NONCE given + * in the message can be accepted. If this callback returns + * PJ_FALSE, 438 (Stale Nonce) response will be created. + * + * @param user_data The user data as specified in the credential. + * @param realm The realm as specified in the message. + * @param username The username as specified in the message. + * @param nonce The nonce to be verified. + * + * @return The callback MUST return non-zero if the + * NONCE can be accepted. + */ + pj_bool_t (*verify_nonce)(void *user_data, + const pj_str_t *realm, + const pj_str_t *username, + const pj_str_t *nonce); + + } dyn_cred; + + } data; + +} pj_stun_auth_cred; + + +/** + * Duplicate authentication credential. + * + * @param pool Pool to be used to allocate memory. + * @param dst Destination credential. + * @param src Source credential. + */ +PJ_DECL(void) pj_stun_auth_cred_dup(pj_pool_t *pool, + pj_stun_auth_cred *dst, + const pj_stun_auth_cred *src); + + +/** + * Verify credential in the STUN message. Note that before calling this + * function, application must have checked that the message contains + * PJ_STUN_ATTR_MESSAGE_INTEGRITY attribute by calling pj_stun_msg_find_attr() + * function, because this function will reject the message with 401 error + * if it doesn't contain PJ_STUN_ATTR_MESSAGE_INTEGRITY attribute. + * + * @param pkt The original packet which has been parsed into + * the message. This packet MUST NOT have been modified + * after the parsing. + * @param pkt_len The length of the packet. + * @param msg The parsed message to be verified. + * @param cred Pointer to credential to be used to authenticate + * the message. + * @param pool If response is to be created, then memory will + * be allocated from this pool. + * @param p_response Optional pointer to receive the response message + * then the credential in the request fails to + * authenticate. + * + * @return PJ_SUCCESS if credential is verified successfully. + * If the verification fails and \a p_response is not + * NULL, an appropriate response will be returned in + * \a p_response. + */ +PJ_DECL(pj_status_t) pj_stun_verify_credential(const pj_uint8_t *pkt, + unsigned pkt_len, + const pj_stun_msg *msg, + pj_stun_auth_cred *cred, + pj_pool_t *pool, + pj_stun_msg **p_response); + + + + +/** + * @} + */ + + +/* Calculate HMAC-SHA1 key for long term credential, by getting + * MD5 digest of username, realm, and password. + */ +void pj_stun_calc_md5_key(pj_uint8_t digest[16], + const pj_str_t *realm, + const pj_str_t *username, + const pj_str_t *passwd); + + +PJ_END_DECL + + +#endif /* __PJLIB_UTIL_STUN_AUTH_H__ */ + diff --git a/pjnath/include/pjnath/stun_doc.h b/pjnath/include/pjnath/stun_doc.h new file mode 100644 index 00000000..612bf1a7 --- /dev/null +++ b/pjnath/include/pjnath/stun_doc.h @@ -0,0 +1,100 @@ +/* $Id$ */ +/* + * Copyright (C) 2003-2005 Benny Prijono + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +#ifndef __PJ_STUN_SERVER_H__ +#define __PJ_STUN_SERVER_H__ + +/* + * STUN documentation. There is no code here. + */ + +/** + * @defgroup PJLIB_UTIL_STUN STUN and TURN + * @ingroup PJLIB_UTIL + + This is the implementation of STUN/TURN in PJLIB-UTIL library. + + The STUN/TURN implementation in PJLIB-UTIL has the following objectives: + - standard based (of course) + - supports both client and server side STUN/TURN services + - independent (that is, only dependent to pjlib), and general purpose + enough to be used not only by pjsip applications but also by other + types of applications + - must be able to support ICE. + + The STUN/TURN implementation is based on the following standards: + - + draft-ietf-behave-rfc3489bis-05.txt + - + draft-ietf-behave-turn-02.txt + + But as STUN standards are currently defined as work in progress at IETF, + the implementation will be updated as these standards are updated. + + + + @section stun_org_sec Organization + + The implementation consists of the following components. + + @subsection stun_msg_sec Messaging and Parsing + + The lowest layer of the STUN implementation is the @ref PJLIB_UTIL_STUN_MSG + component. This part is responsible for encoding and decoding STUN messages. + + This layer only implements message representation and parsing. In particular, + it does not provide any transport functionalities, therefore it can be used + by different types of applications. + + + + @subsection stun_endpt_sec Endpoint + + The @ref PJLIB_UTIL_STUN_ENDPOINT is used by the library to put together + common settings for all STUN objects. For example, the STUN endpoint has a + reference of timer heap to poll all STUN timers, reference to ioqueue to + poll network events for STUN servers, and some common settings used by + various STUN objects. + + + @subsection stun_clt_tsx_sec Client Transaction + + The @ref PJLIB_UTIL_STUN_TRANSACTION is used to manage outgoing STUN request, + for example to retransmit the request and to notify application about the + completion of the request. + + The @ref PJLIB_UTIL_STUN_TRANSACTION does not use any networking operations, + but instead application must supply the transaction with a callback to + be used by the transaction to send outgoing requests. This way the STUN + transaction is made more generic and can work with different types of + networking codes in application. + + + + @subsection stun_srv_sec Server Components + + The @ref PJLIB_UTIL_STUN_SERVER is used for: + - implementing STUN servers, and/or + - implementing server side STUN handling (for example for ICE). + + */ + + + +#endif /* __PJ_STUN_SERVER_H__ */ + diff --git a/pjnath/include/pjnath/stun_endpoint.h b/pjnath/include/pjnath/stun_endpoint.h new file mode 100644 index 00000000..b341309a --- /dev/null +++ b/pjnath/include/pjnath/stun_endpoint.h @@ -0,0 +1,117 @@ +/* $Id$ */ +/* + * Copyright (C) 2003-2005 Benny Prijono + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +#ifndef __PJLIB_UTIL_STUN_ENDPOINT_H__ +#define __PJLIB_UTIL_STUN_ENDPOINT_H__ + +/** + * @file stun_endpoint.h + * @brief STUN endpoint. + */ + +#include + + +PJ_BEGIN_DECL + + +/* **************************************************************************/ +/** + * @defgroup PJLIB_UTIL_STUN_ENDPOINT STUN Endpoint + * @brief Management of incoming and outgoing STUN transactions. + * @ingroup PJLIB_UTIL_STUN + * @{ + */ + +/** + * Opaque declaration for STUN endpoint. STUN endpoint manages client and + * server STUN transactions, and it needs to be initialized before application + * can send or receive STUN messages. + */ +typedef struct pj_stun_endpoint +{ + /** + * Pool factory to be used by the STUN endpoint and all objects created + * that use this STUN endpoint. + */ + pj_pool_factory *pf; + + /** + * Ioqueue used by this endpoint. + */ + pj_ioqueue_t *ioqueue; + + /** + * Timer heap instance used by this endpoint. + */ + pj_timer_heap_t *timer_heap; + + /** + * Internal pool used by this endpoint. This shouldn't be used by + * application. + */ + pj_pool_t *pool; + + /** + * Options. + */ + unsigned options; + + /** + * The default initial STUN round-trip time estimation in msecs. + * The value normally is PJ_STUN_RTO_VALUE. + */ + unsigned rto_msec; + + /** + * The interval to cache outgoing STUN response in the STUN session, + * in miliseconds. + * + * Default 10000 (10 seconds). + */ + unsigned res_cache_msec; + +} pj_stun_endpoint; + + + +/** + * Create a STUN endpoint instance. + */ +PJ_DECL(pj_status_t) pj_stun_endpoint_create(pj_pool_factory *factory, + unsigned options, + pj_ioqueue_t *ioqueue, + pj_timer_heap_t *timer_heap, + pj_stun_endpoint **p_endpt); + +/** + * Destroy STUN endpoint instance. + */ +PJ_DECL(pj_status_t) pj_stun_endpoint_destroy(pj_stun_endpoint *endpt); + + +/** + * @} + */ + + +PJ_END_DECL + + +#endif /* __PJLIB_UTIL_STUN_ENDPOINT_H__ */ + diff --git a/pjnath/include/pjnath/stun_msg.h b/pjnath/include/pjnath/stun_msg.h new file mode 100644 index 00000000..ae66c2d1 --- /dev/null +++ b/pjnath/include/pjnath/stun_msg.h @@ -0,0 +1,1539 @@ +/* $Id$ */ +/* + * Copyright (C) 2003-2005 Benny Prijono + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +#ifndef __PJLIB_UTIL_STUN_MSG_H__ +#define __PJLIB_UTIL_STUN_MSG_H__ + +/** + * @file stun_msg.h + * @brief STUN message components. + */ + +#include +#include + + +PJ_BEGIN_DECL + + +/* **************************************************************************/ +/** + * @defgroup PJLIB_UTIL_STUN_MSG STUN Message Representation and Parsing + * @brief Low-level representation and parsing of STUN messages. + * @ingroup PJLIB_UTIL_STUN + * @{ + */ + + +/** + * The default initial STUN round-trip time estimation (the RTO value + * in RFC 3489-bis), in miliseconds. + * This value is used to control the STUN request + * retransmit time. The initial value of retransmission interval + * would be set to this value, and will be doubled after each + * retransmission. + */ +#ifndef PJ_STUN_RTO_VALUE +# define PJ_STUN_RTO_VALUE 100 +#endif + + +/** + * The STUN transaction timeout value, in miliseconds. + * After the last retransmission is sent and if no response is received + * after this time, the STUN transaction will be considered to have failed. + * + * The default value is 1600 miliseconds (as per RFC 3489-bis). + */ +#ifndef PJ_STUN_TIMEOUT_VALUE +# define PJ_STUN_TIMEOUT_VALUE 1600 +#endif + + +/** + * Maximum number of STUN retransmission count. + * + * Default: 7 (as per RFC 3489-bis) + */ +#ifndef PJ_STUN_MAX_RETRANSMIT_COUNT +# define PJ_STUN_MAX_RETRANSMIT_COUNT 7 +#endif + + +/** + * Maximum size of STUN message. + */ +#ifndef PJ_STUN_MAX_PKT_LEN +# define PJ_STUN_MAX_PKT_LEN 512 +#endif + + +/** + * Default STUN port as defined by RFC 3489. + */ +#define PJ_STUN_PORT 3478 + +/** + * STUN magic cookie. + */ +#define PJ_STUN_MAGIC 0x2112A442 + + +/** + * STUN method constants. + */ +enum pj_stun_method_e +{ + /** + * STUN Binding method as defined by RFC 3489-bis. + */ + PJ_STUN_BINDING_METHOD = 1, + + /** + * STUN Shared Secret method as defined by RFC 3489-bis. + */ + PJ_STUN_SHARED_SECRET_METHOD = 2, + + /** + * STUN/TURN Allocate method as defined by draft-ietf-behave-turn + */ + PJ_STUN_ALLOCATE_METHOD = 3, + + /** + * STUN/TURN Send Indication as defined by draft-ietf-behave-turn + */ + PJ_STUN_SEND_INDICATION_METHOD = 4, + + /** + * STUN/TURN Data Indication as defined by draft-ietf-behave-turn + */ + PJ_STUN_DATA_INDICATION_METHOD = 5, + + /** + * STUN/TURN Set Active Destination as defined by draft-ietf-behave-turn + */ + PJ_STUN_SET_ACTIVE_DESTINATION_METHOD = 6, + + /** + * STUN/TURN Connect method as defined by draft-ietf-behave-turn + */ + PJ_STUN_CONNECT_METHOD = 7, + + /** + * STUN/TURN Connect Status indication method. + */ + PJ_STUN_CONNECT_STATUS_METHOD = 8 +}; + + +/** + * Retrieve the STUN method from the message-type field of the STUN + * message. + */ +#define PJ_STUN_GET_METHOD(msg_type) ((msg_type) & 0xFEEF) + + +/** + * STUN message classes constants. + */ +enum pj_stun_msg_class_e +{ + /** + * This specifies that the message type is a STUN request message. + */ + PJ_STUN_REQUEST_CLASS = 0, + + /** + * This specifies that the message type is a STUN indication message. + */ + PJ_STUN_INDICATION_CLASS = 1, + + /** + * This specifies that the message type is a STUN successful response. + */ + PJ_STUN_SUCCESS_CLASS = 2, + + /** + * This specifies that the message type is a STUN error response. + */ + PJ_STUN_ERROR_CLASS = 3 +}; + + +/** + * Determine if the message type is a request. + */ +#define PJ_STUN_IS_REQUEST(msg_type) (((msg_type) & 0x0110) == 0x0000) + + +/** + * Determine if the message type is a response. + */ +#define PJ_STUN_IS_RESPONSE(msg_type) (((msg_type) & 0x0110) == 0x0100) + + +/** + * The response bit in the message type. + */ +#define PJ_STUN_RESPONSE_BIT (0x0100) + +/** + * Determine if the message type is an error response. + */ +#define PJ_STUN_IS_ERROR_RESPONSE(msg_type) (((msg_type) & 0x0110) == 0x0110) + + +/** + * The error response bit in the message type. + */ +#define PJ_STUN_ERROR_RESPONSE_BIT (0x0110) + + +/** + * Determine if the message type is an indication message. + */ +#define PJ_STUN_IS_INDICATION(msg_type) (((msg_type) & 0x0110) == 0x0010) + + +/** + * The error response bit in the message type. + */ +#define PJ_STUN_INDICATION_BIT (0x0010) + + +/** + * This enumeration describes STUN message types. + */ +typedef enum pj_stun_msg_type +{ + /** + * STUN BINDING request. + */ + PJ_STUN_BINDING_REQUEST = 0x0001, + + /** + * Successful response to STUN BINDING-REQUEST. + */ + PJ_STUN_BINDING_RESPONSE = 0x0101, + + /** + * Error response to STUN BINDING-REQUEST. + */ + PJ_STUN_BINDING_ERROR_RESPONSE = 0x0111, + + /** + * STUN SHARED-SECRET reqeust. + */ + PJ_STUN_SHARED_SECRET_REQUEST = 0x0002, + + /** + * Successful response to STUN SHARED-SECRET reqeust. + */ + PJ_STUN_SHARED_SECRET_RESPONSE = 0x0102, + + /** + * Error response to STUN SHARED-SECRET reqeust. + */ + PJ_STUN_SHARED_SECRET_ERROR_RESPONSE = 0x0112, + + /** + * STUN/TURN Allocate Request + */ + PJ_STUN_ALLOCATE_REQUEST = 0x0003, + + /** + * Successful response to STUN/TURN Allocate Request + */ + PJ_STUN_ALLOCATE_RESPONSE = 0x0103, + + /** + * Failure response to STUN/TURN Allocate Request + */ + PJ_STUN_ALLOCATE_ERROR_RESPONSE = 0x0113, + + /** + * STUN/TURN Send Indication + */ + PJ_STUN_SEND_INDICATION = 0x0014, + + /** + * STUN/TURN Data Indication + */ + PJ_STUN_DATA_INDICATION = 0x0015, + + /** + * STUN/TURN Set Active Destination Request + */ + PJ_STUN_SET_ACTIVE_DESTINATION_REQUEST = 0x0006, + + /** + * STUN/TURN Set Active Destination Response + */ + PJ_STUN_SET_ACTIVE_DESTINATION_RESPONSE = 0x0106, + + /** + * STUN/TURN Set Active Destination Error Response + */ + PJ_STUN_SET_ACTIVE_DESTINATION_ERROR_RESPONSE = 0x0116, + + /** + * STUN/TURN Connect Request + */ + PJ_STUN_CONNECT_REQUEST = 0x0007, + + /** + * STUN/TURN Connect Response + */ + PJ_STUN_CONNECT_RESPONSE = 0x0107, + + /** + * STUN/TURN Connect Error Response + */ + PJ_STUN_CONNECT_ERROR_RESPONSE = 0x0117, + + /** + * STUN/TURN Connect Status Indication + */ + PJ_STUN_CONNECT_STATUS_INDICATION = 0x0018 + + +} pj_stun_msg_type; + + + +/** + * This enumeration describes STUN attribute types. + */ +typedef enum pj_stun_attr_type +{ + PJ_STUN_ATTR_MAPPED_ADDR = 0x0001,/**< MAPPED-ADDRESS. */ + PJ_STUN_ATTR_RESPONSE_ADDR = 0x0002,/**< RESPONSE-ADDRESS (deprcatd)*/ + PJ_STUN_ATTR_CHANGE_REQUEST = 0x0003,/**< CHANGE-REQUEST (deprecated)*/ + PJ_STUN_ATTR_SOURCE_ADDR = 0x0004,/**< SOURCE-ADDRESS (deprecated)*/ + PJ_STUN_ATTR_CHANGED_ADDR = 0x0005,/**< CHANGED-ADDRESS (deprecatd)*/ + PJ_STUN_ATTR_USERNAME = 0x0006,/**< USERNAME attribute. */ + PJ_STUN_ATTR_PASSWORD = 0x0007,/**< PASSWORD attribute. */ + PJ_STUN_ATTR_MESSAGE_INTEGRITY = 0x0008,/**< MESSAGE-INTEGRITY. */ + PJ_STUN_ATTR_ERROR_CODE = 0x0009,/**< ERROR-CODE. */ + PJ_STUN_ATTR_UNKNOWN_ATTRIBUTES = 0x000A,/**< UNKNOWN-ATTRIBUTES. */ + PJ_STUN_ATTR_REFLECTED_FROM = 0x000B,/**< REFLECTED-FROM (deprecatd)*/ + PJ_STUN_ATTR_LIFETIME = 0x000D,/**< LIFETIME attribute. */ + PJ_STUN_ATTR_BANDWIDTH = 0x0010,/**< BANDWIDTH attribute */ + PJ_STUN_ATTR_REMOTE_ADDR = 0x0012,/**< REMOTE-ADDRESS attribute */ + PJ_STUN_ATTR_DATA = 0x0013,/**< DATA attribute. */ + PJ_STUN_ATTR_REALM = 0x0014,/**< REALM attribute. */ + PJ_STUN_ATTR_NONCE = 0x0015,/**< NONCE attribute. */ + PJ_STUN_ATTR_RELAY_ADDR = 0x0016,/**< RELAY-ADDRESS attribute. */ + PJ_STUN_ATTR_REQ_ADDR_TYPE = 0x0017,/**< REQUESTED-ADDRESS-TYPE */ + PJ_STUN_ATTR_REQ_PORT_PROPS = 0x0018,/**< REQUESTED-PORT-PROPS */ + PJ_STUN_ATTR_REQ_TRANSPORT = 0x0019,/**< REQUESTED-TRANSPORT */ + PJ_STUN_ATTR_XOR_MAPPED_ADDR = 0x0020,/**< XOR-MAPPED-ADDRESS */ + PJ_STUN_ATTR_TIMER_VAL = 0x0021,/**< TIMER-VAL attribute. */ + PJ_STUN_ATTR_REQ_IP = 0x0022,/**< REQUESTED-IP attribute */ + PJ_STUN_ATTR_XOR_REFLECTED_FROM = 0x0023,/**< XOR-REFLECTED-FROM */ + PJ_STUN_ATTR_PRIORITY = 0x0024,/**< PRIORITY */ + PJ_STUN_ATTR_USE_CANDIDATE = 0x0025,/**< USE-CANDIDATE */ + PJ_STUN_ATTR_XOR_INTERNAL_ADDR = 0x0026,/**< XOR-INTERNAL-ADDRESS */ + + PJ_STUN_ATTR_END_MANDATORY_ATTR, + + PJ_STUN_ATTR_START_EXTENDED_ATTR= 0x8021, + + PJ_STUN_ATTR_SERVER = 0x8022,/**< SERVER attribute. */ + PJ_STUN_ATTR_ALTERNATE_SERVER = 0x8023,/**< ALTERNATE-SERVER. */ + PJ_STUN_ATTR_REFRESH_INTERVAL = 0x8024,/**< REFRESH-INTERVAL. */ + PJ_STUN_ATTR_FINGERPRINT = 0x8028,/**< FINGERPRINT attribute. */ + + PJ_STUN_ATTR_END_EXTENDED_ATTR + +} pj_stun_attr_type; + + +/** + * STUN error codes, which goes into STUN ERROR-CODE attribute. + */ +typedef enum pj_stun_status +{ + PJ_STUN_SC_TRY_ALTERNATE = 300, /**< Try Alternate */ + PJ_STUN_SC_BAD_REQUEST = 400, /**< Bad Request */ + PJ_STUN_SC_UNAUTHORIZED = 401, /**< Unauthorized */ + PJ_STUN_SC_UNKNOWN_ATTRIBUTE = 420, /**< Unknown Attribute */ + PJ_STUN_SC_STALE_CREDENTIALS = 430, /**< Stale Credentials */ + PJ_STUN_SC_INTEGRITY_CHECK_FAILURE = 431, /**< Integrity Chk Fail */ + PJ_STUN_SC_MISSING_USERNAME = 432, /**< Missing Username */ + PJ_STUN_SC_USE_TLS = 433, /**< Use TLS */ + PJ_STUN_SC_MISSING_REALM = 434, /**< Missing Realm */ + PJ_STUN_SC_MISSING_NONCE = 435, /**< Missing Nonce */ + PJ_STUN_SC_UNKNOWN_USERNAME = 436, /**< Unknown Username */ + PJ_STUN_SC_NO_BINDING = 437, /**< No Binding. */ + PJ_STUN_SC_STALE_NONCE = 438, /**< Stale Nonce */ + PJ_STUN_SC_TRANSITIONING = 439, /**< Transitioning. */ + PJ_STUN_SC_WRONG_USERNAME = 441, /**< Wrong Username. */ + PJ_STUN_SC_UNSUPP_TRANSPORT_PROTO = 442, /**< Unsupported Transport or + Protocol */ + PJ_STUN_SC_INVALID_IP_ADDR = 443, /**< Invalid IP Address */ + PJ_STUN_SC_INVALID_PORT = 444, /**< Invalid Port */ + PJ_STUN_SC_OPER_TCP_ONLY = 445, /**< Operation for TCP Only */ + PJ_STUN_SC_CONNECTION_FAILURE = 446, /**< Connection Failure */ + PJ_STUN_SC_CONNECTION_TIMEOUT = 447, /**< Connection Timeout */ + PJ_STUN_SC_ALLOCATION_QUOTA_REACHED = 486, /**< Allocation Quota Reached + (TURN) */ + PJ_STUN_SC_SERVER_ERROR = 500, /**< Server Error */ + PJ_STUN_SC_INSUFFICIENT_CAPACITY = 507, /**< Insufficient Capacity + (TURN) */ + PJ_STUN_SC_GLOBAL_FAILURE = 600 /**< Global Failure */ +} pj_stun_status; + + +/** + * This structure describes STUN message header. A STUN message has the + * following format: + * + * \verbatim + + 0 1 2 3 + 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + |0 0| STUN Message Type | Message Length | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | Magic Cookie | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + Transaction ID + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + + \endverbatim + */ +typedef struct pj_stun_msg_hdr +{ + /** + * STUN message type, which the first two bits must be zeroes. + */ + pj_uint16_t type; + + /** + * The message length is the size, in bytes, of the message not + * including the 20 byte STUN header. + */ + pj_uint16_t length; + + /** + * The magic cookie is a fixed value, 0x2112A442 (PJ_STUN_MAGIC constant). + * In the previous version of this specification [15] this field was part + * of the transaction ID. + */ + pj_uint32_t magic; + + /** + * The transaction ID is a 96 bit identifier. STUN transactions are + * identified by their unique 96-bit transaction ID. For request/ + * response transactions, the transaction ID is chosen by the STUN + * client and MUST be unique for each new STUN transaction generated by + * that STUN client. The transaction ID MUST be uniformly and randomly + * distributed between 0 and 2**96 - 1. + */ + pj_uint8_t tsx_id[12]; + +} pj_stun_msg_hdr; + + +/** + * This structre describes STUN attribute header. Each attribute is + * TLV encoded, with a 16 bit type, 16 bit length, and variable value. + * Each STUN attribute ends on a 32 bit boundary: + * + * \verbatim + + 0 1 2 3 + 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | Type | Length | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | Value .... | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + + \endverbatim + */ +typedef struct pj_stun_attr_hdr +{ + /** + * STUN attribute type. + */ + pj_uint16_t type; + + /** + * The Length refers to the length of the actual useful content of the + * Value portion of the attribute, measured in bytes. The value + * in the Length field refers to the length of the Value part of the + * attribute prior to padding - i.e., the useful content. + */ + pj_uint16_t length; + +} pj_stun_attr_hdr; + + +/** + * This structure describes STUN generic IP address attribute, used for + * example to represent STUN MAPPED-ADDRESS attribute. + * + * The generic IP address attribute indicates the transport address. + * It consists of an eight bit address family, and a sixteen bit port, + * followed by a fixed length value representing the IP address. If the + * address family is IPv4, the address is 32 bits, in network byte + * order. If the address family is IPv6, the address is 128 bits in + * network byte order. + * + * The format of the generic IP address attribute is: + * + * \verbatim + + 0 1 2 3 + 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + |x x x x x x x x| Family | Port | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | Address (variable) + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + + \endverbatim + */ +typedef struct pj_stun_sockaddr_attr +{ + /** + * Standard STUN attribute header. + */ + pj_stun_attr_hdr hdr; + + /** + * Flag to indicate whether this attribute should be sent in XOR-ed + * format, or has been received in XOR-ed format. + */ + pj_bool_t xor_ed; + + /** + * The socket address (as a union) + */ + union { + pj_sockaddr addr; /**< Generic socket address. */ + pj_sockaddr_in ipv4; /**< IPv4 socket address. */ + pj_sockaddr_in6 ipv6; /**< IPv6 socket address. */ + } addr; + +} pj_stun_sockaddr_attr; + + +/** + * This structure represents a generic STUN attributes with no payload, + * and it is used for example by ICE USE-CANDIDATE attribute. + */ +typedef struct pj_stun_empty_attr +{ + /** + * Standard STUN attribute header. + */ + pj_stun_attr_hdr hdr; + +} pj_stun_empty_attr; + + +/** + * This structure represents generic STUN string attributes, such as STUN + * USERNAME, PASSWORD, SERVER, REALM, and NONCE attributes. Note that for REALM and + * NONCE attributes, the text MUST be quoted with. + */ +typedef struct pj_stun_string_attr +{ + /** + * Standard STUN attribute header. + */ + pj_stun_attr_hdr hdr; + + /** + * The string value. + */ + pj_str_t value; + +} pj_stun_string_attr; + + +/** + * This structure represents a generic STUN attributes with 32bit (unsigned) + * integer value, such as STUN FINGERPRINT and REFRESH-INTERVAL attributes. + */ +typedef struct pj_stun_uint_attr +{ + /** + * Standard STUN attribute header. + */ + pj_stun_attr_hdr hdr; + + /** + * The 32bit value. + */ + pj_uint32_t value; + +} pj_stun_uint_attr; + + +/** + * This structure represents generic STUN attributes to hold a raw binary + * data. + */ +typedef struct pj_stun_binary_attr +{ + /** + * Standard STUN attribute header. + */ + pj_stun_attr_hdr hdr; + + /** + * Length of the data. + */ + unsigned length; + + /** + * The raw data. + */ + pj_uint8_t *data; + +} pj_stun_binary_attr; + + +/** + * This structure describes STUN MESSAGE-INTEGRITY attribute. + * The MESSAGE-INTEGRITY attribute contains an HMAC-SHA1 [10] of the + * STUN message. The MESSAGE-INTEGRITY attribute can be present in any + * STUN message type. Since it uses the SHA1 hash, the HMAC will be 20 + * bytes. + */ +typedef struct pj_stun_msgint_attr +{ + /** + * Standard STUN attribute header. + */ + pj_stun_attr_hdr hdr; + + /** + * The 20 bytes hmac value. + */ + pj_uint8_t hmac[20]; + +} pj_stun_msgint_attr; + + +/** + * This structure describes STUN FINGERPRINT attribute. The FINGERPRINT + * attribute can be present in all STUN messages. It is computed as + * the CRC-32 of the STUN message up to (but excluding) the FINGERPRINT + * attribute itself, xor-d with the 32 bit value 0x5354554e + */ +typedef struct pj_stun_uint_attr pj_stun_fingerprint_attr; + + +/** + * This structure represents STUN ERROR-CODE attribute. The ERROR-CODE + * attribute is present in the Binding Error Response and Shared Secret + * Error Response. It is a numeric value in the range of 100 to 699 + * plus a textual reason phrase encoded in UTF-8 + * + * \verbatim + + 0 1 2 3 + 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | 0 |Class| Number | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | Reason Phrase (variable) .. + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + + \endverbatim + */ +typedef struct pj_stun_errcode_attr +{ + /** + * Standard STUN attribute header. + */ + pj_stun_attr_hdr hdr; + + /** + * The value must be zero. + */ + pj_uint16_t zero; + + /** + * Error class (1-6). + */ + pj_uint8_t err_class; + + /** + * Error number is the error number modulo 100. + */ + pj_uint8_t number; + + /** + * The reason phrase. + */ + pj_str_t reason; + +} pj_stun_errcode_attr; + + +/** + * This describes STUN REALM attribute. + * The REALM attribute is present in requests and responses. It + * contains text which meets the grammar for "realm" as described in RFC + * 3261 [11], and will thus contain a quoted string (including the + * quotes). + */ +typedef struct pj_stun_string_attr pj_stun_realm_attr; + + +/** + * This describes STUN NONCE attribute. + * The NONCE attribute is present in requests and in error responses. + * It contains a sequence of qdtext or quoted-pair, which are defined in + * RFC 3261 [11]. See RFC 2617 [7] for guidance on selection of nonce + * values in a server. + */ +typedef struct pj_stun_string_attr pj_stun_nonce_attr; + + +/** + * This describes STUN UNKNOWN-ATTRIBUTES attribute. + * The UNKNOWN-ATTRIBUTES attribute is present only in an error response + * when the response code in the ERROR-CODE attribute is 420. + * The attribute contains a list of 16 bit values, each of which + * represents an attribute type that was not understood by the server. + * If the number of unknown attributes is an odd number, one of the + * attributes MUST be repeated in the list, so that the total length of + * the list is a multiple of 4 bytes. + */ +typedef struct pj_stun_unknown_attr +{ + /** + * Standard STUN attribute header. + */ + pj_stun_attr_hdr hdr; + + /** + * Number of unknown attributes in the array. + */ + unsigned attr_count; + + /** + * Array of unknown attribute IDs. + */ + pj_uint16_t attrs[PJ_STUN_MAX_ATTR]; + +} pj_stun_unknown_attr; + + +/** + * This structure describes STUN MAPPED-ADDRESS attribute. + * The MAPPED-ADDRESS attribute indicates the mapped transport address. + */ +typedef struct pj_stun_sockaddr_attr pj_stun_mapped_addr_attr; + + +/** + * This describes STUN XOR-MAPPED-ADDRESS attribute (which has the same + * format as STUN MAPPED-ADDRESS attribute). + * The XOR-MAPPED-ADDRESS attribute is present in responses. It + * provides the same information that would present in the MAPPED- + * ADDRESS attribute but because the NAT's public IP address is + * obfuscated through the XOR function, STUN messages are able to pass + * through NATs which would otherwise interfere with STUN. + */ +typedef struct pj_stun_sockaddr_attr pj_stun_xor_mapped_addr_attr; + + +/** + * This describes STUN SERVER attribute. + * The server attribute contains a textual description of the software + * being used by the server, including manufacturer and version number. + * The attribute has no impact on operation of the protocol, and serves + * only as a tool for diagnostic and debugging purposes. The value of + * SERVER is variable length. + */ +typedef struct pj_stun_string_attr pj_stun_server_attr; + + +/** + * This describes STUN ALTERNATE-SERVER attribute. + * The alternate server represents an alternate transport address for a + * different STUN server to try. It is encoded in the same way as + * MAPPED-ADDRESS. + */ +typedef struct pj_stun_sockaddr_attr pj_stun_alt_server_attr; + + +/** + * This describes STUN REFRESH-INTERVAL attribute. + * The REFRESH-INTERVAL indicates the number of milliseconds that the + * server suggests the client should use between refreshes of the NAT + * bindings between the client and server. + */ +typedef struct pj_stun_uint_attr pj_stun_refresh_interval_attr; + + +/** + * This structure describes STUN RESPONSE-ADDRESS attribute. + * The RESPONSE-ADDRESS attribute indicates where the response to a + * Binding Request should be sent. Its syntax is identical to MAPPED- + * ADDRESS. + * + * Note that the usage of this attribute has been deprecated by the + * RFC 3489-bis standard. + */ +typedef struct pj_stun_sockaddr_attr pj_stun_response_addr_attr; + + +/** + * This structure describes STUN CHANGED-ADDRESS attribute. + * The CHANGED-ADDRESS attribute indicates the IP address and port where + * responses would have been sent from if the "change IP" and "change + * port" flags had been set in the CHANGE-REQUEST attribute of the + * Binding Request. The attribute is always present in a Binding + * Response, independent of the value of the flags. Its syntax is + * identical to MAPPED-ADDRESS. + * + * Note that the usage of this attribute has been deprecated by the + * RFC 3489-bis standard. + */ +typedef struct pj_stun_sockaddr_attr pj_stun_changed_addr_attr; + + +/** + * This structure describes STUN CHANGE-REQUEST attribute. + * The CHANGE-REQUEST attribute is used by the client to request that + * the server use a different address and/or port when sending the + * response. + * + * Bit 29 of the value is the "change IP" flag. If true, it requests + * the server to send the Binding Response with a different IP address + * than the one the Binding Request was received on. + * + * Bit 30 of the value is the "change port" flag. If true, it requests + * the server to send the Binding Response with a different port than + * the one the Binding Request was received on. + * + * Note that the usage of this attribute has been deprecated by the + * RFC 3489-bis standard. + */ +typedef struct pj_stun_uint_attr pj_stun_change_request_attr; + +/** + * This structure describes STUN SOURCE-ADDRESS attribute. + * The SOURCE-ADDRESS attribute is present in Binding Responses. It + * indicates the source IP address and port that the server is sending + * the response from. Its syntax is identical to that of MAPPED- + * ADDRESS. + * + * Note that the usage of this attribute has been deprecated by the + * RFC 3489-bis standard. + */ +typedef struct pj_stun_sockaddr_attr pj_stun_src_addr_attr; + + +/** + * This describes the STUN REFLECTED-FROM attribute. + * The REFLECTED-FROM attribute is present only in Binding Responses, + * when the Binding Request contained a RESPONSE-ADDRESS attribute. The + * attribute contains the identity (in terms of IP address) of the + * source where the request came from. Its purpose is to provide + * traceability, so that a STUN server cannot be used as a reflector for + * denial-of-service attacks. + */ +typedef struct pj_stun_sockaddr_attr pj_stun_reflected_from_attr; + + +/** + * This describes STUN USERNAME attribute. + * The USERNAME attribute is used for message integrity. It identifies + * the shared secret used in the message integrity check. Consequently, + * the USERNAME MUST be included in any request that contains the + * MESSAGE-INTEGRITY attribute. + */ +typedef struct pj_stun_string_attr pj_stun_username_attr; + + +/** + * This describes STUN PASSWORD attribute. + * If the message type is Shared Secret Response it MUST include the + * PASSWORD attribute. + */ +typedef struct pj_stun_string_attr pj_stun_password_attr; + + +/** + * This describes STUN LIFETIME attribute. + * The lifetime attribute represents the duration for which the server + * will maintain an allocation in the absence of data traffic either + * from or to the client. It is a 32 bit value representing the number + * of seconds remaining until expiration. + */ +typedef struct pj_stun_uint_attr pj_stun_lifetime_attr; + + +/** + * This describes STUN BANDWIDTH attribute. + * The bandwidth attribute represents the peak bandwidth, measured in + * kbits per second, that the client expects to use on the binding. The + * value represents the sum in the receive and send directions. + */ +typedef struct pj_stun_uint_attr pj_stun_bandwidth_attr; + + +/** + * This describes the STUN REMOTE-ADDRESS attribute. + * The REMOTE-ADDRESS specifies the address and port of the peer as seen + * from the STUN relay server. + */ +typedef struct pj_stun_sockaddr_attr pj_stun_remote_addr_attr; + + +/** + * This describes the STUN DATA attribute. + * The DATA attribute is present in Send Indications and Data + * Indications. It contains raw payload data that is to be sent (in the + * case of a Send Request) or was received (in the case of a Data + * Indication).. + */ +typedef struct pj_stun_binary_attr pj_stun_data_attr; + + +/** + * This describes the STUN RELAY-ADDRESS attribute. + * The RELAY-ADDRESS is present in Allocate responses. It specifies the + * address and port that the server allocated to the client. + */ +typedef struct pj_stun_sockaddr_attr pj_stun_relay_addr_attr; + + +/** + * This describes the REQUESTED-ADDRESS-TYPE attribute. + * The REQUESTED-ADDRESS-TYPE attribute is used by clients to request + * the allocation of a specific address type from a server. The + * following is the format of the REQUESTED-ADDRESS-TYPE attribute. + + \verbatim + + 0 1 2 3 + 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | Family | Reserved | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + + \endverbatim + */ +typedef struct pj_stun_uint_attr pj_stun_req_addr_type; + +/** + * This describes the STUN REQUESTED-PORT-PROPS attribute. + * This attribute allows the client to request certain properties for + * the port that is allocated by the server. The attribute can be used + * with any transport protocol that has the notion of a 16 bit port + * space (including TCP and UDP). The attribute is 32 bits long. Its + * format is: + + \verbatim + + 0 1 2 3 + 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | Reserved = 0 |B| A | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + + \endverbatim + */ +typedef struct pj_stun_uint_attr pj_stun_req_port_props_attr; + + +/** + * This describes the STUN REQUESTED-TRANSPORT attribute. + * This attribute is used by the client to request a specific transport + * protocol for the allocated transport address. It is a 32 bit + * unsigned integer. Its values are: 0x0000 for UDP and 0x0000 for TCP. + */ +typedef struct pj_stun_uint_attr pj_stun_req_transport_attr; + + +/** + * This describes the STUN REQUESTED-IP attribute. + * The REQUESTED-IP attribute is used by the client to request that a + * specific IP address be allocated to it. + */ +typedef struct pj_stun_sockaddr_attr pj_stun_req_ip_attr; + +/** + * This describes the XOR-REFLECTED-FROM attribute, as described by + * draft-macdonald-behave-nat-behavior-discovery-00. + * The XOR-REFLECTED-FROM attribute is used in place of the REFLECTED- + * FROM attribute. It provides the same information, but because the + * NAT's public address is obfuscated through the XOR function, It can + * pass through a NAT that would otherwise attempt to translate it to + * the private network address. XOR-REFLECTED-FROM has identical syntax + * to XOR-MAPPED-ADDRESS. + */ +typedef struct pj_stun_sockaddr_attr pj_stun_xor_reflected_from_attr; + +/** + * This describes the PRIORITY attribute from draft-ietf-mmusic-ice-13. + * The PRIORITY attribute indicates the priority that is to be + * associated with a peer reflexive candidate, should one be discovered + * by this check. It is a 32 bit unsigned integer, and has an attribute + * type of 0x0024. + */ +typedef struct pj_stun_uint_attr pj_stun_priority_attr; + +/** + * This describes the USE-CANDIDATE attribute from draft-ietf-mmusic-ice-13. + * The USE-CANDIDATE attribute indicates that the candidate pair + * resulting from this check should be used for transmission of media. + * The attribute has no content (the Length field of the attribute is + * zero); it serves as a flag. + */ +typedef struct pj_stun_empty_attr pj_stun_use_candidate_attr; + +/** + * This structure describes STUN XOR-INTERNAL-ADDRESS attribute from + * draft-wing-behave-nat-control-stun-usage-00. + * This attribute MUST be present in a Binding Response and may be used + * in other responses as well. This attribute is necessary to allow a + * STUN client to 'walk backwards' and communicate directly with all of + * the STUN-aware NATs along the path. + */ +typedef pj_stun_sockaddr_attr pj_stun_xor_internal_addr_attr; + +/** + * This describes the STUN TIMER-VAL attribute. + * The TIMER-VAL attribute is used only in conjunction with the Set + * Active Destination response. It conveys from the server, to the + * client, the value of the timer used in the server state machine. + */ +typedef struct pj_stun_uint_attr pj_stun_timer_val_attr; + + +/** + * This structure describes a parsed STUN message. All integral fields + * in this structure (including IP addresses) will be in the host + * byte order. + */ +typedef struct pj_stun_msg +{ + /** + * STUN message header. + */ + pj_stun_msg_hdr hdr; + + /** + * Number of attributes in the STUN message. + */ + unsigned attr_count; + + /** + * Array of STUN attributes. + */ + pj_stun_attr_hdr *attr[PJ_STUN_MAX_ATTR]; + +} pj_stun_msg; + + +/** STUN decoding options */ +enum pj_stun_decode_options +{ + /** + * Tell the decoder that the message was received from datagram + * oriented transport (such as UDP). + */ + PJ_STUN_IS_DATAGRAM = 1, + + /** + * Tell pj_stun_msg_decode() to check the validity of the STUN + * message by calling pj_stun_msg_check() before starting to + * decode the packet. + */ + PJ_STUN_CHECK_PACKET = 2 +}; + + +/** + * Get STUN message method name. + * + * @param msg_type The STUN message type (in host byte order) + * + * @return The STUN message method name string. + */ +PJ_DECL(const char*) pj_stun_get_method_name(unsigned msg_type); + + +/** + * Get STUN message class name. + * + * @param msg_type The STUN message type (in host byte order) + * + * @return The STUN message class name string. + */ +PJ_DECL(const char*) pj_stun_get_class_name(unsigned msg_type); + + +/** + * Get STUN attribute name. + * + * @return attr_type The STUN attribute type (in host byte order). + * + * @return The STUN attribute type name string. + */ +PJ_DECL(const char*) pj_stun_get_attr_name(unsigned attr_type); + + +/** + * Get STUN standard reason phrase for the specified error code. + * + * @param err_code The STUN error code. + * + * @return The STUN error reason phrase. + */ +PJ_DECL(pj_str_t) pj_stun_get_err_reason(int err_code); + + +/** + * Create a generic STUN message. + * + * @param pool Pool to create the STUN message. + * @param msg_type The 14bit message type. + * @param magic Magic value to be put to the mesage; for requests, + * the value should be PJ_STUN_MAGIC. + * @param tsx_id Optional transaction ID, or NULL to let the + * function generates a random transaction ID. + * @param p_msg Pointer to receive the message. + * + * @return PJ_SUCCESS on success. + */ +PJ_DECL(pj_status_t) pj_stun_msg_create(pj_pool_t *pool, + unsigned msg_type, + pj_uint32_t magic, + const pj_uint8_t tsx_id[12], + pj_stun_msg **p_msg); + +/** + * Create STUN response message. + * + * @param pool Pool to create the mesage. + * @param req_msg The request message. + * @param err_code STUN error code. If this value is not zero, + * then error response will be created, otherwise + * successful response will be created. + * @param err_msg Optional error message to explain err_code. + * If this value is NULL and err_code is not zero, + * the error string will be taken from the default + * STUN error message. + * @param p_response Pointer to receive the response. + * + * @return PJ_SUCCESS on success, or the appropriate error. + */ +PJ_DECL(pj_status_t) pj_stun_msg_create_response(pj_pool_t *pool, + const pj_stun_msg *req_msg, + unsigned err_code, + const pj_str_t *err_msg, + pj_stun_msg **p_response); + + +/** + * Add STUN attribute to STUN message. + * + * @param msg The STUN message. + * @param attr The STUN attribute to be added to the message. + * + * @return PJ_SUCCESS on success, or PJ_ETOOMANY if there are + * already too many attributes in the message. + */ +PJ_DECL(pj_status_t) pj_stun_msg_add_attr(pj_stun_msg *msg, + pj_stun_attr_hdr *attr); + + +/** + * Print the STUN message structure to a packet buffer, ready to be + * sent to remote destination. This function will take care about + * calculating the MESSAGE-INTEGRITY digest as well as FINGERPRINT + * value. + * + * If MESSAGE-INTEGRITY attribute is present, the function assumes + * that application wants to include credential (short or long term) + * in the message, and this function will calculate the HMAC digest + * from the message using the supplied password in the parameter. + * If REALM attribute is present, the HMAC digest is calculated as + * long term credential, otherwise as short term credential. + * + * If FINGERPRINT attribute is present, this function will calculate + * the FINGERPRINT CRC attribute for the message. + * + * @param msg The STUN message to be printed. Upon return, + * some fields in the header (such as message + * length) will be updated. + * @param pkt_buf The buffer to be filled with the packet. + * @param buf_size Size of the buffer. + * @param options Options, which currently must be zero. + * @param password Password to be used when credential is to be + * included. This parameter MUST be specified when + * the message contains MESSAGE-INTEGRITY attribute. + * @param p_msg_len Upon return, it will be filed with the size of + * the packet in bytes, or negative value on error. + * + * @return PJ_SUCCESS on success or the appropriate error code. + */ +PJ_DECL(pj_status_t) pj_stun_msg_encode(pj_stun_msg *msg, + pj_uint8_t *pkt_buf, + unsigned buf_size, + unsigned options, + const pj_str_t *password, + unsigned *p_msg_len); + +/** + * Check that the PDU is potentially a valid STUN message. This function + * is useful when application needs to multiplex STUN packets with other + * application traffic. When this function returns PJ_SUCCESS, there is a + * big chance that the packet is a STUN packet. + * + * Note that we cannot be sure that the PDU is a really valid STUN message + * until we actually parse the PDU. + * + * @param pdu The packet buffer. + * @param pdu_len The length of the packet buffer. + * @param options Additional options to be applied in the checking, + * which can be taken from pj_stun_decode_options. One + * of the useful option is PJ_STUN_IS_DATAGRAM which + * means that the pdu represents a whole STUN packet. + * + * @return PJ_SUCCESS if the PDU is a potentially valid STUN + * message. + */ +PJ_DECL(pj_status_t) pj_stun_msg_check(const pj_uint8_t *pdu, + unsigned pdu_len, unsigned options); + + +/** + * Decode incoming packet into STUN message. + * + * @param pool Pool to allocate the message. + * @param pdu The incoming packet to be parsed. + * @param pdu_len The length of the incoming packet. + * @param options Parsing flags, according to pj_stun_decode_options. + * @param p_msg Pointer to receive the parsed message. + * @param p_parsed_len Optional pointer to receive how many bytes have + * been parsed for the STUN message. This is useful + * when the packet is received over stream oriented + * transport. + * @param p_response Optional pointer to receive an instance of response + * message, if one can be created. If the packet being + * decoded is a request message, and it contains error, + * and a response can be created, then the STUN + * response message will be returned on this argument. + * + * @return PJ_SUCCESS if a STUN message has been successfully + * decoded. + */ +PJ_DECL(pj_status_t) pj_stun_msg_decode(pj_pool_t *pool, + const pj_uint8_t *pdu, + unsigned pdu_len, + unsigned options, + pj_stun_msg **p_msg, + unsigned *p_parsed_len, + pj_stun_msg **p_response); + +/** + * Dump STUN message to a printable string output. + * + * @param msg The STUN message + * @param buffer Buffer where the printable string output will + * be printed on. + * @param length Specify the maximum length of the buffer. + * @param printed_len Optional pointer, which on output will be filled + * up with the actual length of the output string. + * + * @return The message string output. + */ +PJ_DECL(char*) pj_stun_msg_dump(const pj_stun_msg *msg, + char *buffer, + unsigned length, + unsigned *printed_len); + + +/** + * Find STUN attribute in the STUN message, starting from the specified + * index. + * + * @param msg The STUN message. + * @param attr_type The attribute type to be found, from pj_stun_attr_type. + * @param start_index The start index of the attribute in the message. + * Specify zero to start searching from the first + * attribute. + * + * @return The attribute instance, or NULL if it cannot be + * found. + */ +PJ_DECL(pj_stun_attr_hdr*) pj_stun_msg_find_attr(const pj_stun_msg *msg, + int attr_type, + unsigned start_index); + + +/** + * Create a generic STUN IP address attribute. The \a addr_len and + * \a addr parameters specify whether the address is IPv4 or IPv4 + * address. + * + * @param pool The pool to allocate memory from. + * @param attr_type Attribute type, from #pj_stun_attr_type. + * @param xor_ed If non-zero, the port and address will be XOR-ed + * with magic, to make the XOR-MAPPED-ADDRESS attribute. + * @param addr A pj_sockaddr_in or pj_sockaddr_in6 structure. + * @param addr_len Length of \a addr parameter. + * @param p_attr Pointer to receive the attribute. + * + * @return PJ_SUCCESS on success or the appropriate error code. + */ +PJ_DECL(pj_status_t) pj_stun_sockaddr_attr_create(pj_pool_t *pool, + int attr_type, + pj_bool_t xor_ed, + const pj_sockaddr_t *addr, + unsigned addr_len, + pj_stun_sockaddr_attr **p_attr); + + +/** + * Create and add generic STUN IP address attribute to a STUN message. + * The \a addr_len and \a addr parameters specify whether the address is + * IPv4 or IPv4 address. + * + * @param pool The pool to allocate memory from. + * @param msg The STUN message. + * @param attr_type Attribute type, from #pj_stun_attr_type. + * @param xor_ed If non-zero, the port and address will be XOR-ed + * with magic, to make the XOR-MAPPED-ADDRESS attribute. + * @param addr A pj_sockaddr_in or pj_sockaddr_in6 structure. + * @param addr_len Length of \a addr parameter. + * + * @return PJ_SUCCESS on success or the appropriate error code. + */ +PJ_DECL(pj_status_t) pj_stun_msg_add_sockaddr_attr(pj_pool_t *pool, + pj_stun_msg *msg, + int attr_type, + pj_bool_t xor_ed, + const pj_sockaddr_t *addr, + unsigned addr_len); + +/** + * Create a STUN generic string attribute. + * + * @param pool The pool to allocate memory from. + * @param attr_type Attribute type, from #pj_stun_attr_type. + * @param value The string value to be assigned to the attribute. + * @param p_attr Pointer to receive the attribute. + * + * @return PJ_SUCCESS on success or the appropriate error code. + */ +PJ_DECL(pj_status_t) pj_stun_string_attr_create(pj_pool_t *pool, + int attr_type, + const pj_str_t *value, + pj_stun_string_attr **p_attr); + +/** + * Create and add STUN generic string attribute to the message. + * + * @param pool The pool to allocate memory from. + * @param msg The STUN message. + * @param attr_type Attribute type, from #pj_stun_attr_type. + * @param value The string value to be assigned to the attribute. + * + * @return PJ_SUCCESS on success or the appropriate error code. + */ +PJ_DECL(pj_status_t) pj_stun_msg_add_string_attr(pj_pool_t *pool, + pj_stun_msg *msg, + int attr_type, + const pj_str_t *value); + +/** + * Create a STUN generic 32bit value attribute. + * + * @param pool The pool to allocate memory from. + * @param attr_type Attribute type, from #pj_stun_attr_type. + * @param value The 32bit value to be assigned to the attribute. + * @param p_attr Pointer to receive the attribute. + * + * @return PJ_SUCCESS on success or the appropriate error code. + */ +PJ_DECL(pj_status_t) pj_stun_uint_attr_create(pj_pool_t *pool, + int attr_type, + pj_uint32_t value, + pj_stun_uint_attr **p_attr); + +/** + * Create and add STUN generic 32bit value attribute to the message. + * + * @param pool The pool to allocate memory from. + * @param msg The STUN message + * @param attr_type Attribute type, from #pj_stun_attr_type. + * @param value The 32bit value to be assigned to the attribute. + * + * @return PJ_SUCCESS on success or the appropriate error code. + */ +PJ_DECL(pj_status_t) pj_stun_msg_add_uint_attr(pj_pool_t *pool, + pj_stun_msg *msg, + int attr_type, + pj_uint32_t value); + + +/** + * Create a STUN MESSAGE-INTEGRITY attribute. + * + * @param pool The pool to allocate memory from. + * @param p_attr Pointer to receive the attribute. + * + * @return PJ_SUCCESS on success or the appropriate error code. + */ +PJ_DECL(pj_status_t) pj_stun_msgint_attr_create(pj_pool_t *pool, + pj_stun_msgint_attr **p_attr); + +/** + * Create and add STUN MESSAGE-INTEGRITY attribute. + * + * @param pool The pool to allocate memory from. + * @param msg The STUN message + * + * @return PJ_SUCCESS on success or the appropriate error code. + */ +PJ_DECL(pj_status_t) pj_stun_msg_add_msgint_attr(pj_pool_t *pool, + pj_stun_msg *msg); + +/** + * Create a STUN ERROR-CODE attribute. + * + * @param pool The pool to allocate memory from. + * @param err_code STUN error code. + * @param err_reason Optional STUN error reason. If NULL is given, the + * standard error reason will be given. + * @param p_attr Pointer to receive the attribute. + * + * @return PJ_SUCCESS on success or the appropriate error code. + */ +PJ_DECL(pj_status_t) pj_stun_errcode_attr_create(pj_pool_t *pool, + int err_code, + const pj_str_t *err_reason, + pj_stun_errcode_attr **p_attr); + + +/** + * Create and add STUN ERROR-CODE attribute to the message. + * + * @param pool The pool to allocate memory from. + * @param msg The STUN mesage. + * @param err_code STUN error code. + * @param err_reason Optional STUN error reason. If NULL is given, the + * standard error reason will be given. + * + * @return PJ_SUCCESS on success or the appropriate error code. + */ +PJ_DECL(pj_status_t) pj_stun_msg_add_errcode_attr(pj_pool_t *pool, + pj_stun_msg *msg, + int err_code, + const pj_str_t *err_reason); + +/** + * Create instance of STUN UNKNOWN-ATTRIBUTES attribute and copy the + * unknown attribute array to the attribute. + * + * @param pool The pool to allocate memory from. + * @param attr_cnt Number of attributes in the array (can be zero). + * @param attr Optional array of attributes. + * @param p_attr Pointer to receive the attribute. + * + * @return PJ_SUCCESS on success or the appropriate error code. + */ +PJ_DECL(pj_status_t) pj_stun_unknown_attr_create(pj_pool_t *pool, + unsigned attr_cnt, + const pj_uint16_t attr[], + pj_stun_unknown_attr **p_attr); + +/** + * Create and add STUN UNKNOWN-ATTRIBUTES attribute to the message. + * + * @param pool The pool to allocate memory from. + * @param msg The STUN message. + * @param attr_cnt Number of attributes in the array (can be zero). + * @param attr Optional array of attributes. + * + * @return PJ_SUCCESS on success or the appropriate error code. + */ +PJ_DECL(pj_status_t) pj_stun_msg_add_unknown_attr(pj_pool_t *pool, + pj_stun_msg *msg, + unsigned attr_cnt, + const pj_uint16_t attr[]); + +/** + * Create STUN binary attribute. + * + * @param pool The pool to allocate memory from. + * @param attr_type The attribute type, from #pj_stun_attr_type. + * @param data Data to be coped to the attribute, or NULL + * if no data to be copied now. + * @param length Length of data, or zero if no data is to be + * copied now. + * @param p_attr Pointer to receive the attribute. + * + * @return PJ_SUCCESS on success or the appropriate error code. + */ +PJ_DECL(pj_status_t) pj_stun_binary_attr_create(pj_pool_t *pool, + int attr_type, + const pj_uint8_t *data, + unsigned length, + pj_stun_binary_attr **p_attr); + +/** + * Create STUN binary attribute and add the attribute to the message. + * + * @param pool The pool to allocate memory from. + * @param msg The STUN message. + * @param attr_type The attribute type, from #pj_stun_attr_type. + * @param data Data to be coped to the attribute, or NULL + * if no data to be copied now. + * @param length Length of data, or zero if no data is to be + * copied now. + * @param p_attr Pointer to receive the attribute. + * + * @return PJ_SUCCESS on success or the appropriate error code. + */ +PJ_DECL(pj_status_t) pj_stun_msg_add_binary_attr(pj_pool_t *pool, + pj_stun_msg *msg, + int attr_type, + const pj_uint8_t *data, + unsigned length); + + +/** + * @} + */ + + +PJ_END_DECL + + +#endif /* __PJLIB_UTIL_STUN_MSG_H__ */ + diff --git a/pjnath/include/pjnath/stun_session.h b/pjnath/include/pjnath/stun_session.h new file mode 100644 index 00000000..fa18dc3a --- /dev/null +++ b/pjnath/include/pjnath/stun_session.h @@ -0,0 +1,372 @@ +/* $Id$ */ +/* + * Copyright (C) 2003-2005 Benny Prijono + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +#ifndef __PJLIB_UTIL_STUN_SESSION_H__ +#define __PJLIB_UTIL_STUN_SESSION_H__ + +#include +#include +#include +#include +#include +#include + +PJ_BEGIN_DECL + + +/* **************************************************************************/ +/** + * @defgroup PJLIB_UTIL_STUN_SESSION STUN Client/Server Session + * @brief STUN client and server session + * @ingroup PJLIB_UTIL_STUN + * @{ + */ + + +/** Forward declaration for pj_stun_tx_data */ +typedef struct pj_stun_tx_data pj_stun_tx_data; + +/** Forward declaration for pj_stun_session */ +typedef struct pj_stun_session pj_stun_session; + + +/** + * This is the callback to be registered to pj_stun_session, to send + * outgoing message and to receive various notifications from the STUN + * session. + */ +typedef struct pj_stun_session_cb +{ + /** + * Callback to be called by the STUN session to send outgoing message. + * + * @param sess The STUN session. + * @param pkt Packet to be sent. + * @param pkt_size Size of the packet to be sent. + * @param dst_addr The destination address. + * @param addr_len Length of destination address. + * + * @return The callback should return the status of the + * packet sending. + */ + pj_status_t (*on_send_msg)(pj_stun_session *sess, + const void *pkt, + pj_size_t pkt_size, + const pj_sockaddr_t *dst_addr, + unsigned addr_len); + + /** + * Callback to be called on incoming STUN request message. In the + * callback processing, application MUST create a response by calling + * pj_stun_session_create_response() function and send the response + * with pj_stun_session_send_msg() function, before returning from + * the callback. + * + * @param sess The STUN session. + * @param pkt Pointer to the original STUN packet. + * @param pkt_len Length of the STUN packet. + * @param msg The parsed STUN request. + * @param src_addr Source address of the packet. + * @param src_addr_len Length of the source address. + * + * @return The return value of this callback will be + * returned back to pj_stun_session_on_rx_pkt() + * function. + */ + pj_status_t (*on_rx_request)(pj_stun_session *sess, + const pj_uint8_t *pkt, + unsigned pkt_len, + const pj_stun_msg *msg, + const pj_sockaddr_t *src_addr, + unsigned src_addr_len); + + /** + * Callback to be called when response is received or the transaction + * has timed out. + * + * @param sess The STUN session. + * @param status Status of the request. If the value if not + * PJ_SUCCESS, the transaction has timed-out + * or other error has occurred, and the response + * argument may be NULL. + * @param request The original STUN request. + * @param response The response message, on successful transaction. + */ + void (*on_request_complete)(pj_stun_session *sess, + pj_status_t status, + pj_stun_tx_data *tdata, + const pj_stun_msg *response); + + + /** + * Type of callback to be called on incoming STUN indication. + */ + pj_status_t (*on_rx_indication)(pj_stun_session *sess, + const pj_uint8_t *pkt, + unsigned pkt_len, + const pj_stun_msg *msg, + const pj_sockaddr_t *src_addr, + unsigned src_addr_len); + +} pj_stun_session_cb; + + +/** + * This structure describe the outgoing STUN transmit data to carry the + * message to be sent. + */ +struct pj_stun_tx_data +{ + PJ_DECL_LIST_MEMBER(struct pj_stun_tx_data); + + pj_pool_t *pool; /**< Pool. */ + pj_stun_session *sess; /**< The STUN session. */ + pj_stun_msg *msg; /**< The STUN message. */ + + pj_stun_client_tsx *client_tsx; /**< Client STUN transaction. */ + pj_uint32_t msg_magic; /**< Message magic. */ + pj_uint8_t msg_key[12]; /**< Message/transaction key. */ + + void *pkt; /**< The STUN packet. */ + unsigned max_len; /**< Length of packet buffer. */ + unsigned pkt_size; /**< The actual length of STUN pkt. */ + + unsigned addr_len; /**< Length of destination address. */ + const pj_sockaddr_t *dst_addr; /**< Destination address. */ + + pj_timer_entry res_timer; /**< Response cache timer. */ +}; + + +/** + * Create a STUN session. + * + * @param endpt The STUN endpoint, to be used to register timers etc. + * @param name Optional name to be associated with this instance. The + * name will be used for example for logging purpose. + * @param cb Session callback. + * @param fingerprint Enable message fingerprint for outgoing messages. + * @param p_sess Pointer to receive STUN session instance. + * + * @return PJ_SUCCESS on success, or the appropriate error code. + */ +PJ_DECL(pj_status_t) pj_stun_session_create(pj_stun_endpoint *endpt, + const char *name, + const pj_stun_session_cb *cb, + pj_bool_t fingerprint, + pj_stun_session **p_sess); + +/** + * Destroy the STUN session. + * + * @param sess The STUN session instance. + * + * @return PJ_SUCCESS on success, or the appropriate error code. + */ +PJ_DECL(pj_status_t) pj_stun_session_destroy(pj_stun_session *sess); + +/** + * Associated an arbitrary data with this STUN session. The user data may + * be retrieved later with pj_stun_session_get_user_data() function. + * + * @param sess The STUN session instance. + * + * @return PJ_SUCCESS on success, or the appropriate error code. + */ +PJ_DECL(pj_status_t) pj_stun_session_set_user_data(pj_stun_session *sess, + void *user_data); + +/** + * Retrieve the user data previously associated to this STUN session with + * pj_stun_session_set_user_data(). + * + * @param sess The STUN session instance. + * + * @return The user data associated with this STUN session. + */ +PJ_DECL(void*) pj_stun_session_get_user_data(pj_stun_session *sess); + +/** + * Set server name to be included in all response. + * + * @param sess The STUN session instance. + * @param srv_name Server name string. + * + * @return The user data associated with this STUN session. + */ +PJ_DECL(pj_status_t) pj_stun_session_set_server_name(pj_stun_session *sess, + const pj_str_t *srv_name); + +/** + * Set credential to be used by this session. Once credential is set, all + * outgoing messages will include MESSAGE-INTEGRITY, and all incoming + * message will be authenticated against this credential. + * + * To disable authentication after it has been set, call this function + * again with NULL as the argument. + * + * @param sess The STUN session instance. + * @param cred The credential to be used by this session. If NULL + * is specified, authentication will be disabled. + * + * @return PJ_SUCCESS on success, or the appropriate error code. + */ +PJ_DECL(void) pj_stun_session_set_credential(pj_stun_session *sess, + const pj_stun_auth_cred *cred); + +/** + * Create a STUN request message. After the message has been successfully + * created, application can send the message by calling + * pj_stun_session_send_msg(). + * + * @param sess The STUN session instance. + * @param msg_type The STUN request message type, from pj_stun_method_e or + * from pj_stun_msg_type. + * @param p_tdata Pointer to receive STUN transmit data instance containing + * the request. + * + * @return PJ_SUCCESS on success, or the appropriate error code. + */ +PJ_DECL(pj_status_t) pj_stun_session_create_req(pj_stun_session *sess, + int msg_type, + pj_stun_tx_data **p_tdata); + +/** + * Create a STUN Indication message. After the message has been successfully + * created, application can send the message by calling + * pj_stun_session_send_msg(). + * + * @param sess The STUN session instance. + * @param msg_type The STUN request message type, from pj_stun_method_e or + * from pj_stun_msg_type. This function will add the + * indication bit as necessary. + * @param p_tdata Pointer to receive STUN transmit data instance containing + * the message. + * + * @return PJ_SUCCESS on success, or the appropriate error code. + */ +PJ_DECL(pj_status_t) pj_stun_session_create_ind(pj_stun_session *sess, + int msg_type, + pj_stun_tx_data **p_tdata); + +/** + * Create a STUN response message. After the message has been + * successfully created, application can send the message by calling + * pj_stun_session_send_msg(). + * + * @param sess The STUN session instance. + * @param req The STUN request where the response is to be created. + * @param err_code Error code to be set in the response, if error response + * is to be created, according to pj_stun_status enumeration. + * This argument MUST be zero if successful response is + * to be created. + * @param err_msg Optional pointer for the error message string, when + * creating error response. If the value is NULL and the + * \a err_code is non-zero, then default error message will + * be used. + * @param p_tdata Pointer to receive the response message created. + * + * @return PJ_SUCCESS on success, or the appropriate error code. + */ +PJ_DECL(pj_status_t) pj_stun_session_create_response(pj_stun_session *sess, + const pj_stun_msg *req, + unsigned err_code, + const pj_str_t *err_msg, + pj_stun_tx_data **p_tdata); + + +/** + * Send STUN message to the specified destination. This function will encode + * the pj_stun_msg instance to a packet buffer, and add credential or + * fingerprint if necessary. If the message is a request, the session will + * also create and manage a STUN client transaction to be used to manage the + * retransmission of the request. After the message has been encoded and + * transaction is setup, the \a on_send_msg() callback of pj_stun_session_cb + * (which is registered when the STUN session is created) will be called + * to actually send the message to the wire. + * + * @param sess The STUN session instance. + * @param cache_res If PJ_TRUE then response will be cached. + * @param dst_addr The destination socket address. + * @param addr_len Length of destination address. + * @param tdata The STUN transmit data containing the STUN message to + * be sent. + * + * @return PJ_SUCCESS on success, or the appropriate error code. + */ +PJ_DECL(pj_status_t) pj_stun_session_send_msg(pj_stun_session *sess, + pj_bool_t cache_res, + const pj_sockaddr_t *dst_addr, + unsigned addr_len, + pj_stun_tx_data *tdata); + +/** + * Application must call this function to notify the STUN session about + * the arrival of STUN packet. The STUN packet MUST have been checked + * first with #pj_stun_msg_check() to verify that this is indeed a valid + * STUN packet. + * + * The STUN session will decode the packet into pj_stun_msg, and process + * the message accordingly. If the message is a response, it will search + * through the outstanding STUN client transactions for a matching + * transaction ID and hand over the response to the transaction. + * + * On successful message processing, application will be notified about + * the message via one of the pj_stun_session_cb callback. + * + * @param sess The STUN session instance. + * @param packet The packet containing STUN message. + * @param pkt_size Size of the packet. + * @param options Options, from #pj_stun_decode_options. + * @param parsed_len Optional pointer to receive the size of the parsed + * STUN message (useful if packet is received via a + * stream oriented protocol). + * + * @return PJ_SUCCESS on success, or the appropriate error code. + */ +PJ_DECL(pj_status_t) pj_stun_session_on_rx_pkt(pj_stun_session *sess, + const void *packet, + pj_size_t pkt_size, + unsigned options, + unsigned *parsed_len, + const pj_sockaddr_t *src_addr, + unsigned src_addr_len); + +/** + * Destroy the transmit data. Call this function only when tdata has been + * created but application doesn't want to send the message (perhaps + * because of other error). + * + * @param sess The STUN session. + * @param tdata The transmit data. + * + * @return PJ_SUCCESS on success, or the appropriate error code. + */ +PJ_DECL(void) pj_stun_msg_destroy_tdata(pj_stun_session *sess, + pj_stun_tx_data *tdata); + + +/** + * @} + */ + + +PJ_END_DECL + +#endif /* __PJLIB_UTIL_STUN_SESSION_H__ */ + diff --git a/pjnath/include/pjnath/stun_transaction.h b/pjnath/include/pjnath/stun_transaction.h new file mode 100644 index 00000000..c7a5bf93 --- /dev/null +++ b/pjnath/include/pjnath/stun_transaction.h @@ -0,0 +1,217 @@ +/* $Id$ */ +/* + * Copyright (C) 2003-2005 Benny Prijono + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +#ifndef __PJLIB_UTIL_STUN_TRANSACTION_H__ +#define __PJLIB_UTIL_STUN_TRANSACTION_H__ + +/** + * @file stun_transaction.h + * @brief STUN transaction + */ + +#include +#include + + +PJ_BEGIN_DECL + + +/* **************************************************************************/ +/** + * @defgroup PJLIB_UTIL_STUN_TRANSACTION STUN Client Transaction + * @brief STUN client transaction + * @ingroup PJLIB_UTIL_STUN + * @{ + * + The @ref PJLIB_UTIL_STUN_TRANSACTION is used to manage outgoing STUN request, + for example to retransmit the request and to notify application about the + completion of the request. + + The @ref PJLIB_UTIL_STUN_TRANSACTION does not use any networking operations, + but instead application must supply the transaction with a callback to + be used by the transaction to send outgoing requests. This way the STUN + transaction is made more generic and can work with different types of + networking codes in application. + + + */ + +/** + * Opaque declaration of STUN client transaction. + */ +typedef struct pj_stun_client_tsx pj_stun_client_tsx; + +/** + * STUN client transaction callback. + */ +typedef struct pj_stun_tsx_cb +{ + /** + * This callback is called when the STUN transaction completed. + * + * @param tsx The STUN transaction. + * @param status Status of the transaction. Status PJ_SUCCESS + * means that the request has received a successful + * response. + * @param response The STUN response, which value may be NULL if + * \a status is not PJ_SUCCESS. + */ + void (*on_complete)(pj_stun_client_tsx *tsx, + pj_status_t status, + const pj_stun_msg *response); + + /** + * This callback is called by the STUN transaction when it wants to send + * outgoing message. + * + * @param tsx The STUN transaction instance. + * @param stun_pkt The STUN packet to be sent. + * @param pkt_size Size of the STUN packet. + * + * @return If return value of the callback is not PJ_SUCCESS, + * the transaction will fail. + */ + pj_status_t (*on_send_msg)(pj_stun_client_tsx *tsx, + const void *stun_pkt, + pj_size_t pkt_size); + +} pj_stun_tsx_cb; + + + +/** + * Create an instance of STUN client transaction. The STUN client + * transaction is used to transmit outgoing STUN request and to + * ensure the reliability of the request by periodically retransmitting + * the request, if necessary. + * + * @param endpt The STUN endpoint, which will be used to retrieve + * various settings for the transaction. + * @param pool Pool to be used to allocate memory from. + * @param cb Callback structure, to be used by the transaction + * to send message and to notify the application about + * the completion of the transaction. + * @param p_tsx Pointer to receive the transaction instance. + * + * @return PJ_SUCCESS on success, or the appropriate error code. + */ +PJ_DECL(pj_status_t) pj_stun_client_tsx_create( pj_stun_endpoint *endpt, + pj_pool_t *pool, + const pj_stun_tsx_cb *cb, + pj_stun_client_tsx **p_tsx); + +/** + * Destroy a STUN client transaction. + * + * @param tsx The STUN transaction. + * + * @return PJ_SUCCESS on success, or the appropriate error code. + */ +PJ_DECL(pj_status_t) pj_stun_client_tsx_destroy(pj_stun_client_tsx *tsx); + + +/** + * Check if transaction has completed. + * + * @param tsx The STUN transaction. + * + * @return Non-zero if transaction has completed. + */ +PJ_DECL(pj_bool_t) pj_stun_client_tsx_is_complete(pj_stun_client_tsx *tsx); + + +/** + * Associate an arbitrary data with the STUN transaction. This data + * can be then retrieved later from the transaction, by using + * pj_stun_client_tsx_get_data() function. + * + * @param tsx The STUN client transaction. + * @param data Application data to be associated with the + * STUN transaction. + * + * @return PJ_SUCCESS on success. + */ +PJ_DECL(pj_status_t) pj_stun_client_tsx_set_data(pj_stun_client_tsx *tsx, + void *data); + + +/** + * Get the user data that was previously associated with the STUN + * transaction. + * + * @param tsx The STUN client transaction. + * + * @return The user data. + */ +PJ_DECL(void*) pj_stun_client_tsx_get_data(pj_stun_client_tsx *tsx); + + +/** + * Start the STUN client transaction by sending STUN request using + * this transaction. If reliable transport such as TCP or TLS is used, + * the retransmit flag should be set to PJ_FALSE because reliablity + * will be assured by the transport layer. + * + * @param tsx The STUN client transaction. + * @param retransmit Should this message be retransmitted by the + * STUN transaction. + * @param pkt The STUN packet to send. + * @param pkt_len Length of STUN packet. + * + * @return PJ_SUCCESS on success or the appropriate error code. + */ +PJ_DECL(pj_status_t) pj_stun_client_tsx_send_msg(pj_stun_client_tsx *tsx, + pj_bool_t retransmit, + void *pkt, + unsigned pkt_len); + + + +/** + * Notify the STUN transaction about the arrival of STUN response. + * If the STUN response contains a final error (300 and greater), the + * transaction will be terminated and callback will be called. If the + * STUN response contains response code 100-299, retransmission + * will cease, but application must still call this function again + * with a final response later to allow the transaction to complete. + * + * @param tsx The STUN client transaction instance. + * @param packet The incoming packet. + * @param pkt_size Size of the incoming packet. + * @param parsed_len Optional pointer to receive the number of bytes + * that have been parsed from the incoming packet + * for the STUN message. This is useful if the + * STUN transaction is running over stream oriented + * socket such as TCP or TLS. + * + * @return PJ_SUCCESS on success or the appropriate error code. + */ +PJ_DECL(pj_status_t) pj_stun_client_tsx_on_rx_msg(pj_stun_client_tsx *tsx, + const pj_stun_msg *msg); + + +/** + * @} + */ + + +PJ_END_DECL + + +#endif /* __PJLIB_UTIL_STUN_TRANSACTION_H__ */ + diff --git a/pjnath/include/pjnath/turn_client.h b/pjnath/include/pjnath/turn_client.h new file mode 100644 index 00000000..83d8d2d6 --- /dev/null +++ b/pjnath/include/pjnath/turn_client.h @@ -0,0 +1,132 @@ +/* $Id$ */ +/* + * Copyright (C) 2003-2005 Benny Prijono + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +#ifndef __PJLIB_UTIL_TURN_CLIENT_H__ +#define __PJLIB_UTIL_TURN_CLIENT_H__ + +/** + * @file turn_client.h + * @brief TURN client session. + */ + +#include + + +PJ_BEGIN_DECL + + +/** + * @defgroup PJLIB_UTIL_TURN_CLIENT TURN Client Session + * @brief Management of STUN/TURN client session + * @ingroup PJLIB_UTIL_STUN + * @{ + */ + +typedef struct pj_turn_client pj_turn_client; + +/** + * This describes TURN client config. + */ +typedef struct pj_turn_client_cb +{ + /** + * Callback to be called by the TURN session to send outgoing message. + * + * @param client The TURN client session. + * @param pkt Packet to be sent. + * @param pkt_size Size of the packet to be sent. + * @param dst_addr The destination address. + * @param addr_len Length of destination address. + * + * @return The callback should return the status of the + * packet sending. + */ + pj_status_t (*on_send_msg)(pj_turn_client *client, + const void *pkt, + pj_size_t pkt_size, + const pj_sockaddr_t *dst_addr, + unsigned addr_len); + + /** + * Callback to be called by TURN session when its state has changed. + */ + pj_status_t (*on_state_changed)(pj_turn_client *client); + +} pj_turn_client_cb; + + +/** + * Options + */ +typedef struct pj_turn_client_config +{ + int bandwidth; + int lifetime; + int sock_type; + int port; +} pj_turn_client_config; + + +PJ_INLINE(void) pj_turn_client_config_default(pj_turn_client_config *cfg) +{ + pj_bzero(cfg, sizeof(*cfg)); + cfg->bandwidth = -1; + cfg->lifetime = -1; + cfg->sock_type = -1; + cfg->port = -1; +} + + +/** + * This describes the TURN client session. + */ +struct pj_turn_client +{ + pj_pool_t *pool; + pj_stun_session *session; + pj_timer_entry alloc_timer; + pj_sockaddr_in mapped_addr; + pj_sockaddr_in relay_addr; +}; + + + + +/** + * Create the TURN client session. + */ +PJ_DECL(pj_status_t) pj_turn_client_create(pj_stun_endpoint *endpt, + const pj_turn_client_config *cfg, + const pj_turn_client_cb *cb, + pj_turn_client **p_client); + +/** + * Start the TURN client session by sending Allocate request to the server. + */ + + +/** + * @} + */ + + +PJ_END_DECL + + +#endif /* __PJLIB_UTIL_TURN_CLIENT_H__ */ + diff --git a/pjnath/src/pjnath/stun_auth.c b/pjnath/src/pjnath/stun_auth.c new file mode 100644 index 00000000..9a94fe0d --- /dev/null +++ b/pjnath/src/pjnath/stun_auth.c @@ -0,0 +1,341 @@ +/* $Id$ */ +/* + * Copyright (C) 2003-2005 Benny Prijono + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +#include +#include +#include +#include +#include +#include + + +/* Duplicate credential */ +PJ_DEF(void) pj_stun_auth_cred_dup( pj_pool_t *pool, + pj_stun_auth_cred *dst, + const pj_stun_auth_cred *src) +{ + dst->type = src->type; + + switch (src->type) { + case PJ_STUN_AUTH_CRED_STATIC: + pj_strdup(pool, &dst->data.static_cred.realm, + &src->data.static_cred.realm); + pj_strdup(pool, &dst->data.static_cred.username, + &src->data.static_cred.username); + dst->data.static_cred.data_type = src->data.static_cred.data_type; + pj_strdup(pool, &dst->data.static_cred.data, + &src->data.static_cred.data); + pj_strdup(pool, &dst->data.static_cred.nonce, + &src->data.static_cred.nonce); + break; + case PJ_STUN_AUTH_CRED_DYNAMIC: + pj_memcpy(&dst->data.dyn_cred, &src->data.dyn_cred, + sizeof(src->data.dyn_cred)); + break; + } +} + + +PJ_INLINE(pj_uint16_t) GET_VAL16(const pj_uint8_t *pdu, unsigned pos) +{ + return (pj_uint16_t) ((pdu[pos] << 8) + pdu[pos+1]); +} + + +/* Send 401 response */ +static pj_status_t create_challenge(pj_pool_t *pool, + const pj_stun_msg *msg, + int err_code, + const pj_str_t *err_msg, + const pj_str_t *realm, + const pj_str_t *nonce, + pj_stun_msg **p_response) +{ + pj_stun_msg *response; + pj_str_t tmp_nonce; + pj_status_t rc; + + rc = pj_stun_msg_create_response(pool, msg, + err_code, err_msg, &response); + if (rc != PJ_SUCCESS) + return rc; + + + if (realm && realm->slen) { + rc = pj_stun_msg_add_string_attr(pool, response, + PJ_STUN_ATTR_REALM, + realm); + if (rc != PJ_SUCCESS) + return rc; + + /* long term must include nonce */ + if (!nonce || nonce->slen == 0) { + tmp_nonce = pj_str("pjstun"); + nonce = &tmp_nonce; + } + } + + if (nonce && nonce->slen) { + rc = pj_stun_msg_add_string_attr(pool, response, + PJ_STUN_ATTR_NONCE, + nonce); + if (rc != PJ_SUCCESS) + return rc; + } + + *p_response = response; + + return PJ_SUCCESS; +} + + +/* Verify credential */ +PJ_DEF(pj_status_t) pj_stun_verify_credential( const pj_uint8_t *pkt, + unsigned pkt_len, + const pj_stun_msg *msg, + pj_stun_auth_cred *cred, + pj_pool_t *pool, + pj_stun_msg **p_response) +{ + pj_str_t realm, nonce, password; + const pj_stun_msgint_attr *amsgi; + unsigned amsgi_pos; + const pj_stun_username_attr *auser; + pj_bool_t username_ok; + const pj_stun_realm_attr *arealm; + const pj_stun_realm_attr *anonce; + pj_uint8_t digest[PJ_SHA1_DIGEST_SIZE]; + pj_uint8_t md5_digest[16]; + pj_str_t key; + pj_status_t status; + + /* msg and credential MUST be specified */ + PJ_ASSERT_RETURN(pkt && pkt_len && msg && cred, PJ_EINVAL); + + /* If p_response is specified, pool MUST be specified. */ + PJ_ASSERT_RETURN(!p_response || pool, PJ_EINVAL); + + if (p_response) + *p_response = NULL; + + if (!PJ_STUN_IS_REQUEST(msg->hdr.type)) + p_response = NULL; + + /* Get realm and nonce */ + realm.slen = nonce.slen = 0; + if (cred->type == PJ_STUN_AUTH_CRED_STATIC) { + realm = cred->data.static_cred.realm; + nonce = cred->data.static_cred.nonce; + } else if (cred->type == PJ_STUN_AUTH_CRED_DYNAMIC) { + status = cred->data.dyn_cred.get_auth(cred->data.dyn_cred.user_data, + pool, &realm, &nonce); + if (status != PJ_SUCCESS) + return status; + } else { + pj_assert(!"Unexpected"); + return PJ_EBUG; + } + + /* First check that MESSAGE-INTEGRITY is present */ + amsgi = (const pj_stun_msgint_attr*) + pj_stun_msg_find_attr(msg, PJ_STUN_ATTR_MESSAGE_INTEGRITY, 0); + if (amsgi == NULL) { + if (p_response) { + create_challenge(pool, msg, PJ_STUN_SC_UNAUTHORIZED, NULL, + &realm, &nonce, p_response); + } + return PJLIB_UTIL_ESTUNMSGINT; + } + + /* Next check that USERNAME is present */ + auser = (const pj_stun_username_attr*) + pj_stun_msg_find_attr(msg, PJ_STUN_ATTR_USERNAME, 0); + if (auser == NULL) { + if (p_response) { + create_challenge(pool, msg, PJ_STUN_SC_MISSING_USERNAME, NULL, + &realm, &nonce, p_response); + } + return PJLIB_UTIL_ESTUNNOUSERNAME; + } + + /* Get REALM, if any */ + arealm = (const pj_stun_realm_attr*) + pj_stun_msg_find_attr(msg, PJ_STUN_ATTR_REALM, 0); + + /* Check if username match */ + if (cred->type == PJ_STUN_AUTH_CRED_STATIC) { + username_ok = !pj_strcmp(&auser->value, + &cred->data.static_cred.username); + password = cred->data.static_cred.data; + } else if (cred->type == PJ_STUN_AUTH_CRED_DYNAMIC) { + int data_type = 0; + pj_status_t rc; + rc = cred->data.dyn_cred.get_password(cred->data.dyn_cred.user_data, + (arealm?&arealm->value:NULL), + &auser->value, pool, + &data_type, &password); + username_ok = (rc == PJ_SUCCESS); + } else { + username_ok = PJ_TRUE; + password.slen = 0; + } + + if (!username_ok) { + /* Username mismatch */ + if (p_response) { + create_challenge(pool, msg, PJ_STUN_SC_UNKNOWN_USERNAME, NULL, + &realm, &nonce, p_response); + } + return PJLIB_UTIL_ESTUNUSERNAME; + } + + + /* Get NONCE attribute */ + anonce = (pj_stun_nonce_attr*) + pj_stun_msg_find_attr(msg, PJ_STUN_ATTR_NONCE, 0); + + /* Check for long term/short term requirements. */ + if (realm.slen != 0 && arealm == NULL) { + /* Long term credential is required and REALM is not present */ + if (p_response) { + create_challenge(pool, msg, PJ_STUN_SC_MISSING_REALM, NULL, + &realm, &nonce, p_response); + } + return PJLIB_UTIL_ESTUNNOREALM; + + } else if (realm.slen != 0 && arealm != NULL) { + /* We want long term, and REALM is present */ + + /* NONCE must be present. */ + if (anonce == NULL) { + if (p_response) { + create_challenge(pool, msg, PJ_STUN_SC_MISSING_NONCE, + NULL, &realm, &nonce, p_response); + } + return PJLIB_UTIL_ESTUNNONCE; + } + + /* Verify REALM matches */ + if (pj_stricmp(&arealm->value, &realm)) { + /* REALM doesn't match */ + if (p_response) { + create_challenge(pool, msg, PJ_STUN_SC_MISSING_REALM, + NULL, &realm, &nonce, p_response); + } + return PJLIB_UTIL_ESTUNNOREALM; + } + + /* Valid case, will validate the message integrity later */ + + } else if (realm.slen == 0 && arealm != NULL) { + /* We want to use short term credential, but client uses long + * term credential. The draft doesn't mention anything about + * switching between long term and short term. + */ + + /* For now just accept the credential, anyway it will probably + * cause wrong message integrity value later. + */ + } else if (realm.slen==0 && arealm == NULL) { + /* Short term authentication is wanted, and one is supplied */ + + /* Application MAY request NONCE to be supplied */ + if (nonce.slen != 0) { + if (p_response) { + create_challenge(pool, msg, PJ_STUN_SC_MISSING_NONCE, + NULL, &realm, &nonce, p_response); + } + return PJLIB_UTIL_ESTUNNONCE; + } + } + + /* If NONCE is present, validate it */ + if (anonce) { + pj_bool_t ok; + + if (cred->type == PJ_STUN_AUTH_CRED_DYNAMIC) { + ok=cred->data.dyn_cred.verify_nonce(cred->data.dyn_cred.user_data, + (arealm?&arealm->value:NULL), + &auser->value, + &anonce->value); + } else { + if (nonce.slen) { + ok = !pj_strcmp(&anonce->value, &nonce); + } else { + ok = PJ_TRUE; + } + } + + if (!ok) { + if (p_response) { + create_challenge(pool, msg, PJ_STUN_SC_STALE_NONCE, + NULL, &realm, &nonce, p_response); + } + return PJLIB_UTIL_ESTUNNONCE; + } + } + + /* Get the position of MESSAGE-INTEGRITY in the packet */ + amsgi_pos = 20+msg->hdr.length-24; + if (GET_VAL16(pkt, amsgi_pos) == PJ_STUN_ATTR_MESSAGE_INTEGRITY) { + /* Found MESSAGE-INTEGRITY as the last attribute */ + } else { + amsgi_pos = 0; + } + + if (amsgi_pos==0) { + amsgi_pos = 20+msg->hdr.length-8-24; + if (GET_VAL16(pkt, amsgi_pos) == PJ_STUN_ATTR_MESSAGE_INTEGRITY) { + /* Found MESSAGE-INTEGRITY before FINGERPRINT */ + } else { + amsgi_pos = 0; + } + } + + if (amsgi_pos==0) { + pj_assert(!"Unable to find MESSAGE-INTEGRITY in the message!"); + return PJ_EBUG; + } + + /* Determine which key to use */ + if (realm.slen) { + pj_stun_calc_md5_key(md5_digest, &realm, &auser->value, &password); + key.ptr = (char*)md5_digest; + key.slen = 16; + } else { + key = password; + } + + /* Now calculate HMAC of the message */ + pj_hmac_sha1(pkt, amsgi_pos, (pj_uint8_t*)key.ptr, key.slen, digest); + + /* Compare HMACs */ + if (pj_memcmp(amsgi->hmac, digest, 20)) { + /* HMAC value mismatch */ + if (p_response) { + create_challenge(pool, msg, PJ_STUN_SC_INTEGRITY_CHECK_FAILURE, + NULL, &realm, &nonce, p_response); + } + return PJLIB_UTIL_ESTUNMSGINT; + } + + /* Everything looks okay! */ + return PJ_SUCCESS; +} + + diff --git a/pjnath/src/pjnath/stun_endpoint.c b/pjnath/src/pjnath/stun_endpoint.c new file mode 100644 index 00000000..277e385e --- /dev/null +++ b/pjnath/src/pjnath/stun_endpoint.c @@ -0,0 +1,69 @@ +/* $Id$ */ +/* + * Copyright (C) 2003-2005 Benny Prijono + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +#include +#include +#include +#include + + +/* + * Create a STUN endpoint instance. + */ +PJ_DEF(pj_status_t) pj_stun_endpoint_create( pj_pool_factory *factory, + unsigned options, + pj_ioqueue_t *ioqueue, + pj_timer_heap_t *timer_heap, + pj_stun_endpoint **p_endpt) +{ + pj_pool_t *pool; + pj_stun_endpoint *endpt; + + PJ_ASSERT_RETURN(factory && p_endpt, PJ_EINVAL); + + pool = pj_pool_create(factory, "stunendpt", 1000, 1000, NULL); + if (!pool) + return PJ_ENOMEM; + + endpt = PJ_POOL_ZALLOC_T(pool, pj_stun_endpoint); + endpt->pool = pool; + endpt->pf = factory; + endpt->options = options; + endpt->ioqueue = ioqueue; + endpt->timer_heap = timer_heap; + endpt->rto_msec = PJ_STUN_RTO_VALUE; + endpt->res_cache_msec = 10000; + + *p_endpt = endpt; + + return PJ_SUCCESS; +} + + +/* + * Destroy STUN endpoint instance. + */ +PJ_DEF(pj_status_t) pj_stun_endpoint_destroy(pj_stun_endpoint *endpt) +{ + PJ_ASSERT_RETURN(endpt, PJ_EINVAL); + + pj_pool_release(endpt->pool); + + return PJ_SUCCESS; +} + diff --git a/pjnath/src/pjnath/stun_msg.c b/pjnath/src/pjnath/stun_msg.c new file mode 100644 index 00000000..1c750d8e --- /dev/null +++ b/pjnath/src/pjnath/stun_msg.c @@ -0,0 +1,2162 @@ +/* $Id$ */ +/* + * Copyright (C) 2003-2005 Benny Prijono + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define THIS_FILE "stun_msg.c" +#define STUN_XOR_FINGERPRINT 0x5354554eL + +static const char *stun_method_names[] = +{ + "Unknown", /* 0 */ + "Binding", /* 1 */ + "Shared Secret", /* 2 */ + "Allocate", /* 3 */ + "Send", /* 4 */ + "Data", /* 5 */ + "Set Active Destination", /* 6 */ + "Connect", /* 7 */ + "Connect Status" /* 8 */ +}; + +static struct +{ + int err_code; + const char *err_msg; +} stun_err_msg_map[] = +{ + { PJ_STUN_SC_TRY_ALTERNATE, "Try Alternate"}, + { PJ_STUN_SC_BAD_REQUEST, "Bad Request"}, + { PJ_STUN_SC_UNAUTHORIZED, "Unauthorized"}, + { PJ_STUN_SC_UNKNOWN_ATTRIBUTE, "Unknown Attribute"}, + { PJ_STUN_SC_STALE_CREDENTIALS, "Stale Credentials"}, + { PJ_STUN_SC_INTEGRITY_CHECK_FAILURE, "Integrity Check Failure"}, + { PJ_STUN_SC_MISSING_USERNAME, "Missing Username"}, + { PJ_STUN_SC_USE_TLS, "Use TLS"}, + { PJ_STUN_SC_MISSING_REALM, "Missing Realm"}, + { PJ_STUN_SC_MISSING_NONCE, "Missing Nonce"}, + { PJ_STUN_SC_UNKNOWN_USERNAME, "Unknown Username"}, + { PJ_STUN_SC_NO_BINDING, "No Binding"}, + { PJ_STUN_SC_STALE_NONCE, "Stale Nonce"}, + { PJ_STUN_SC_TRANSITIONING, "Active Destination Already Set"}, + { PJ_STUN_SC_WRONG_USERNAME, "Wrong Username"}, + { PJ_STUN_SC_UNSUPP_TRANSPORT_PROTO, "Unsupported Transport Protocol"}, + { PJ_STUN_SC_INVALID_IP_ADDR, "Invalid IP Address"}, + { PJ_STUN_SC_INVALID_PORT, "Invalid Port"}, + { PJ_STUN_SC_OPER_TCP_ONLY, "Operation for TCP Only"}, + { PJ_STUN_SC_CONNECTION_FAILURE, "Connection Failure"}, + { PJ_STUN_SC_CONNECTION_TIMEOUT, "Connection Timeout"}, + { PJ_STUN_SC_ALLOCATION_QUOTA_REACHED, "Allocation Quota Reached"}, + { PJ_STUN_SC_SERVER_ERROR, "Server Error"}, + { PJ_STUN_SC_INSUFFICIENT_CAPACITY, "Insufficient Capacity"}, + { PJ_STUN_SC_GLOBAL_FAILURE, "Global Failure"} +}; + + + +struct attr_desc +{ + const char *name; + pj_status_t (*decode_attr)(pj_pool_t *pool, const pj_uint8_t *buf, + void **p_attr); + pj_status_t (*encode_attr)(const void *a, pj_uint8_t *buf, + unsigned len, unsigned *printed); + +}; + +static pj_status_t decode_sockaddr_attr(pj_pool_t *pool, + const pj_uint8_t *buf, + void **p_attr); +static pj_status_t decode_xored_sockaddr_attr(pj_pool_t *pool, + const pj_uint8_t *buf, + void **p_attr); +static pj_status_t encode_sockaddr_attr(const void *a, pj_uint8_t *buf, + unsigned len, + unsigned *printed); +static pj_status_t decode_string_attr(pj_pool_t *pool, + const pj_uint8_t *buf, + void **p_attr); +static pj_status_t encode_string_attr(const void *a, pj_uint8_t *buf, + unsigned len, unsigned *printed); +static pj_status_t decode_msgint_attr(pj_pool_t *pool, + const pj_uint8_t *buf, + void **p_attr); +static pj_status_t encode_msgint_attr(const void *a, pj_uint8_t *buf, + unsigned len, unsigned *printed); +static pj_status_t decode_errcode_attr(pj_pool_t *pool, + const pj_uint8_t *buf, + void **p_attr); +static pj_status_t encode_errcode_attr(const void *a, pj_uint8_t *buf, + unsigned len, unsigned *printed); +static pj_status_t decode_unknown_attr(pj_pool_t *pool, + const pj_uint8_t *buf, + void **p_attr); +static pj_status_t encode_unknown_attr(const void *a, pj_uint8_t *buf, + unsigned len, unsigned *printed); +static pj_status_t decode_uint_attr(pj_pool_t *pool, + const pj_uint8_t *buf, + void **p_attr); +static pj_status_t encode_uint_attr(const void *a, pj_uint8_t *buf, + unsigned len, unsigned *printed); +static pj_status_t decode_binary_attr(pj_pool_t *pool, + const pj_uint8_t *buf, + void **p_attr); +static pj_status_t encode_binary_attr(const void *a, pj_uint8_t *buf, + unsigned len, unsigned *printed); +static pj_status_t decode_empty_attr(pj_pool_t *pool, + const pj_uint8_t *buf, + void **p_attr); +static pj_status_t encode_empty_attr(const void *a, pj_uint8_t *buf, + unsigned len, unsigned *printed); + + +struct attr_desc mandatory_attr_desc[] = +{ + { + /* type zero */ + NULL, + NULL, + NULL + }, + { + /* PJ_STUN_ATTR_MAPPED_ADDR, */ + "MAPPED-ADDRESS", + &decode_sockaddr_attr, + &encode_sockaddr_attr + }, + { + /* PJ_STUN_ATTR_RESPONSE_ADDR, */ + "RESPONSE-ADDRESS", + &decode_sockaddr_attr, + &encode_sockaddr_attr + }, + { + /* PJ_STUN_ATTR_CHANGE_REQUEST, */ + "CHANGE-REQUEST", + &decode_uint_attr, + &encode_uint_attr + }, + { + /* PJ_STUN_ATTR_SOURCE_ADDR, */ + "SOURCE-ADDRESS", + &decode_sockaddr_attr, + &encode_sockaddr_attr + }, + { + /* PJ_STUN_ATTR_CHANGED_ADDR, */ + "CHANGED-ADDRESS", + &decode_sockaddr_attr, + &encode_sockaddr_attr + }, + { + /* PJ_STUN_ATTR_USERNAME, */ + "USERNAME", + &decode_string_attr, + &encode_string_attr + }, + { + /* PJ_STUN_ATTR_PASSWORD, */ + "PASSWORD", + &decode_string_attr, + &encode_string_attr + }, + { + /* PJ_STUN_ATTR_MESSAGE_INTEGRITY, */ + "MESSAGE-INTEGRITY", + &decode_msgint_attr, + &encode_msgint_attr + }, + { + /* PJ_STUN_ATTR_ERROR_CODE, */ + "ERROR-CODE", + &decode_errcode_attr, + &encode_errcode_attr + }, + { + /* PJ_STUN_ATTR_UNKNOWN_ATTRIBUTES, */ + "UNKNOWN-ATTRIBUTES", + &decode_unknown_attr, + &encode_unknown_attr + }, + { + /* PJ_STUN_ATTR_REFLECTED_FROM, */ + "REFLECTED-FROM", + &decode_sockaddr_attr, + &encode_sockaddr_attr + }, + { + /* ID 0x000C is not assigned */ + NULL, + NULL, + NULL + }, + { + /* PJ_STUN_ATTR_LIFETIME, */ + "LIFETIME", + &decode_uint_attr, + &encode_uint_attr + }, + { + /* ID 0x000E is not assigned */ + NULL, + NULL, + NULL + }, + { + /* ID 0x000F is not assigned */ + NULL, + NULL, + NULL + }, + { + /* PJ_STUN_ATTR_BANDWIDTH, */ + "BANDWIDTH", + &decode_uint_attr, + &encode_uint_attr + }, + { + /* ID 0x0011 is not assigned */ + NULL, + NULL, + NULL + }, + { + /* PJ_STUN_ATTR_REMOTE_ADDRESS, */ + "REMOTE-ADDRESS", + &decode_sockaddr_attr, + &encode_sockaddr_attr + }, + { + /* PJ_STUN_ATTR_DATA, */ + "DATA", + &decode_binary_attr, + &encode_binary_attr + }, + { + /* PJ_STUN_ATTR_REALM, */ + "REALM", + &decode_string_attr, + &encode_string_attr + }, + { + /* PJ_STUN_ATTR_NONCE, */ + "NONCE", + &decode_string_attr, + &encode_string_attr + }, + { + /* PJ_STUN_ATTR_RELAY_ADDRESS, */ + "RELAY-ADDRESS", + &decode_sockaddr_attr, + &encode_sockaddr_attr + }, + { + /* PJ_STUN_ATTR_REQUESTED_ADDR_TYPE, */ + "REQUESTED-ADDRESS-TYPE", + &decode_uint_attr, + &encode_uint_attr + }, + { + /* PJ_STUN_ATTR_REQUESTED_PORT_PROPS, */ + "REQUESTED-PORT-PROPS", + &decode_uint_attr, + &encode_uint_attr + }, + { + /* PJ_STUN_ATTR_REQUESTED_TRANSPORT, */ + "REQUESTED-TRANSPORT", + &decode_uint_attr, + &encode_uint_attr + }, + { + /* ID 0x001A is not assigned */ + NULL, + NULL, + NULL + }, + { + /* ID 0x001B is not assigned */ + NULL, + NULL, + NULL + }, + { + /* ID 0x001C is not assigned */ + NULL, + NULL, + NULL + }, + { + /* ID 0x001D is not assigned */ + NULL, + NULL, + NULL + }, + { + /* ID 0x001E is not assigned */ + NULL, + NULL, + NULL + }, + { + /* ID 0x001F is not assigned */ + NULL, + NULL, + NULL + }, + { + /* PJ_STUN_ATTR_XOR_MAPPED_ADDRESS, */ + "XOR-MAPPED-ADDRESS", + &decode_xored_sockaddr_attr, + &encode_sockaddr_attr + }, + { + /* PJ_STUN_ATTR_TIMER_VAL, */ + "TIMER-VAL", + &decode_uint_attr, + &encode_uint_attr + }, + { + /* PJ_STUN_ATTR_REQUESTED_IP, */ + "REQUESTED-IP", + &decode_sockaddr_attr, + &encode_sockaddr_attr + }, + { + /* PJ_STUN_ATTR_XOR_REFLECTED_FROM, */ + "XOR-REFLECTED-FROM", + &decode_xored_sockaddr_attr, + &encode_sockaddr_attr + }, + { + /* PJ_STUN_ATTR_PRIORITY, */ + "PRIORITY", + &decode_uint_attr, + &encode_uint_attr + }, + { + /* PJ_STUN_ATTR_USE_CANDIDATE, */ + "USE-CANDIDATE", + &decode_empty_attr, + &encode_empty_attr + }, + { + /* PJ_STUN_ATTR_XOR_INTERNAL_ADDR, */ + "XOR-INTERNAL-ADDRESS", + &decode_xored_sockaddr_attr, + &encode_sockaddr_attr + }, + + /* Sentinel */ + { + /* PJ_STUN_ATTR_END_MANDATORY_ATTR */ + NULL, + NULL, + NULL + } +}; + +static struct attr_desc extended_attr_desc[] = +{ + { + /* ID 0x8021 is not assigned */ + NULL, + NULL, + NULL + }, + { + /* PJ_STUN_ATTR_SERVER, */ + "SERVER", + &decode_string_attr, + &encode_string_attr + }, + { + /* PJ_STUN_ATTR_ALTERNATE_SERVER, */ + "ALTERNATE-SERVER", + &decode_sockaddr_attr, + &encode_sockaddr_attr + }, + { + /* PJ_STUN_ATTR_REFRESH_INTERVAL, */ + "REFRESH-INTERVAL", + &decode_uint_attr, + &encode_uint_attr + }, + { + /* ID 0x8025 is not assigned*/ + NULL, + NULL, + NULL + }, + { + /* PADDING, 0x8026 */ + NULL, + NULL, + NULL + }, + { + /* CACHE-TIMEOUT, 0x8027 */ + NULL, + NULL, + NULL + }, + { + /* PJ_STUN_ATTR_FINGERPRINT, */ + "FINGERPRINT", + &decode_uint_attr, + &encode_uint_attr + } +}; + + + +/* + * Get STUN message type name. + */ +PJ_DEF(const char*) pj_stun_get_method_name(unsigned msg_type) +{ + unsigned method = PJ_STUN_GET_METHOD(msg_type); + + if (method >= PJ_ARRAY_SIZE(stun_method_names)) + return "???"; + + return stun_method_names[method]; +} + + +/* + * Get STUN message class name. + */ +PJ_DEF(const char*) pj_stun_get_class_name(unsigned msg_type) +{ + if (PJ_STUN_IS_REQUEST(msg_type)) + return "request"; + else if (PJ_STUN_IS_RESPONSE(msg_type)) + return "success response"; + else if (PJ_STUN_IS_ERROR_RESPONSE(msg_type)) + return "error response"; + else if (PJ_STUN_IS_INDICATION(msg_type)) + return "indication"; + else + return "???"; +} + + +static const struct attr_desc *find_attr_desc(unsigned attr_type) +{ + struct attr_desc *desc; + + /* Check that attr_desc array is valid */ + pj_assert(PJ_ARRAY_SIZE(mandatory_attr_desc)== + PJ_STUN_ATTR_END_MANDATORY_ATTR+1); + pj_assert(mandatory_attr_desc[PJ_STUN_ATTR_END_MANDATORY_ATTR].decode_attr + == NULL); + pj_assert(mandatory_attr_desc[PJ_STUN_ATTR_USE_CANDIDATE].decode_attr + == &decode_empty_attr); + pj_assert(PJ_ARRAY_SIZE(extended_attr_desc) == + PJ_STUN_ATTR_END_EXTENDED_ATTR-PJ_STUN_ATTR_START_EXTENDED_ATTR); + + if (attr_type < PJ_STUN_ATTR_START_EXTENDED_ATTR) + desc = &mandatory_attr_desc[attr_type]; + else if (attr_type >= PJ_STUN_ATTR_START_EXTENDED_ATTR && + attr_type < PJ_STUN_ATTR_END_EXTENDED_ATTR) + desc = &extended_attr_desc[attr_type-PJ_STUN_ATTR_START_EXTENDED_ATTR]; + else + return NULL; + + return desc->decode_attr == NULL ? NULL : desc; +} + + +/* + * Get STUN attribute name. + */ +PJ_DEF(const char*) pj_stun_get_attr_name(unsigned attr_type) +{ + const struct attr_desc *attr_desc; + + attr_desc = find_attr_desc(attr_type); + if (!attr_desc || attr_desc->name==NULL) + return "???"; + + return attr_desc->name; +} + + +/** + * Get STUN standard reason phrase for the specified error code. + */ +PJ_DEF(pj_str_t) pj_stun_get_err_reason(int err_code) +{ + unsigned i; + + for (i=0; ihdr.type=(pj_uint16_t)(t), \ + (a)->hdr.length=(pj_uint16_t)(l) +#define ATTR_HDR_LEN 4 + +#define getval16(p, pos) (pj_uint16_t)(((p)[(pos)] << 8) | \ + ((p)[(pos) + 1] << 0)) + + +////////////////////////////////////////////////////////////////////////////// +/* + * STUN generic IP address container + */ +#define STUN_GENERIC_IP_ADDR_LEN 8 + +/* + * Create a generic STUN IP address attribute for IPv4 address. + */ +PJ_DEF(pj_status_t) +pj_stun_sockaddr_attr_create(pj_pool_t *pool, + int attr_type, + pj_bool_t xor_ed, + const pj_sockaddr_t *addr, + unsigned addr_len, + pj_stun_sockaddr_attr **p_attr) +{ + pj_stun_sockaddr_attr *attr; + + PJ_ASSERT_RETURN(pool && addr_len && addr && p_attr, PJ_EINVAL); + PJ_ASSERT_RETURN(addr_len == sizeof(pj_sockaddr_in) || + addr_len == sizeof(pj_sockaddr_in6), PJ_EINVAL); + + attr = PJ_POOL_ZALLOC_T(pool, pj_stun_sockaddr_attr); + INIT_ATTR(attr, attr_type, STUN_GENERIC_IP_ADDR_LEN); + + pj_memcpy(&attr->addr, addr, addr_len); + attr->xor_ed = xor_ed; + + *p_attr = attr; + + return PJ_SUCCESS; +} + + +/* + * Create and add generic STUN IP address attribute to a STUN message. + */ +PJ_DEF(pj_status_t) +pj_stun_msg_add_sockaddr_attr(pj_pool_t *pool, + pj_stun_msg *msg, + int attr_type, + pj_bool_t xor_ed, + const pj_sockaddr_t *addr, + unsigned addr_len) +{ + pj_stun_sockaddr_attr *attr; + pj_status_t status; + + status = pj_stun_sockaddr_attr_create(pool, attr_type, xor_ed, + addr, addr_len, &attr); + if (status != PJ_SUCCESS) + return status; + + return pj_stun_msg_add_attr(msg, &attr->hdr); +} + +static pj_status_t decode_sockaddr_attr(pj_pool_t *pool, + const pj_uint8_t *buf, + void **p_attr) +{ + pj_stun_sockaddr_attr *attr; + pj_uint32_t val; + + /* Create the attribute */ + attr = PJ_POOL_ZALLOC_T(pool, pj_stun_sockaddr_attr); + pj_memcpy(attr, buf, ATTR_HDR_LEN); + + /* Convert to host byte order */ + attr->hdr.type = pj_ntohs(attr->hdr.type); + attr->hdr.length = pj_ntohs(attr->hdr.length); + + /* Check that the attribute length is valid */ + if (attr->hdr.length != STUN_GENERIC_IP_ADDR_LEN) + return PJLIB_UTIL_ESTUNINATTRLEN; + + /* Check address family */ + val = *(pj_uint8_t*)(buf + ATTR_HDR_LEN + 1); + + /* Check address family is valid (only supports ipv4 for now) */ + if (val != 1) + return PJLIB_UTIL_ESTUNIPV6NOTSUPP; + + /* Get port and address */ + pj_sockaddr_in_init(&attr->addr.ipv4, NULL, 0); + pj_memcpy(&attr->addr.ipv4.sin_port, buf+ATTR_HDR_LEN+2, 2); + pj_memcpy(&attr->addr.ipv4.sin_addr, buf+ATTR_HDR_LEN+4, 4); + + /* Done */ + *p_attr = attr; + + return PJ_SUCCESS; +} + + +static pj_status_t decode_xored_sockaddr_attr(pj_pool_t *pool, + const pj_uint8_t *buf, + void **p_attr) +{ + pj_stun_sockaddr_attr *attr; + pj_uint32_t val; + + /* Create the attribute */ + attr = PJ_POOL_ZALLOC_T(pool, pj_stun_sockaddr_attr); + pj_memcpy(attr, buf, ATTR_HDR_LEN); + + /* Convert to host byte order */ + attr->hdr.type = pj_ntohs(attr->hdr.type); + attr->hdr.length = pj_ntohs(attr->hdr.length); + + /* Check that the attribute length is valid */ + if (attr->hdr.length != STUN_GENERIC_IP_ADDR_LEN) + return PJLIB_UTIL_ESTUNINATTRLEN; + + /* Check address family */ + val = *(pj_uint8_t*)(buf + ATTR_HDR_LEN + 1); + + /* Check address family is valid (only supports ipv4 for now) */ + if (val != 1) + return PJLIB_UTIL_ESTUNIPV6NOTSUPP; + + /* Get port and address */ + pj_sockaddr_in_init(&attr->addr.ipv4, NULL, 0); + pj_memcpy(&attr->addr.ipv4.sin_port, buf+ATTR_HDR_LEN+2, 2); + pj_memcpy(&attr->addr.ipv4.sin_addr, buf+ATTR_HDR_LEN+4, 4); + + attr->addr.ipv4.sin_port ^= 0x2112; + attr->addr.ipv4.sin_addr.s_addr ^= pj_htonl(0x2112A442); + + /* Done */ + *p_attr = attr; + + return PJ_SUCCESS; +} + + +static pj_status_t encode_sockaddr_attr(const void *a, pj_uint8_t *buf, + unsigned len, unsigned *printed) +{ + enum { + ATTR_LEN = ATTR_HDR_LEN + STUN_GENERIC_IP_ADDR_LEN + }; + pj_uint8_t *start_buf = buf; + const pj_stun_sockaddr_attr *ca = + (const pj_stun_sockaddr_attr *)a; + pj_stun_sockaddr_attr *attr; + + if (len < ATTR_LEN) + return PJ_ETOOSMALL; + + /* Copy and convert headers to network byte order */ + pj_memcpy(buf, a, ATTR_HDR_LEN); + attr = (pj_stun_sockaddr_attr*) buf; + attr->hdr.type = pj_htons(attr->hdr.type); + attr->hdr.length = pj_htons((pj_uint16_t)STUN_GENERIC_IP_ADDR_LEN); + buf += ATTR_HDR_LEN; + + /* Ignored */ + *buf++ = '\0'; + + /* Family (IPv4 only for now) */ + PJ_ASSERT_RETURN(ca->addr.addr.sa_family == PJ_AF_INET, PJ_EINVAL); + *buf++ = 1; + + if (ca->xor_ed) { + pj_uint32_t addr; + pj_uint16_t port; + + addr = ca->addr.ipv4.sin_addr.s_addr; + port = ca->addr.ipv4.sin_port; + + port ^= 0x2112; + addr ^= pj_htonl(0x2112A442); + + /* Port */ + pj_memcpy(buf, &port, 2); + buf += 2; + + /* Address */ + pj_memcpy(buf, &addr, 4); + buf += 4; + + } else { + /* Port */ + pj_memcpy(buf, &ca->addr.ipv4.sin_port, 2); + buf += 2; + + /* Address */ + pj_memcpy(buf, &ca->addr.ipv4.sin_addr, 4); + buf += 4; + } + + pj_assert(buf - start_buf == ATTR_LEN); + + /* Done */ + *printed = buf - start_buf; + + return PJ_SUCCESS; +} + + +////////////////////////////////////////////////////////////////////////////// +/* + * STUN generic string attribute + */ + +/* + * Create a STUN generic string attribute. + */ +PJ_DEF(pj_status_t) +pj_stun_string_attr_create(pj_pool_t *pool, + int attr_type, + const pj_str_t *value, + pj_stun_string_attr **p_attr) +{ + pj_stun_string_attr *attr; + + PJ_ASSERT_RETURN(pool && value && p_attr, PJ_EINVAL); + + attr = PJ_POOL_ZALLOC_T(pool, pj_stun_string_attr); + INIT_ATTR(attr, attr_type, value->slen); + pj_strdup(pool, &attr->value, value); + + *p_attr = attr; + + return PJ_SUCCESS; +} + + +/* + * Create and add STUN generic string attribute to the message. + */ +PJ_DEF(pj_status_t) +pj_stun_msg_add_string_attr(pj_pool_t *pool, + pj_stun_msg *msg, + int attr_type, + const pj_str_t *value) +{ + pj_stun_string_attr *attr = NULL; + pj_status_t status; + + status = pj_stun_string_attr_create(pool, attr_type, value, + &attr); + if (status != PJ_SUCCESS) + return status; + + return pj_stun_msg_add_attr(msg, &attr->hdr); +} + + +static pj_status_t decode_string_attr(pj_pool_t *pool, + const pj_uint8_t *buf, + void **p_attr) +{ + pj_stun_string_attr *attr; + pj_str_t value; + + /* Create the attribute */ + attr = PJ_POOL_ZALLOC_T(pool, pj_stun_string_attr); + + /* Copy the header */ + pj_memcpy(attr, buf, ATTR_HDR_LEN); + + /* Convert to host byte order */ + attr->hdr.type = pj_ntohs(attr->hdr.type); + attr->hdr.length = pj_ntohs(attr->hdr.length); + + /* Get pointer to the string in the message */ + value.ptr = ((char*)buf + ATTR_HDR_LEN); + value.slen = attr->hdr.length; + + /* Copy the string to the attribute */ + pj_strdup(pool, &attr->value, &value); + + /* Done */ + *p_attr = attr; + + return PJ_SUCCESS; + +} + + +static pj_status_t encode_string_attr(const void *a, pj_uint8_t *buf, + unsigned len, unsigned *printed) +{ + const pj_stun_string_attr *ca = + (const pj_stun_string_attr*)a; + pj_stun_attr_hdr *attr; + + /* Calculated total attr_len (add padding if necessary) */ + *printed = (ca->value.slen + ATTR_HDR_LEN + 3) & (~3); + if (len < *printed) { + *printed = 0; + return PJ_ETOOSMALL; + } + + /* Copy header */ + pj_memcpy(buf, a, ATTR_HDR_LEN); + attr = (pj_stun_attr_hdr*)buf; + + /* Set the correct length */ + attr->length = (pj_uint16_t) ca->value.slen; + + /* Convert to network byte order */ + attr->type = pj_htons(attr->type); + attr->length = pj_htons(attr->length); + + /* Copy the string */ + pj_memcpy(buf+ATTR_HDR_LEN, ca->value.ptr, ca->value.slen); + + /* Done */ + return PJ_SUCCESS; +} + + +////////////////////////////////////////////////////////////////////////////// +/* + * STUN empty attribute (used by USE-CANDIDATE). + */ + +/* + * Create a STUN empty attribute. + */ +PJ_DEF(pj_status_t) +pj_stun_empty_attr_create(pj_pool_t *pool, + int attr_type, + pj_stun_empty_attr **p_attr) +{ + pj_stun_empty_attr *attr; + + PJ_ASSERT_RETURN(pool && p_attr, PJ_EINVAL); + + attr = PJ_POOL_ZALLOC_T(pool, pj_stun_empty_attr); + INIT_ATTR(attr, attr_type, sizeof(pj_stun_empty_attr)); + + *p_attr = attr; + + return PJ_SUCCESS; +} + + +static pj_status_t decode_empty_attr(pj_pool_t *pool, + const pj_uint8_t *buf, + void **p_attr) +{ + pj_stun_empty_attr *attr; + + /* Check that the struct address is valid */ + pj_assert(sizeof(pj_stun_empty_attr) == ATTR_HDR_LEN); + + /* Create the attribute */ + attr = PJ_POOL_ZALLOC_T(pool, pj_stun_empty_attr); + pj_memcpy(attr, buf, ATTR_HDR_LEN); + + /* Convert to host byte order */ + attr->hdr.type = pj_ntohs(attr->hdr.type); + attr->hdr.length = pj_ntohs(attr->hdr.length); + + /* Check that the attribute length is valid */ + if (attr->hdr.length != ATTR_HDR_LEN) + return PJLIB_UTIL_ESTUNINATTRLEN; + + /* Done */ + *p_attr = attr; + + return PJ_SUCCESS; +} + + +static pj_status_t encode_empty_attr(const void *a, pj_uint8_t *buf, + unsigned len, unsigned *printed) +{ + pj_stun_empty_attr *attr; + + if (len < ATTR_HDR_LEN) + return PJ_ETOOSMALL; + + /* Copy and convert attribute to network byte order */ + pj_memcpy(buf, a, ATTR_HDR_LEN); + attr = (pj_stun_empty_attr*) buf; + attr->hdr.type = pj_htons(attr->hdr.type); + pj_assert(attr->hdr.length == ATTR_HDR_LEN); + attr->hdr.length = pj_htons(ATTR_HDR_LEN); + + /* Done */ + *printed = ATTR_HDR_LEN; + + return PJ_SUCCESS; +} + + +////////////////////////////////////////////////////////////////////////////// +/* + * STUN generic 32bit integer attribute. + */ +#define STUN_UINT_LEN 4 + +/* + * Create a STUN generic 32bit value attribute. + */ +PJ_DEF(pj_status_t) +pj_stun_uint_attr_create(pj_pool_t *pool, + int attr_type, + pj_uint32_t value, + pj_stun_uint_attr **p_attr) +{ + pj_stun_uint_attr *attr; + + PJ_ASSERT_RETURN(pool && p_attr, PJ_EINVAL); + + attr = PJ_POOL_ZALLOC_T(pool, pj_stun_uint_attr); + INIT_ATTR(attr, attr_type, STUN_UINT_LEN); + attr->value = value; + + *p_attr = attr; + + return PJ_SUCCESS; +} + +/* Create and add STUN generic 32bit value attribute to the message. */ +PJ_DEF(pj_status_t) +pj_stun_msg_add_uint_attr(pj_pool_t *pool, + pj_stun_msg *msg, + int attr_type, + pj_uint32_t value) +{ + pj_stun_uint_attr *attr = NULL; + pj_status_t status; + + status = pj_stun_uint_attr_create(pool, attr_type, value, &attr); + if (status != PJ_SUCCESS) + return status; + + return pj_stun_msg_add_attr(msg, &attr->hdr); +} + +static pj_status_t decode_uint_attr(pj_pool_t *pool, + const pj_uint8_t *buf, + void **p_attr) +{ + enum + { + ATTR_LEN = STUN_UINT_LEN + ATTR_HDR_LEN + }; + pj_stun_uint_attr *attr; + + /* Check that the struct address is valid */ + pj_assert(sizeof(pj_stun_uint_attr) == ATTR_LEN); + + /* Create the attribute */ + attr = PJ_POOL_ZALLOC_T(pool, pj_stun_uint_attr); + pj_memcpy(attr, buf, ATTR_LEN); + + /* Convert to host byte order */ + attr->hdr.type = pj_ntohs(attr->hdr.type); + attr->hdr.length = pj_ntohs(attr->hdr.length); + attr->value = pj_ntohl(attr->value); + + /* Check that the attribute length is valid */ + if (attr->hdr.length != STUN_UINT_LEN) + return PJLIB_UTIL_ESTUNINATTRLEN; + + /* Done */ + *p_attr = attr; + + return PJ_SUCCESS; +} + + +static pj_status_t encode_uint_attr(const void *a, pj_uint8_t *buf, + unsigned len, unsigned *printed) +{ + enum + { + ATTR_LEN = STUN_UINT_LEN + ATTR_HDR_LEN + }; + pj_stun_uint_attr *attr; + + if (len < ATTR_LEN) + return PJ_ETOOSMALL; + + /* Copy and convert attribute to network byte order */ + pj_memcpy(buf, a, ATTR_LEN); + attr = (pj_stun_uint_attr*) buf; + attr->hdr.type = pj_htons(attr->hdr.type); + pj_assert(attr->hdr.length == STUN_UINT_LEN); + attr->hdr.length = pj_htons(STUN_UINT_LEN); + attr->value = pj_htonl(attr->value); + + /* Done */ + *printed = ATTR_LEN; + + return PJ_SUCCESS; +} + +////////////////////////////////////////////////////////////////////////////// +/* + * STUN MESSAGE-INTEGRITY attribute. + */ + +#define STUN_MSG_INTEGRITY_LEN 20 + +/* + * Create a STUN MESSAGE-INTEGRITY attribute. + */ +PJ_DEF(pj_status_t) +pj_stun_msgint_attr_create(pj_pool_t *pool, + pj_stun_msgint_attr **p_attr) +{ + pj_stun_msgint_attr *attr; + + PJ_ASSERT_RETURN(pool && p_attr, PJ_EINVAL); + + attr = PJ_POOL_ZALLOC_T(pool, pj_stun_msgint_attr); + INIT_ATTR(attr, PJ_STUN_ATTR_MESSAGE_INTEGRITY, STUN_MSG_INTEGRITY_LEN); + + *p_attr = attr; + + return PJ_SUCCESS; +} + + +PJ_DEF(pj_status_t) pj_stun_msg_add_msgint_attr(pj_pool_t *pool, + pj_stun_msg *msg) +{ + pj_stun_msgint_attr *attr = NULL; + pj_status_t status; + + status = pj_stun_msgint_attr_create(pool, &attr); + if (status != PJ_SUCCESS) + return status; + + return pj_stun_msg_add_attr(msg, &attr->hdr); +} + +static pj_status_t decode_msgint_attr(pj_pool_t *pool, + const pj_uint8_t *buf, + void **p_attr) +{ + enum + { + ATTR_LEN = STUN_MSG_INTEGRITY_LEN + ATTR_HDR_LEN + }; + pj_stun_msgint_attr *attr; + + /* Check that struct size is valid */ + pj_assert(sizeof(pj_stun_msgint_attr)==ATTR_LEN); + + /* Create attribute */ + attr = PJ_POOL_ZALLOC_T(pool, pj_stun_msgint_attr); + pj_memcpy(attr, buf, sizeof(pj_stun_msgint_attr)); + attr->hdr.type = pj_ntohs(attr->hdr.type); + attr->hdr.length = pj_ntohs(attr->hdr.length); + + /* Check that the attribute length is valid */ + if (attr->hdr.length != STUN_MSG_INTEGRITY_LEN) + return PJLIB_UTIL_ESTUNINATTRLEN; + + /* Done */ + *p_attr = attr; + return PJ_SUCCESS; +} + + +static pj_status_t encode_msgint_attr(const void *a, pj_uint8_t *buf, + unsigned len, unsigned *printed) +{ + enum + { + ATTR_LEN = STUN_MSG_INTEGRITY_LEN + ATTR_HDR_LEN + }; + pj_stun_msgint_attr *attr; + + if (len < ATTR_LEN) + return PJ_ETOOSMALL; + + /* Copy and convert attribute to network byte order */ + pj_memcpy(buf, a, ATTR_LEN); + attr = (pj_stun_msgint_attr*) buf; + attr->hdr.type = pj_htons(attr->hdr.type); + pj_assert(attr->hdr.length == STUN_MSG_INTEGRITY_LEN); + attr->hdr.length = pj_htons(STUN_MSG_INTEGRITY_LEN); + + /* Done */ + *printed = ATTR_LEN; + + return PJ_SUCCESS; +} + +////////////////////////////////////////////////////////////////////////////// +/* + * STUN ERROR-CODE + */ + +/* + * Create a STUN ERROR-CODE attribute. + */ +PJ_DEF(pj_status_t) +pj_stun_errcode_attr_create(pj_pool_t *pool, + int err_code, + const pj_str_t *err_reason, + pj_stun_errcode_attr **p_attr) +{ + pj_stun_errcode_attr *attr; + char err_buf[80]; + pj_str_t str; + + PJ_ASSERT_RETURN(pool && err_code && p_attr, PJ_EINVAL); + + if (err_reason == NULL) { + str = pj_stun_get_err_reason(err_code); + if (str.slen == 0) { + str.slen = pj_ansi_snprintf(err_buf, sizeof(err_buf), + "Unknown error %d", err_code); + str.ptr = err_buf; + } + err_reason = &str; + } + + attr = PJ_POOL_ZALLOC_T(pool, pj_stun_errcode_attr); + INIT_ATTR(attr, PJ_STUN_ATTR_ERROR_CODE, 4+err_reason->slen); + attr->err_class = (pj_uint8_t)(err_code / 100); + attr->number = (pj_uint8_t) (err_code % 100); + pj_strdup(pool, &attr->reason, err_reason); + + *p_attr = attr; + + return PJ_SUCCESS; +} + + +PJ_DEF(pj_status_t) pj_stun_msg_add_errcode_attr(pj_pool_t *pool, + pj_stun_msg *msg, + int err_code, + const pj_str_t *err_reason) +{ + pj_stun_errcode_attr *err_attr = NULL; + pj_status_t status; + + status = pj_stun_errcode_attr_create(pool, err_code, err_reason, + &err_attr); + if (status != PJ_SUCCESS) + return status; + + return pj_stun_msg_add_attr(msg, &err_attr->hdr); +} + +static pj_status_t decode_errcode_attr(pj_pool_t *pool, + const pj_uint8_t *buf, + void **p_attr) +{ + pj_stun_errcode_attr *attr; + pj_str_t value; + + /* Create the attribute */ + attr = PJ_POOL_ZALLOC_T(pool, pj_stun_errcode_attr); + + /* Copy the header */ + pj_memcpy(attr, buf, ATTR_HDR_LEN + 4); + + /* Convert to host byte order */ + attr->hdr.type = pj_ntohs(attr->hdr.type); + attr->hdr.length = pj_ntohs(attr->hdr.length); + + /* Get pointer to the string in the message */ + value.ptr = ((char*)buf + ATTR_HDR_LEN + 4); + value.slen = attr->hdr.length - 4; + + /* Copy the string to the attribute */ + pj_strdup(pool, &attr->reason, &value); + + /* Done */ + *p_attr = attr; + + return PJ_SUCCESS; +} + + +static pj_status_t encode_errcode_attr(const void *a, pj_uint8_t *buf, + unsigned len, unsigned *printed) +{ + const pj_stun_errcode_attr *ca = + (const pj_stun_errcode_attr*)a; + pj_stun_errcode_attr *attr; + + if (len < ATTR_HDR_LEN + 4 + (unsigned)ca->reason.slen) + return PJ_ETOOSMALL; + + /* Copy and convert attribute to network byte order */ + pj_memcpy(buf, ca, ATTR_HDR_LEN + 4); + + /* Update length */ + attr = (pj_stun_errcode_attr*) buf; + attr->hdr.length = (pj_uint16_t)(4 + ca->reason.slen); + + /* Convert fiends to network byte order */ + attr->hdr.type = pj_htons(attr->hdr.type); + attr->hdr.length = pj_htons(attr->hdr.length); + + /* Copy error string */ + pj_memcpy(buf + ATTR_HDR_LEN + 4, ca->reason.ptr, ca->reason.slen); + + /* Done */ + *printed = (ATTR_HDR_LEN + 4 + ca->reason.slen + 3) & (~3); + + return PJ_SUCCESS; +} + +////////////////////////////////////////////////////////////////////////////// +/* + * STUN UNKNOWN-ATTRIBUTES attribute + */ + +/* + * Create an empty instance of STUN UNKNOWN-ATTRIBUTES attribute. + * + * @param pool The pool to allocate memory from. + * @param p_attr Pointer to receive the attribute. + * + * @return PJ_SUCCESS on success or the appropriate error code. + */ +PJ_DEF(pj_status_t) +pj_stun_unknown_attr_create(pj_pool_t *pool, + unsigned attr_cnt, + const pj_uint16_t attr_array[], + pj_stun_unknown_attr **p_attr) +{ + pj_stun_unknown_attr *attr; + unsigned i; + + PJ_ASSERT_RETURN(pool && attr_cnt < PJ_STUN_MAX_ATTR && p_attr, PJ_EINVAL); + + attr = PJ_POOL_ZALLOC_T(pool, pj_stun_unknown_attr); + INIT_ATTR(attr, PJ_STUN_ATTR_UNKNOWN_ATTRIBUTES, attr_cnt * 2); + + attr->attr_count = attr_cnt; + for (i=0; iattrs[i] = attr_array[i]; + } + + /* If the number of unknown attributes is an odd number, one of the + * attributes MUST be repeated in the list. + */ + if ((attr_cnt & 0x01)) { + attr->attrs[attr_cnt] = attr_array[attr_cnt-1]; + } + + *p_attr = NULL; + + return PJ_SUCCESS; +} + + +/* Create and add STUN UNKNOWN-ATTRIBUTES attribute to the message. */ +PJ_DEF(pj_status_t) +pj_stun_msg_add_unknown_attr(pj_pool_t *pool, + pj_stun_msg *msg, + unsigned attr_cnt, + const pj_uint16_t attr_types[]) +{ + pj_stun_unknown_attr *attr = NULL; + pj_status_t status; + + status = pj_stun_unknown_attr_create(pool, attr_cnt, attr_types, &attr); + if (status != PJ_SUCCESS) + return status; + + return pj_stun_msg_add_attr(msg, &attr->hdr); +} + +static pj_status_t decode_unknown_attr(pj_pool_t *pool, + const pj_uint8_t *buf, + void **p_attr) +{ + pj_stun_unknown_attr *attr; + const pj_uint16_t *punk_attr; + unsigned i; + + attr = PJ_POOL_ZALLOC_T(pool, pj_stun_unknown_attr); + pj_memcpy(attr, buf, ATTR_HDR_LEN); + + attr->hdr.type = pj_ntohs(attr->hdr.type); + attr->hdr.length = pj_ntohs(attr->hdr.length); + + attr->attr_count = (attr->hdr.length >> 1); + if (attr->attr_count > PJ_STUN_MAX_ATTR) + return PJ_ETOOMANY; + + punk_attr = (const pj_uint16_t*)(buf + ATTR_HDR_LEN); + for (i=0; iattr_count; ++i) { + attr->attrs[i] = pj_ntohs(punk_attr[i]); + } + + /* Done */ + *p_attr = attr; + + return PJ_SUCCESS; +} + + +static pj_status_t encode_unknown_attr(const void *a, pj_uint8_t *buf, + unsigned len, unsigned *printed) +{ + const pj_stun_unknown_attr *ca = (const pj_stun_unknown_attr*) a; + pj_stun_unknown_attr *attr; + pj_uint16_t *dst_unk_attr; + unsigned i; + + /* Check that buffer is enough */ + if (len < ATTR_HDR_LEN + (ca->attr_count << 1)) + return PJ_ETOOSMALL; + + /* Copy to message */ + pj_memcpy(buf, ca, ATTR_HDR_LEN); + + /* Set the correct length */ + attr = (pj_stun_unknown_attr *) buf; + attr->hdr.length = (pj_uint16_t)(ca->attr_count << 1); + + /* Convert to network byte order */ + attr->hdr.type = pj_htons(attr->hdr.type); + attr->hdr.length = pj_htons(attr->hdr.length); + + /* Copy individual attribute */ + dst_unk_attr = (pj_uint16_t*)(buf + ATTR_HDR_LEN); + for (i=0; i < ca->attr_count; ++i, ++dst_unk_attr) { + *dst_unk_attr = pj_htons(attr->attrs[i]); + } + + /* Done */ + *printed = (ATTR_HDR_LEN + (ca->attr_count << 1) + 3) & (~3); + + return PJ_SUCCESS; +} + + +////////////////////////////////////////////////////////////////////////////// +/* + * STUN generic binary attribute + */ + +/* + * Create a blank binary attribute. + */ +PJ_DEF(pj_status_t) +pj_stun_binary_attr_create(pj_pool_t *pool, + int attr_type, + const pj_uint8_t *data, + unsigned length, + pj_stun_binary_attr **p_attr) +{ + pj_stun_binary_attr *attr; + + PJ_ASSERT_RETURN(pool && attr_type && p_attr, PJ_EINVAL); + + attr = PJ_POOL_ZALLOC_T(pool, pj_stun_binary_attr); + INIT_ATTR(attr, attr_type, sizeof(pj_stun_binary_attr)); + + if (data && length) { + attr->length = length; + attr->data = pj_pool_alloc(pool, length); + pj_memcpy(attr->data, data, length); + } + + *p_attr = attr; + + return PJ_SUCCESS; +} + + +/* Create and add binary attr. */ +PJ_DEF(pj_status_t) +pj_stun_msg_add_binary_attr(pj_pool_t *pool, + pj_stun_msg *msg, + int attr_type, + const pj_uint8_t *data, + unsigned length) +{ + pj_stun_binary_attr *attr = NULL; + pj_status_t status; + + status = pj_stun_binary_attr_create(pool, attr_type, + data, length, &attr); + if (status != PJ_SUCCESS) + return status; + + return pj_stun_msg_add_attr(msg, &attr->hdr); +} + + +static pj_status_t decode_binary_attr(pj_pool_t *pool, + const pj_uint8_t *buf, + void **p_attr) +{ + pj_stun_binary_attr *attr; + + /* Create the attribute */ + attr = PJ_POOL_ZALLOC_T(pool, pj_stun_binary_attr); + + /* Copy the header */ + pj_memcpy(attr, buf, ATTR_HDR_LEN); + + /* Convert to host byte order */ + attr->hdr.type = pj_ntohs(attr->hdr.type); + attr->hdr.length = pj_ntohs(attr->hdr.length); + + /* Copy the data to the attribute */ + attr->length = attr->hdr.length; + attr->data = pj_pool_alloc(pool, attr->length); + pj_memcpy(attr->data, buf+ATTR_HDR_LEN, attr->length); + + /* Done */ + *p_attr = attr; + + return PJ_SUCCESS; + +} + + +static pj_status_t encode_binary_attr(const void *a, pj_uint8_t *buf, + unsigned len, unsigned *printed) +{ + const pj_stun_binary_attr *ca = (const pj_stun_binary_attr*)a; + pj_stun_attr_hdr *attr; + + /* Calculated total attr_len (add padding if necessary) */ + *printed = (ca->length + ATTR_HDR_LEN + 3) & (~3); + if (len < *printed) + return PJ_ETOOSMALL; + + /* Copy header */ + pj_memcpy(buf, a, ATTR_HDR_LEN); + + /* Set the correct length */ + attr = (pj_stun_attr_hdr*)buf; + attr->length = (pj_uint16_t) ca->length; + + /* Convert to network byte order */ + attr->type = pj_htons(attr->type); + attr->length = pj_htons(attr->length); + + /* Copy the data */ + pj_memcpy(buf+ATTR_HDR_LEN, ca->data, ca->length); + + /* Done */ + return PJ_SUCCESS; +} + + +////////////////////////////////////////////////////////////////////////////// + +/* + * Create a blank STUN message. + */ +PJ_DEF(pj_status_t) pj_stun_msg_create( pj_pool_t *pool, + unsigned msg_type, + pj_uint32_t magic, + const pj_uint8_t tsx_id[12], + pj_stun_msg **p_msg) +{ + pj_stun_msg *msg; + + PJ_ASSERT_RETURN(pool && msg_type && p_msg, PJ_EINVAL); + + msg = PJ_POOL_ZALLOC_T(pool, pj_stun_msg); + msg->hdr.type = (pj_uint16_t) msg_type; + msg->hdr.magic = magic; + + if (tsx_id) { + pj_memcpy(&msg->hdr.tsx_id, tsx_id, sizeof(msg->hdr.tsx_id)); + } else { + struct transaction_id + { + pj_uint32_t proc_id; + pj_uint32_t random; + pj_uint32_t counter; + } id; + static pj_uint32_t pj_stun_tsx_id_counter; + + id.proc_id = pj_getpid(); + id.random = pj_rand(); + id.counter = pj_stun_tsx_id_counter++; + + pj_memcpy(&msg->hdr.tsx_id, &id, sizeof(msg->hdr.tsx_id)); + } + + *p_msg = msg; + + return PJ_SUCCESS; +} + + +/* + * Add STUN attribute to STUN message. + */ +PJ_DEF(pj_status_t) pj_stun_msg_add_attr(pj_stun_msg *msg, + pj_stun_attr_hdr *attr) +{ + PJ_ASSERT_RETURN(msg && attr, PJ_EINVAL); + PJ_ASSERT_RETURN(msg->attr_count < PJ_STUN_MAX_ATTR, PJ_ETOOMANY); + + msg->attr[msg->attr_count++] = attr; + return PJ_SUCCESS; +} + + +PJ_INLINE(pj_uint16_t) GET_VAL16(const pj_uint8_t *pdu, unsigned pos) +{ + return (pj_uint16_t) ((pdu[pos] << 8) + pdu[pos+1]); +} + +PJ_INLINE(pj_uint32_t) GET_VAL32(const pj_uint8_t *pdu, unsigned pos) +{ + return (pdu[pos+0] << 24) + + (pdu[pos+1] << 16) + + (pdu[pos+2] << 8) + + (pdu[pos+3]); +} + + +/* + * Check that the PDU is potentially a valid STUN message. + */ +PJ_DEF(pj_status_t) pj_stun_msg_check(const pj_uint8_t *pdu, unsigned pdu_len, + unsigned options) +{ + unsigned msg_len; + + PJ_ASSERT_RETURN(pdu, PJ_EINVAL); + + if (pdu_len < sizeof(pj_stun_msg_hdr)) + return PJLIB_UTIL_ESTUNINMSGLEN; + + /* First byte of STUN message is always 0x00 or 0x01. */ + if (*pdu != 0x00 && *pdu != 0x01) + return PJLIB_UTIL_ESTUNINMSGTYPE; + + /* Check the PDU length */ + msg_len = GET_VAL16(pdu, 2); + if ((msg_len + 20 > pdu_len) || + ((options & PJ_STUN_IS_DATAGRAM) && msg_len + 20 != pdu_len)) + { + return PJLIB_UTIL_ESTUNINMSGLEN; + } + + /* If magic is set, then there is great possibility that this is + * a STUN message. + */ + if (GET_VAL32(pdu, 4) == PJ_STUN_MAGIC) { + + /* Check if FINGERPRINT attribute is present */ + if (GET_VAL16(pdu, msg_len + 20) == PJ_STUN_ATTR_FINGERPRINT) { + pj_uint16_t attr_len = GET_VAL16(pdu, msg_len + 22); + pj_uint32_t fingerprint = GET_VAL32(pdu, msg_len + 24); + pj_uint32_t crc; + + if (attr_len != 4) + return PJLIB_UTIL_ESTUNINATTRLEN; + + crc = pj_crc32_calc(pdu, msg_len + 20); + crc ^= STUN_XOR_FINGERPRINT; + + if (crc != fingerprint) + return PJLIB_UTIL_ESTUNFINGERPRINT; + } + } + + /* Could be a STUN message */ + return PJ_SUCCESS; +} + + +/* Create error response */ +PJ_DEF(pj_status_t) pj_stun_msg_create_response(pj_pool_t *pool, + const pj_stun_msg *req_msg, + unsigned err_code, + const pj_str_t *err_msg, + pj_stun_msg **p_response) +{ + unsigned msg_type = req_msg->hdr.type; + pj_stun_msg *response = NULL; + pj_status_t status; + + PJ_ASSERT_RETURN(pool && p_response, PJ_EINVAL); + + PJ_ASSERT_RETURN(PJ_STUN_IS_REQUEST(msg_type), + PJLIB_UTIL_ESTUNINMSGTYPE); + + /* Create response or error response */ + if (err_code) + msg_type |= PJ_STUN_ERROR_RESPONSE_BIT; + else + msg_type |= PJ_STUN_RESPONSE_BIT; + + status = pj_stun_msg_create(pool, msg_type, req_msg->hdr.magic, + req_msg->hdr.tsx_id, &response); + if (status != PJ_SUCCESS) { + return status; + } + + /* Add error code attribute */ + if (err_code) { + status = pj_stun_msg_add_errcode_attr(pool, response, + err_code, err_msg); + if (status != PJ_SUCCESS) { + return status; + } + } + + *p_response = response; + return PJ_SUCCESS; +} + + +/* + * Parse incoming packet into STUN message. + */ +PJ_DEF(pj_status_t) pj_stun_msg_decode(pj_pool_t *pool, + const pj_uint8_t *pdu, + unsigned pdu_len, + unsigned options, + pj_stun_msg **p_msg, + unsigned *p_parsed_len, + pj_stun_msg **p_response) +{ + + pj_stun_msg *msg; + unsigned uattr_cnt; + const pj_uint8_t *start_pdu = pdu; + pj_bool_t has_msg_int = PJ_FALSE; + pj_bool_t has_fingerprint = PJ_FALSE; + pj_status_t status; + + PJ_UNUSED_ARG(options); + + PJ_ASSERT_RETURN(pool && pdu && pdu_len && p_msg, PJ_EINVAL); + PJ_ASSERT_RETURN(sizeof(pj_stun_msg_hdr) == 20, PJ_EBUG); + + if (p_parsed_len) + *p_parsed_len = 0; + if (p_response) + *p_response = NULL; + + /* Check if this is a STUN message, if necessary */ + if (options & PJ_STUN_CHECK_PACKET) { + status = pj_stun_msg_check(pdu, pdu_len, options); + if (status != PJ_SUCCESS) + return status; + } + + /* Create the message, copy the header, and convert to host byte order */ + msg = PJ_POOL_ZALLOC_T(pool, pj_stun_msg); + pj_memcpy(&msg->hdr, pdu, sizeof(pj_stun_msg_hdr)); + msg->hdr.type = pj_ntohs(msg->hdr.type); + msg->hdr.length = pj_ntohs(msg->hdr.length); + msg->hdr.magic = pj_ntohl(msg->hdr.magic); + + pdu += sizeof(pj_stun_msg_hdr); + /* pdu_len -= sizeof(pj_stun_msg_hdr); */ + pdu_len = msg->hdr.length; + + /* No need to create response if this is not a request */ + if (!PJ_STUN_IS_REQUEST(msg->hdr.type)) + p_response = NULL; + + /* Parse attributes */ + uattr_cnt = 0; + while (pdu_len > 0) { + unsigned attr_type, attr_val_len; + const struct attr_desc *adesc; + + /* Get attribute type and length. If length is not aligned + * to 4 bytes boundary, add padding. + */ + attr_type = pj_ntohs(*(pj_uint16_t*)pdu); + attr_val_len = pj_ntohs(*(pj_uint16_t*)(pdu+2)); + attr_val_len = (attr_val_len + 3) & (~3); + + /* Check length */ + if (pdu_len < attr_val_len) { + pj_str_t err_msg; + char err_msg_buf[80]; + + err_msg.ptr = err_msg_buf; + err_msg.slen = pj_ansi_snprintf(err_msg_buf, sizeof(err_msg_buf), + "Attribute %s has invalid length", + pj_stun_get_attr_name(attr_type)); + + PJ_LOG(4,(THIS_FILE, "Error decoding message: %.*s", + (int)err_msg.slen, err_msg.ptr)); + + if (p_response) { + pj_stun_msg_create_response(pool, msg, + PJ_STUN_SC_BAD_REQUEST, + &err_msg, p_response); + } + return PJLIB_UTIL_ESTUNINATTRLEN; + } + + /* Get the attribute descriptor */ + adesc = find_attr_desc(attr_type); + + if (adesc == NULL) { + /* Unrecognized attribute */ + + PJ_LOG(4,(THIS_FILE, "Unrecognized attribute type %d", + attr_type)); + + /* Is this a fatal condition? */ + if (attr_type <= 0x7FFF) { + /* This is a mandatory attribute, we must return error + * if we don't understand the attribute. + */ + if (p_response) { + unsigned err_code = PJ_STUN_SC_UNKNOWN_ATTRIBUTE; + + status = pj_stun_msg_create_response(pool, msg, + err_code, NULL, + p_response); + if (status==PJ_SUCCESS) { + pj_uint16_t d = (pj_uint16_t)attr_type; + pj_stun_msg_add_unknown_attr(pool, *p_response, 1, &d); + } + } + + return PJLIB_UTIL_ESTUNUNKNOWNATTR; + } + + } else { + void *attr; + char err_msg1[PJ_ERR_MSG_SIZE], + err_msg2[PJ_ERR_MSG_SIZE]; + + /* Parse the attribute */ + status = (adesc->decode_attr)(pool, pdu, &attr); + + if (status != PJ_SUCCESS) { + pj_strerror(status, err_msg1, sizeof(err_msg1)); + + if (p_response) { + pj_str_t e; + + e.ptr = err_msg2; + e.slen= pj_ansi_snprintf(err_msg2, sizeof(err_msg2), + "%s in %s", + err_msg1, + pj_stun_get_attr_name(attr_type)); + + pj_stun_msg_create_response(pool, msg, + PJ_STUN_SC_BAD_REQUEST, + &e, p_response); + } + + PJ_LOG(4,(THIS_FILE, + "Error parsing STUN attribute %s: %s", + pj_stun_get_attr_name(attr_type), + err_msg1)); + + return status; + } + + if (attr_type == PJ_STUN_ATTR_MESSAGE_INTEGRITY && + !has_fingerprint) + { + if (has_msg_int) { + /* Already has MESSAGE-INTEGRITY */ + if (p_response) { + pj_str_t e; + e = pj_str("MESSAGE-INTEGRITY already present"); + pj_stun_msg_create_response(pool, msg, + PJ_STUN_SC_BAD_REQUEST, + NULL, p_response); + } + return PJLIB_UTIL_ESTUNDUPATTR; + } + has_msg_int = PJ_TRUE; + + } else if (attr_type == PJ_STUN_ATTR_FINGERPRINT) { + if (has_fingerprint) { + /* Already has FINGERPRINT */ + if (p_response) { + pj_str_t e; + e = pj_str("FINGERPRINT already present"); + pj_stun_msg_create_response(pool, msg, + PJ_STUN_SC_BAD_REQUEST, + NULL, p_response); + } + return PJLIB_UTIL_ESTUNDUPATTR; + } + has_fingerprint = PJ_TRUE; + } else { + if (has_msg_int || has_fingerprint) { + /* Another attribute is found which is not FINGERPRINT + * after FINGERPRINT or MESSAGE-INTEGRITY */ + if (p_response) { + pj_str_t e; + e = pj_str("Invalid attribute order"); + pj_stun_msg_create_response(pool, msg, + PJ_STUN_SC_BAD_REQUEST, + NULL, p_response); + } + return has_fingerprint ? PJLIB_UTIL_ESTUNFINGERPOS : + PJLIB_UTIL_ESTUNMSGINTPOS; + } + } + + /* Make sure we have rooms for the new attribute */ + if (msg->attr_count >= PJ_STUN_MAX_ATTR) { + if (p_response) { + pj_str_t e; + + e = pj_str("Too many attributes"); + pj_stun_msg_create_response(pool, msg, + PJ_STUN_SC_BAD_REQUEST, + &e, p_response); + } + return PJLIB_UTIL_ESTUNTOOMANYATTR; + } + + /* Add the attribute */ + msg->attr[msg->attr_count++] = (pj_stun_attr_hdr*)attr; + } + + pdu += (attr_val_len + 4); + pdu_len -= (attr_val_len + 4); + } + + *p_msg = msg; + + if (p_parsed_len) + *p_parsed_len = (pdu - start_pdu); + + return PJ_SUCCESS; +} + +/* Calculate HMAC-SHA1 key for long term credential, by getting + * MD5 digest of username, realm, and password. + */ +void pj_stun_calc_md5_key(pj_uint8_t digest[16], + const pj_str_t *realm, + const pj_str_t *username, + const pj_str_t *passwd) +{ + /* The 16-byte key for MESSAGE-INTEGRITY HMAC is formed by taking + * the MD5 hash of the result of concatenating the following five + * fields: (1) The username, with any quotes and trailing nulls + * removed, (2) A single colon, (3) The realm, with any quotes and + * trailing nulls removed, (4) A single colon, and (5) The + * password, with any trailing nulls removed. + */ + pj_md5_context ctx; + pj_str_t s; + + pj_md5_init(&ctx); + +#define REMOVE_QUOTE(s) if (s.slen && *s.ptr=='"') \ + s.ptr++, s.slen--; \ + if (s.slen && s.ptr[s.slen-1]=='"') \ + s.slen--; + + /* Add username */ + s = *username; + REMOVE_QUOTE(s); + pj_md5_update(&ctx, (pj_uint8_t*)s.ptr, s.slen); + + /* Add single colon */ + pj_md5_update(&ctx, (pj_uint8_t*)":", 1); + + /* Add realm */ + s = *realm; + REMOVE_QUOTE(s); + pj_md5_update(&ctx, (pj_uint8_t*)s.ptr, s.slen); + +#undef REMOVE_QUOTE + + /* Another colon */ + pj_md5_update(&ctx, (pj_uint8_t*)":", 1); + + /* Add password */ + pj_md5_update(&ctx, (pj_uint8_t*)passwd->ptr, passwd->slen); + + /* Done */ + pj_md5_final(&ctx, digest); +} + + +/* +static char *print_binary(const pj_uint8_t *data, unsigned data_len) +{ + static char static_buffer[1024]; + char *buffer = static_buffer; + unsigned length=sizeof(static_buffer), i; + + if (length < data_len * 2 + 8) + return ""; + + pj_ansi_sprintf(buffer, ", data="); + buffer += 7; + + for (i=0; ihdr, sizeof(pj_stun_msg_hdr)); + hdr = (pj_stun_msg_hdr*) buf; + hdr->magic = pj_htonl(hdr->magic); + hdr->type = pj_htons(hdr->type); + /* We'll fill in the length later */ + + buf += sizeof(pj_stun_msg_hdr); + buf_size -= sizeof(pj_stun_msg_hdr); + + /* Print each attribute */ + for (i=0; iattr_count; ++i) { + const struct attr_desc *adesc; + const pj_stun_attr_hdr *attr_hdr = msg->attr[i]; + + if (attr_hdr->type == PJ_STUN_ATTR_MESSAGE_INTEGRITY) { + pj_assert(amsgint == NULL); + amsgint = (pj_stun_msgint_attr*) attr_hdr; + + /* Stop when encountering MESSAGE-INTEGRITY */ + break; + + } else if (attr_hdr->type == PJ_STUN_ATTR_USERNAME) { + pj_assert(auname == NULL); + auname = (pj_stun_username_attr*) attr_hdr; + + } else if (attr_hdr->type == PJ_STUN_ATTR_REALM) { + pj_assert(arealm == NULL); + arealm = (pj_stun_realm_attr*) attr_hdr; + + } else if (attr_hdr->type == PJ_STUN_ATTR_FINGERPRINT) { + afingerprint = (pj_stun_fingerprint_attr*) attr_hdr; + break; + } + + adesc = find_attr_desc(attr_hdr->type); + PJ_ASSERT_RETURN(adesc != NULL, PJ_EBUG); + + status = adesc->encode_attr(attr_hdr, buf, buf_size, &printed); + if (status != PJ_SUCCESS) + return status; + + buf += printed; + buf_size -= printed; + } + + /* We may have stopped printing attribute because we found + * MESSAGE-INTEGRITY or FINGERPRINT. Scan the rest of the + * attributes. + */ + for ( ++i; iattr_count; ++i) { + const pj_stun_attr_hdr *attr_hdr = msg->attr[i]; + + /* There mustn't any attribute after FINGERPRINT */ + PJ_ASSERT_RETURN(afingerprint == NULL, PJLIB_UTIL_ESTUNFINGERPOS); + + if (attr_hdr->type == PJ_STUN_ATTR_MESSAGE_INTEGRITY) { + /* There mustn't be MESSAGE-INTEGRITY before */ + PJ_ASSERT_RETURN(amsgint == NULL, + PJLIB_UTIL_ESTUNMSGINTPOS); + amsgint = (pj_stun_msgint_attr*) attr_hdr; + + } else if (attr_hdr->type == PJ_STUN_ATTR_FINGERPRINT) { + afingerprint = (pj_stun_fingerprint_attr*) attr_hdr; + } + } + + /* We MUST update the message length in the header NOW before + * calculating MESSAGE-INTEGRITY and FINGERPRINT. + * Note that length is not including the 20 bytes header. + */ + if (amsgint && afingerprint) { + msg->hdr.length = (pj_uint16_t)((buf - start) - 20 + 24 + 8); + } else if (amsgint) { + msg->hdr.length = (pj_uint16_t)((buf - start) - 20 + 24); + } else if (afingerprint) { + msg->hdr.length = (pj_uint16_t)((buf - start) - 20 + 8); + } else { + msg->hdr.length = (pj_uint16_t)((buf - start) - 20); + } + + /* hdr->length = pj_htons(length); */ + start[2] = (pj_uint8_t)((msg->hdr.length >> 8) & 0x00FF); + start[3] = (pj_uint8_t)(msg->hdr.length & 0x00FF); + + /* Calculate message integrity, if present */ + if (amsgint != NULL) { + + pj_uint8_t md5_key_buf[16]; + pj_str_t key; + + /* MESSAGE-INTEGRITY must be the last attribute in the message, or + * the last attribute before FINGERPRINT. + */ + if (i < msg->attr_count-2) { + /* Should not happen for message generated by us */ + pj_assert(PJ_FALSE); + return PJLIB_UTIL_ESTUNMSGINTPOS; + + } else if (i == msg->attr_count-2) { + if (msg->attr[i+1]->type != PJ_STUN_ATTR_FINGERPRINT) { + /* Should not happen for message generated by us */ + pj_assert(PJ_FALSE); + return PJLIB_UTIL_ESTUNMSGINTPOS; + } else { + afingerprint = (pj_stun_fingerprint_attr*) msg->attr[i+1]; + } + } + + /* Must have USERNAME attribute */ + if (auname == NULL) { + /* Should not happen for message generated by us */ + pj_assert(PJ_FALSE); + return PJLIB_UTIL_ESTUNNOUSERNAME; + } + + /* Password must be specified */ + PJ_ASSERT_RETURN(password, PJ_EINVAL); + + /* Get the key to sign the message */ + if (arealm == NULL ) { + /* For short term credential, the key is the password */ + key = *password; + + } else { + pj_stun_calc_md5_key(md5_key_buf, &arealm->value, + &auname->value, password); + key.ptr = (char*) md5_key_buf; + key.slen = 16; + } + + /* Calculate HMAC-SHA1 digest */ + pj_hmac_sha1((pj_uint8_t*)start, buf-start, + (pj_uint8_t*)key.ptr, key.slen, + amsgint->hmac); + + /* Put this attribute in the message */ + status = encode_msgint_attr(amsgint, buf, buf_size, + &printed); + if (status != PJ_SUCCESS) + return status; + + buf += printed; + buf_size -= printed; + } + + /* Calculate FINGERPRINT if present */ + if (afingerprint != NULL) { + afingerprint->value = pj_crc32_calc(start, buf-start); + afingerprint->value ^= STUN_XOR_FINGERPRINT; + + /* Put this attribute in the message */ + status = encode_uint_attr(afingerprint, buf, buf_size, + &printed); + if (status != PJ_SUCCESS) + return status; + + buf += printed; + buf_size -= printed; + } + + /* Done */ + if (p_msg_len) + *p_msg_len = (buf - start); + + return PJ_SUCCESS; +} + + +/* + * Find STUN attribute in the STUN message, starting from the specified + * index. + */ +PJ_DEF(pj_stun_attr_hdr*) pj_stun_msg_find_attr( const pj_stun_msg *msg, + int attr_type, + unsigned index) +{ + PJ_ASSERT_RETURN(msg, NULL); + + for (; index < msg->attr_count; ++index) { + if (msg->attr[index]->type == attr_type) + return (pj_stun_attr_hdr*) msg->attr[index]; + } + + return NULL; +} + diff --git a/pjnath/src/pjnath/stun_msg_dump.c b/pjnath/src/pjnath/stun_msg_dump.c new file mode 100644 index 00000000..0ee0ebe4 --- /dev/null +++ b/pjnath/src/pjnath/stun_msg_dump.c @@ -0,0 +1,250 @@ +/* $Id$ */ +/* + * Copyright (C) 2003-2005 Benny Prijono + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +#include +#include +#include +#include + + +#define APPLY() if (len < 1 || len >= (end-p)) \ + goto on_return; \ + p += len + +static int print_binary(char *buffer, unsigned length, + const pj_uint8_t *data, unsigned data_len) +{ + unsigned i; + + if (length < data_len * 2 + 8) + return -1; + + pj_ansi_sprintf(buffer, ", data="); + buffer += 7; + + for (i=0; itype), + (int)ahdr->length); + APPLY(); + + + switch (ahdr->type) { + case PJ_STUN_ATTR_MAPPED_ADDR: + case PJ_STUN_ATTR_RESPONSE_ADDR: + case PJ_STUN_ATTR_SOURCE_ADDR: + case PJ_STUN_ATTR_CHANGED_ADDR: + case PJ_STUN_ATTR_REFLECTED_FROM: + case PJ_STUN_ATTR_REMOTE_ADDR: + case PJ_STUN_ATTR_RELAY_ADDR: + case PJ_STUN_ATTR_XOR_MAPPED_ADDR: + case PJ_STUN_ATTR_REQ_IP: + case PJ_STUN_ATTR_XOR_REFLECTED_FROM: + case PJ_STUN_ATTR_XOR_INTERNAL_ADDR: + case PJ_STUN_ATTR_ALTERNATE_SERVER: + { + const pj_stun_sockaddr_attr *attr; + + attr = (const pj_stun_sockaddr_attr*)ahdr; + + if (attr->addr.addr.sa_family == PJ_AF_INET) { + len = pj_ansi_snprintf(p, end-p, + ", IPv4 addr=%s:%d\n", + pj_inet_ntoa(attr->addr.ipv4.sin_addr), + pj_ntohs(attr->addr.ipv4.sin_port)); + + } else if (attr->addr.addr.sa_family == PJ_AF_INET6) { + len = pj_ansi_snprintf(p, end-p, + ", IPv6 addr present\n"); + } else { + len = pj_ansi_snprintf(p, end-p, + ", INVALID ADDRESS FAMILY!\n"); + } + } + break; + + case PJ_STUN_ATTR_CHANGE_REQUEST: + case PJ_STUN_ATTR_LIFETIME: + case PJ_STUN_ATTR_BANDWIDTH: + case PJ_STUN_ATTR_REQ_ADDR_TYPE: + case PJ_STUN_ATTR_REQ_PORT_PROPS: + case PJ_STUN_ATTR_REQ_TRANSPORT: + case PJ_STUN_ATTR_TIMER_VAL: + case PJ_STUN_ATTR_PRIORITY: + case PJ_STUN_ATTR_FINGERPRINT: + case PJ_STUN_ATTR_REFRESH_INTERVAL: + { + const pj_stun_uint_attr *attr; + + attr = (const pj_stun_uint_attr*)ahdr; + len = pj_ansi_snprintf(p, end-p, + ", value=%d (0x%x)\n", + (pj_uint32_t)attr->value, + (pj_uint32_t)attr->value); + } + break; + + case PJ_STUN_ATTR_USERNAME: + case PJ_STUN_ATTR_PASSWORD: + case PJ_STUN_ATTR_REALM: + case PJ_STUN_ATTR_NONCE: + case PJ_STUN_ATTR_SERVER: + { + const pj_stun_string_attr *attr; + + attr = (pj_stun_string_attr*)ahdr; + len = pj_ansi_snprintf(p, end-p, + ", value=\"%.*s\"\n", + (int)attr->value.slen, + attr->value.ptr); + } + break; + + case PJ_STUN_ATTR_ERROR_CODE: + { + const pj_stun_errcode_attr *attr; + + attr = (const pj_stun_errcode_attr*) ahdr; + len = pj_ansi_snprintf(p, end-p, + ", err_code=%d, reason=\"%.*s\"\n", + attr->err_class*100 + attr->number, + (int)attr->reason.slen, + attr->reason.ptr); + } + break; + + case PJ_STUN_ATTR_UNKNOWN_ATTRIBUTES: + { + const pj_stun_unknown_attr *attr; + unsigned j; + + attr = (const pj_stun_unknown_attr*) ahdr; + + len = pj_ansi_snprintf(p, end-p, + ", unknown list:"); + APPLY(); + + for (j=0; jattr_count; ++j) { + len = pj_ansi_snprintf(p, end-p, + " %d", + (int)attr->attrs[j]); + APPLY(); + } + } + break; + + case PJ_STUN_ATTR_MESSAGE_INTEGRITY: + { + const pj_stun_msgint_attr *attr; + + attr = (const pj_stun_msgint_attr*) ahdr; + len = print_binary(p, end-p, attr->hmac, 20); + APPLY(); + } + break; + + case PJ_STUN_ATTR_DATA: + { + const pj_stun_binary_attr *attr; + + attr = (const pj_stun_binary_attr*) ahdr; + len = print_binary(p, end-p, attr->data, attr->length); + APPLY(); + } + break; + case PJ_STUN_ATTR_USE_CANDIDATE: + default: + len = pj_ansi_snprintf(p, end-p, "\n"); + + break; + } + + APPLY(); + + return (p-buffer); + +on_return: + return len; +} + + +/* + * Dump STUN message to a printable string output. + */ +PJ_DEF(char*) pj_stun_msg_dump(const pj_stun_msg *msg, + char *buffer, + unsigned length, + unsigned *printed_len) +{ + char *p, *end; + int len; + unsigned i; + + PJ_ASSERT_RETURN(msg && buffer && length, NULL); + + p = buffer; + end = buffer + length; + + len = pj_ansi_snprintf(p, end-p, "STUN %s %s\n", + pj_stun_get_method_name(msg->hdr.type), + pj_stun_get_class_name(msg->hdr.type)); + APPLY(); + + len = pj_ansi_snprintf(p, end-p, + " Hdr: length=%d, magic=%08x, tsx_id=%08x %08x %08x\n" + " Attributes:\n", + msg->hdr.length, + msg->hdr.magic, + *(pj_uint32_t*)&msg->hdr.tsx_id[0], + *(pj_uint32_t*)&msg->hdr.tsx_id[4], + *(pj_uint32_t*)&msg->hdr.tsx_id[8]); + APPLY(); + + for (i=0; iattr_count; ++i) { + len = print_attr(p, end-p, msg->attr[i]); + APPLY(); + } + +on_return: + *p = '\0'; + if (printed_len) + *printed_len = (p-buffer); + return buffer; + +} + + +#undef APPLY diff --git a/pjnath/src/pjnath/stun_session.c b/pjnath/src/pjnath/stun_session.c new file mode 100644 index 00000000..b4e7356c --- /dev/null +++ b/pjnath/src/pjnath/stun_session.c @@ -0,0 +1,903 @@ +/* $Id$ */ +/* + * Copyright (C) 2003-2005 Benny Prijono + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +#include +#include + +struct pj_stun_session +{ + pj_stun_endpoint *endpt; + pj_pool_t *pool; + pj_mutex_t *mutex; + pj_stun_session_cb cb; + void *user_data; + + pj_bool_t use_fingerprint; + pj_stun_auth_cred *cred; + pj_str_t srv_name; + + pj_stun_tx_data pending_request_list; + pj_stun_tx_data cached_response_list; +}; + +#define SNAME(s_) ((s_)->pool->obj_name) + +#if PJ_LOG_MAX_LEVEL >= 5 +# define TRACE_(expr) PJ_LOG(5,expr) +#else +# define TRACE_(expr) +#endif + +#if PJ_LOG_MAX_LEVEL >= 4 +# define LOG_ERR_(sess, title, rc) stun_perror(sess, title, rc) +static void stun_perror(pj_stun_session *sess, const char *title, + pj_status_t status) +{ + char errmsg[PJ_ERR_MSG_SIZE]; + + pj_strerror(status, errmsg, sizeof(errmsg)); + + PJ_LOG(4,(SNAME(sess), "%s: %s", title, errmsg)); +} + +#else +# define LOG_ERR_(sess, title, rc) +#endif + +#define TDATA_POOL_SIZE 1024 +#define TDATA_POOL_INC 1024 + + +static void tsx_on_complete(pj_stun_client_tsx *tsx, + pj_status_t status, + const pj_stun_msg *response); +static pj_status_t tsx_on_send_msg(pj_stun_client_tsx *tsx, + const void *stun_pkt, + pj_size_t pkt_size); + +static pj_stun_tsx_cb tsx_cb = +{ + &tsx_on_complete, + &tsx_on_send_msg +}; + + +static pj_status_t tsx_add(pj_stun_session *sess, + pj_stun_tx_data *tdata) +{ + pj_list_push_back(&sess->pending_request_list, tdata); + return PJ_SUCCESS; +} + +static pj_status_t tsx_erase(pj_stun_session *sess, + pj_stun_tx_data *tdata) +{ + PJ_UNUSED_ARG(sess); + pj_list_erase(tdata); + return PJ_SUCCESS; +} + +static pj_stun_tx_data* tsx_lookup(pj_stun_session *sess, + const pj_stun_msg *msg) +{ + pj_stun_tx_data *tdata; + + tdata = sess->pending_request_list.next; + while (tdata != &sess->pending_request_list) { + pj_assert(sizeof(tdata->msg_key)==sizeof(msg->hdr.tsx_id)); + if (tdata->msg_magic == msg->hdr.magic && + pj_memcmp(tdata->msg_key, msg->hdr.tsx_id, + sizeof(msg->hdr.tsx_id))==0) + { + return tdata; + } + tdata = tdata->next; + } + + return NULL; +} + +static pj_status_t create_tdata(pj_stun_session *sess, + pj_stun_tx_data **p_tdata) +{ + pj_pool_t *pool; + pj_stun_tx_data *tdata; + + /* Create pool and initialize basic tdata attributes */ + pool = pj_pool_create(sess->endpt->pf, "tdata%p", + TDATA_POOL_SIZE, TDATA_POOL_INC, NULL); + PJ_ASSERT_RETURN(pool, PJ_ENOMEM); + + tdata = PJ_POOL_ZALLOC_T(pool, pj_stun_tx_data); + tdata->pool = pool; + tdata->sess = sess; + + *p_tdata = tdata; + + return PJ_SUCCESS; +} + +static pj_status_t create_request_tdata(pj_stun_session *sess, + unsigned msg_type, + pj_stun_tx_data **p_tdata) +{ + pj_status_t status; + pj_stun_tx_data *tdata; + + status = create_tdata(sess, &tdata); + if (status != PJ_SUCCESS) + return status; + + /* Create STUN message */ + status = pj_stun_msg_create(tdata->pool, msg_type, PJ_STUN_MAGIC, + NULL, &tdata->msg); + if (status != PJ_SUCCESS) { + pj_pool_release(tdata->pool); + return status; + } + + /* copy the request's transaction ID as the transaction key. */ + pj_assert(sizeof(tdata->msg_key)==sizeof(tdata->msg->hdr.tsx_id)); + tdata->msg_magic = tdata->msg->hdr.magic; + pj_memcpy(tdata->msg_key, tdata->msg->hdr.tsx_id, + sizeof(tdata->msg->hdr.tsx_id)); + + *p_tdata = tdata; + + return PJ_SUCCESS; +} + +static void destroy_tdata(pj_stun_tx_data *tdata) +{ + if (tdata->client_tsx) { + tsx_erase(tdata->sess, tdata); + pj_stun_client_tsx_destroy(tdata->client_tsx); + tdata->client_tsx = NULL; + } + if (tdata->res_timer.id != PJ_FALSE) { + pj_timer_heap_cancel(tdata->sess->endpt->timer_heap, + &tdata->res_timer); + tdata->res_timer.id = PJ_FALSE; + pj_list_erase(tdata); + } + pj_pool_release(tdata->pool); +} + +/* + * Destroy the transmit data. + */ +PJ_DEF(void) pj_stun_msg_destroy_tdata( pj_stun_session *sess, + pj_stun_tx_data *tdata) +{ + PJ_UNUSED_ARG(sess); + destroy_tdata(tdata); +} + + +/* Timer callback to be called when it's time to destroy response cache */ +static void on_cache_timeout(pj_timer_heap_t *timer_heap, + struct pj_timer_entry *entry) +{ + pj_stun_tx_data *tdata; + + PJ_UNUSED_ARG(timer_heap); + + entry->id = PJ_FALSE; + tdata = (pj_stun_tx_data*) entry->user_data; + + PJ_LOG(5,(SNAME(tdata->sess), "Response cache deleted")); + + pj_list_erase(tdata); + pj_stun_msg_destroy_tdata(tdata->sess, tdata); +} + +static pj_str_t *get_passwd(pj_stun_session *sess) +{ + if (sess->cred == NULL) + return NULL; + else if (sess->cred->type == PJ_STUN_AUTH_CRED_STATIC) + return &sess->cred->data.static_cred.data; + else + return NULL; +} + +static pj_status_t apply_msg_options(pj_stun_session *sess, + pj_pool_t *pool, + pj_stun_msg *msg) +{ + pj_status_t status = 0; + + /* The server SHOULD include a SERVER attribute in all responses */ + if (PJ_STUN_IS_RESPONSE(msg->hdr.type) || + PJ_STUN_IS_ERROR_RESPONSE(msg->hdr.type)) + { + pj_stun_msg_add_string_attr(pool, msg, PJ_STUN_ATTR_SERVER, + &sess->srv_name); + } + + /* From draft-ietf-behave-rfc3489bis-05.txt + * Section 8.3.1. Formulating the Request Message + * + * Note: only put MESSAGE-INTEGRITY in non error response. + */ + if (sess->cred && sess->cred->type == PJ_STUN_AUTH_CRED_STATIC && + !PJ_STUN_IS_ERROR_RESPONSE(msg->hdr.type)) + { + const pj_str_t *username; + + /* Create and add USERNAME attribute */ + username = &sess->cred->data.static_cred.username; + status = pj_stun_msg_add_string_attr(pool, msg, + PJ_STUN_ATTR_USERNAME, + username); + PJ_ASSERT_RETURN(status==PJ_SUCCESS, status); + + /* Add REALM only when long term credential is used */ + if (sess->cred->data.static_cred.realm.slen) { + const pj_str_t *realm = &sess->cred->data.static_cred.realm; + status = pj_stun_msg_add_string_attr(pool, msg, + PJ_STUN_ATTR_REALM, + realm); + } + + /* Add MESSAGE-INTEGRITY attribute */ + status = pj_stun_msg_add_msgint_attr(pool, msg); + PJ_ASSERT_RETURN(status==PJ_SUCCESS, status); + + } + + /* Add FINGERPRINT attribute if necessary */ + if (sess->use_fingerprint) { + status = pj_stun_msg_add_uint_attr(pool, msg, + PJ_STUN_ATTR_FINGERPRINT, 0); + PJ_ASSERT_RETURN(status==PJ_SUCCESS, status); + } + + return PJ_SUCCESS; +} + + +static void tsx_on_complete(pj_stun_client_tsx *tsx, + pj_status_t status, + const pj_stun_msg *response) +{ + pj_stun_tx_data *tdata; + + tdata = (pj_stun_tx_data*) pj_stun_client_tsx_get_data(tsx); + + if (tdata->sess->cb.on_request_complete) { + (*tdata->sess->cb.on_request_complete)(tdata->sess, status, tdata, + response); + } +} + +static pj_status_t tsx_on_send_msg(pj_stun_client_tsx *tsx, + const void *stun_pkt, + pj_size_t pkt_size) +{ + pj_stun_tx_data *tdata; + + tdata = (pj_stun_tx_data*) pj_stun_client_tsx_get_data(tsx); + + return tdata->sess->cb.on_send_msg(tdata->sess, stun_pkt, pkt_size, + tdata->dst_addr, tdata->addr_len); +} + +/* **************************************************************************/ + +PJ_DEF(pj_status_t) pj_stun_session_create( pj_stun_endpoint *endpt, + const char *name, + const pj_stun_session_cb *cb, + pj_bool_t fingerprint, + pj_stun_session **p_sess) +{ + pj_pool_t *pool; + pj_stun_session *sess; + pj_status_t status; + + PJ_ASSERT_RETURN(endpt && cb && p_sess, PJ_EINVAL); + + if (name==NULL) + name = "sess%p"; + + pool = pj_pool_create(endpt->pf, name, 4000, 4000, NULL); + PJ_ASSERT_RETURN(pool, PJ_ENOMEM); + + sess = PJ_POOL_ZALLOC_T(pool, pj_stun_session); + sess->endpt = endpt; + sess->pool = pool; + pj_memcpy(&sess->cb, cb, sizeof(*cb)); + sess->use_fingerprint = fingerprint; + + sess->srv_name.ptr = pj_pool_alloc(pool, 32); + sess->srv_name.slen = pj_ansi_snprintf(sess->srv_name.ptr, 32, + "pj_stun-%s", PJ_VERSION); + + pj_list_init(&sess->pending_request_list); + pj_list_init(&sess->cached_response_list); + + status = pj_mutex_create_recursive(pool, name, &sess->mutex); + if (status != PJ_SUCCESS) { + pj_pool_release(pool); + return status; + } + + *p_sess = sess; + + return PJ_SUCCESS; +} + +PJ_DEF(pj_status_t) pj_stun_session_destroy(pj_stun_session *sess) +{ + PJ_ASSERT_RETURN(sess, PJ_EINVAL); + + pj_mutex_lock(sess->mutex); + while (!pj_list_empty(&sess->pending_request_list)) { + pj_stun_tx_data *tdata = sess->pending_request_list.next; + destroy_tdata(tdata); + } + while (!pj_list_empty(&sess->cached_response_list)) { + pj_stun_tx_data *tdata = sess->cached_response_list.next; + destroy_tdata(tdata); + } + pj_mutex_unlock(sess->mutex); + + pj_mutex_destroy(sess->mutex); + pj_pool_release(sess->pool); + + return PJ_SUCCESS; +} + + +PJ_DEF(pj_status_t) pj_stun_session_set_user_data( pj_stun_session *sess, + void *user_data) +{ + PJ_ASSERT_RETURN(sess, PJ_EINVAL); + pj_mutex_lock(sess->mutex); + sess->user_data = user_data; + pj_mutex_unlock(sess->mutex); + return PJ_SUCCESS; +} + +PJ_DEF(void*) pj_stun_session_get_user_data(pj_stun_session *sess) +{ + PJ_ASSERT_RETURN(sess, NULL); + return sess->user_data; +} + +PJ_DEF(pj_status_t) pj_stun_session_set_server_name(pj_stun_session *sess, + const pj_str_t *srv_name) +{ + PJ_ASSERT_RETURN(sess && srv_name, PJ_EINVAL); + pj_strdup(sess->pool, &sess->srv_name, srv_name); + return PJ_SUCCESS; +} + +PJ_DEF(void) pj_stun_session_set_credential(pj_stun_session *sess, + const pj_stun_auth_cred *cred) +{ + PJ_ASSERT_ON_FAIL(sess, return); + if (cred) { + if (!sess->cred) + sess->cred = pj_pool_alloc(sess->pool, sizeof(pj_stun_auth_cred)); + pj_stun_auth_cred_dup(sess->pool, sess->cred, cred); + } else { + sess->cred = NULL; + } +} + + +PJ_DEF(pj_status_t) pj_stun_session_create_req(pj_stun_session *sess, + int method, + pj_stun_tx_data **p_tdata) +{ + pj_stun_tx_data *tdata = NULL; + pj_status_t status; + + PJ_ASSERT_RETURN(sess && p_tdata, PJ_EINVAL); + + status = create_request_tdata(sess, method, &tdata); + if (status != PJ_SUCCESS) + return status; + + *p_tdata = tdata; + return PJ_SUCCESS; +} + +PJ_DEF(pj_status_t) pj_stun_session_create_ind(pj_stun_session *sess, + int msg_type, + pj_stun_tx_data **p_tdata) +{ + pj_stun_tx_data *tdata = NULL; + pj_status_t status; + + PJ_ASSERT_RETURN(sess && p_tdata, PJ_EINVAL); + + status = create_tdata(sess, &tdata); + if (status != PJ_SUCCESS) + return status; + + /* Create STUN message */ + msg_type |= PJ_STUN_INDICATION_BIT; + status = pj_stun_msg_create(tdata->pool, msg_type, PJ_STUN_MAGIC, + NULL, &tdata->msg); + if (status != PJ_SUCCESS) { + pj_pool_release(tdata->pool); + return status; + } + + *p_tdata = tdata; + return PJ_SUCCESS; +} + +/* + * Create a STUN response message. + */ +PJ_DEF(pj_status_t) pj_stun_session_create_response( pj_stun_session *sess, + const pj_stun_msg *req, + unsigned err_code, + const pj_str_t *err_msg, + pj_stun_tx_data **p_tdata) +{ + pj_status_t status; + pj_stun_tx_data *tdata = NULL; + + status = create_tdata(sess, &tdata); + if (status != PJ_SUCCESS) + return status; + + /* Create STUN response message */ + status = pj_stun_msg_create_response(tdata->pool, req, err_code, err_msg, + &tdata->msg); + if (status != PJ_SUCCESS) { + pj_pool_release(tdata->pool); + return status; + } + + /* copy the request's transaction ID as the transaction key. */ + pj_assert(sizeof(tdata->msg_key)==sizeof(req->hdr.tsx_id)); + tdata->msg_magic = req->hdr.magic; + pj_memcpy(tdata->msg_key, req->hdr.tsx_id, sizeof(req->hdr.tsx_id)); + + *p_tdata = tdata; + + return PJ_SUCCESS; +} + + +/* Print outgoing message to log */ +static void dump_tx_msg(pj_stun_session *sess, const pj_stun_msg *msg, + unsigned pkt_size, const pj_sockaddr_t *addr) +{ + const char *dst_name; + int dst_port; + const pj_sockaddr *dst = (const pj_sockaddr*)addr; + char buf[512]; + + if (dst->sa_family == PJ_AF_INET) { + const pj_sockaddr_in *dst4 = (const pj_sockaddr_in*)dst; + dst_name = pj_inet_ntoa(dst4->sin_addr); + dst_port = pj_ntohs(dst4->sin_port); + } else if (dst->sa_family == PJ_AF_INET6) { + const pj_sockaddr_in6 *dst6 = (const pj_sockaddr_in6*)dst; + dst_name = "IPv6"; + dst_port = pj_ntohs(dst6->sin6_port); + } else { + LOG_ERR_(sess, "Invalid address family", PJ_EINVAL); + return; + } + + PJ_LOG(5,(SNAME(sess), + "TX %d bytes STUN message to %s:%d:\n" + "--- begin STUN message ---\n" + "%s" + "--- end of STUN message ---\n", + pkt_size, dst_name, dst_port, + pj_stun_msg_dump(msg, buf, sizeof(buf), NULL))); + +} + + +PJ_DEF(pj_status_t) pj_stun_session_send_msg( pj_stun_session *sess, + pj_bool_t cache_res, + const pj_sockaddr_t *server, + unsigned addr_len, + pj_stun_tx_data *tdata) +{ + pj_status_t status; + + PJ_ASSERT_RETURN(sess && addr_len && server && tdata, PJ_EINVAL); + + /* Allocate packet */ + tdata->max_len = PJ_STUN_MAX_PKT_LEN; + tdata->pkt = pj_pool_alloc(tdata->pool, tdata->max_len); + + /* Start locking the session now */ + pj_mutex_lock(sess->mutex); + + /* Apply options */ + status = apply_msg_options(sess, tdata->pool, tdata->msg); + if (status != PJ_SUCCESS) { + pj_stun_msg_destroy_tdata(sess, tdata); + pj_mutex_unlock(sess->mutex); + LOG_ERR_(sess, "Error applying options", status); + return status; + } + + /* Encode message */ + status = pj_stun_msg_encode(tdata->msg, tdata->pkt, tdata->max_len, + 0, get_passwd(sess), &tdata->pkt_size); + if (status != PJ_SUCCESS) { + pj_stun_msg_destroy_tdata(sess, tdata); + pj_mutex_unlock(sess->mutex); + LOG_ERR_(sess, "STUN encode() error", status); + return status; + } + + /* Dump packet */ + dump_tx_msg(sess, tdata->msg, tdata->pkt_size, server); + + /* If this is a STUN request message, then send the request with + * a new STUN client transaction. + */ + if (PJ_STUN_IS_REQUEST(tdata->msg->hdr.type)) { + + /* Create STUN client transaction */ + status = pj_stun_client_tsx_create(sess->endpt, tdata->pool, + &tsx_cb, &tdata->client_tsx); + PJ_ASSERT_RETURN(status==PJ_SUCCESS, status); + pj_stun_client_tsx_set_data(tdata->client_tsx, (void*)tdata); + + /* Save the remote address */ + tdata->addr_len = addr_len; + tdata->dst_addr = server; + + /* Send the request! */ + status = pj_stun_client_tsx_send_msg(tdata->client_tsx, PJ_TRUE, + tdata->pkt, tdata->pkt_size); + if (status != PJ_SUCCESS && status != PJ_EPENDING) { + pj_stun_msg_destroy_tdata(sess, tdata); + pj_mutex_unlock(sess->mutex); + LOG_ERR_(sess, "Error sending STUN request", status); + return status; + } + + /* Add to pending request list */ + tsx_add(sess, tdata); + + } else { + if (cache_res && + (PJ_STUN_IS_RESPONSE(tdata->msg->hdr.type) || + PJ_STUN_IS_ERROR_RESPONSE(tdata->msg->hdr.type))) + { + /* Requested to keep the response in the cache */ + pj_time_val timeout; + + pj_memset(&tdata->res_timer, 0, sizeof(tdata->res_timer)); + pj_timer_entry_init(&tdata->res_timer, PJ_TRUE, tdata, + &on_cache_timeout); + + timeout.sec = sess->endpt->res_cache_msec / 1000; + timeout.msec = sess->endpt->res_cache_msec % 1000; + + status = pj_timer_heap_schedule(sess->endpt->timer_heap, + &tdata->res_timer, + &timeout); + if (status != PJ_SUCCESS) { + pj_stun_msg_destroy_tdata(sess, tdata); + pj_mutex_unlock(sess->mutex); + LOG_ERR_(sess, "Error scheduling response timer", status); + return status; + } + + pj_list_push_back(&sess->cached_response_list, tdata); + } + + /* Otherwise for non-request message, send directly to transport. */ + status = sess->cb.on_send_msg(sess, tdata->pkt, tdata->pkt_size, + server, addr_len); + + if (status != PJ_SUCCESS && status != PJ_EPENDING) { + LOG_ERR_(sess, "Error sending STUN request", status); + } + + /* Destroy only when response is not cached*/ + if (tdata->res_timer.id == 0) { + pj_stun_msg_destroy_tdata(sess, tdata); + } + } + + + pj_mutex_unlock(sess->mutex); + return status; +} + + +/* Send response */ +static pj_status_t send_response(pj_stun_session *sess, + pj_pool_t *pool, pj_stun_msg *response, + pj_bool_t retransmission, + const pj_sockaddr_t *addr, unsigned addr_len) +{ + pj_uint8_t *out_pkt; + unsigned out_max_len, out_len; + pj_status_t status; + + /* Alloc packet buffer */ + out_max_len = PJ_STUN_MAX_PKT_LEN; + out_pkt = pj_pool_alloc(pool, out_max_len); + + /* Apply options */ + if (!retransmission) { + apply_msg_options(sess, pool, response); + } + + /* Encode */ + status = pj_stun_msg_encode(response, out_pkt, out_max_len, 0, + get_passwd(sess), &out_len); + if (status != PJ_SUCCESS) { + LOG_ERR_(sess, "Error encoding message", status); + return status; + } + + /* Print log */ + dump_tx_msg(sess, response, out_len, addr); + + /* Send packet */ + status = sess->cb.on_send_msg(sess, out_pkt, out_len, addr, addr_len); + + return status; +} + +/* Authenticate incoming message */ +static pj_status_t authenticate_msg(pj_stun_session *sess, + const pj_uint8_t *pkt, + unsigned pkt_len, + const pj_stun_msg *msg, + pj_pool_t *tmp_pool, + const pj_sockaddr_t *src_addr, + unsigned src_addr_len) +{ + pj_stun_msg *response; + pj_status_t status; + + if (PJ_STUN_IS_ERROR_RESPONSE(msg->hdr.type) || sess->cred == NULL) + return PJ_SUCCESS; + + status = pj_stun_verify_credential(pkt, pkt_len, msg, sess->cred, + tmp_pool, &response); + if (status != PJ_SUCCESS && response != NULL) { + PJ_LOG(5,(SNAME(sess), "Message authentication failed")); + send_response(sess, tmp_pool, response, PJ_FALSE, + src_addr, src_addr_len); + } + + return status; +} + + +/* Handle incoming response */ +static pj_status_t on_incoming_response(pj_stun_session *sess, + pj_stun_msg *msg) +{ + pj_stun_tx_data *tdata; + pj_status_t status; + + /* Lookup pending client transaction */ + tdata = tsx_lookup(sess, msg); + if (tdata == NULL) { + PJ_LOG(4,(SNAME(sess), + "Transaction not found, response silently discarded")); + return PJ_SUCCESS; + } + + /* Pass the response to the transaction. + * If the message is accepted, transaction callback will be called, + * and this will call the session callback too. + */ + status = pj_stun_client_tsx_on_rx_msg(tdata->client_tsx, msg); + if (status != PJ_SUCCESS) { + return status; + } + + /* If transaction has completed, destroy the transmit data. + * This will remove the transaction from the pending list too. + */ + if (pj_stun_client_tsx_is_complete(tdata->client_tsx)) { + pj_stun_msg_destroy_tdata(sess, tdata); + tdata = NULL; + } + + return PJ_SUCCESS; +} + + +/* For requests, check if we cache the response */ +static pj_status_t check_cached_response(pj_stun_session *sess, + pj_pool_t *tmp_pool, + const pj_stun_msg *msg, + const pj_sockaddr_t *src_addr, + unsigned src_addr_len) +{ + pj_stun_tx_data *t; + + /* First lookup response in response cache */ + t = sess->cached_response_list.next; + while (t != &sess->cached_response_list) { + if (t->msg_magic == msg->hdr.magic && + pj_memcmp(t->msg_key, msg->hdr.tsx_id, + sizeof(msg->hdr.tsx_id))==0) + { + break; + } + t = t->next; + } + + if (t != &sess->cached_response_list) { + /* Found response in the cache */ + + PJ_LOG(5,(SNAME(sess), + "Request retransmission, sending cached response")); + + send_response(sess, tmp_pool, t->msg, PJ_TRUE, + src_addr, src_addr_len); + return PJ_SUCCESS; + } + + return PJ_ENOTFOUND; +} + +/* Handle incoming request */ +static pj_status_t on_incoming_request(pj_stun_session *sess, + pj_pool_t *tmp_pool, + const pj_uint8_t *in_pkt, + unsigned in_pkt_len, + const pj_stun_msg *msg, + const pj_sockaddr_t *src_addr, + unsigned src_addr_len) +{ + pj_status_t status; + + /* Distribute to handler, or respond with Bad Request */ + if (sess->cb.on_rx_request) { + status = (*sess->cb.on_rx_request)(sess, in_pkt, in_pkt_len, msg, + src_addr, src_addr_len); + } else { + pj_stun_msg *response; + + status = pj_stun_msg_create_response(tmp_pool, msg, + PJ_STUN_SC_BAD_REQUEST, NULL, + &response); + if (status == PJ_SUCCESS && response) { + status = send_response(sess, tmp_pool, response, + PJ_FALSE, src_addr, src_addr_len); + } + } + + return status; +} + + +/* Handle incoming indication */ +static pj_status_t on_incoming_indication(pj_stun_session *sess, + pj_pool_t *tmp_pool, + const pj_uint8_t *in_pkt, + unsigned in_pkt_len, + const pj_stun_msg *msg, + const pj_sockaddr_t *src_addr, + unsigned src_addr_len) +{ + PJ_UNUSED_ARG(tmp_pool); + + /* Distribute to handler */ + if (sess->cb.on_rx_indication) { + return (*sess->cb.on_rx_indication)(sess, in_pkt, in_pkt_len, msg, + src_addr, src_addr_len); + } else { + return PJ_SUCCESS; + } +} + + +PJ_DEF(pj_status_t) pj_stun_session_on_rx_pkt(pj_stun_session *sess, + const void *packet, + pj_size_t pkt_size, + unsigned options, + unsigned *parsed_len, + const pj_sockaddr_t *src_addr, + unsigned src_addr_len) +{ + pj_stun_msg *msg, *response; + pj_pool_t *tmp_pool; + char *dump; + pj_status_t status; + + PJ_ASSERT_RETURN(sess && packet && pkt_size, PJ_EINVAL); + + tmp_pool = pj_pool_create(sess->endpt->pf, "tmpstun", 1024, 1024, NULL); + if (!tmp_pool) + return PJ_ENOMEM; + + /* Try to parse the message */ + status = pj_stun_msg_decode(tmp_pool, (const pj_uint8_t*)packet, + pkt_size, options, + &msg, parsed_len, &response); + if (status != PJ_SUCCESS) { + LOG_ERR_(sess, "STUN msg_decode() error", status); + if (response) { + send_response(sess, tmp_pool, response, + PJ_FALSE, src_addr, src_addr_len); + } + pj_pool_release(tmp_pool); + return status; + } + + dump = pj_pool_alloc(tmp_pool, PJ_STUN_MAX_PKT_LEN); + + PJ_LOG(5,(SNAME(sess), + "RX STUN message:\n" + "--- begin STUN message ---\n" + "%s" + "--- end of STUN message ---\n", + pj_stun_msg_dump(msg, dump, PJ_STUN_MAX_PKT_LEN, NULL))); + + pj_mutex_lock(sess->mutex); + + /* For requests, check if we have cached response */ + status = check_cached_response(sess, tmp_pool, msg, + src_addr, src_addr_len); + if (status == PJ_SUCCESS) { + goto on_return; + } + + /* Authenticate the message */ + status = authenticate_msg(sess, packet, pkt_size, msg, tmp_pool, + src_addr, src_addr_len); + if (status != PJ_SUCCESS) { + goto on_return; + } + + /* Handle message */ + if (PJ_STUN_IS_RESPONSE(msg->hdr.type) || + PJ_STUN_IS_ERROR_RESPONSE(msg->hdr.type)) + { + status = on_incoming_response(sess, msg); + + } else if (PJ_STUN_IS_REQUEST(msg->hdr.type)) { + + status = on_incoming_request(sess, tmp_pool, packet, pkt_size, msg, + src_addr, src_addr_len); + + } else if (PJ_STUN_IS_INDICATION(msg->hdr.type)) { + + status = on_incoming_indication(sess, tmp_pool, packet, pkt_size, + msg, src_addr, src_addr_len); + + } else { + pj_assert(!"Unexpected!"); + status = PJ_EBUG; + } + +on_return: + pj_mutex_unlock(sess->mutex); + + pj_pool_release(tmp_pool); + return status; +} + + diff --git a/pjnath/src/pjnath/stun_transaction.c b/pjnath/src/pjnath/stun_transaction.c new file mode 100644 index 00000000..0000e3a6 --- /dev/null +++ b/pjnath/src/pjnath/stun_transaction.c @@ -0,0 +1,315 @@ +/* $Id$ */ +/* + * Copyright (C) 2003-2005 Benny Prijono + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +#include +#include +#include +#include +#include +#include +#include + + +#define TIMER_ACTIVE 1 + + +struct pj_stun_client_tsx +{ + char obj_name[PJ_MAX_OBJ_NAME]; + pj_stun_endpoint *endpt; + pj_stun_tsx_cb cb; + void *user_data; + + pj_bool_t complete; + \ + pj_bool_t require_retransmit; + pj_timer_entry timer; + unsigned transmit_count; + pj_time_val retransmit_time; + + void *last_pkt; + unsigned last_pkt_size; +}; + + +static void retransmit_timer_callback(pj_timer_heap_t *timer_heap, + pj_timer_entry *timer); + +static void stun_perror(pj_stun_client_tsx *tsx, const char *title, + pj_status_t status) +{ + char errmsg[PJ_ERR_MSG_SIZE]; + + pj_strerror(status, errmsg, sizeof(errmsg)); + PJ_LOG(4,(tsx->obj_name, "%s: %s", title, errmsg)); +} + + +/* + * Create a STUN client transaction. + */ +PJ_DEF(pj_status_t) pj_stun_client_tsx_create(pj_stun_endpoint *endpt, + pj_pool_t *pool, + const pj_stun_tsx_cb *cb, + pj_stun_client_tsx **p_tsx) +{ + pj_stun_client_tsx *tsx; + + PJ_ASSERT_RETURN(endpt && cb && p_tsx, PJ_EINVAL); + PJ_ASSERT_RETURN(cb->on_send_msg, PJ_EINVAL); + + tsx = PJ_POOL_ZALLOC_T(pool, pj_stun_client_tsx); + tsx->endpt = endpt; + pj_memcpy(&tsx->cb, cb, sizeof(*cb)); + + tsx->timer.cb = &retransmit_timer_callback; + tsx->timer.user_data = tsx; + + pj_ansi_snprintf(tsx->obj_name, sizeof(tsx->obj_name), "stuntsx%p", tsx); + + *p_tsx = tsx; + + PJ_LOG(4,(tsx->obj_name, "STUN client transaction created")); + return PJ_SUCCESS; +} + + +/* + * . + */ +PJ_DEF(pj_status_t) pj_stun_client_tsx_destroy(pj_stun_client_tsx *tsx) +{ + PJ_ASSERT_RETURN(tsx, PJ_EINVAL); + + if (tsx->timer.id != 0) { + pj_timer_heap_cancel(tsx->endpt->timer_heap, &tsx->timer); + tsx->timer.id = 0; + } + return PJ_SUCCESS; +} + + +/* + * Check if transaction has completed. + */ +PJ_DEF(pj_bool_t) pj_stun_client_tsx_is_complete(pj_stun_client_tsx *tsx) +{ + PJ_ASSERT_RETURN(tsx, PJ_FALSE); + return tsx->complete; +} + + +/* + * Set user data. + */ +PJ_DEF(pj_status_t) pj_stun_client_tsx_set_data(pj_stun_client_tsx *tsx, + void *data) +{ + PJ_ASSERT_RETURN(tsx, PJ_EINVAL); + tsx->user_data = data; + return PJ_SUCCESS; +} + + +/* + * Get the user data + */ +PJ_DEF(void*) pj_stun_client_tsx_get_data(pj_stun_client_tsx *tsx) +{ + PJ_ASSERT_RETURN(tsx, NULL); + return tsx->user_data; +} + + +/* + * Transmit message. + */ +static pj_status_t tsx_transmit_msg(pj_stun_client_tsx *tsx) +{ + pj_status_t status; + + PJ_ASSERT_RETURN(tsx->timer.id == 0, PJ_EBUSY); + + if (tsx->require_retransmit) { + /* Calculate retransmit/timeout delay */ + if (tsx->transmit_count == 0) { + tsx->retransmit_time.sec = 0; + tsx->retransmit_time.msec = tsx->endpt->rto_msec; + + } else if (tsx->transmit_count < PJ_STUN_MAX_RETRANSMIT_COUNT-1) { + unsigned msec; + + msec = PJ_TIME_VAL_MSEC(tsx->retransmit_time); + msec = (msec << 1) + 100; + tsx->retransmit_time.sec = msec / 1000; + tsx->retransmit_time.msec = msec % 1000; + + } else { + tsx->retransmit_time.sec = PJ_STUN_TIMEOUT_VALUE / 1000; + tsx->retransmit_time.msec = PJ_STUN_TIMEOUT_VALUE % 1000; + } + + /* Schedule timer first because when send_msg() failed we can + * cancel it (as opposed to when schedule_timer() failed we cannot + * cancel transmission). + */; + status = pj_timer_heap_schedule(tsx->endpt->timer_heap, &tsx->timer, + &tsx->retransmit_time); + if (status != PJ_SUCCESS) { + tsx->timer.id = 0; + return status; + } + tsx->timer.id = TIMER_ACTIVE; + } + + + /* Send message */ + status = tsx->cb.on_send_msg(tsx, tsx->last_pkt, tsx->last_pkt_size); + if (status != PJ_SUCCESS) { + if (tsx->timer.id != 0) { + pj_timer_heap_cancel(tsx->endpt->timer_heap, &tsx->timer); + tsx->timer.id = 0; + } + stun_perror(tsx, "STUN error sending message", status); + return status; + } + + tsx->transmit_count++; + + PJ_LOG(4,(tsx->obj_name, "STUN sending message (transmit count=%d)", + tsx->transmit_count)); + return status; +} + + +/* + * Send outgoing message and start STUN transaction. + */ +PJ_DEF(pj_status_t) pj_stun_client_tsx_send_msg(pj_stun_client_tsx *tsx, + pj_bool_t retransmit, + void *pkt, + unsigned pkt_len) +{ + PJ_ASSERT_RETURN(tsx && pkt && pkt_len, PJ_EINVAL); + PJ_ASSERT_RETURN(tsx->timer.id == 0, PJ_EBUSY); + + /* Encode message */ + tsx->last_pkt = pkt; + tsx->last_pkt_size = pkt_len; + + /* Update STUN retransmit flag */ + tsx->require_retransmit = retransmit; + + /* Send the message */ + return tsx_transmit_msg(tsx); +} + + +/* Retransmit timer callback */ +static void retransmit_timer_callback(pj_timer_heap_t *timer_heap, + pj_timer_entry *timer) +{ + pj_stun_client_tsx *tsx = (pj_stun_client_tsx *) timer->user_data; + pj_status_t status; + + PJ_UNUSED_ARG(timer_heap); + + if (tsx->transmit_count >= PJ_STUN_MAX_RETRANSMIT_COUNT) { + /* Retransmission count exceeded. Transaction has failed */ + tsx->timer.id = 0; + PJ_LOG(4,(tsx->obj_name, "STUN timeout waiting for response")); + tsx->complete = PJ_TRUE; + if (tsx->cb.on_complete) { + tsx->cb.on_complete(tsx, PJLIB_UTIL_ESTUNNOTRESPOND, NULL); + } + return; + } + + tsx->timer.id = 0; + status = tsx_transmit_msg(tsx); + if (status != PJ_SUCCESS) { + tsx->timer.id = 0; + tsx->complete = PJ_TRUE; + if (tsx->cb.on_complete) { + tsx->cb.on_complete(tsx, status, NULL); + } + } +} + + + +/* + * Notify the STUN transaction about the arrival of STUN response. + */ +PJ_DEF(pj_status_t) pj_stun_client_tsx_on_rx_msg(pj_stun_client_tsx *tsx, + const pj_stun_msg *msg) +{ + pj_stun_errcode_attr *err_attr; + pj_status_t status; + + /* Must be STUN response message */ + if (!PJ_STUN_IS_RESPONSE(msg->hdr.type) && + !PJ_STUN_IS_ERROR_RESPONSE(msg->hdr.type)) + { + PJ_LOG(4,(tsx->obj_name, + "STUN rx_msg() error: not response message")); + return PJLIB_UTIL_ESTUNNOTRESPONSE; + } + + + /* We have a response with matching transaction ID. + * We can cancel retransmit timer now. + */ + if (tsx->timer.id) { + pj_timer_heap_cancel(tsx->endpt->timer_heap, &tsx->timer); + tsx->timer.id = 0; + } + + /* Find STUN error code attribute */ + err_attr = (pj_stun_errcode_attr*) + pj_stun_msg_find_attr(msg, PJ_STUN_ATTR_ERROR_CODE, 0); + + if (err_attr && err_attr->err_class <= 2) { + /* draft-ietf-behave-rfc3489bis-05.txt Section 8.3.2: + * Any response between 100 and 299 MUST result in the cessation + * of request retransmissions, but otherwise is discarded. + */ + PJ_LOG(4,(tsx->obj_name, + "STUN rx_msg() error: received provisional %d code (%.*s)", + err_attr->err_class * 100 + err_attr->number, + (int)err_attr->reason.slen, + err_attr->reason.ptr)); + return PJ_SUCCESS; + } + + if (err_attr == NULL) { + status = PJ_SUCCESS; + } else { + status = PJLIB_UTIL_ESTUNTSXFAILED; + } + + /* Call callback */ + tsx->complete = PJ_TRUE; + if (tsx->cb.on_complete) { + tsx->cb.on_complete(tsx, status, msg); + } + + return PJ_SUCCESS; + +} + diff --git a/pjnath/src/pjstun-client/client_main.c b/pjnath/src/pjstun-client/client_main.c new file mode 100644 index 00000000..be65b516 --- /dev/null +++ b/pjnath/src/pjstun-client/client_main.c @@ -0,0 +1,680 @@ +/* $Id$ */ +/* + * Copyright (C) 2003-2005 Benny Prijono + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +#include +#include + + +#define THIS_FILE "client_main.c" +#define LOCAL_PORT 1998 +#define BANDWIDTH 64 /* -1 to disable */ +#define LIFETIME 600 /* -1 to disable */ +#define REQ_TRANSPORT -1 /* 0: udp, 1: tcp, -1: disable */ +#define REQ_PORT_PROPS -1 /* -1 to disable */ +#define REQ_IP NULL /* IP address string */ + + +static struct global +{ + pj_stun_endpoint *endpt; + pj_pool_t *pool; + pj_caching_pool cp; + pj_timer_heap_t *th; + pj_stun_session *sess; + pj_sock_t sock; + pj_thread_t *thread; + pj_bool_t quit; + pj_sockaddr_in peer_addr; + pj_sockaddr_in srv_addr; + pj_sockaddr_in relay_addr; + char data_buf[256]; + char *data; +} g; + +static struct options +{ + char *srv_addr; + char *srv_port; + char *realm; + char *user_name; + char *password; + char *nonce; + char *peer_addr; + pj_bool_t use_fingerprint; +} o; + + +static pj_status_t parse_addr(const char *input, pj_sockaddr_in *addr); + + +static my_perror(const char *title, pj_status_t status) +{ + char errmsg[PJ_ERR_MSG_SIZE]; + pj_strerror(status, errmsg, sizeof(errmsg)); + + PJ_LOG(3,(THIS_FILE, "%s: %s", title, errmsg)); +} + +static pj_status_t on_send_msg(pj_stun_session *sess, + const void *pkt, + pj_size_t pkt_size, + const pj_sockaddr_t *srv_addr, + unsigned addr_len) +{ + pj_ssize_t len; + pj_status_t status; + + len = pkt_size; + status = pj_sock_sendto(g.sock, pkt, &len, 0, srv_addr, addr_len); + + if (status != PJ_SUCCESS) + my_perror("Error sending packet", status); + + return status; +} + +static void on_request_complete(pj_stun_session *sess, + pj_status_t status, + pj_stun_tx_data *tdata, + const pj_stun_msg *response) +{ + if (status == PJ_SUCCESS) { + switch (response->hdr.type) { + case PJ_STUN_ALLOCATE_RESPONSE: + { + pj_stun_relay_addr_attr *ar; + + ar = (pj_stun_relay_addr_attr*) + pj_stun_msg_find_attr(response, + PJ_STUN_ATTR_RELAY_ADDR, 0); + if (ar) { + pj_memcpy(&g.relay_addr, &ar->addr.ipv4, + sizeof(pj_sockaddr_in)); + PJ_LOG(3,(THIS_FILE, "Relay address is %s:%d", + pj_inet_ntoa(g.relay_addr.sin_addr), + (int)pj_ntohs(g.relay_addr.sin_port))); + } else { + pj_memset(&g.relay_addr, 0, sizeof(g.relay_addr)); + } + } + break; + } + } else { + my_perror("Client transaction error", status); + } +} + +static int worker_thread(void *unused) +{ + PJ_UNUSED_ARG(unused); + + while (!g.quit) { + pj_time_val timeout = {0, 50}; + pj_fd_set_t readset; + int n; + + pj_timer_heap_poll(g.th, NULL); + + PJ_FD_ZERO(&readset); + PJ_FD_SET(g.sock, &readset); + + n = pj_sock_select(g.sock+1, &readset, NULL, NULL, &timeout); + if (n > 0) { + if (PJ_FD_ISSET(g.sock, &readset)) { + char buffer[512]; + pj_ssize_t len; + pj_sockaddr_in addr; + int addrlen; + pj_status_t rc; + + len = sizeof(buffer); + addrlen = sizeof(addr); + rc = pj_sock_recvfrom(g.sock, buffer, &len, 0, &addr, &addrlen); + if (rc != PJ_SUCCESS || len <= 0) + continue; + + if (pj_stun_msg_check(buffer, len, PJ_STUN_IS_DATAGRAM)==PJ_SUCCESS) { + rc = pj_stun_session_on_rx_pkt(g.sess, buffer, len, + 0, + NULL, &addr, addrlen); + if (rc != PJ_SUCCESS) + my_perror("Error processing packet", rc); + + } else { + buffer[len] = '\0'; + PJ_LOG(3,(THIS_FILE, "Received data: %s", (char*)buffer)); + } + } + } else if (n < 0) + pj_thread_sleep(50); + } + + return 0; +} + +static int init() +{ + pj_sockaddr_in addr; + pj_stun_session_cb stun_cb; + int len; + pj_status_t status; + + g.sock = PJ_INVALID_SOCKET; + + status = pj_init(); + status = pjlib_util_init(); + + pj_caching_pool_init(&g.cp, &pj_pool_factory_default_policy, 0); + + if (o.srv_addr) { + pj_str_t s; + pj_uint16_t port; + + if (o.srv_port) + port = (pj_uint16_t) atoi(o.srv_port); + else + port = PJ_STUN_PORT; + + status = pj_sockaddr_in_init(&g.srv_addr, pj_cstr(&s, o.srv_addr), port); + if (status != PJ_SUCCESS) { + my_perror("Invalid address", status); + return status; + } + + printf("Destination address set to %s:%d\n", o.srv_addr, (int)port); + } else { + printf("Error: address must be specified\n"); + return PJ_EINVAL; + } + + g.pool = pj_pool_create(&g.cp.factory, NULL, 1000, 1000, NULL); + + status = pj_timer_heap_create(g.pool, 1000, &g.th); + pj_assert(status == PJ_SUCCESS); + + status = pj_stun_endpoint_create(&g.cp.factory, 0, NULL, g.th, &g.endpt); + pj_assert(status == PJ_SUCCESS); + + status = pj_sock_socket(PJ_AF_INET, PJ_SOCK_DGRAM, 0, &g.sock); + pj_assert(status == PJ_SUCCESS); + + status = pj_sockaddr_in_init(&addr, NULL, 0); + pj_assert(status == PJ_SUCCESS); + + addr.sin_port = pj_htons((pj_uint16_t)LOCAL_PORT); + status = pj_sock_bind(g.sock, &addr, sizeof(addr)); + pj_assert(status == PJ_SUCCESS); + + len = sizeof(addr); + status = pj_sock_getsockname(g.sock, &addr, &len); + pj_assert(status == PJ_SUCCESS); + + PJ_LOG(3,(THIS_FILE, "Listening on port %d", (int)pj_ntohs(addr.sin_port))); + + pj_memcpy(&g.peer_addr, &addr, sizeof(pj_sockaddr_in)); + if (g.peer_addr.sin_addr.s_addr == 0) + pj_gethostip(&g.peer_addr.sin_addr); + + pj_memset(&stun_cb, 0, sizeof(stun_cb)); + stun_cb.on_send_msg = &on_send_msg; + stun_cb.on_request_complete = &on_request_complete; + + status = pj_stun_session_create(g.endpt, NULL, &stun_cb, + o.use_fingerprint!=0, &g.sess); + pj_assert(status == PJ_SUCCESS); + + if (o.user_name) { + pj_stun_auth_cred cred; + + pj_bzero(&cred, sizeof(cred)); + + cred.type = PJ_STUN_AUTH_CRED_STATIC; + cred.data.static_cred.realm = pj_str(o.realm); + cred.data.static_cred.username = pj_str(o.user_name); + cred.data.static_cred.data_type = 0; + cred.data.static_cred.data = pj_str(o.password); + cred.data.static_cred.nonce = pj_str(o.nonce); + + pj_stun_session_set_credential(g.sess, &cred); + puts("Session credential set"); + } else { + puts("Credential not set"); + } + + if (o.peer_addr) { + if (parse_addr(o.peer_addr, &g.peer_addr)!=PJ_SUCCESS) + return -1; + } + + status = pj_thread_create(g.pool, "stun", &worker_thread, NULL, + 0, 0, &g.thread); + if (status != PJ_SUCCESS) + return status; + + return PJ_SUCCESS; +} + + +static int shutdown() +{ + if (g.thread) { + g.quit = 1; + pj_thread_join(g.thread); + pj_thread_destroy(g.thread); + g.thread = NULL; + } + if (g.sess) + pj_stun_session_destroy(g.sess); + if (g.endpt) + pj_stun_endpoint_destroy(g.endpt); + if (g.sock != PJ_INVALID_SOCKET) + pj_sock_close(g.sock); + if (g.th) + pj_timer_heap_destroy(g.th); + if (g.pool) + pj_pool_release(g.pool); + + pj_pool_factory_dump(&g.cp.factory, PJ_TRUE); + pj_caching_pool_destroy(&g.cp); + + return PJ_SUCCESS; +} + +static void send_bind_request(void) +{ + pj_stun_tx_data *tdata; + pj_status_t rc; + + rc = pj_stun_session_create_req(g.sess, PJ_STUN_BINDING_REQUEST, &tdata); + pj_assert(rc == PJ_SUCCESS); + + rc = pj_stun_session_send_msg(g.sess, PJ_FALSE, + &g.srv_addr, sizeof(g.srv_addr), + tdata); + if (rc != PJ_SUCCESS) + my_perror("Error sending STUN request", rc); +} + +static void send_allocate_request(pj_bool_t allocate) +{ + pj_stun_tx_data *tdata; + pj_status_t rc; + + rc = pj_stun_session_create_req(g.sess, PJ_STUN_ALLOCATE_REQUEST, &tdata); + pj_assert(rc == PJ_SUCCESS); + + + if (BANDWIDTH != -1) { + pj_stun_msg_add_uint_attr(tdata->pool, tdata->msg, + PJ_STUN_ATTR_BANDWIDTH, BANDWIDTH); + } + + if (!allocate) { + pj_stun_msg_add_uint_attr(tdata->pool, tdata->msg, + PJ_STUN_ATTR_LIFETIME, 0); + + } else { + if (LIFETIME != -1) { + pj_stun_msg_add_uint_attr(tdata->pool, tdata->msg, + PJ_STUN_ATTR_LIFETIME, LIFETIME); + } + + if (REQ_TRANSPORT != -1) { + pj_stun_msg_add_uint_attr(tdata->pool, tdata->msg, + PJ_STUN_ATTR_REQ_TRANSPORT, REQ_TRANSPORT); + } + + if (REQ_PORT_PROPS != -1) { + pj_stun_msg_add_uint_attr(tdata->pool, tdata->msg, + PJ_STUN_ATTR_REQ_PORT_PROPS, REQ_PORT_PROPS); + } + + if (REQ_IP != NULL) { + pj_sockaddr_in addr; + pj_str_t tmp; + + pj_sockaddr_in_init(&addr, pj_cstr(&tmp, REQ_IP), 0); + pj_stun_msg_add_sockaddr_attr(tdata->pool, tdata->msg, + PJ_STUN_ATTR_REQ_IP, PJ_FALSE, + &addr, sizeof(addr)); + } + } + + rc = pj_stun_session_send_msg(g.sess, PJ_FALSE, + &g.srv_addr, sizeof(g.srv_addr), + tdata); + pj_assert(rc == PJ_SUCCESS); +} + +static void send_sad_request(pj_bool_t set) +{ + pj_stun_tx_data *tdata; + pj_status_t rc; + + if (g.peer_addr.sin_addr.s_addr == 0 || + g.peer_addr.sin_port == 0) + { + puts("Error: peer address is not set"); + return; + } + + rc = pj_stun_session_create_req(g.sess, PJ_STUN_SET_ACTIVE_DESTINATION_REQUEST, &tdata); + pj_assert(rc == PJ_SUCCESS); + + if (set) { + pj_stun_msg_add_sockaddr_attr(tdata->pool, tdata->msg, + PJ_STUN_ATTR_REMOTE_ADDR, PJ_FALSE, + &g.peer_addr, sizeof(g.peer_addr)); + } + + rc = pj_stun_session_send_msg(g.sess, PJ_FALSE, + &g.srv_addr, sizeof(g.srv_addr), + tdata); + pj_assert(rc == PJ_SUCCESS); +} + +static void send_send_ind(void) +{ + pj_stun_tx_data *tdata; + int len; + pj_status_t rc; + + if (g.peer_addr.sin_addr.s_addr == 0 || + g.peer_addr.sin_port == 0) + { + puts("Error: peer address is not set"); + return; + } + + len = strlen(g.data); + if (len==0) { + puts("Error: data is not set"); + return; + } + + rc = pj_stun_session_create_ind(g.sess, PJ_STUN_SEND_INDICATION, &tdata); + pj_assert(rc == PJ_SUCCESS); + + pj_stun_msg_add_sockaddr_attr(tdata->pool, tdata->msg, + PJ_STUN_ATTR_REMOTE_ADDR, PJ_FALSE, + &g.peer_addr, sizeof(g.peer_addr)); + pj_stun_msg_add_binary_attr(tdata->pool, tdata->msg, + PJ_STUN_ATTR_DATA, g.data, len); + + rc = pj_stun_session_send_msg(g.sess, PJ_FALSE, + &g.srv_addr, sizeof(g.srv_addr), + tdata); + pj_assert(rc == PJ_SUCCESS); + +} + +static void send_raw_data_to_srv(void) +{ + pj_ssize_t len; + + if (g.srv_addr.sin_addr.s_addr == 0 || + g.srv_addr.sin_port == 0) + { + puts("Error: server address is not set"); + return; + } + + len = strlen(g.data); + if (len==0) { + puts("Error: data is not set"); + return; + } + + len = strlen(g.data); + pj_sock_sendto(g.sock, g.data, &len, 0, &g.srv_addr, sizeof(g.srv_addr)); +} + +static void send_raw_data_to_relay(void) +{ + pj_ssize_t len; + + if (g.relay_addr.sin_addr.s_addr == 0 || + g.relay_addr.sin_port == 0) + { + puts("Error: relay address is not set"); + return; + } + + len = strlen(g.data); + if (len==0) { + puts("Error: data is not set"); + return; + } + + len = strlen(g.data); + pj_sock_sendto(g.sock, g.data, &len, 0, &g.relay_addr, sizeof(g.relay_addr)); +} + +static pj_status_t parse_addr(const char *input, + pj_sockaddr_in *addr) +{ + const char *pos; + pj_str_t ip; + pj_uint16_t port; + pj_sockaddr_in tmp_addr; + + pos = pj_ansi_strchr(input, ':'); + if (pos==NULL) { + puts("Invalid format"); + return -1; + } + + ip.ptr = (char*)input; + ip.slen = pos - input; + port = (pj_uint16_t)atoi(pos+1); + + if (port==0) { + puts("Invalid port"); + return -1; + } + + if (pj_sockaddr_in_init(&tmp_addr, &ip, port)!=PJ_SUCCESS) { + puts("Invalid address"); + return -1; + } + + pj_memcpy(addr, &tmp_addr, sizeof(tmp_addr)); + + return PJ_SUCCESS; +} + +static void set_peer_addr(void) +{ + char addr[64]; + + printf("Current peer address: %s:%d\n", + pj_inet_ntoa(g.peer_addr.sin_addr), + pj_ntohs(g.peer_addr.sin_port)); + + printf("Input peer address in IP:PORT format: "); + fflush(stdout); + gets(addr); + + if (parse_addr(addr, &g.peer_addr) != PJ_SUCCESS) { + return; + } + +} + +static void menu(void) +{ + puts("Menu:"); + printf(" pr Set peer address (currently %s:%d)\n", + pj_inet_ntoa(g.peer_addr.sin_addr), pj_ntohs(g.peer_addr.sin_port)); + printf(" dt Set data (currently \"%s\")\n", g.data); + puts(" br Send Bind request"); + puts(" ar Send Allocate request"); + puts(" dr Send de-Allocate request"); + puts(" sr Send Set Active Destination request"); + puts(" cr Send clear Active Destination request"); + puts(" si Send data with Send Indication"); + puts(" rw Send raw data to TURN server"); + puts(" rW Send raw data to relay address"); + puts(" q Quit"); + puts(""); + printf("Choice: "); +} + + +static void console_main(void) +{ + while (!g.quit) { + char input[10]; + + menu(); + + fgets(input, sizeof(input), stdin); + + if (0) { + + } else if (input[0]=='d' && input[1]=='t') { + printf("Input data: "); + gets(g.data); + + } else if (input[0]=='p' && input[1]=='r') { + set_peer_addr(); + + } else if (input[0]=='b' && input[1]=='r') { + send_bind_request(); + + } else if (input[0]=='a' && input[1]=='r') { + send_allocate_request(PJ_TRUE); + + } else if (input[0]=='d' && input[1]=='r') { + send_allocate_request(PJ_FALSE); + + } else if (input[0]=='s' && input[1]=='r') { + send_sad_request(PJ_TRUE); + + } else if (input[0]=='c' && input[1]=='r') { + send_sad_request(PJ_FALSE); + + } else if (input[0]=='s' && input[1]=='i') { + send_send_ind(); + + } else if (input[0]=='r' && input[1]=='w') { + send_raw_data_to_srv(); + + } else if (input[0]=='r' && input[1]=='W') { + send_raw_data_to_relay(); + + } else if (input[0]=='q') { + g.quit = 1; + } + } +} + + +static void usage(void) +{ + puts("Usage: pjstun_client TARGET [OPTIONS]"); + puts(""); + puts("where TARGET is \"host[:port]\""); + puts(""); + puts("and OPTIONS:"); + puts(" --realm, -r Set realm of the credential"); + puts(" --username, -u Set username of the credential"); + puts(" --password, -p Set password of the credential"); + puts(" --nonce, -N Set NONCE"); + puts(" --fingerprint, -F Use fingerprint for outgoing requests"); + puts(" --peer, -P Set peer address (address is in HOST:PORT format)"); + puts(" --data, -D Set data"); + puts(" --help, -h"); +} + +int main(int argc, char *argv[]) +{ + struct pj_getopt_option long_options[] = { + { "realm", 1, 0, 'r'}, + { "username", 1, 0, 'u'}, + { "password", 1, 0, 'p'}, + { "nonce", 1, 0, 'N'}, + { "fingerprint",0, 0, 'F'}, + { "peer", 1, 0, 'P'}, + { "data", 1, 0, 'D'}, + { "help", 0, 0, 'h'} + }; + int c, opt_id; + char *pos; + pj_status_t status; + + g.data = g.data_buf; + + while((c=pj_getopt_long(argc,argv, "r:u:p:hF", long_options, &opt_id))!=-1) { + switch (c) { + case 'r': + o.realm = pj_optarg; + break; + case 'u': + o.user_name = pj_optarg; + break; + case 'p': + o.password = pj_optarg; + break; + case 'N': + o.nonce = pj_optarg; + break; + case 'h': + usage(); + return 0; + case 'F': + o.use_fingerprint = PJ_TRUE; + break; + case 'P': + o.peer_addr = pj_optarg; + break; + case 'D': + g.data = pj_optarg; + break; + + default: + printf("Argument \"%s\" is not valid. Use -h to see help", + argv[pj_optind]); + return 1; + } + } + + if (pj_optind == argc) { + puts("Error: TARGET is needed"); + return 1; + } + + if ((pos=pj_ansi_strchr(argv[pj_optind], ':')) != NULL) { + o.srv_addr = argv[pj_optind]; + *pos = '\0'; + o.srv_port = pos+1; + } else { + o.srv_addr = argv[pj_optind]; + } + + status = init(); + if (status != PJ_SUCCESS) + goto on_return; + + console_main(); + +on_return: + shutdown(); + return status ? 1 : 0; +} + diff --git a/pjnath/src/pjstun-srv-test/bind_usage.c b/pjnath/src/pjstun-srv-test/bind_usage.c new file mode 100644 index 00000000..fc10fb91 --- /dev/null +++ b/pjnath/src/pjstun-srv-test/bind_usage.c @@ -0,0 +1,206 @@ +/* $Id$ */ +/* + * Copyright (C) 2003-2005 Benny Prijono + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +#include "server.h" + +#define THIS_FILE "bind_usage.c" + +static void usage_on_rx_data(pj_stun_usage *usage, + void *pkt, + pj_size_t pkt_size, + const pj_sockaddr_t *src_addr, + unsigned src_addr_len); +static void usage_on_destroy(pj_stun_usage *usage); +static pj_status_t sess_on_send_msg(pj_stun_session *sess, + const void *pkt, + pj_size_t pkt_size, + const pj_sockaddr_t *dst_addr, + unsigned addr_len); +static pj_status_t sess_on_rx_request(pj_stun_session *sess, + const pj_uint8_t *pkt, + unsigned pkt_len, + const pj_stun_msg *msg, + const pj_sockaddr_t *src_addr, + unsigned src_addr_len); + +struct bind_usage +{ + pj_pool_t *pool; + pj_stun_usage *usage; + pj_stun_session *session; +}; + + +PJ_DEF(pj_status_t) pj_stun_bind_usage_create(pj_stun_server *srv, + const pj_str_t *ip_addr, + unsigned port, + pj_stun_usage **p_bu) +{ + pj_pool_t *pool; + struct bind_usage *bu; + pj_stun_server_info *si; + pj_stun_usage_cb usage_cb; + pj_stun_session_cb sess_cb; + pj_sockaddr_in local_addr; + pj_status_t status; + + si = pj_stun_server_get_info(srv); + + pool = pj_pool_create(si->pf, "bind%p", 128, 128, NULL); + bu = PJ_POOL_ZALLOC_T(pool, struct bind_usage); + bu->pool = pool; + + status = pj_sockaddr_in_init(&local_addr, ip_addr, (pj_uint16_t)port); + if (status != PJ_SUCCESS) + return status; + + pj_bzero(&usage_cb, sizeof(usage_cb)); + usage_cb.on_rx_data = &usage_on_rx_data; + usage_cb.on_destroy = &usage_on_destroy; + + status = pj_stun_usage_create(srv, "bind%p", &usage_cb, + PJ_AF_INET, PJ_SOCK_DGRAM, 0, + &local_addr, sizeof(local_addr), + &bu->usage); + if (status != PJ_SUCCESS) { + pj_pool_release(pool); + return status; + } + + pj_bzero(&sess_cb, sizeof(sess_cb)); + sess_cb.on_send_msg = &sess_on_send_msg; + sess_cb.on_rx_request = &sess_on_rx_request; + status = pj_stun_session_create(si->endpt, "bind%p", &sess_cb, PJ_FALSE, + &bu->session); + if (status != PJ_SUCCESS) { + pj_stun_usage_destroy(bu->usage); + return status; + } + + pj_stun_usage_set_user_data(bu->usage, bu); + pj_stun_session_set_user_data(bu->session, bu); + + if (p_bu) + *p_bu = bu->usage; + + return PJ_SUCCESS; +} + + +static void usage_on_rx_data(pj_stun_usage *usage, + void *pkt, + pj_size_t pkt_size, + const pj_sockaddr_t *src_addr, + unsigned src_addr_len) +{ + struct bind_usage *bu; + pj_stun_session *session; + pj_status_t status; + + bu = (struct bind_usage*) pj_stun_usage_get_user_data(usage); + session = bu->session; + + /* Handle packet to session */ + status = pj_stun_session_on_rx_pkt(session, (pj_uint8_t*)pkt, pkt_size, + PJ_STUN_IS_DATAGRAM | PJ_STUN_CHECK_PACKET, + NULL, src_addr, src_addr_len); + if (status != PJ_SUCCESS) { + pj_stun_perror(THIS_FILE, "Error handling incoming packet", status); + return; + } +} + + +static pj_status_t sess_on_send_msg(pj_stun_session *sess, + const void *pkt, + pj_size_t pkt_size, + const pj_sockaddr_t *dst_addr, + unsigned addr_len) +{ + struct bind_usage *bu; + pj_stun_usage *usage; + + bu = (struct bind_usage*) pj_stun_session_get_user_data(sess); + usage = bu->usage; + + return pj_stun_usage_sendto(usage, pkt, pkt_size, 0, + dst_addr, addr_len); +} + + +static pj_status_t sess_on_rx_request(pj_stun_session *sess, + const pj_uint8_t *pkt, + unsigned pkt_len, + const pj_stun_msg *msg, + const pj_sockaddr_t *src_addr, + unsigned src_addr_len) +{ + pj_stun_tx_data *tdata; + pj_status_t status; + + PJ_UNUSED_ARG(pkt); + PJ_UNUSED_ARG(pkt_len); + + /* Create response */ + status = pj_stun_session_create_response(sess, msg, 0, NULL, &tdata); + if (status != PJ_SUCCESS) + return status; + + /* Create MAPPED-ADDRESS attribute */ + status = pj_stun_msg_add_sockaddr_attr(tdata->pool, tdata->msg, + PJ_STUN_ATTR_MAPPED_ADDR, + PJ_FALSE, + src_addr, src_addr_len); + if (status != PJ_SUCCESS) { + pj_stun_perror(THIS_FILE, "Error creating response", status); + pj_stun_msg_destroy_tdata(sess, tdata); + return status; + } + + /* On the presence of magic, create XOR-MAPPED-ADDRESS attribute */ + if (msg->hdr.magic == PJ_STUN_MAGIC) { + status = + pj_stun_msg_add_sockaddr_attr(tdata->pool, tdata->msg, + PJ_STUN_ATTR_XOR_MAPPED_ADDR, + PJ_TRUE, + src_addr, src_addr_len); + if (status != PJ_SUCCESS) { + pj_stun_perror(THIS_FILE, "Error creating response", status); + pj_stun_msg_destroy_tdata(sess, tdata); + return status; + } + } + + /* Send */ + status = pj_stun_session_send_msg(sess, PJ_TRUE, + src_addr, src_addr_len, tdata); + return status; + +} + +static void usage_on_destroy(pj_stun_usage *usage) +{ + struct bind_usage *bu; + + bu = (struct bind_usage*) pj_stun_usage_get_user_data(usage); + if (bu==NULL) + return; + + pj_stun_session_destroy(bu->session); + pj_pool_release(bu->pool); +} diff --git a/pjnath/src/pjstun-srv-test/main.c b/pjnath/src/pjstun-srv-test/main.c new file mode 100644 index 00000000..c462d47e --- /dev/null +++ b/pjnath/src/pjstun-srv-test/main.c @@ -0,0 +1,146 @@ +/* $Id$ */ +/* + * Copyright (C) 2003-2005 Benny Prijono + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +#include "server.h" + +#define THIS_FILE "main.c" + +struct options +{ + char *realm; + char *user_name; + char *password; + char *nonce; + pj_bool_t use_fingerprint; +} o; + +static void usage(void) +{ + puts("Usage: pjstun_srv_test [OPTIONS]"); + puts(""); + puts("where OPTIONS:"); + puts(" --realm, -r Set realm of the credential"); + puts(" --username, -u Set username of the credential"); + puts(" --password, -p Set password of the credential"); + puts(" --nonce, -N Set NONCE"); + puts(" --fingerprint, -F Use fingerprint for outgoing requests"); + puts(" --help, -h"); +} + + +static void server_main(pj_stun_server *srv) +{ + int quit = 0; + + while (!quit) { + char line[10]; + + printf("Menu:\n" + " d Dump status\n" + " q Quit\n" + "Choice:"); + + fgets(line, sizeof(line), stdin); + if (line[0] == 'q') { + quit = 1; + } else if (line[0] == 'd') { + pj_stun_server_info *si = pj_stun_server_get_info(srv); + pj_pool_factory_dump(si->pf, PJ_TRUE); + } + } +} + +int main(int argc, char *argv[]) +{ + struct pj_getopt_option long_options[] = { + { "realm", 1, 0, 'r'}, + { "username", 1, 0, 'u'}, + { "password", 1, 0, 'p'}, + { "nonce", 1, 0, 'N'}, + { "fingerprint",0, 0, 'F'}, + { "help", 0, 0, 'h'} + }; + int c, opt_id; + pj_caching_pool cp; + pj_stun_server *srv; + pj_status_t status; + + while((c=pj_getopt_long(argc,argv, "r:u:p:hF", long_options, &opt_id))!=-1) { + switch (c) { + case 'r': + o.realm = pj_optarg; + break; + case 'u': + o.user_name = pj_optarg; + break; + case 'p': + o.password = pj_optarg; + break; + case 'N': + o.nonce = pj_optarg; + break; + case 'h': + usage(); + return 0; + case 'F': + o.use_fingerprint = PJ_TRUE; + break; + default: + printf("Argument \"%s\" is not valid. Use -h to see help", + argv[pj_optind]); + return 1; + } + } + + if (pj_optind != argc) { + puts("Error: invalid arguments"); + return 1; + } + + pj_init(); + pjlib_util_init(); + pj_caching_pool_init(&cp, &pj_pool_factory_default_policy, 0); + + status = pj_stun_server_create(&cp.factory, 1, &srv); + if (status != PJ_SUCCESS) { + pj_stun_perror(THIS_FILE, "Unable to create server", status); + return 1; + } + + /* + status = pj_stun_bind_usage_create(srv, NULL, 3478, NULL); + if (status != PJ_SUCCESS) { + pj_stun_perror(THIS_FILE, "Unable to create bind usage", status); + return 1; + } + */ + + status = pj_stun_turn_usage_create(srv, PJ_SOCK_DGRAM, NULL, + 3478, NULL); + if (status != PJ_SUCCESS) { + pj_stun_perror(THIS_FILE, "Unable to create bind usage", status); + return 1; + } + + server_main(srv); + + pj_stun_server_destroy(srv); + pj_pool_factory_dump(&cp.factory, PJ_TRUE); + pj_shutdown(); + return 0; +} diff --git a/pjnath/src/pjstun-srv-test/server.c b/pjnath/src/pjstun-srv-test/server.c new file mode 100644 index 00000000..5fdb233e --- /dev/null +++ b/pjnath/src/pjstun-srv-test/server.c @@ -0,0 +1,185 @@ +/* $Id$ */ +/* + * Copyright (C) 2003-2005 Benny Prijono + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "server.h" + +#define THIS_FILE "server.c" + +struct pj_stun_server +{ + pj_stun_server_info si; + + pj_pool_t *pool; + + pj_bool_t thread_quit_flag; + pj_thread_t **threads; + + unsigned usage_cnt; + pj_stun_usage *usage[32]; +}; + +PJ_DEF(pj_status_t) pj_stun_perror( const char *sender, + const char *title, + pj_status_t status) +{ + char errmsg[PJ_ERR_MSG_SIZE]; + pj_strerror(status, errmsg, sizeof(errmsg)); + + PJ_LOG(3,(sender, "%s: %s", title, errmsg)); + return status; +} + +static int worker_thread(void *p) +{ + pj_stun_server *srv = (pj_stun_server*)p; + + while (!srv->thread_quit_flag) { + pj_time_val timeout = { 0, 50 }; + pj_timer_heap_poll(srv->si.timer_heap, NULL); + pj_ioqueue_poll(srv->si.ioqueue, &timeout); + } + + return 0; +} + + +PJ_DEF(pj_status_t) pj_stun_server_create(pj_pool_factory *pf, + unsigned thread_cnt, + pj_stun_server **p_srv) +{ + pj_pool_t *pool; + pj_stun_server *srv; + unsigned i; + pj_status_t status; + + pool = pj_pool_create(pf, "server%p", 4000, 4000, NULL); + + srv = PJ_POOL_ZALLOC_T(pool, pj_stun_server); + srv->pool = pool; + srv->si.pf = pf; + + status = pj_ioqueue_create(srv->pool, PJ_IOQUEUE_MAX_HANDLES, + &srv->si.ioqueue); + if (status != PJ_SUCCESS) + goto on_error; + + status = pj_timer_heap_create(srv->pool, 1024, &srv->si.timer_heap); + if (status != PJ_SUCCESS) + goto on_error; + + status = pj_stun_endpoint_create(srv->si.pf, 0, srv->si.ioqueue, + srv->si.timer_heap, &srv->si.endpt); + if (status != PJ_SUCCESS) + goto on_error; + + srv->si.thread_cnt = thread_cnt; + srv->threads = pj_pool_calloc(pool, thread_cnt, sizeof(pj_thread_t*)); + for (i=0; ithreads[i]); + if (status != PJ_SUCCESS) + goto on_error; + } + + *p_srv = srv; + return PJ_SUCCESS; + +on_error: + pj_stun_server_destroy(srv); + return status; +} + + +PJ_DEF(pj_stun_server_info*) pj_stun_server_get_info(pj_stun_server *srv) +{ + return &srv->si; +} + + +pj_status_t pj_stun_server_register_usage(pj_stun_server *srv, + pj_stun_usage *usage) +{ + unsigned i; + + for (i=0; iusage); ++i) { + if (srv->usage[i] == usage) + return PJ_SUCCESS; + } + + for (i=0; iusage); ++i) { + if (srv->usage[i] == NULL) + break; + } + + if (i == PJ_ARRAY_SIZE(srv->usage)) + return PJ_ETOOMANY; + + srv->usage[i] = usage; + ++srv->usage_cnt; + + return PJ_SUCCESS; +} + +pj_status_t pj_stun_server_unregister_usage(pj_stun_server *srv, + pj_stun_usage *usage) +{ + unsigned i; + + for (i=0; iusage); ++i) { + if (srv->usage[i] == usage) + break; + } + + if (i != PJ_ARRAY_SIZE(srv->usage)) { + srv->usage[i] = NULL; + --srv->usage_cnt; + return PJ_SUCCESS; + } + + return PJ_ENOTFOUND; +} + + +PJ_DEF(pj_status_t) pj_stun_server_destroy(pj_stun_server *srv) +{ + unsigned i; + + for (i=0; iusage); ++i) { + if (!srv->usage[i]) + continue; + + pj_stun_usage_destroy(srv->usage[i]); + pj_stun_server_unregister_usage(srv, srv->usage[i]); + } + + srv->thread_quit_flag = PJ_TRUE; + for (i=0; isi.thread_cnt; ++i) { + pj_thread_join(srv->threads[i]); + srv->threads[i] = NULL; + } + + pj_stun_endpoint_destroy(srv->si.endpt); + pj_timer_heap_destroy(srv->si.timer_heap); + pj_ioqueue_destroy(srv->si.ioqueue); + pj_pool_release(srv->pool); + + return PJ_SUCCESS; +} + + diff --git a/pjnath/src/pjstun-srv-test/server.h b/pjnath/src/pjstun-srv-test/server.h new file mode 100644 index 00000000..a88d87c2 --- /dev/null +++ b/pjnath/src/pjstun-srv-test/server.h @@ -0,0 +1,135 @@ +/* $Id$ */ +/* + * Copyright (C) 2003-2005 Benny Prijono + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +#ifndef __STUN_SERVER_H__ +#define __STUN_SERVER_H__ + +#include +#include + + +/** Opaque declaration for STUN server instance */ +typedef struct pj_stun_server pj_stun_server; + +/** STUN server info */ +typedef struct pj_stun_server_info +{ + pj_pool_factory *pf; + pj_stun_endpoint *endpt; + pj_ioqueue_t *ioqueue; + pj_timer_heap_t *timer_heap; + unsigned thread_cnt; +} pj_stun_server_info; + +/** STUN usage */ +typedef struct pj_stun_usage pj_stun_usage; + +/** STUN usage callback */ +typedef struct pj_stun_usage_cb +{ + void (*on_rx_data)(pj_stun_usage *usage, + void *pkt, + pj_size_t pkt_size, + const pj_sockaddr_t *src_addr, + unsigned src_addr_len); + void (*on_destroy)(pj_stun_usage *usage); +} pj_stun_usage_cb; + + +PJ_DECL(pj_status_t) pj_stun_perror(const char *sender, + const char *title, + pj_status_t status); + +/** + * Create instance of STUN server. + */ +PJ_DECL(pj_status_t) pj_stun_server_create(pj_pool_factory *pf, + unsigned thread_cnt, + pj_stun_server **p_srv); + +/** + * Get STUN server info. + */ +PJ_DECL(pj_stun_server_info*) pj_stun_server_get_info(pj_stun_server *srv); + + +/** + * Destroy STUN server. + */ +PJ_DECL(pj_status_t) pj_stun_server_destroy(pj_stun_server *srv); + + +/** + * Create STUN usage. + */ +PJ_DECL(pj_status_t) pj_stun_usage_create(pj_stun_server *srv, + const char *name, + const pj_stun_usage_cb *cb, + int family, + int type, + int protocol, + const pj_sockaddr_t *local_addr, + int addr_len, + pj_stun_usage **p_usage); + +/** + * Destroy usage. + */ +PJ_DECL(pj_status_t) pj_stun_usage_destroy(pj_stun_usage *usage); + +/** + * Set user data. + */ +PJ_DECL(pj_status_t) pj_stun_usage_set_user_data(pj_stun_usage *usage, + void *user_data); +/** + * Get user data. + */ +PJ_DECL(void*) pj_stun_usage_get_user_data(pj_stun_usage *usage); + +/** + * Send with the usage. + */ +PJ_DECL(pj_status_t) pj_stun_usage_sendto(pj_stun_usage *usage, + const void *pkt, + pj_size_t pkt_size, + unsigned flags, + const pj_sockaddr_t *dst_addr, + unsigned addr_len); + +PJ_DECL(pj_status_t) pj_stun_bind_usage_create(pj_stun_server *srv, + const pj_str_t *ip_addr, + unsigned port, + pj_stun_usage **p_bu); + +PJ_DECL(pj_status_t) pj_stun_turn_usage_create(pj_stun_server *srv, + int type, + const pj_str_t *ip_addr, + unsigned port, + pj_stun_usage **p_bu); + + +pj_status_t pj_stun_server_register_usage(pj_stun_server *srv, + pj_stun_usage *usage); +pj_status_t pj_stun_server_unregister_usage(pj_stun_server *srv, + pj_stun_usage *usage); + + +#endif /* __STUN_SERVER_H__ */ + + diff --git a/pjnath/src/pjstun-srv-test/turn_usage.c b/pjnath/src/pjstun-srv-test/turn_usage.c new file mode 100644 index 00000000..e3d2e595 --- /dev/null +++ b/pjnath/src/pjstun-srv-test/turn_usage.c @@ -0,0 +1,1408 @@ +/* $Id$ */ +/* + * Copyright (C) 2003-2005 Benny Prijono + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +#include "server.h" + +#define THIS_FILE "turn_usage.c" + +#define MAX_CLIENTS 8000 +#define MAX_PEER_PER_CLIENT 16 +#define START_PORT 2000 +#define END_PORT 65530 + +/* + * Forward declarations. + */ +struct turn_usage; +struct turn_client; + +static void tu_on_rx_data(pj_stun_usage *usage, + void *pkt, + pj_size_t pkt_size, + const pj_sockaddr_t *src_addr, + unsigned src_addr_len); +static void tu_on_destroy(pj_stun_usage *usage); +static pj_status_t tu_sess_on_send_msg(pj_stun_session *sess, + const void *pkt, + pj_size_t pkt_size, + const pj_sockaddr_t *dst_addr, + unsigned addr_len); +static pj_status_t tu_sess_on_rx_request(pj_stun_session *sess, + const pj_uint8_t *pkt, + unsigned pkt_len, + const pj_stun_msg *msg, + const pj_sockaddr_t *src_addr, + unsigned src_addr_len); + +static pj_status_t handle_binding_req(pj_stun_session *session, + const pj_stun_msg *msg, + const pj_sockaddr_t *src_addr, + unsigned src_addr_len); + +static pj_status_t client_create(struct turn_usage *tu, + const pj_sockaddr_t *src_addr, + unsigned src_addr_len, + struct turn_client **p_client); +static pj_status_t client_destroy(struct turn_client *client, + pj_status_t reason); +static pj_status_t client_handle_stun_msg(struct turn_client *client, + const pj_stun_msg *msg, + const pj_sockaddr_t *src_addr, + unsigned src_addr_len); + + +struct turn_usage +{ + pj_pool_factory *pf; + pj_stun_endpoint *endpt; + pj_ioqueue_t *ioqueue; + pj_timer_heap_t *timer_heap; + pj_pool_t *pool; + pj_mutex_t *mutex; + pj_stun_usage *usage; + int type; + pj_stun_session *default_session; + pj_hash_table_t *client_htable; + + unsigned max_bw_kbps; + unsigned max_lifetime; + + unsigned next_port; +}; + +struct peer; + +struct turn_client +{ + char obj_name[PJ_MAX_OBJ_NAME]; + struct turn_usage *tu; + pj_pool_t *pool; + pj_stun_session *session; + pj_mutex_t *mutex; + + pj_sockaddr_in client_src_addr; + + /* Socket and socket address of the allocated port */ + int sock_type; + pj_sock_t sock; + pj_ioqueue_key_t *key; + pj_sockaddr_in alloc_addr; + + /* Allocation properties */ + unsigned bw_kbps; + unsigned lifetime; + pj_timer_entry expiry_timer; + + + /* Hash table to keep all peers, key-ed by their address */ + pj_hash_table_t *peer_htable; + + /* Active destination, or sin_addr.s_addr will be zero if + * no active destination is set. + */ + struct peer *active_peer; + + /* Current packet received/sent from/to the allocated port */ + pj_uint8_t pkt[4000]; + pj_sockaddr_in pkt_src_addr; + int pkt_src_addr_len; + pj_ioqueue_op_key_t pkt_read_key; + pj_ioqueue_op_key_t pkt_write_key; +}; + +struct peer +{ + struct turn_client *client; + pj_sockaddr_in addr; +}; + +struct session_data +{ + struct turn_usage *tu; + struct turn_client *client; +}; + + +/* + * This is the only public API, to create and start the TURN usage. + */ +PJ_DEF(pj_status_t) pj_stun_turn_usage_create(pj_stun_server *srv, + int type, + const pj_str_t *ip_addr, + unsigned port, + pj_stun_usage **p_bu) +{ + pj_pool_t *pool; + struct turn_usage *tu; + pj_stun_server_info *si; + pj_stun_usage_cb usage_cb; + pj_stun_session_cb sess_cb; + struct session_data *sd; + pj_sockaddr_in local_addr; + pj_status_t status; + + PJ_ASSERT_RETURN(srv && (type==PJ_SOCK_DGRAM||type==PJ_SOCK_STREAM), + PJ_EINVAL); + si = pj_stun_server_get_info(srv); + + pool = pj_pool_create(si->pf, "turn%p", 4000, 4000, NULL); + tu = PJ_POOL_ZALLOC_T(pool, struct turn_usage); + tu->pool = pool; + tu->type = type; + tu->pf = si->pf; + tu->endpt = si->endpt; + tu->ioqueue = si->ioqueue; + tu->timer_heap = si->timer_heap; + tu->next_port = START_PORT; + tu->max_bw_kbps = 64; + tu->max_lifetime = 10 * 60; + + status = pj_sockaddr_in_init(&local_addr, ip_addr, (pj_uint16_t)port); + if (status != PJ_SUCCESS) + return status; + + /* Create usage */ + pj_bzero(&usage_cb, sizeof(usage_cb)); + usage_cb.on_rx_data = &tu_on_rx_data; + usage_cb.on_destroy = &tu_on_destroy; + status = pj_stun_usage_create(srv, "turn%p", &usage_cb, + PJ_AF_INET, tu->type, 0, + &local_addr, sizeof(local_addr), + &tu->usage); + if (status != PJ_SUCCESS) { + pj_pool_release(pool); + return status; + } + pj_stun_usage_set_user_data(tu->usage, tu); + + /* Init hash tables */ + tu->client_htable = pj_hash_create(tu->pool, MAX_CLIENTS); + + /* Create default session */ + pj_bzero(&sess_cb, sizeof(sess_cb)); + sess_cb.on_send_msg = &tu_sess_on_send_msg; + sess_cb.on_rx_request = &tu_sess_on_rx_request; + status = pj_stun_session_create(si->endpt, "turns%p", &sess_cb, PJ_FALSE, + &tu->default_session); + if (status != PJ_SUCCESS) { + pj_stun_usage_destroy(tu->usage); + return status; + } + + sd = PJ_POOL_ZALLOC_T(pool, struct session_data); + sd->tu = tu; + pj_stun_session_set_user_data(tu->default_session, sd); + + /* Create mutex */ + status = pj_mutex_create_recursive(pool, "turn%p", &tu->mutex); + if (status != PJ_SUCCESS) { + pj_stun_usage_destroy(tu->usage); + return status; + } + + if (p_bu) { + *p_bu = tu->usage; + } + + return PJ_SUCCESS; +} + + +/* + * This is a callback called by usage.c when the particular STUN usage + * is to be destroyed. + */ +static void tu_on_destroy(pj_stun_usage *usage) +{ + struct turn_usage *tu; + pj_hash_iterator_t hit, *it; + + tu = (struct turn_usage*) pj_stun_usage_get_user_data(usage); + + /* Destroy all clients */ + if (tu->client_htable) { + it = pj_hash_first(tu->client_htable, &hit); + while (it) { + struct turn_client *client; + + client = (struct turn_client *)pj_hash_this(tu->client_htable, it); + client_destroy(client, PJ_SUCCESS); + + it = pj_hash_first(tu->client_htable, &hit); + } + } + + pj_stun_session_destroy(tu->default_session); + pj_mutex_destroy(tu->mutex); + pj_pool_release(tu->pool); +} + + +/* + * This is a callback called by the usage.c to notify the TURN usage, + * that incoming packet (may or may not be a STUN packet) is received + * on the port where the TURN usage is listening. + */ +static void tu_on_rx_data(pj_stun_usage *usage, + void *pkt, + pj_size_t pkt_size, + const pj_sockaddr_t *src_addr, + unsigned src_addr_len) +{ + struct turn_usage *tu; + struct turn_client *client; + unsigned flags; + pj_status_t status; + + /* Which usage instance is this */ + tu = (struct turn_usage*) pj_stun_usage_get_user_data(usage); + + /* Lookup client structure based on source address */ + client = (struct turn_client*) pj_hash_get(tu->client_htable, src_addr, + src_addr_len, NULL); + + /* STUN message decoding flag */ + flags = 0; + if (tu->type == PJ_SOCK_DGRAM) + flags |= PJ_STUN_IS_DATAGRAM; + + + if (client) { + status = pj_stun_msg_check(pkt, pkt_size, flags); + + if (status == PJ_SUCCESS) { + /* Received STUN message */ + status = pj_stun_session_on_rx_pkt(client->session, + (pj_uint8_t*)pkt, pkt_size, + flags, NULL, + src_addr, src_addr_len); + } else if (client->active_peer) { + /* Received non-STUN message and client has active destination */ + pj_ssize_t sz = pkt_size; + pj_ioqueue_sendto(client->key, &client->pkt_write_key, + pkt, &sz, 0, + &client->active_peer->addr, + sizeof(client->active_peer->addr)); + } else { + /* Received non-STUN message and client doesn't have active + * destination. + */ + /* Ignore */ + } + + } else { + /* Received packet (could be STUN or no) from new source */ + flags |= PJ_STUN_CHECK_PACKET; + pj_stun_session_on_rx_pkt(tu->default_session, (pj_uint8_t*)pkt, + pkt_size, flags, NULL, + src_addr, src_addr_len); + } +} + + +/* + * This is a utility function provided by TU (Turn Usage) to reserve + * or allocate internal port/socket. The allocation needs to be + * coordinated to minimize bind() collissions. + */ +static pj_status_t tu_alloc_port(struct turn_usage *tu, + int type, + unsigned rpp_bits, + const pj_sockaddr_in *req_addr, + pj_sock_t *p_sock, + int *err_code) +{ + enum { RETRY = 100 }; + pj_sockaddr_in addr; + pj_sock_t sock = PJ_INVALID_SOCKET; + unsigned retry; + pj_status_t status; + + if (req_addr && req_addr->sin_port != 0) { + + *err_code = PJ_STUN_SC_INVALID_PORT; + + /* Allocate specific port */ + status = pj_sock_socket(PJ_AF_INET, type, 0, &sock); + if (status != PJ_SUCCESS) + return status; + + /* Bind */ + status = pj_sock_bind(sock, req_addr, sizeof(pj_sockaddr_in)); + if (status != PJ_SUCCESS) { + pj_sock_close(sock); + return status; + } + + /* Success */ + *p_sock = sock; + return PJ_SUCCESS; + + } else { + status = -1; + *err_code = PJ_STUN_SC_INSUFFICIENT_CAPACITY; + + if (req_addr && req_addr->sin_addr.s_addr) { + *err_code = PJ_STUN_SC_INVALID_IP_ADDR; + pj_memcpy(&addr, req_addr, sizeof(pj_sockaddr_in)); + } else { + pj_sockaddr_in_init(&addr, NULL, 0); + } + + for (retry=0; retrynext_port & 0x01)==0) + tu->next_port++; + break; + case 2: + case 3: + if ((tu->next_port & 0x01)==1) + tu->next_port++; + break; + } + + status = pj_sock_socket(PJ_AF_INET, type, 0, &sock); + if (status != PJ_SUCCESS) + return status; + + addr.sin_port = pj_htons((pj_uint16_t)tu->next_port); + + if (++tu->next_port > END_PORT) + tu->next_port = START_PORT; + + status = pj_sock_bind(sock, &addr, sizeof(addr)); + if (status != PJ_SUCCESS) { + pj_sock_close(sock); + sock = PJ_INVALID_SOCKET; + + /* If client requested specific IP address, assume that + * bind failed because the IP address is not valid. We + * don't want to retry that since it will exhaust our + * port space. + */ + if (req_addr && req_addr->sin_addr.s_addr) + break; + } + } + + if (sock == PJ_INVALID_SOCKET) { + return status; + } + + *p_sock = sock; + return PJ_SUCCESS; + } +} + + +/* + * This callback is called by the TU's STUN session when it receives + * a valid STUN message. This is called from tu_on_rx_data above. + */ +static pj_status_t tu_sess_on_rx_request(pj_stun_session *sess, + const pj_uint8_t *pkt, + unsigned pkt_len, + const pj_stun_msg *msg, + const pj_sockaddr_t *src_addr, + unsigned src_addr_len) +{ + struct session_data *sd; + struct turn_client *client; + pj_stun_tx_data *tdata; + pj_status_t status; + + PJ_UNUSED_ARG(pkt); + PJ_UNUSED_ARG(pkt_len); + + sd = (struct session_data*) pj_stun_session_get_user_data(sess); + + pj_assert(sd->client == NULL); + + if (msg->hdr.type == PJ_STUN_BINDING_REQUEST) { + return handle_binding_req(sess, msg, src_addr, src_addr_len); + + } else if (msg->hdr.type != PJ_STUN_ALLOCATE_REQUEST) { + if (PJ_STUN_IS_REQUEST(msg->hdr.type)) { + status = pj_stun_session_create_response(sess, msg, + PJ_STUN_SC_NO_BINDING, + NULL, &tdata); + if (status==PJ_SUCCESS) { + status = pj_stun_session_send_msg(sess, PJ_FALSE, + src_addr, src_addr_len, + tdata); + } + } else { + PJ_LOG(4,(THIS_FILE, + "Received %s %s without matching Allocation, " + "ignored", pj_stun_get_method_name(msg->hdr.type), + pj_stun_get_class_name(msg->hdr.type))); + } + return PJ_SUCCESS; + } + + status = client_create(sd->tu, src_addr, src_addr_len, &client); + if (status != PJ_SUCCESS) { + pj_stun_perror(THIS_FILE, "Error creating new TURN client", + status); + return status; + } + + + /* Hand over message to client */ + pj_mutex_lock(client->mutex); + status = client_handle_stun_msg(client, msg, src_addr, src_addr_len); + pj_mutex_unlock(client->mutex); + + return status; +} + + +/* + * This callback is called by STUN session when it needs to send packet + * to the network. + */ +static pj_status_t tu_sess_on_send_msg(pj_stun_session *sess, + const void *pkt, + pj_size_t pkt_size, + const pj_sockaddr_t *dst_addr, + unsigned addr_len) +{ + struct session_data *sd; + + sd = (struct session_data*) pj_stun_session_get_user_data(sess); + + if (sd->tu->type == PJ_SOCK_DGRAM) { + return pj_stun_usage_sendto(sd->tu->usage, pkt, pkt_size, 0, + dst_addr, addr_len); + } else { + return PJ_ENOTSUP; + } +} + + +/****************************************************************************/ +/* + * TURN client operations. + */ + +/* Function prototypes */ +static pj_status_t client_create_relay(struct turn_client *client); +static pj_status_t client_destroy_relay(struct turn_client *client); +static void client_on_expired(pj_timer_heap_t *th, pj_timer_entry *e); +static void client_on_read_complete(pj_ioqueue_key_t *key, + pj_ioqueue_op_key_t *op_key, + pj_ssize_t bytes_read); +static pj_status_t client_respond(struct turn_client *client, + const pj_stun_msg *msg, + int err_code, + const char *err_msg, + const pj_sockaddr_t *dst_addr, + int dst_addr_len); +static struct peer* client_get_peer(struct turn_client *client, + const pj_sockaddr_in *peer_addr, + pj_uint32_t *hval); +static struct peer* client_add_peer(struct turn_client *client, + const pj_sockaddr_in *peer_addr, + pj_uint32_t hval); + +static const char *get_tp_type(int type) +{ + if (type==PJ_SOCK_DGRAM) + return "udp"; + else if (type==PJ_SOCK_STREAM) + return "tcp"; + else + return "???"; +} + + +/* + * This callback is called when incoming STUN message is received + * in the TURN usage. This is called from by tu_on_rx_data() when + * the packet is handed over to the client. + */ +static pj_status_t client_sess_on_rx_msg(pj_stun_session *sess, + const pj_uint8_t *pkt, + unsigned pkt_len, + const pj_stun_msg *msg, + const pj_sockaddr_t *src_addr, + unsigned src_addr_len) +{ + struct session_data *sd; + + PJ_UNUSED_ARG(pkt); + PJ_UNUSED_ARG(pkt_len); + + sd = (struct session_data*) pj_stun_session_get_user_data(sess); + pj_assert(sd->client != PJ_SUCCESS); + + return client_handle_stun_msg(sd->client, msg, src_addr, src_addr_len); +} + + +/* + * This callback is called by client's STUN session to send outgoing + * STUN packet. It's called when client calls pj_stun_session_send_msg() + * function. + */ +static pj_status_t client_sess_on_send_msg(pj_stun_session *sess, + const void *pkt, + pj_size_t pkt_size, + const pj_sockaddr_t *dst_addr, + unsigned addr_len) +{ + struct session_data *sd; + + sd = (struct session_data*) pj_stun_session_get_user_data(sess); + + if (sd->tu->type == PJ_SOCK_DGRAM) { + return pj_stun_usage_sendto(sd->tu->usage, pkt, pkt_size, 0, + dst_addr, addr_len); + } else { + return PJ_ENOTSUP; + } +} + + +/* + * Create a new TURN client for the specified source address. + */ +static pj_status_t client_create(struct turn_usage *tu, + const pj_sockaddr_t *src_addr, + unsigned src_addr_len, + struct turn_client **p_client) +{ + pj_pool_t *pool; + struct turn_client *client; + pj_stun_session_cb sess_cb; + struct session_data *sd; + pj_status_t status; + + PJ_ASSERT_RETURN(src_addr_len==sizeof(pj_sockaddr_in), PJ_EINVAL); + + pool = pj_pool_create(tu->pf, "turnc%p", 4000, 4000, NULL); + client = PJ_POOL_ZALLOC_T(pool, struct turn_client); + client->pool = pool; + client->tu = tu; + client->sock = PJ_INVALID_SOCKET; + + pj_memcpy(&client->client_src_addr, src_addr, + sizeof(client->client_src_addr)); + + if (src_addr) { + const pj_sockaddr_in *a4 = (const pj_sockaddr_in *)src_addr; + pj_ansi_snprintf(client->obj_name, sizeof(client->obj_name), + "%s:%s:%d", + get_tp_type(tu->type), + pj_inet_ntoa(a4->sin_addr), + (int)pj_ntohs(a4->sin_port)); + client->obj_name[sizeof(client->obj_name)-1] = '\0'; + } + + /* Create session */ + pj_bzero(&sess_cb, sizeof(sess_cb)); + sess_cb.on_send_msg = &client_sess_on_send_msg; + sess_cb.on_rx_request = &client_sess_on_rx_msg; + sess_cb.on_rx_indication = &client_sess_on_rx_msg; + status = pj_stun_session_create(tu->endpt, client->obj_name, + &sess_cb, PJ_FALSE, + &client->session); + if (status != PJ_SUCCESS) { + pj_pool_release(pool); + return status; + } + + sd = PJ_POOL_ZALLOC_T(pool, struct session_data); + sd->tu = tu; + sd->client = client; + pj_stun_session_set_user_data(client->session, sd); + + /* Mutex */ + status = pj_mutex_create_recursive(client->pool, pool->obj_name, + &client->mutex); + if (status != PJ_SUCCESS) { + client_destroy(client, status); + return status; + } + + /* Create hash table */ + client->peer_htable = pj_hash_create(client->pool, MAX_PEER_PER_CLIENT); + if (client->peer_htable == NULL) { + client_destroy(client, status); + return PJ_ENOMEM; + } + + /* Init timer entry */ + client->expiry_timer.user_data = client; + client->expiry_timer.cb = &client_on_expired; + client->expiry_timer.id = 0; + + /* Register to hash table */ + pj_mutex_lock(tu->mutex); + pj_hash_set(pool, tu->client_htable, src_addr, src_addr_len, 0, client); + pj_mutex_unlock(tu->mutex); + + /* Done */ + *p_client = client; + + PJ_LOG(4,(THIS_FILE, "TURN client %s created", client->obj_name)); + + return PJ_SUCCESS; +} + + +/* + * Destroy TURN client. + */ +static pj_status_t client_destroy(struct turn_client *client, + pj_status_t reason) +{ + struct turn_usage *tu = client->tu; + char name[PJ_MAX_OBJ_NAME]; + + pj_assert(sizeof(name)==sizeof(client->obj_name)); + pj_memcpy(name, client->obj_name, sizeof(name)); + + /* Kill timer if it's active */ + if (client->expiry_timer.id != 0) { + pj_timer_heap_cancel(tu->timer_heap, &client->expiry_timer); + client->expiry_timer.id = PJ_FALSE; + } + + /* Destroy relay */ + client_destroy_relay(client); + + /* Unregister client from hash table */ + pj_mutex_lock(tu->mutex); + pj_hash_set(NULL, tu->client_htable, + &client->client_src_addr, sizeof(client->client_src_addr), + 0, NULL); + pj_mutex_unlock(tu->mutex); + + /* Destroy STUN session */ + if (client->session) { + pj_stun_session_destroy(client->session); + client->session = NULL; + } + + /* Mutex */ + if (client->mutex) { + pj_mutex_destroy(client->mutex); + client->mutex = NULL; + } + + /* Finally destroy pool */ + if (client->pool) { + pj_pool_t *pool = client->pool; + client->pool = NULL; + pj_pool_release(pool); + } + + if (reason == PJ_SUCCESS) { + PJ_LOG(4,(THIS_FILE, "TURN client %s destroyed", name)); + } + + return PJ_SUCCESS; +} + + +/* + * This utility function is used to setup relay (with ioqueue) after + * socket has been allocated for the TURN client. + */ +static pj_status_t client_create_relay(struct turn_client *client) +{ + pj_ioqueue_callback client_ioq_cb; + int addrlen; + pj_status_t status; + + /* Update address */ + addrlen = sizeof(pj_sockaddr_in); + status = pj_sock_getsockname(client->sock, &client->alloc_addr, + &addrlen); + if (status != PJ_SUCCESS) { + pj_sock_close(client->sock); + client->sock = PJ_INVALID_SOCKET; + return status; + } + + if (client->alloc_addr.sin_addr.s_addr == 0) { + status = pj_gethostip(&client->alloc_addr.sin_addr); + if (status != PJ_SUCCESS) { + pj_sock_close(client->sock); + client->sock = PJ_INVALID_SOCKET; + return status; + } + } + + /* Register to ioqueue */ + pj_bzero(&client_ioq_cb, sizeof(client_ioq_cb)); + client_ioq_cb.on_read_complete = &client_on_read_complete; + status = pj_ioqueue_register_sock(client->pool, client->tu->ioqueue, + client->sock, client, + &client_ioq_cb, &client->key); + if (status != PJ_SUCCESS) { + pj_sock_close(client->sock); + client->sock = PJ_INVALID_SOCKET; + return status; + } + + pj_ioqueue_op_key_init(&client->pkt_read_key, + sizeof(client->pkt_read_key)); + pj_ioqueue_op_key_init(&client->pkt_write_key, + sizeof(client->pkt_write_key)); + + /* Trigger the first read */ + client_on_read_complete(client->key, &client->pkt_read_key, 0); + + PJ_LOG(4,(THIS_FILE, "TURN client %s: relay allocated on %s:%s:%d", + client->obj_name, + get_tp_type(client->sock_type), + pj_inet_ntoa(client->alloc_addr.sin_addr), + (int)pj_ntohs(client->alloc_addr.sin_port))); + + return PJ_SUCCESS; +} + + +/* + * This utility function is used to destroy the port allocated for + * the TURN client. + */ +static pj_status_t client_destroy_relay(struct turn_client *client) +{ + /* Close socket */ + if (client->key) { + pj_ioqueue_unregister(client->key); + client->key = NULL; + client->sock = PJ_INVALID_SOCKET; + } else if (client->sock && client->sock != PJ_INVALID_SOCKET) { + pj_sock_close(client->sock); + client->sock = PJ_INVALID_SOCKET; + } + + PJ_LOG(4,(THIS_FILE, "TURN client %s: relay allocation %s:%s:%d destroyed", + client->obj_name, + get_tp_type(client->sock_type), + pj_inet_ntoa(client->alloc_addr.sin_addr), + (int)pj_ntohs(client->alloc_addr.sin_port))); + return PJ_SUCCESS; +} + + +/* + * From the source packet address, get the peer instance from hash table. + */ +static struct peer* client_get_peer(struct turn_client *client, + const pj_sockaddr_in *peer_addr, + pj_uint32_t *hval) +{ + return (struct peer*) + pj_hash_get(client->peer_htable, peer_addr, sizeof(*peer_addr), hval); +} + + +/* + * Add a peer instance to the peer hash table. + */ +static struct peer* client_add_peer(struct turn_client *client, + const pj_sockaddr_in *peer_addr, + unsigned hval) +{ + struct peer *peer; + + peer = PJ_POOL_ZALLOC_T(client->pool, struct peer); + peer->client = client; + pj_memcpy(&peer->addr, peer_addr, sizeof(peer->addr)); + + pj_hash_set(client->pool, client->peer_htable, + &peer->addr, sizeof(peer->addr), hval, peer); + + PJ_LOG(4,(THIS_FILE, "TURN client %s: peer %s:%s:%d added", + client->obj_name, get_tp_type(client->sock_type), + pj_inet_ntoa(peer->addr.sin_addr), + (int)pj_ntohs(peer->addr.sin_port))); + + return peer; +} + + +/* + * Utility to send STUN response message (normally to send error response). + */ +static pj_status_t client_respond(struct turn_client *client, + const pj_stun_msg *msg, + int err_code, + const char *custom_msg, + const pj_sockaddr_t *dst_addr, + int dst_addr_len) +{ + pj_str_t err_msg; + pj_str_t *p_err_msg = NULL; + pj_stun_tx_data *response; + pj_status_t status; + + if (custom_msg) + pj_cstr(&err_msg, custom_msg), p_err_msg = &err_msg; + + status = pj_stun_session_create_response(client->session, msg, + err_code, p_err_msg, + &response); + if (status == PJ_SUCCESS) + status = pj_stun_session_send_msg(client->session, PJ_TRUE, + dst_addr, dst_addr_len, response); + + return status; +} + + +/* + * Handle incoming initial or subsequent Allocate Request. + * This function is called by client_handle_stun_msg() below. + */ +static pj_status_t client_handle_allocate_req(struct turn_client *client, + const pj_stun_msg *msg, + const pj_sockaddr_t *src_addr, + unsigned src_addr_len) +{ + const pj_stun_bandwidth_attr *a_bw; + const pj_stun_lifetime_attr *a_lf; + const pj_stun_req_port_props_attr *a_rpp; + const pj_stun_req_transport_attr *a_rt; + const pj_stun_req_ip_attr *a_rip; + pj_stun_tx_data *response; + pj_sockaddr_in req_addr; + int addr_len; + unsigned req_bw, rpp_bits; + pj_time_val timeout; + pj_status_t status; + + a_bw = (const pj_stun_bandwidth_attr *) + pj_stun_msg_find_attr(msg, PJ_STUN_ATTR_BANDWIDTH, 0); + a_lf = (const pj_stun_lifetime_attr*) + pj_stun_msg_find_attr(msg, PJ_STUN_ATTR_LIFETIME, 0); + a_rpp = (const pj_stun_req_port_props_attr*) + pj_stun_msg_find_attr(msg, PJ_STUN_ATTR_REQ_PORT_PROPS, 0); + a_rt = (const pj_stun_req_transport_attr*) + pj_stun_msg_find_attr(msg, PJ_STUN_ATTR_REQ_TRANSPORT, 0); + a_rip = (const pj_stun_req_ip_attr*) + pj_stun_msg_find_attr(msg, PJ_STUN_ATTR_REQ_IP, 0); + + /* Init requested local address */ + pj_sockaddr_in_init(&req_addr, NULL, 0); + + /* Process BANDWIDTH attribute */ + if (a_bw && a_bw->value > client->tu->max_bw_kbps) { + client_respond(client, msg, PJ_STUN_SC_INSUFFICIENT_CAPACITY, NULL, + src_addr, src_addr_len); + return PJ_SUCCESS; + } else if (a_bw) { + client->bw_kbps = req_bw = a_bw->value; + } else { + req_bw = 0; + client->bw_kbps = client->tu->max_bw_kbps; + } + + /* Process REQUESTED-TRANSPORT attribute */ + if (a_rt && a_rt->value != 0) { + client_respond(client, msg, PJ_STUN_SC_UNSUPP_TRANSPORT_PROTO, NULL, + src_addr, src_addr_len); + return PJ_SUCCESS; + } else if (a_rt) { + client->sock_type = a_rt->value ? PJ_SOCK_STREAM : PJ_SOCK_DGRAM; + } else { + client->sock_type = client->tu->type;; + } + + /* Process REQUESTED-IP attribute */ + if (a_rip && a_rip->addr.addr.sa_family != PJ_AF_INET) { + client_respond(client, msg, PJ_STUN_SC_INVALID_IP_ADDR, NULL, + src_addr, src_addr_len); + return PJ_SUCCESS; + + } else if (a_rip) { + req_addr.sin_addr.s_addr = a_rip->addr.ipv4.sin_addr.s_addr; + } + + /* Process REQUESTED-PORT-PROPS attribute */ + if (a_rpp) { + unsigned port; + + rpp_bits = (a_rpp->value & 0x00030000) >> 16; + port = (a_rpp->value & 0xFFFF); + req_addr.sin_port = pj_htons((pj_uint8_t)port); + } else { + rpp_bits = 0; + } + + /* Process LIFETIME attribute */ + if (a_lf && a_lf->value > client->tu->max_lifetime) { + client->lifetime = client->tu->max_lifetime; + } else if (a_lf) { + client->lifetime = a_lf->value; + } else { + client->lifetime = client->tu->max_lifetime; + } + + /* Allocate socket if we don't have one */ + if (client->key == NULL) { + int err_code; + + PJ_LOG(4,(THIS_FILE, "TURN client %s: received initial Allocate " + "request, requested type:addr:port=%s:%s:%d, rpp " + "bits=%d, bw=%dkbps, lifetime=%d", + client->obj_name, get_tp_type(client->sock_type), + pj_inet_ntoa(req_addr.sin_addr), pj_ntohs(req_addr.sin_port), + rpp_bits, client->bw_kbps, client->lifetime)); + + status = tu_alloc_port(client->tu, client->sock_type, rpp_bits, + &req_addr, &client->sock, &err_code); + if (status != PJ_SUCCESS) { + char errmsg[PJ_ERR_MSG_SIZE]; + + pj_strerror(status, errmsg, sizeof(errmsg)); + PJ_LOG(4,(THIS_FILE, "TURN client %s: error allocating relay port" + ": %s", + client->obj_name, errmsg)); + + client_respond(client, msg, err_code, NULL, + src_addr, src_addr_len); + + return status; + } + + status = client_create_relay(client); + if (status != PJ_SUCCESS) { + client_respond(client, msg, PJ_STUN_SC_SERVER_ERROR, NULL, + src_addr, src_addr_len); + return status; + } + } else { + /* Otherwise check if the port parameter stays the same */ + /* TODO */ + PJ_LOG(4,(THIS_FILE, "TURN client %s: received Allocate refresh, " + "lifetime=%d", + client->obj_name, client->lifetime)); + } + + /* Refresh timer */ + if (client->expiry_timer.id != PJ_FALSE) { + pj_timer_heap_cancel(client->tu->timer_heap, &client->expiry_timer); + client->expiry_timer.id = PJ_FALSE; + } + timeout.sec = client->lifetime; + timeout.msec = 0; + pj_timer_heap_schedule(client->tu->timer_heap, &client->expiry_timer, &timeout); + client->expiry_timer.id = PJ_TRUE; + + /* Done successfully, create and send success response */ + status = pj_stun_session_create_response(client->session, msg, + 0, NULL, &response); + if (status != PJ_SUCCESS) { + return status; + } + + pj_stun_msg_add_uint_attr(response->pool, response->msg, + PJ_STUN_ATTR_BANDWIDTH, client->bw_kbps); + pj_stun_msg_add_uint_attr(response->pool, response->msg, + PJ_STUN_ATTR_LIFETIME, client->lifetime); + pj_stun_msg_add_sockaddr_attr(response->pool, response->msg, + PJ_STUN_ATTR_MAPPED_ADDR, PJ_FALSE, + src_addr, src_addr_len); + pj_stun_msg_add_sockaddr_attr(response->pool, response->msg, + PJ_STUN_ATTR_XOR_MAPPED_ADDR, PJ_TRUE, + src_addr, src_addr_len); + + addr_len = sizeof(req_addr); + pj_sock_getsockname(client->sock, &req_addr, &addr_len); + pj_stun_msg_add_sockaddr_attr(response->pool, response->msg, + PJ_STUN_ATTR_RELAY_ADDR, PJ_FALSE, + &client->alloc_addr, addr_len); + + PJ_LOG(4,(THIS_FILE, "TURN client %s: relay allocated or refreshed, " + "internal address is %s:%s:%d", + client->obj_name, + get_tp_type(client->sock_type), + pj_inet_ntoa(req_addr.sin_addr), + (int)pj_ntohs(req_addr.sin_port))); + + return pj_stun_session_send_msg(client->session, PJ_TRUE, + src_addr, src_addr_len, response); +} + + +/* + * Handle incoming Binding request. + * This function is called by client_handle_stun_msg() below. + */ +static pj_status_t handle_binding_req(pj_stun_session *session, + const pj_stun_msg *msg, + const pj_sockaddr_t *src_addr, + unsigned src_addr_len) +{ + pj_stun_tx_data *tdata; + pj_status_t status; + + /* Create response */ + status = pj_stun_session_create_response(session, msg, 0, NULL, + &tdata); + if (status != PJ_SUCCESS) + return status; + + /* Create MAPPED-ADDRESS attribute */ + pj_stun_msg_add_sockaddr_attr(tdata->pool, tdata->msg, + PJ_STUN_ATTR_MAPPED_ADDR, + PJ_FALSE, + src_addr, src_addr_len); + + /* On the presence of magic, create XOR-MAPPED-ADDRESS attribute */ + if (msg->hdr.magic == PJ_STUN_MAGIC) { + status = + pj_stun_msg_add_sockaddr_attr(tdata->pool, tdata->msg, + PJ_STUN_ATTR_XOR_MAPPED_ADDR, + PJ_TRUE, + src_addr, src_addr_len); + } + + /* Send */ + status = pj_stun_session_send_msg(session, PJ_TRUE, + src_addr, src_addr_len, tdata); + return status; +} + + +/* + * client handling incoming STUN Set Active Destination request + * This function is called by client_handle_stun_msg() below. + */ +static pj_status_t client_handle_sad(struct turn_client *client, + const pj_stun_msg *msg, + const pj_sockaddr_t *src_addr, + unsigned src_addr_len) +{ + pj_stun_remote_addr_attr *a_raddr; + + a_raddr = (pj_stun_remote_addr_attr*) + pj_stun_msg_find_attr(msg, PJ_STUN_ATTR_REMOTE_ADDR, 0); + if (!a_raddr) { + /* Remote active destination needs to be cleared */ + client->active_peer = NULL; + + } else if (a_raddr->addr.addr.sa_family != PJ_AF_INET) { + /* Bad request (not IPv4) */ + client_respond(client, msg, PJ_STUN_SC_BAD_REQUEST, NULL, + src_addr, src_addr_len); + return PJ_SUCCESS; + + } else if (client->active_peer) { + /* Client tries to set new active destination without clearing + * it first. Reject with 439. + */ + client_respond(client, msg, PJ_STUN_SC_TRANSITIONING, NULL, + src_addr, src_addr_len); + return PJ_SUCCESS; + + } else { + struct peer *peer; + pj_uint32_t hval = 0; + + /* Add a new peer/permission if we don't have one for this address */ + peer = client_get_peer(client, &a_raddr->addr.ipv4, &hval); + if (peer==NULL) { + peer = client_add_peer(client, &a_raddr->addr.ipv4, hval); + } + + /* Set active destination */ + client->active_peer = peer; + } + + if (client->active_peer) { + PJ_LOG(4,(THIS_FILE, + "TURN client %s: active destination set to %s:%d", + client->obj_name, + pj_inet_ntoa(client->active_peer->addr.sin_addr), + (int)pj_ntohs(client->active_peer->addr.sin_port))); + } else { + PJ_LOG(4,(THIS_FILE, "TURN client %s: active destination cleared", + client->obj_name)); + } + + /* Respond with successful response */ + client_respond(client, msg, 0, NULL, src_addr, src_addr_len); + + return PJ_SUCCESS; +} + + +/* + * client handling incoming STUN Send Indication + * This function is called by client_handle_stun_msg() below. + */ +static pj_status_t client_handle_send_ind(struct turn_client *client, + const pj_stun_msg *msg) +{ + pj_stun_remote_addr_attr *a_raddr; + pj_stun_data_attr *a_data; + pj_uint32_t hval = 0; + const pj_uint8_t *data; + pj_ssize_t datalen; + + /* Get REMOTE-ADDRESS attribute */ + a_raddr = (pj_stun_remote_addr_attr*) + pj_stun_msg_find_attr(msg, PJ_STUN_ATTR_REMOTE_ADDR, 0); + if (!a_raddr) { + /* REMOTE-ADDRESS not present, discard packet */ + return PJ_SUCCESS; + + } else if (a_raddr->addr.addr.sa_family != PJ_AF_INET) { + /* REMOTE-ADDRESS present but not IPv4, discard packet */ + return PJ_SUCCESS; + + } + + /* Get the DATA attribute */ + a_data = (pj_stun_data_attr*) + pj_stun_msg_find_attr(msg, PJ_STUN_ATTR_DATA, 0); + if (a_data) { + data = (const pj_uint8_t *)a_data->data; + datalen = a_data->length; + + } else if (client->sock_type == PJ_SOCK_STREAM) { + /* Discard if no Data and Allocation type is TCP */ + return PJ_SUCCESS; + + } else { + data = (const pj_uint8_t *)""; + datalen = 0; + } + + /* Add to peer table if necessary */ + if (client_get_peer(client, &a_raddr->addr.ipv4, &hval)==NULL) + client_add_peer(client, &a_raddr->addr.ipv4, hval); + + /* Send the packet */ + pj_ioqueue_sendto(client->key, &client->pkt_write_key, + data, &datalen, 0, + &a_raddr->addr.ipv4, sizeof(a_raddr->addr.ipv4)); + + return PJ_SUCCESS; +} + + +/* + * client handling unknown incoming STUN message. + * This function is called by client_handle_stun_msg() below. + */ +static pj_status_t client_handle_unknown_msg(struct turn_client *client, + const pj_stun_msg *msg, + const pj_sockaddr_t *src_addr, + unsigned src_addr_len) +{ + PJ_LOG(4,(THIS_FILE, "TURN client %s: unhandled %s %s", + client->obj_name, pj_stun_get_method_name(msg->hdr.type), + pj_stun_get_class_name(msg->hdr.type))); + + if (PJ_STUN_IS_REQUEST(msg->hdr.type)) { + return client_respond(client, msg, PJ_STUN_SC_BAD_REQUEST, NULL, + src_addr, src_addr_len); + } else { + /* Ignore */ + return PJ_SUCCESS; + } +} + + +/* + * Main entry for handling STUN messages arriving on the main TURN port, + * for this client + */ +static pj_status_t client_handle_stun_msg(struct turn_client *client, + const pj_stun_msg *msg, + const pj_sockaddr_t *src_addr, + unsigned src_addr_len) +{ + pj_status_t status; + + switch (msg->hdr.type) { + case PJ_STUN_SEND_INDICATION: + status = client_handle_send_ind(client, msg); + break; + + case PJ_STUN_SET_ACTIVE_DESTINATION_REQUEST: + status = client_handle_sad(client, msg, + src_addr, src_addr_len); + break; + + case PJ_STUN_ALLOCATE_REQUEST: + status = client_handle_allocate_req(client, msg, + src_addr, src_addr_len); + break; + + case PJ_STUN_BINDING_REQUEST: + status = handle_binding_req(client->session, msg, + src_addr, src_addr_len); + break; + + default: + status = client_handle_unknown_msg(client, msg, + src_addr, src_addr_len); + break; + } + + return status; +} + + +PJ_INLINE(pj_uint32_t) GET_VAL32(const pj_uint8_t *pdu, unsigned pos) +{ + return (pdu[pos+0] << 24) + + (pdu[pos+1] << 16) + + (pdu[pos+2] << 8) + + (pdu[pos+3]); +} + + +/* + * Handle incoming data from peer + * This function is called by client_on_read_complete() below. + */ +static void client_handle_peer_data(struct turn_client *client, + unsigned bytes_read) +{ + struct peer *peer; + pj_bool_t has_magic_cookie; + pj_status_t status; + + /* Has the sender been registered as peer? */ + peer = client_get_peer(client, &client->pkt_src_addr, NULL); + if (peer == NULL) { + /* Nope. Discard packet */ + PJ_LOG(5,(THIS_FILE, + "TURN client %s: discarded data from %s:%d", + client->obj_name, + pj_inet_ntoa(client->pkt_src_addr.sin_addr), + (int)pj_ntohs(client->pkt_src_addr.sin_port))); + return; + } + + /* Check if packet has STUN magic cookie */ + has_magic_cookie = (GET_VAL32(client->pkt, 4) == PJ_STUN_MAGIC); + + /* If this is the Active Destination and the packet doesn't have + * STUN magic cookie, send the packet to client as is. + */ + if (peer == client->active_peer && !has_magic_cookie) { + pj_stun_usage_sendto(client->tu->usage, client->pkt, bytes_read, 0, + &client->pkt_src_addr, client->pkt_src_addr_len); + } else { + /* Otherwise wrap in Data Indication */ + pj_stun_tx_data *data_ind; + + status = pj_stun_session_create_ind(client->session, + PJ_STUN_DATA_INDICATION, + &data_ind); + if (status != PJ_SUCCESS) + return; + + pj_stun_msg_add_sockaddr_attr(data_ind->pool, data_ind->msg, + PJ_STUN_ATTR_REMOTE_ADDR, PJ_FALSE, + &client->pkt_src_addr, + client->pkt_src_addr_len); + pj_stun_msg_add_binary_attr(data_ind->pool, data_ind->msg, + PJ_STUN_ATTR_DATA, + client->pkt, bytes_read); + + + pj_stun_session_send_msg(client->session, PJ_FALSE, + &client->pkt_src_addr, + client->pkt_src_addr_len, + data_ind); + } +} + + +/* + * This callback is called by the ioqueue when read operation has + * completed on the allocated relay port. + */ +static void client_on_read_complete(pj_ioqueue_key_t *key, + pj_ioqueue_op_key_t *op_key, + pj_ssize_t bytes_read) +{ + enum { MAX_LOOP = 10 }; + struct turn_client *client; + unsigned count; + pj_status_t status; + + PJ_UNUSED_ARG(op_key); + + client = pj_ioqueue_get_user_data(key); + + /* Lock client */ + pj_mutex_lock(client->mutex); + + for (count=0; ; ++count) { + unsigned flags; + + if (bytes_read > 0) { + /* Received data from peer! */ + client_handle_peer_data(client, bytes_read); + + } else if (bytes_read < 0) { + char errmsg[PJ_ERR_MSG_SIZE]; + pj_strerror(-bytes_read, errmsg, sizeof(errmsg)); + PJ_LOG(4,(THIS_FILE, "TURN client %s: error reading data " + "from allocated relay port: %s", + client->obj_name, errmsg)); + } + + bytes_read = sizeof(client->pkt); + flags = (count >= MAX_LOOP) ? PJ_IOQUEUE_ALWAYS_ASYNC : 0; + client->pkt_src_addr_len = sizeof(client->pkt_src_addr); + status = pj_ioqueue_recvfrom(client->key, + &client->pkt_read_key, + client->pkt, &bytes_read, flags, + &client->pkt_src_addr, + &client->pkt_src_addr_len); + if (status == PJ_EPENDING) + break; + } + + /* Unlock client */ + pj_mutex_unlock(client->mutex); +} + + +/* On Allocation timer timeout (i.e. we don't receive new Allocate request + * to refresh the allocation in time) + */ +static void client_on_expired(pj_timer_heap_t *th, pj_timer_entry *e) +{ + struct turn_client *client; + + PJ_UNUSED_ARG(th); + + client = (struct turn_client*) e->user_data; + + PJ_LOG(4,(THIS_FILE, "TURN client %s: allocation timer timeout, " + "destroying client", + client->obj_name)); + client_destroy(client, PJ_SUCCESS); +} + diff --git a/pjnath/src/pjstun-srv-test/usage.c b/pjnath/src/pjstun-srv-test/usage.c new file mode 100644 index 00000000..a8a5c274 --- /dev/null +++ b/pjnath/src/pjstun-srv-test/usage.c @@ -0,0 +1,271 @@ +/* $Id$ */ +/* + * Copyright (C) 2003-2005 Benny Prijono + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +#include "server.h" + +struct worker +{ + pj_ioqueue_op_key_t read_key; + unsigned index; + pj_uint8_t readbuf[4000]; + pj_sockaddr src_addr; + int src_addr_len; +}; + +struct pj_stun_usage +{ + pj_pool_t *pool; + pj_stun_server *srv; + pj_mutex_t *mutex; + pj_stun_usage_cb cb; + int type; + pj_sock_t sock; + pj_ioqueue_key_t *key; + unsigned worker_cnt; + struct worker *worker; + + pj_ioqueue_op_key_t *send_key; + unsigned send_count, send_index; + + pj_bool_t quitting; + void *user_data; +}; + + +static void on_read_complete(pj_ioqueue_key_t *key, + pj_ioqueue_op_key_t *op_key, + pj_ssize_t bytes_read); + +/* + * Create STUN usage. + */ +PJ_DEF(pj_status_t) pj_stun_usage_create( pj_stun_server *srv, + const char *name, + const pj_stun_usage_cb *cb, + int family, + int type, + int protocol, + const pj_sockaddr_t *local_addr, + int addr_len, + pj_stun_usage **p_usage) +{ + pj_stun_server_info *si; + pj_pool_t *pool; + pj_stun_usage *usage; + pj_ioqueue_callback ioqueue_cb; + unsigned i; + pj_status_t status; + + si = pj_stun_server_get_info(srv); + + pool = pj_pool_create(si->pf, name, 4000, 4000, NULL); + usage = PJ_POOL_ZALLOC_T(pool, pj_stun_usage); + usage->pool = pool; + usage->srv = srv; + + status = pj_mutex_create_simple(pool, name, &usage->mutex); + if (status != PJ_SUCCESS) + goto on_error; + + usage->type = type; + status = pj_sock_socket(family, type, protocol, &usage->sock); + if (status != PJ_SUCCESS) + goto on_error; + + status = pj_sock_bind(usage->sock, local_addr, addr_len); + if (status != PJ_SUCCESS) + goto on_error; + + pj_bzero(&ioqueue_cb, sizeof(ioqueue_cb)); + ioqueue_cb.on_read_complete = &on_read_complete; + status = pj_ioqueue_register_sock(usage->pool, si->ioqueue, usage->sock, + usage, &ioqueue_cb, &usage->key); + if (status != PJ_SUCCESS) + goto on_error; + + usage->worker_cnt = si->thread_cnt; + usage->worker = pj_pool_calloc(pool, si->thread_cnt, + sizeof(struct worker)); + for (i=0; ithread_cnt; ++i) { + pj_ioqueue_op_key_init(&usage->worker[i].read_key, + sizeof(usage->worker[i].read_key)); + usage->worker[i].index = i; + } + + usage->send_count = usage->worker_cnt * 2; + usage->send_key = pj_pool_calloc(pool, usage->send_count, + sizeof(pj_ioqueue_op_key_t)); + for (i=0; isend_count; ++i) { + pj_ioqueue_op_key_init(&usage->send_key[i], + sizeof(usage->send_key[i])); + } + + for (i=0; ithread_cnt; ++i) { + pj_ssize_t size; + + size = sizeof(usage->worker[i].readbuf); + usage->worker[i].src_addr_len = sizeof(usage->worker[i].src_addr); + status = pj_ioqueue_recvfrom(usage->key, &usage->worker[i].read_key, + usage->worker[i].readbuf, &size, + PJ_IOQUEUE_ALWAYS_ASYNC, + &usage->worker[i].src_addr, + &usage->worker[i].src_addr_len); + if (status != PJ_EPENDING) + goto on_error; + } + + pj_stun_server_register_usage(srv, usage); + + /* Only after everything has been initialized we copy the callback, + * to prevent callback from being called when we encounter error + * during initialiation (decendant would not expect this). + */ + pj_memcpy(&usage->cb, cb, sizeof(*cb)); + + *p_usage = usage; + return PJ_SUCCESS; + +on_error: + pj_stun_usage_destroy(usage); + return status; +} + + +/** + * Destroy usage. + */ +PJ_DEF(pj_status_t) pj_stun_usage_destroy(pj_stun_usage *usage) +{ + pj_stun_server_unregister_usage(usage->srv, usage); + if (usage->cb.on_destroy) + (*usage->cb.on_destroy)(usage); + + if (usage->key) { + pj_ioqueue_unregister(usage->key); + usage->key = NULL; + usage->sock = PJ_INVALID_SOCKET; + } else if (usage->sock != 0 && usage->sock != PJ_INVALID_SOCKET) { + pj_sock_close(usage->sock); + usage->sock = PJ_INVALID_SOCKET; + } + + if (usage->mutex) { + pj_mutex_destroy(usage->mutex); + usage->mutex = NULL; + } + + if (usage->pool) { + pj_pool_t *pool = usage->pool; + usage->pool = NULL; + pj_pool_release(pool); + } + + return PJ_SUCCESS; +} + + +/** + * Set user data. + */ +PJ_DEF(pj_status_t) pj_stun_usage_set_user_data( pj_stun_usage *usage, + void *user_data) +{ + usage->user_data = user_data; + return PJ_SUCCESS; +} + +/** + * Get user data. + */ +PJ_DEF(void*) pj_stun_usage_get_user_data(pj_stun_usage *usage) +{ + return usage->user_data; +} + + +/** + * Send with the usage. + */ +PJ_DEF(pj_status_t) pj_stun_usage_sendto( pj_stun_usage *usage, + const void *pkt, + pj_size_t pkt_size, + unsigned flags, + const pj_sockaddr_t *dst_addr, + unsigned addr_len) +{ + pj_ssize_t size = pkt_size; + unsigned i, count = usage->send_count, index; + + pj_mutex_lock(usage->mutex); + for (i=0, ++usage->send_index; isend_index) { + if (usage->send_index >= usage->send_count) + usage->send_index = 0; + + if (pj_ioqueue_is_pending(usage->key, &usage->send_key[usage->send_index])==0) { + break; + } + } + + if (i==count) { + pj_mutex_unlock(usage->mutex); + return PJ_EBUSY; + } + + index = usage->send_index; + pj_mutex_unlock(usage->mutex); + + return pj_ioqueue_sendto(usage->key, &usage->send_key[index], + pkt, &size, flags, + dst_addr, addr_len); +} + + +static void on_read_complete(pj_ioqueue_key_t *key, + pj_ioqueue_op_key_t *op_key, + pj_ssize_t bytes_read) +{ + enum { MAX_LOOP = 10 }; + pj_stun_usage *usage = pj_ioqueue_get_user_data(key); + struct worker *worker = (struct worker*) op_key; + unsigned count; + pj_status_t status; + + for (count=0; !usage->quitting; ++count) { + unsigned flags; + + if (bytes_read > 0) { + (*usage->cb.on_rx_data)(usage, worker->readbuf, bytes_read, + &worker->src_addr, worker->src_addr_len); + } else if (bytes_read < 0) { + pj_stun_perror(usage->pool->obj_name, "recv() error", -bytes_read); + } + + if (usage->quitting) + break; + + bytes_read = sizeof(worker->readbuf); + flags = (count >= MAX_LOOP) ? PJ_IOQUEUE_ALWAYS_ASYNC : 0; + worker->src_addr_len = sizeof(worker->src_addr); + status = pj_ioqueue_recvfrom(usage->key, &worker->read_key, + worker->readbuf, &bytes_read, flags, + &worker->src_addr, &worker->src_addr_len); + if (status == PJ_EPENDING) + break; + } +} + -- cgit v1.2.3