Index: pjproject/trunk/pjlib-util/build/pjlib_util.dsp
===================================================================
--- pjproject/trunk/pjlib-util/build/pjlib_util.dsp	(revision 1061)
+++ pjproject/trunk/pjlib-util/build/pjlib_util.dsp	(revision 1062)
@@ -146,24 +146,4 @@
 # 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
@@ -171,8 +151,4 @@
 
 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
@@ -250,33 +226,5 @@
 # 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
Index: pjproject/trunk/pjlib-util/build/pjlib_util.dsw
===================================================================
--- pjproject/trunk/pjlib-util/build/pjlib_util.dsw	(revision 1061)
+++ pjproject/trunk/pjlib-util/build/pjlib_util.dsw	(revision 1062)
@@ -58,40 +58,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:
 
Index: pjproject/trunk/pjlib-util/build/pjlib_util.vcproj
===================================================================
--- pjproject/trunk/pjlib-util/build/pjlib_util.vcproj	(revision 1061)
+++ pjproject/trunk/pjlib-util/build/pjlib_util.vcproj	(revision 1062)
@@ -5,4 +5,5 @@
 	Name="pjlib_util"
 	ProjectGUID="{FE07F272-AE7F-4549-9E9F-EF9B80CB1693}"
+	RootNamespace="pjlib_util"
 	>
 	<Platforms>
@@ -416,24 +417,4 @@
 			</File>
 			<File
-				RelativePath="..\src\pjlib-util\stun_auth.c"
-				>
-			</File>
-			<File
-				RelativePath="..\src\pjlib-util\stun_endpoint.c"
-				>
-			</File>
-			<File
-				RelativePath="..\src\pjlib-util\stun_msg.c"
-				>
-			</File>
-			<File
-				RelativePath="..\src\pjlib-util\stun_msg_dump.c"
-				>
-			</File>
-			<File
-				RelativePath="..\src\pjlib-util\stun_session.c"
-				>
-			</File>
-			<File
 				RelativePath="..\src\pjlib-util\stun_simple.c"
 				>
@@ -441,8 +422,4 @@
 			<File
 				RelativePath="..\src\pjlib-util\stun_simple_client.c"
-				>
-			</File>
-			<File
-				RelativePath="..\src\pjlib-util\stun_transaction.c"
 				>
 			</File>
@@ -557,29 +534,5 @@
 			</File>
 			<File
-				RelativePath="..\include\pjlib-util\stun_auth.h"
-				>
-			</File>
-			<File
-				RelativePath="..\include\pjlib-util\stun_doc.h"
-				>
-			</File>
-			<File
-				RelativePath="..\include\pjlib-util\stun_endpoint.h"
-				>
-			</File>
-			<File
-				RelativePath="..\include\pjlib-util\stun_msg.h"
-				>
-			</File>
-			<File
-				RelativePath="..\include\pjlib-util\stun_session.h"
-				>
-			</File>
-			<File
 				RelativePath="..\include\pjlib-util\stun_simple.h"
-				>
-			</File>
-			<File
-				RelativePath="..\include\pjlib-util\stun_transaction.h"
 				>
 			</File>
Index: pjproject/trunk/pjlib-util/build/pjstun_client.dsp
===================================================================
--- pjproject/trunk/pjlib-util/build/pjstun_client.dsp	(revision 1061)
+++ 	(revision )
@@ -1,102 +1,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
Index: pjproject/trunk/pjlib-util/build/pjstun_srv_test.dsp
===================================================================
--- pjproject/trunk/pjlib-util/build/pjstun_srv_test.dsp	(revision 1061)
+++ 	(revision )
@@ -1,122 +1,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
Index: pjproject/trunk/pjlib-util/build/wince-evc4/pjlib_util_wince.vcp
===================================================================
--- pjproject/trunk/pjlib-util/build/wince-evc4/pjlib_util_wince.vcp	(revision 1061)
+++ pjproject/trunk/pjlib-util/build/wince-evc4/pjlib_util_wince.vcp	(revision 1062)
@@ -364,5 +364,7 @@
 	"..\..\..\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"\
 	
 
@@ -6106,2550 +6108,9 @@
 # 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"
 
 DEP_CPP_STUN_=\
-	"..\..\..\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\types.h"\
-	
-
-!ELSEIF  "$(CFG)" == "pjlib_util_wince - Win32 (WCE emulator) Debug"
-
-DEP_CPP_STUN_=\
-	"..\..\..\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\types.h"\
-	
-
-!ELSEIF  "$(CFG)" == "pjlib_util_wince - Win32 (WCE ARMV4I) Release"
-
-DEP_CPP_STUN_=\
-	"..\..\..\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\types.h"\
-	
-
-!ELSEIF  "$(CFG)" == "pjlib_util_wince - Win32 (WCE ARMV4I) Debug"
-
-DEP_CPP_STUN_=\
-	"..\..\..\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\types.h"\
-	
-
-!ELSEIF  "$(CFG)" == "pjlib_util_wince - Win32 (WCE ARMV4) Release"
-
-DEP_CPP_STUN_=\
-	"..\..\..\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\types.h"\
-	
-
-!ELSEIF  "$(CFG)" == "pjlib_util_wince - Win32 (WCE ARMV4) Debug"
-
-DEP_CPP_STUN_=\
-	"..\..\..\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\types.h"\
-	
-
-!ELSEIF  "$(CFG)" == "pjlib_util_wince - Win32 (WCE ARMV4T) Release"
-
-DEP_CPP_STUN_=\
-	"..\..\..\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\types.h"\
-	
-
-!ELSEIF  "$(CFG)" == "pjlib_util_wince - Win32 (WCE ARMV4T) Debug"
-
-DEP_CPP_STUN_=\
-	"..\..\..\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\types.h"\
-	
-
-!ELSEIF  "$(CFG)" == "pjlib_util_wince - Win32 (WCE x86) Release"
-
-DEP_CPP_STUN_=\
-	"..\..\..\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\types.h"\
-	
-
-!ELSEIF  "$(CFG)" == "pjlib_util_wince - Win32 (WCE x86) Debug"
-
-DEP_CPP_STUN_=\
-	"..\..\..\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\types.h"\
-	
-
-!ENDIF 
-
-# End Source File
-# Begin Source File
-
-SOURCE="..\..\src\pjlib-util\stun_msg.c"
-
-!IF  "$(CFG)" == "pjlib_util_wince - Win32 (WCE emulator) Release"
-
-DEP_CPP_STUN_M=\
-	"..\..\..\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 emulator) Debug"
-
-DEP_CPP_STUN_M=\
-	"..\..\..\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\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\types.h"\
-	
-
-!ELSEIF  "$(CFG)" == "pjlib_util_wince - Win32 (WCE ARMV4I) Release"
-
-DEP_CPP_STUN_M=\
-	"..\..\..\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 ARMV4I) Debug"
-
-DEP_CPP_STUN_M=\
-	"..\..\..\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 ARMV4) Release"
-
-DEP_CPP_STUN_M=\
-	"..\..\..\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 ARMV4) Debug"
-
-DEP_CPP_STUN_M=\
-	"..\..\..\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 ARMV4T) Release"
-
-DEP_CPP_STUN_M=\
-	"..\..\..\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 ARMV4T) Debug"
-
-DEP_CPP_STUN_M=\
-	"..\..\..\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_M=\
-	"..\..\..\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_M=\
-	"..\..\..\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_msg_dump.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"\
-	"..\..\..\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 emulator) 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 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"\
-	"..\..\..\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 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"\
-	"..\..\..\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 ARMV4) 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 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"\
-	"..\..\..\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) 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 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"\
@@ -8713,5 +6174,5 @@
 !ELSEIF  "$(CFG)" == "pjlib_util_wince - Win32 (WCE emulator) Debug"
 
-DEP_CPP_STUN_SI=\
+DEP_CPP_STUN_=\
 	"..\..\..\pjlib\include\pj\addr_resolv.h"\
 	"..\..\..\pjlib\include\pj\array.h"\
@@ -8775,5 +6236,5 @@
 !ELSEIF  "$(CFG)" == "pjlib_util_wince - Win32 (WCE ARMV4I) Release"
 
-DEP_CPP_STUN_SI=\
+DEP_CPP_STUN_=\
 	"..\..\..\pjlib\include\pj\addr_resolv.h"\
 	"..\..\..\pjlib\include\pj\array.h"\
@@ -8837,5 +6298,5 @@
 !ELSEIF  "$(CFG)" == "pjlib_util_wince - Win32 (WCE ARMV4I) Debug"
 
-DEP_CPP_STUN_SI=\
+DEP_CPP_STUN_=\
 	"..\..\..\pjlib\include\pj\addr_resolv.h"\
 	"..\..\..\pjlib\include\pj\array.h"\
@@ -8899,5 +6360,5 @@
 !ELSEIF  "$(CFG)" == "pjlib_util_wince - Win32 (WCE ARMV4) Release"
 
-DEP_CPP_STUN_SI=\
+DEP_CPP_STUN_=\
 	"..\..\..\pjlib\include\pj\addr_resolv.h"\
 	"..\..\..\pjlib\include\pj\array.h"\
@@ -8961,5 +6422,5 @@
 !ELSEIF  "$(CFG)" == "pjlib_util_wince - Win32 (WCE ARMV4) Debug"
 
-DEP_CPP_STUN_SI=\
+DEP_CPP_STUN_=\
 	"..\..\..\pjlib\include\pj\addr_resolv.h"\
 	"..\..\..\pjlib\include\pj\array.h"\
@@ -9023,5 +6484,5 @@
 !ELSEIF  "$(CFG)" == "pjlib_util_wince - Win32 (WCE ARMV4T) Release"
 
-DEP_CPP_STUN_SI=\
+DEP_CPP_STUN_=\
 	"..\..\..\pjlib\include\pj\addr_resolv.h"\
 	"..\..\..\pjlib\include\pj\array.h"\
@@ -9085,5 +6546,5 @@
 !ELSEIF  "$(CFG)" == "pjlib_util_wince - Win32 (WCE ARMV4T) Debug"
 
-DEP_CPP_STUN_SI=\
+DEP_CPP_STUN_=\
 	"..\..\..\pjlib\include\pj\addr_resolv.h"\
 	"..\..\..\pjlib\include\pj\array.h"\
@@ -9147,5 +6608,5 @@
 !ELSEIF  "$(CFG)" == "pjlib_util_wince - Win32 (WCE x86) Release"
 
-DEP_CPP_STUN_SI=\
+DEP_CPP_STUN_=\
 	"..\..\..\pjlib\include\pj\addr_resolv.h"\
 	"..\..\..\pjlib\include\pj\array.h"\
@@ -9209,5 +6670,5 @@
 !ELSEIF  "$(CFG)" == "pjlib_util_wince - Win32 (WCE x86) Debug"
 
-DEP_CPP_STUN_SI=\
+DEP_CPP_STUN_=\
 	"..\..\..\pjlib\include\pj\addr_resolv.h"\
 	"..\..\..\pjlib\include\pj\array.h"\
@@ -9278,5 +6739,5 @@
 !IF  "$(CFG)" == "pjlib_util_wince - Win32 (WCE emulator) Release"
 
-DEP_CPP_STUN_SIM=\
+DEP_CPP_STUN_S=\
 	"..\..\..\pjlib\include\pj\addr_resolv.h"\
 	"..\..\..\pjlib\include\pj\array.h"\
@@ -9340,5 +6801,5 @@
 !ELSEIF  "$(CFG)" == "pjlib_util_wince - Win32 (WCE emulator) Debug"
 
-DEP_CPP_STUN_SIM=\
+DEP_CPP_STUN_S=\
 	"..\..\..\pjlib\include\pj\addr_resolv.h"\
 	"..\..\..\pjlib\include\pj\array.h"\
@@ -9402,5 +6863,5 @@
 !ELSEIF  "$(CFG)" == "pjlib_util_wince - Win32 (WCE ARMV4I) Release"
 
-DEP_CPP_STUN_SIM=\
+DEP_CPP_STUN_S=\
 	"..\..\..\pjlib\include\pj\addr_resolv.h"\
 	"..\..\..\pjlib\include\pj\array.h"\
@@ -9464,5 +6925,5 @@
 !ELSEIF  "$(CFG)" == "pjlib_util_wince - Win32 (WCE ARMV4I) Debug"
 
-DEP_CPP_STUN_SIM=\
+DEP_CPP_STUN_S=\
 	"..\..\..\pjlib\include\pj\addr_resolv.h"\
 	"..\..\..\pjlib\include\pj\array.h"\
@@ -9526,5 +6987,5 @@
 !ELSEIF  "$(CFG)" == "pjlib_util_wince - Win32 (WCE ARMV4) Release"
 
-DEP_CPP_STUN_SIM=\
+DEP_CPP_STUN_S=\
 	"..\..\..\pjlib\include\pj\addr_resolv.h"\
 	"..\..\..\pjlib\include\pj\array.h"\
@@ -9588,5 +7049,5 @@
 !ELSEIF  "$(CFG)" == "pjlib_util_wince - Win32 (WCE ARMV4) Debug"
 
-DEP_CPP_STUN_SIM=\
+DEP_CPP_STUN_S=\
 	"..\..\..\pjlib\include\pj\addr_resolv.h"\
 	"..\..\..\pjlib\include\pj\array.h"\
@@ -9650,5 +7111,5 @@
 !ELSEIF  "$(CFG)" == "pjlib_util_wince - Win32 (WCE ARMV4T) Release"
 
-DEP_CPP_STUN_SIM=\
+DEP_CPP_STUN_S=\
 	"..\..\..\pjlib\include\pj\addr_resolv.h"\
 	"..\..\..\pjlib\include\pj\array.h"\
@@ -9712,5 +7173,5 @@
 !ELSEIF  "$(CFG)" == "pjlib_util_wince - Win32 (WCE ARMV4T) Debug"
 
-DEP_CPP_STUN_SIM=\
+DEP_CPP_STUN_S=\
 	"..\..\..\pjlib\include\pj\addr_resolv.h"\
 	"..\..\..\pjlib\include\pj\array.h"\
@@ -9774,5 +7235,5 @@
 !ELSEIF  "$(CFG)" == "pjlib_util_wince - Win32 (WCE x86) Release"
 
-DEP_CPP_STUN_SIM=\
+DEP_CPP_STUN_S=\
 	"..\..\..\pjlib\include\pj\addr_resolv.h"\
 	"..\..\..\pjlib\include\pj\array.h"\
@@ -9836,5 +7297,5 @@
 !ELSEIF  "$(CFG)" == "pjlib_util_wince - Win32 (WCE x86) Debug"
 
-DEP_CPP_STUN_SIM=\
+DEP_CPP_STUN_S=\
 	"..\..\..\pjlib\include\pj\addr_resolv.h"\
 	"..\..\..\pjlib\include\pj\array.h"\
@@ -9893,651 +7354,4 @@
 	"..\..\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"\
 	
@@ -11074,25 +7888,5 @@
 # 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
Index: pjproject/trunk/pjlib-util/include/pjlib-util.h
===================================================================
--- pjproject/trunk/pjlib-util/include/pjlib-util.h	(revision 1061)
+++ pjproject/trunk/pjlib-util/include/pjlib-util.h	(revision 1062)
@@ -49,12 +49,4 @@
 #include <pjlib-util/xml.h>
 
-/* New STUN */
-#include <pjlib-util/stun_auth.h>
-#include <pjlib-util/stun_endpoint.h>
-#include <pjlib-util/stun_msg.h>
-#include <pjlib-util/stun_session.h>
-#include <pjlib-util/stun_transaction.h>
-/*#include <pjlib-util/turn_client.h>*/
-
 /* Old STUN */
 #include <pjlib-util/stun_simple.h>
Index: pjproject/trunk/pjlib-util/include/pjlib-util/stun_auth.h
===================================================================
--- pjproject/trunk/pjlib-util/include/pjlib-util/stun_auth.h	(revision 1061)
+++ 	(revision )
@@ -1,275 +1,0 @@
-/* $Id$ */
-/* 
- * Copyright (C) 2003-2005 Benny Prijono <benny@prijono.org>
- *
- * 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 <pjlib-util/stun_msg.h>
-
-
-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__ */
-
Index: pjproject/trunk/pjlib-util/include/pjlib-util/stun_doc.h
===================================================================
--- pjproject/trunk/pjlib-util/include/pjlib-util/stun_doc.h	(revision 1061)
+++ 	(revision )
@@ -1,100 +1,0 @@
-/* $Id$ */
-/* 
- * Copyright (C) 2003-2005 Benny Prijono <benny@prijono.org>
- *
- * 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:
- - <A HREF="http://www.ietf.org/internet-drafts/draft-ietf-behave-rfc3489bis-05.txt">
-   draft-ietf-behave-rfc3489bis-05.txt</A>
- - <A HREF="http://www.ietf.org/internet-drafts/draft-ietf-behave-turn-02.txt">
-   draft-ietf-behave-turn-02.txt</A>
-
- 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__ */
-
Index: pjproject/trunk/pjlib-util/include/pjlib-util/stun_endpoint.h
===================================================================
--- pjproject/trunk/pjlib-util/include/pjlib-util/stun_endpoint.h	(revision 1061)
+++ 	(revision )
@@ -1,117 +1,0 @@
-/* $Id$ */
-/* 
- * Copyright (C) 2003-2005 Benny Prijono <benny@prijono.org>
- *
- * 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 <pjlib-util/stun_msg.h>
-
-
-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__ */
-
Index: pjproject/trunk/pjlib-util/include/pjlib-util/stun_msg.h
===================================================================
--- pjproject/trunk/pjlib-util/include/pjlib-util/stun_msg.h	(revision 1061)
+++ 	(revision )
@@ -1,1539 +1,0 @@
-/* $Id$ */
-/* 
- * Copyright (C) 2003-2005 Benny Prijono <benny@prijono.org>
- *
- * 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 <pjlib-util/types.h>
-#include <pj/sock.h>
-
-
-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__ */
-
Index: pjproject/trunk/pjlib-util/include/pjlib-util/stun_session.h
===================================================================
--- pjproject/trunk/pjlib-util/include/pjlib-util/stun_session.h	(revision 1061)
+++ 	(revision )
@@ -1,372 +1,0 @@
-/* $Id$ */
-/* 
- * Copyright (C) 2003-2005 Benny Prijono <benny@prijono.org>
- *
- * 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 <pjlib-util/stun_msg.h>
-#include <pjlib-util/stun_auth.h>
-#include <pjlib-util/stun_endpoint.h>
-#include <pjlib-util/stun_transaction.h>
-#include <pj/list.h>
-#include <pj/timer.h>
-
-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__ */
-
Index: pjproject/trunk/pjlib-util/include/pjlib-util/stun_transaction.h
===================================================================
--- pjproject/trunk/pjlib-util/include/pjlib-util/stun_transaction.h	(revision 1061)
+++ 	(revision )
@@ -1,217 +1,0 @@
-/* $Id$ */
-/* 
- * Copyright (C) 2003-2005 Benny Prijono <benny@prijono.org>
- *
- * 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 <pjlib-util/stun_msg.h>
-#include <pjlib-util/stun_endpoint.h>
-
-
-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__ */
-
Index: pjproject/trunk/pjlib-util/include/pjlib-util/turn_client.h
===================================================================
--- pjproject/trunk/pjlib-util/include/pjlib-util/turn_client.h	(revision 1061)
+++ 	(revision )
@@ -1,132 +1,0 @@
-/* $Id$ */
-/* 
- * Copyright (C) 2003-2005 Benny Prijono <benny@prijono.org>
- *
- * 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 <pjlib-util/stun_msg.h>
-
-
-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__ */
-
Index: pjproject/trunk/pjlib-util/src/pjlib-util/stun_auth.c
===================================================================
--- pjproject/trunk/pjlib-util/src/pjlib-util/stun_auth.c	(revision 1061)
+++ 	(revision )
@@ -1,341 +1,0 @@
-/* $Id$ */
-/* 
- * Copyright (C) 2003-2005 Benny Prijono <benny@prijono.org>
- *
- * 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 <pjlib-util/stun_auth.h>
-#include <pjlib-util/errno.h>
-#include <pjlib-util/hmac_sha1.h>
-#include <pjlib-util/sha1.h>
-#include <pj/assert.h>
-#include <pj/string.h>
-
-
-/* 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;
-}
-
-
Index: pjproject/trunk/pjlib-util/src/pjlib-util/stun_endpoint.c
===================================================================
--- pjproject/trunk/pjlib-util/src/pjlib-util/stun_endpoint.c	(revision 1061)
+++ 	(revision )
@@ -1,69 +1,0 @@
-/* $Id$ */
-/* 
- * Copyright (C) 2003-2005 Benny Prijono <benny@prijono.org>
- *
- * 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 <pjlib-util/stun_endpoint.h>
-#include <pjlib-util/errno.h>
-#include <pj/assert.h>
-#include <pj/pool.h>
-
-
-/*
- * 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;
-}
-
Index: pjproject/trunk/pjlib-util/src/pjlib-util/stun_msg.c
===================================================================
--- pjproject/trunk/pjlib-util/src/pjlib-util/stun_msg.c	(revision 1061)
+++ 	(revision )
@@ -1,2162 +1,0 @@
-/* $Id$ */
-/* 
- * Copyright (C) 2003-2005 Benny Prijono <benny@prijono.org>
- *
- * 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 <pjlib-util/stun_msg.h>
-#include <pjlib-util/crc32.h>
-#include <pjlib-util/errno.h>
-#include <pjlib-util/hmac_sha1.h>
-#include <pjlib-util/md5.h>
-#include <pj/assert.h>
-#include <pj/log.h>
-#include <pj/os.h>
-#include <pj/pool.h>
-#include <pj/rand.h>
-#include <pj/string.h>
-
-#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; i<PJ_ARRAY_SIZE(stun_err_msg_map); ++i) {
-	if (stun_err_msg_map[i].err_code == err_code)
-	    return pj_str((char*)stun_err_msg_map[i].err_msg);
-    }
-    return pj_str(NULL);
-}
-
-
-
-#define INIT_ATTR(a,t,l)    (a)->hdr.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; i<attr_cnt; ++i) {
-	attr->attrs[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; i<attr->attr_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; i<data_len; ++i) {
-	pj_ansi_sprintf(buffer, "%02x", (*data) & 0xFF);
-	buffer += 2;
-	data++;
-    }
-
-    pj_ansi_sprintf(buffer, "\n");
-    buffer++;
-
-    return static_buffer;
-}
-*/
-
-/*
- * Print the message structure to a buffer.
- */
-PJ_DEF(pj_status_t) pj_stun_msg_encode(pj_stun_msg *msg,
-				       pj_uint8_t *buf, unsigned buf_size,
-				       unsigned options,
-				       const pj_str_t *password,
-				       unsigned *p_msg_len)
-{
-    pj_stun_msg_hdr *hdr;
-    pj_uint8_t *start = buf;
-    pj_stun_realm_attr *arealm = NULL;
-    pj_stun_username_attr *auname = NULL;
-    pj_stun_msgint_attr *amsgint = NULL;
-    pj_stun_fingerprint_attr *afingerprint = NULL;
-    unsigned printed = 0;
-    pj_status_t status;
-    unsigned i;
-
-
-    PJ_ASSERT_RETURN(msg && buf && buf_size, PJ_EINVAL);
-
-    PJ_UNUSED_ARG(options);
-    PJ_ASSERT_RETURN(options == 0, PJ_EINVAL);
-
-    /* Copy the message header part and convert the header fields to
-     * network byte order
-     */
-    if (buf_size < sizeof(pj_stun_msg_hdr))
-	return PJ_ETOOSMALL;
-    pj_memcpy(buf, &msg->hdr, 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; i<msg->attr_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; i<msg->attr_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;
-}
-
Index: pjproject/trunk/pjlib-util/src/pjlib-util/stun_msg_dump.c
===================================================================
--- pjproject/trunk/pjlib-util/src/pjlib-util/stun_msg_dump.c	(revision 1061)
+++ 	(revision )
@@ -1,250 +1,0 @@
-/* $Id$ */
-/* 
- * Copyright (C) 2003-2005 Benny Prijono <benny@prijono.org>
- *
- * 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 <pjlib-util/stun_msg.h>
-#include <pjlib-util/errno.h>
-#include <pj/assert.h>
-#include <pj/string.h>
-
-
-#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; i<data_len; ++i) {
-	pj_ansi_sprintf(buffer, "%02x", (*data) & 0xFF);
-	buffer += 2;
-	data++;
-    }
-
-    pj_ansi_sprintf(buffer, "\n");
-    buffer++;
-
-    return data_len * 2 + 8;
-}
-
-static int print_attr(char *buffer, unsigned length,
-		      const pj_stun_attr_hdr *ahdr)
-{
-    char *p = buffer, *end = buffer + length;
-    int len;
-
-    len = pj_ansi_snprintf(p, end-p,
-			   "  %s: length=%d",
-			   pj_stun_get_attr_name(ahdr->type),
-			   (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; j<attr->attr_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; i<msg->attr_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
Index: pjproject/trunk/pjlib-util/src/pjlib-util/stun_session.c
===================================================================
--- pjproject/trunk/pjlib-util/src/pjlib-util/stun_session.c	(revision 1061)
+++ 	(revision )
@@ -1,903 +1,0 @@
-/* $Id$ */
-/* 
- * Copyright (C) 2003-2005 Benny Prijono <benny@prijono.org>
- *
- * 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 <pjlib-util/stun_session.h>
-#include <pjlib.h>
-
-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;
-}
-
-
Index: pjproject/trunk/pjlib-util/src/pjlib-util/stun_transaction.c
===================================================================
--- pjproject/trunk/pjlib-util/src/pjlib-util/stun_transaction.c	(revision 1061)
+++ 	(revision )
@@ -1,315 +1,0 @@
-/* $Id$ */
-/* 
- * Copyright (C) 2003-2005 Benny Prijono <benny@prijono.org>
- *
- * 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 <pjlib-util/stun_transaction.h>
-#include <pjlib-util/errno.h>
-#include <pj/assert.h>
-#include <pj/log.h>
-#include <pj/pool.h>
-#include <pj/string.h>
-#include <pj/timer.h>
-
-
-#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;
-
-}
-
Index: pjproject/trunk/pjlib/build/wince-evc4/pjlib_wince.vcp
===================================================================
--- pjproject/trunk/pjlib/build/wince-evc4/pjlib_wince.vcp	(revision 1061)
+++ pjproject/trunk/pjlib/build/wince-evc4/pjlib_wince.vcp	(revision 1062)
@@ -371,4 +371,6 @@
 	"..\..\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"\
@@ -780,4 +782,6 @@
 	"..\..\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"\
@@ -1159,4 +1163,6 @@
 	"..\..\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"\
@@ -1405,4 +1411,6 @@
 	"..\..\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"\
@@ -1667,4 +1675,6 @@
 	"..\..\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"\
@@ -2039,4 +2049,6 @@
 	"..\..\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"\
@@ -2372,4 +2384,6 @@
 	"..\..\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"\
@@ -2652,4 +2666,6 @@
 	"..\..\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"\
@@ -2988,4 +3004,6 @@
 	"..\..\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"\
@@ -3278,4 +3296,6 @@
 	"..\..\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"\
@@ -3644,4 +3664,6 @@
 	"..\..\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"\
@@ -4028,4 +4050,6 @@
 	"..\..\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"\
@@ -4449,4 +4473,6 @@
 	"..\..\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"\
@@ -4895,4 +4921,6 @@
 	"..\..\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"\
@@ -5162,4 +5190,6 @@
 	"..\..\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"\
@@ -5568,4 +5598,6 @@
 	"..\..\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"\
@@ -5933,4 +5965,6 @@
 	"..\..\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"\
@@ -6213,4 +6247,6 @@
 	"..\..\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"\
@@ -6655,4 +6691,6 @@
 	"..\..\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"\
@@ -7043,4 +7081,6 @@
 	"..\..\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"\
@@ -7336,4 +7376,6 @@
 	"..\..\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"\
@@ -7584,4 +7626,6 @@
 	"..\..\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"\
@@ -7863,4 +7907,6 @@
 	"..\..\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"\
@@ -8290,4 +8336,6 @@
 	"..\..\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"\
@@ -8837,4 +8885,6 @@
 	"..\..\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"\
@@ -9228,5 +9278,7 @@
 	"..\..\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"\
@@ -9601,4 +9653,6 @@
 	"..\..\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"\
@@ -9855,4 +9909,6 @@
 	"..\..\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"\
@@ -10124,4 +10180,6 @@
 	"..\..\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"\
@@ -10536,4 +10594,6 @@
 	"..\..\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"\
@@ -10843,4 +10903,6 @@
 	"..\..\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"\
@@ -11237,4 +11299,6 @@
 	"..\..\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"\
@@ -11631,4 +11695,6 @@
 	"..\..\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"\
@@ -11886,4 +11952,6 @@
 	"..\..\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"\
@@ -12326,4 +12394,8 @@
 # Begin Source File
 
+SOURCE=..\..\include\pj\config_site_sample.h
+# End Source File
+# Begin Source File
+
 SOURCE=..\..\include\pj\ctype.h
 # End Source File
Index: pjproject/trunk/pjnath/build/pjnath.dsw
===================================================================
--- pjproject/trunk/pjnath/build/pjnath.dsw	(revision 1062)
+++ pjproject/trunk/pjnath/build/pjnath.dsw	(revision 1062)
@@ -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>
+{{{
+}}}
+
+###############################################################################
+
Index: pjproject/trunk/pjnath/build/pjstun_client.dsp
===================================================================
--- pjproject/trunk/pjnath/build/pjstun_client.dsp	(revision 1062)
+++ pjproject/trunk/pjnath/build/pjstun_client.dsp	(revision 1062)
@@ -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
Index: pjproject/trunk/pjnath/build/pjstun_srv_test.dsp
===================================================================
--- pjproject/trunk/pjnath/build/pjstun_srv_test.dsp	(revision 1062)
+++ pjproject/trunk/pjnath/build/pjstun_srv_test.dsp	(revision 1062)
@@ -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
Index: pjproject/trunk/pjnath/include/pjnath/stun_auth.h
===================================================================
--- pjproject/trunk/pjnath/include/pjnath/stun_auth.h	(revision 1062)
+++ pjproject/trunk/pjnath/include/pjnath/stun_auth.h	(revision 1062)
@@ -0,0 +1,275 @@
+/* $Id$ */
+/* 
+ * Copyright (C) 2003-2005 Benny Prijono <benny@prijono.org>
+ *
+ * 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 <pjlib-util/stun_msg.h>
+
+
+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__ */
+
Index: pjproject/trunk/pjnath/include/pjnath/stun_doc.h
===================================================================
--- pjproject/trunk/pjnath/include/pjnath/stun_doc.h	(revision 1062)
+++ pjproject/trunk/pjnath/include/pjnath/stun_doc.h	(revision 1062)
@@ -0,0 +1,100 @@
+/* $Id$ */
+/* 
+ * Copyright (C) 2003-2005 Benny Prijono <benny@prijono.org>
+ *
+ * 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:
+ - <A HREF="http://www.ietf.org/internet-drafts/draft-ietf-behave-rfc3489bis-05.txt">
+   draft-ietf-behave-rfc3489bis-05.txt</A>
+ - <A HREF="http://www.ietf.org/internet-drafts/draft-ietf-behave-turn-02.txt">
+   draft-ietf-behave-turn-02.txt</A>
+
+ 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__ */
+
Index: pjproject/trunk/pjnath/include/pjnath/stun_endpoint.h
===================================================================
--- pjproject/trunk/pjnath/include/pjnath/stun_endpoint.h	(revision 1062)
+++ pjproject/trunk/pjnath/include/pjnath/stun_endpoint.h	(revision 1062)
@@ -0,0 +1,117 @@
+/* $Id$ */
+/* 
+ * Copyright (C) 2003-2005 Benny Prijono <benny@prijono.org>
+ *
+ * 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 <pjlib-util/stun_msg.h>
+
+
+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__ */
+
Index: pjproject/trunk/pjnath/include/pjnath/stun_msg.h
===================================================================
--- pjproject/trunk/pjnath/include/pjnath/stun_msg.h	(revision 1062)
+++ pjproject/trunk/pjnath/include/pjnath/stun_msg.h	(revision 1062)
@@ -0,0 +1,1539 @@
+/* $Id$ */
+/* 
+ * Copyright (C) 2003-2005 Benny Prijono <benny@prijono.org>
+ *
+ * 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 <pjlib-util/types.h>
+#include <pj/sock.h>
+
+
+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__ */
+
Index: pjproject/trunk/pjnath/include/pjnath/stun_session.h
===================================================================
--- pjproject/trunk/pjnath/include/pjnath/stun_session.h	(revision 1062)
+++ pjproject/trunk/pjnath/include/pjnath/stun_session.h	(revision 1062)
@@ -0,0 +1,372 @@
+/* $Id$ */
+/* 
+ * Copyright (C) 2003-2005 Benny Prijono <benny@prijono.org>
+ *
+ * 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 <pjlib-util/stun_msg.h>
+#include <pjlib-util/stun_auth.h>
+#include <pjlib-util/stun_endpoint.h>
+#include <pjlib-util/stun_transaction.h>
+#include <pj/list.h>
+#include <pj/timer.h>
+
+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__ */
+
Index: pjproject/trunk/pjnath/include/pjnath/stun_transaction.h
===================================================================
--- pjproject/trunk/pjnath/include/pjnath/stun_transaction.h	(revision 1062)
+++ pjproject/trunk/pjnath/include/pjnath/stun_transaction.h	(revision 1062)
@@ -0,0 +1,217 @@
+/* $Id$ */
+/* 
+ * Copyright (C) 2003-2005 Benny Prijono <benny@prijono.org>
+ *
+ * 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 <pjlib-util/stun_msg.h>
+#include <pjlib-util/stun_endpoint.h>
+
+
+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__ */
+
Index: pjproject/trunk/pjnath/include/pjnath/turn_client.h
===================================================================
--- pjproject/trunk/pjnath/include/pjnath/turn_client.h	(revision 1062)
+++ pjproject/trunk/pjnath/include/pjnath/turn_client.h	(revision 1062)
@@ -0,0 +1,132 @@
+/* $Id$ */
+/* 
+ * Copyright (C) 2003-2005 Benny Prijono <benny@prijono.org>
+ *
+ * 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 <pjlib-util/stun_msg.h>
+
+
+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__ */
+
Index: pjproject/trunk/pjnath/src/pjnath/stun_auth.c
===================================================================
--- pjproject/trunk/pjnath/src/pjnath/stun_auth.c	(revision 1062)
+++ pjproject/trunk/pjnath/src/pjnath/stun_auth.c	(revision 1062)
@@ -0,0 +1,341 @@
+/* $Id$ */
+/* 
+ * Copyright (C) 2003-2005 Benny Prijono <benny@prijono.org>
+ *
+ * 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 <pjlib-util/stun_auth.h>
+#include <pjlib-util/errno.h>
+#include <pjlib-util/hmac_sha1.h>
+#include <pjlib-util/sha1.h>
+#include <pj/assert.h>
+#include <pj/string.h>
+
+
+/* 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;
+}
+
+
Index: pjproject/trunk/pjnath/src/pjnath/stun_endpoint.c
===================================================================
--- pjproject/trunk/pjnath/src/pjnath/stun_endpoint.c	(revision 1062)
+++ pjproject/trunk/pjnath/src/pjnath/stun_endpoint.c	(revision 1062)
@@ -0,0 +1,69 @@
+/* $Id$ */
+/* 
+ * Copyright (C) 2003-2005 Benny Prijono <benny@prijono.org>
+ *
+ * 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 <pjlib-util/stun_endpoint.h>
+#include <pjlib-util/errno.h>
+#include <pj/assert.h>
+#include <pj/pool.h>
+
+
+/*
+ * 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;
+}
+
Index: pjproject/trunk/pjnath/src/pjnath/stun_msg.c
===================================================================
--- pjproject/trunk/pjnath/src/pjnath/stun_msg.c	(revision 1062)
+++ pjproject/trunk/pjnath/src/pjnath/stun_msg.c	(revision 1062)
@@ -0,0 +1,2162 @@
+/* $Id$ */
+/* 
+ * Copyright (C) 2003-2005 Benny Prijono <benny@prijono.org>
+ *
+ * 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 <pjlib-util/stun_msg.h>
+#include <pjlib-util/crc32.h>
+#include <pjlib-util/errno.h>
+#include <pjlib-util/hmac_sha1.h>
+#include <pjlib-util/md5.h>
+#include <pj/assert.h>
+#include <pj/log.h>
+#include <pj/os.h>
+#include <pj/pool.h>
+#include <pj/rand.h>
+#include <pj/string.h>
+
+#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; i<PJ_ARRAY_SIZE(stun_err_msg_map); ++i) {
+	if (stun_err_msg_map[i].err_code == err_code)
+	    return pj_str((char*)stun_err_msg_map[i].err_msg);
+    }
+    return pj_str(NULL);
+}
+
+
+
+#define INIT_ATTR(a,t,l)    (a)->hdr.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; i<attr_cnt; ++i) {
+	attr->attrs[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; i<attr->attr_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; i<data_len; ++i) {
+	pj_ansi_sprintf(buffer, "%02x", (*data) & 0xFF);
+	buffer += 2;
+	data++;
+    }
+
+    pj_ansi_sprintf(buffer, "\n");
+    buffer++;
+
+    return static_buffer;
+}
+*/
+
+/*
+ * Print the message structure to a buffer.
+ */
+PJ_DEF(pj_status_t) pj_stun_msg_encode(pj_stun_msg *msg,
+				       pj_uint8_t *buf, unsigned buf_size,
+				       unsigned options,
+				       const pj_str_t *password,
+				       unsigned *p_msg_len)
+{
+    pj_stun_msg_hdr *hdr;
+    pj_uint8_t *start = buf;
+    pj_stun_realm_attr *arealm = NULL;
+    pj_stun_username_attr *auname = NULL;
+    pj_stun_msgint_attr *amsgint = NULL;
+    pj_stun_fingerprint_attr *afingerprint = NULL;
+    unsigned printed = 0;
+    pj_status_t status;
+    unsigned i;
+
+
+    PJ_ASSERT_RETURN(msg && buf && buf_size, PJ_EINVAL);
+
+    PJ_UNUSED_ARG(options);
+    PJ_ASSERT_RETURN(options == 0, PJ_EINVAL);
+
+    /* Copy the message header part and convert the header fields to
+     * network byte order
+     */
+    if (buf_size < sizeof(pj_stun_msg_hdr))
+	return PJ_ETOOSMALL;
+    pj_memcpy(buf, &msg->hdr, 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; i<msg->attr_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; i<msg->attr_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;
+}
+
Index: pjproject/trunk/pjnath/src/pjnath/stun_msg_dump.c
===================================================================
--- pjproject/trunk/pjnath/src/pjnath/stun_msg_dump.c	(revision 1062)
+++ pjproject/trunk/pjnath/src/pjnath/stun_msg_dump.c	(revision 1062)
@@ -0,0 +1,250 @@
+/* $Id$ */
+/* 
+ * Copyright (C) 2003-2005 Benny Prijono <benny@prijono.org>
+ *
+ * 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 <pjlib-util/stun_msg.h>
+#include <pjlib-util/errno.h>
+#include <pj/assert.h>
+#include <pj/string.h>
+
+
+#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; i<data_len; ++i) {
+	pj_ansi_sprintf(buffer, "%02x", (*data) & 0xFF);
+	buffer += 2;
+	data++;
+    }
+
+    pj_ansi_sprintf(buffer, "\n");
+    buffer++;
+
+    return data_len * 2 + 8;
+}
+
+static int print_attr(char *buffer, unsigned length,
+		      const pj_stun_attr_hdr *ahdr)
+{
+    char *p = buffer, *end = buffer + length;
+    int len;
+
+    len = pj_ansi_snprintf(p, end-p,
+			   "  %s: length=%d",
+			   pj_stun_get_attr_name(ahdr->type),
+			   (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; j<attr->attr_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; i<msg->attr_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
Index: pjproject/trunk/pjnath/src/pjnath/stun_session.c
===================================================================
--- pjproject/trunk/pjnath/src/pjnath/stun_session.c	(revision 1062)
+++ pjproject/trunk/pjnath/src/pjnath/stun_session.c	(revision 1062)
@@ -0,0 +1,903 @@
+/* $Id$ */
+/* 
+ * Copyright (C) 2003-2005 Benny Prijono <benny@prijono.org>
+ *
+ * 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 <pjlib-util/stun_session.h>
+#include <pjlib.h>
+
+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;
+}
+
+
Index: pjproject/trunk/pjnath/src/pjnath/stun_transaction.c
===================================================================
--- pjproject/trunk/pjnath/src/pjnath/stun_transaction.c	(revision 1062)
+++ pjproject/trunk/pjnath/src/pjnath/stun_transaction.c	(revision 1062)
@@ -0,0 +1,315 @@
+/* $Id$ */
+/* 
+ * Copyright (C) 2003-2005 Benny Prijono <benny@prijono.org>
+ *
+ * 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 <pjlib-util/stun_transaction.h>
+#include <pjlib-util/errno.h>
+#include <pj/assert.h>
+#include <pj/log.h>
+#include <pj/pool.h>
+#include <pj/string.h>
+#include <pj/timer.h>
+
+
+#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;
+
+}
+
Index: pjproject/trunk/pjnath/src/pjstun-client/client_main.c
===================================================================
--- pjproject/trunk/pjnath/src/pjstun-client/client_main.c	(revision 1062)
+++ pjproject/trunk/pjnath/src/pjstun-client/client_main.c	(revision 1062)
@@ -0,0 +1,680 @@
+/* $Id$ */
+/* 
+ * Copyright (C) 2003-2005 Benny Prijono <benny@prijono.org>
+ *
+ * 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 <pjlib-util.h>
+#include <pjlib.h>
+
+
+#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;
+}
+
Index: pjproject/trunk/pjnath/src/pjstun-srv-test/bind_usage.c
===================================================================
--- pjproject/trunk/pjnath/src/pjstun-srv-test/bind_usage.c	(revision 1062)
+++ pjproject/trunk/pjnath/src/pjstun-srv-test/bind_usage.c	(revision 1062)
@@ -0,0 +1,206 @@
+/* $Id$ */
+/* 
+ * Copyright (C) 2003-2005 Benny Prijono <benny@prijono.org>
+ *
+ * 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);
+}
Index: pjproject/trunk/pjnath/src/pjstun-srv-test/main.c
===================================================================
--- pjproject/trunk/pjnath/src/pjstun-srv-test/main.c	(revision 1062)
+++ pjproject/trunk/pjnath/src/pjstun-srv-test/main.c	(revision 1062)
@@ -0,0 +1,146 @@
+/* $Id$ */
+/* 
+ * Copyright (C) 2003-2005 Benny Prijono <benny@prijono.org>
+ *
+ * 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;
+}
Index: pjproject/trunk/pjnath/src/pjstun-srv-test/server.c
===================================================================
--- pjproject/trunk/pjnath/src/pjstun-srv-test/server.c	(revision 1062)
+++ pjproject/trunk/pjnath/src/pjstun-srv-test/server.c	(revision 1062)
@@ -0,0 +1,185 @@
+/* $Id$ */
+/* 
+ * Copyright (C) 2003-2005 Benny Prijono <benny@prijono.org>
+ *
+ * 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; i<thread_cnt; ++i) {
+	status = pj_thread_create(pool, "worker%p", &worker_thread,
+				  srv, 0, 0, &srv->threads[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; i<PJ_ARRAY_SIZE(srv->usage); ++i) {
+	if (srv->usage[i] == usage)
+	    return PJ_SUCCESS;
+    }
+
+    for (i=0; i<PJ_ARRAY_SIZE(srv->usage); ++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; i<PJ_ARRAY_SIZE(srv->usage); ++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; i<PJ_ARRAY_SIZE(srv->usage); ++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; i<srv->si.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;
+}
+
+
Index: pjproject/trunk/pjnath/src/pjstun-srv-test/server.h
===================================================================
--- pjproject/trunk/pjnath/src/pjstun-srv-test/server.h	(revision 1062)
+++ pjproject/trunk/pjnath/src/pjstun-srv-test/server.h	(revision 1062)
@@ -0,0 +1,135 @@
+/* $Id$ */
+/* 
+ * Copyright (C) 2003-2005 Benny Prijono <benny@prijono.org>
+ *
+ * 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 <pjlib-util.h>
+#include <pjlib.h>
+
+
+/** 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__ */
+
+
Index: pjproject/trunk/pjnath/src/pjstun-srv-test/turn_usage.c
===================================================================
--- pjproject/trunk/pjnath/src/pjstun-srv-test/turn_usage.c	(revision 1062)
+++ pjproject/trunk/pjnath/src/pjstun-srv-test/turn_usage.c	(revision 1062)
@@ -0,0 +1,1408 @@
+/* $Id$ */
+/* 
+ * Copyright (C) 2003-2005 Benny Prijono <benny@prijono.org>
+ *
+ * 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; retry<RETRY && sock == PJ_INVALID_SOCKET; ++retry) {
+	    switch (rpp_bits) {
+	    case 1:
+		if ((tu->next_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);
+}
+
Index: pjproject/trunk/pjnath/src/pjstun-srv-test/usage.c
===================================================================
--- pjproject/trunk/pjnath/src/pjstun-srv-test/usage.c	(revision 1062)
+++ pjproject/trunk/pjnath/src/pjstun-srv-test/usage.c	(revision 1062)
@@ -0,0 +1,271 @@
+/* $Id$ */
+/* 
+ * Copyright (C) 2003-2005 Benny Prijono <benny@prijono.org>
+ *
+ * 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; i<si->thread_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; i<usage->send_count; ++i) {
+	pj_ioqueue_op_key_init(&usage->send_key[i], 
+			       sizeof(usage->send_key[i]));
+    }
+
+    for (i=0; i<si->thread_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; i<count; ++i, ++usage->send_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;
+    }
+}
+
