Changed pj_sockaddr structure and added pjnath project for ICE/STUN stuffs

git-svn-id: https://svn.pjsip.org/repos/pjproject/trunk@1080 74dad513-b988-da41-8d7b-12977e46ad98
diff --git a/pjlib/include/pj/errno.h b/pjlib/include/pj/errno.h
index 6ff304d..71ba69f 100644
--- a/pjlib/include/pj/errno.h
+++ b/pjlib/include/pj/errno.h
@@ -341,6 +341,7 @@
  *  - PJMEDIA_ERRNO_START	(PJ_ERRNO_START_USER + PJ_ERRNO_SPACE_SIZE)
  *  - PJSIP_SIMPLE_ERRNO_START	(PJ_ERRNO_START_USER + PJ_ERRNO_SPACE_SIZE*2)
  *  - PJLIB_UTIL_ERRNO_START	(PJ_ERRNO_START_USER + PJ_ERRNO_SPACE_SIZE*3)
+ *  - PJNATH_ERRNO_START	(PJ_ERRNO_START_USER + PJ_ERRNO_SPACE_SIZE*4)
  */
 
 
diff --git a/pjlib/include/pj/sock.h b/pjlib/include/pj/sock.h
index e7bcee1..d2da570 100644
--- a/pjlib/include/pj/sock.h
+++ b/pjlib/include/pj/sock.h
@@ -175,26 +175,6 @@
  */
 #define PJ_INVALID_SOCKET   (-1)
 
-/**
- * Structure describing a generic socket address.
- * If PJ_SOCKADDR_HAS_LEN is not zero, then sa_zero_len member is added
- * to this struct. As far the application is concerned, the value of
- * this member will always be zero. Internally, PJLIB may modify the value
- * before calling OS socket API, and reset the value back to zero before
- * returning the struct to application.
- */
-typedef struct pj_sockaddr
-{
-#if defined(PJ_SOCKADDR_HAS_LEN) && PJ_SOCKADDR_HAS_LEN!=0
-    pj_uint8_t  sa_zero_len;
-    pj_uint8_t  sa_family;
-#else
-    pj_uint16_t	sa_family;	/**< Common data: address family.   */
-#endif
-    char	sa_data[14];	/**< Address data.		    */
-} pj_sockaddr;
-
-
 #undef s_addr
 
 /**
@@ -276,6 +256,36 @@
 } pj_sockaddr_in6;
 
 
+/**
+ * This structure describes common attributes found in transport addresses.
+ * If PJ_SOCKADDR_HAS_LEN is not zero, then sa_zero_len member is added
+ * to this struct. As far the application is concerned, the value of
+ * this member will always be zero. Internally, PJLIB may modify the value
+ * before calling OS socket API, and reset the value back to zero before
+ * returning the struct to application.
+ */
+typedef struct pj_addr_hdr
+{
+#if defined(PJ_SOCKADDR_HAS_LEN) && PJ_SOCKADDR_HAS_LEN!=0
+    pj_uint8_t  sa_zero_len;
+    pj_uint8_t  sa_family;
+#else
+    pj_uint16_t	sa_family;	/**< Common data: address family.   */
+#endif
+} pj_addr_hdr;
+
+
+/**
+ * This union describes a generic socket address.
+ */
+typedef union pj_sockaddr
+{
+    pj_addr_hdr	    addr;	/**< Generic transport address.	    */
+    pj_sockaddr_in  ipv4;	/**< IPv4 transport address.	    */
+    pj_sockaddr_in6 ipv6;	/**< IPv6 transport address.	    */
+} pj_sockaddr;
+
+
 /*****************************************************************************
  *
  * SOCKET ADDRESS MANIPULATION.
diff --git a/pjmedia/build/wince-evc4/pjmedia_wince.vcp b/pjmedia/build/wince-evc4/pjmedia_wince.vcp
index d90b39f..69c3d04 100644
--- a/pjmedia/build/wince-evc4/pjmedia_wince.vcp
+++ b/pjmedia/build/wince-evc4/pjmedia_wince.vcp
@@ -76,8 +76,8 @@
 # PROP BASE Target_Dir ""
 # PROP Use_MFC 0
 # PROP Use_Debug_Libraries 1
-# PROP Output_Dir "output/pjmedia_emulatorDbg"
-# PROP Intermediate_Dir "output/pjmedia_emulatorDbg"
+# PROP Output_Dir "./output/pjmedia_emulatorDbg"
+# PROP Intermediate_Dir "./output/pjmedia_emulatorDbg"
 # PROP CPU_ID "{32E52003-403E-442D-BE48-DE10F8C6131D}"
 # PROP Platform_ID "{8A9A2F80-6887-11D3-842E-005004848CBA}"
 # PROP Target_Dir ""
diff --git a/pjnath/build/pjnath.dsp b/pjnath/build/pjnath.dsp
new file mode 100644
index 0000000..74af4bf
--- /dev/null
+++ b/pjnath/build/pjnath.dsp
@@ -0,0 +1,174 @@
+# Microsoft Developer Studio Project File - Name="pjnath" - Package Owner=<4>

+# Microsoft Developer Studio Generated Build File, Format Version 6.00

+# ** DO NOT EDIT **

+

+# TARGTYPE "Win32 (x86) Static Library" 0x0104

+

+CFG=pjnath - 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 "pjnath.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 "pjnath.mak" CFG="pjnath - Win32 Debug"

+!MESSAGE 

+!MESSAGE Possible choices for configuration are:

+!MESSAGE 

+!MESSAGE "pjnath - Win32 Release" (based on "Win32 (x86) Static Library")

+!MESSAGE "pjnath - Win32 Debug" (based on "Win32 (x86) Static Library")

+!MESSAGE 

+

+# Begin Project

+# PROP AllowPerConfigDependencies 0

+# PROP Scc_ProjName ""

+# PROP Scc_LocalPath ""

+CPP=cl.exe

+RSC=rc.exe

+

+!IF  "$(CFG)" == "pjnath - Win32 Release"

+

+# PROP BASE Use_MFC 0

+# PROP BASE Use_Debug_Libraries 0

+# PROP BASE Output_Dir "./output/pjnath-i386-win32-vc6-release"

+# PROP BASE Intermediate_Dir "./output/pjnath-i386-win32-vc6-release"

+# PROP BASE Target_Dir ""

+# PROP Use_MFC 0

+# PROP Use_Debug_Libraries 0

+# PROP Output_Dir "./output/pjnath-i386-win32-vc6-release"

+# PROP Intermediate_Dir "./output/pjnath-i386-win32-vc6-release"

+# PROP Target_Dir ""

+# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /YX /FD /c

+# ADD CPP /nologo /MD /W4 /GX /Zi /O2 /Ob2 /I "../include" /I "../../pjlib/include" /D "NDEBUG" /D "WIN32" /D "_MBCS" /D "_LIB" /D PJ_WIN32=1 /D PJ_M_I386=1 /FR /FD /c

+# SUBTRACT CPP /YX

+# ADD BASE RSC /l 0x409 /d "NDEBUG"

+# ADD RSC /l 0x409 /d "NDEBUG"

+BSC32=bscmake.exe

+# ADD BASE BSC32 /nologo

+# ADD BSC32 /nologo

+LIB32=link.exe -lib

+# ADD BASE LIB32 /nologo

+# ADD LIB32 /nologo /out:"../lib/pjnath-i386-win32-vc6-release.lib"

+

+!ELSEIF  "$(CFG)" == "pjnath - Win32 Debug"

+

+# PROP BASE Use_MFC 0

+# PROP BASE Use_Debug_Libraries 1

+# PROP BASE Output_Dir "./output/pjnath-i386-win32-vc6-debug"

+# PROP BASE Intermediate_Dir "./output/pjnath-i386-win32-vc6-debug"

+# PROP BASE Target_Dir ""

+# PROP Use_MFC 0

+# PROP Use_Debug_Libraries 1

+# PROP Output_Dir "./output/pjnath-i386-win32-vc6-debug"

+# PROP Intermediate_Dir "./output/pjnath-i386-win32-vc6-debug"

+# PROP Target_Dir ""

+# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /YX /FD /GZ /c

+# ADD CPP /nologo /MTd /W4 /Gm /GX /ZI /Od /I "../include" /I "../../pjlib/include" /D "_DEBUG" /D "WIN32" /D "_MBCS" /D "_LIB" /D PJ_WIN32=1 /D PJ_M_I386=1 /FR /FD /GZ /c

+# SUBTRACT CPP /YX

+# ADD BASE RSC /l 0x409 /d "_DEBUG"

+# ADD RSC /l 0x409 /d "_DEBUG"

+BSC32=bscmake.exe

+# ADD BASE BSC32 /nologo

+# ADD BSC32 /nologo

+LIB32=link.exe -lib

+# ADD BASE LIB32 /nologo

+# ADD LIB32 /nologo /out:"../lib/pjnath-i386-win32-vc6-debug.lib"

+

+!ENDIF 

+

+# Begin Target

+

+# Name "pjnath - Win32 Release"

+# Name "pjnath - Win32 Debug"

+# Begin Group "Source Files"

+

+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"

+# Begin Source File

+

+SOURCE=..\src\pjnath\errno.c

+# End Source File

+# Begin Source File

+

+SOURCE=..\src\pjnath\ice.c

+# End Source File

+# Begin Source File

+

+SOURCE=..\src\pjnath\stun_auth.c

+# End Source File

+# Begin Source File

+

+SOURCE=..\src\pjnath\stun_endpoint.c

+# End Source File

+# Begin Source File

+

+SOURCE=..\src\pjnath\stun_msg.c

+# End Source File

+# Begin Source File

+

+SOURCE=..\src\pjnath\stun_msg_dump.c

+# End Source File

+# Begin Source File

+

+SOURCE=..\src\pjnath\stun_session.c

+# End Source File

+# Begin Source File

+

+SOURCE=..\src\pjnath\stun_transaction.c

+# End Source File

+# End Group

+# Begin Group "Header Files"

+

+# PROP Default_Filter "h;hpp;hxx;hm;inl"

+# Begin Source File

+

+SOURCE=..\include\pjnath\config.h

+# End Source File

+# Begin Source File

+

+SOURCE=..\include\pjnath\errno.h

+# End Source File

+# Begin Source File

+

+SOURCE=..\include\pjnath\ice.h

+# End Source File

+# Begin Source File

+

+SOURCE=..\include\pjnath.h

+# End Source File

+# Begin Source File

+

+SOURCE=..\include\pjnath\stun_auth.h

+# End Source File

+# Begin Source File

+

+SOURCE=..\include\pjnath\stun_doc.h

+# End Source File

+# Begin Source File

+

+SOURCE=..\include\pjnath\stun_endpoint.h

+# End Source File

+# Begin Source File

+

+SOURCE=..\include\pjnath\stun_msg.h

+# End Source File

+# Begin Source File

+

+SOURCE=..\include\pjnath\stun_session.h

+# End Source File

+# Begin Source File

+

+SOURCE=..\include\pjnath\stun_transaction.h

+# End Source File

+# Begin Source File

+

+SOURCE=..\include\pjnath\turn_client.h

+# End Source File

+# Begin Source File

+

+SOURCE=..\include\pjnath\types.h

+# End Source File

+# End Group

+# End Target

+# End Project

diff --git a/pjnath/build/pjnath.dsw b/pjnath/build/pjnath.dsw
index 2105962..03b80cd 100644
--- a/pjnath/build/pjnath.dsw
+++ b/pjnath/build/pjnath.dsw
@@ -15,7 +15,7 @@
 

 ###############################################################################

 

-Project: "pjlib_test"=..\..\pjlib\build\pjlib_test.dsp - Package Owner=<4>

+Project: "pjlib_util"="..\..\pjlib-util\build\pjlib_util.dsp" - Package Owner=<4>

 

 Package=<5>

 {{{

@@ -27,7 +27,7 @@
 

 ###############################################################################

 

-Project: "pjlib_util"="..\..\pjlib-util\build\pjlib_util.dsp" - Package Owner=<4>

+Project: "pjnath"=.\pjnath.dsp - Package Owner=<4>

 

 Package=<5>

 {{{

@@ -53,6 +53,9 @@
     Begin Project Dependency

     Project_Dep_Name pjlib_util

     End Project Dependency

+    Begin Project Dependency

+    Project_Dep_Name pjnath

+    End Project Dependency

 }}}

 

 ###############################################################################

@@ -71,6 +74,9 @@
     Begin Project Dependency

     Project_Dep_Name pjlib_util

     End Project Dependency

+    Begin Project Dependency

+    Project_Dep_Name pjnath

+    End Project Dependency

 }}}

 

 ###############################################################################

diff --git a/pjnath/include/pjnath.h b/pjnath/include/pjnath.h
new file mode 100644
index 0000000..7562120
--- /dev/null
+++ b/pjnath/include/pjnath.h
@@ -0,0 +1,27 @@
+/* $Id$ */
+/* 
+ * Copyright (C) 2003-2007 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 <pjnath/config.h>
+#include <pjnath/errno.h>
+#include <pjnath/stun_auth.h>
+#include <pjnath/stun_endpoint.h>
+#include <pjnath/stun_msg.h>
+#include <pjnath/stun_session.h>
+#include <pjnath/stun_transaction.h>
+#include <pjnath/types.h>
diff --git a/pjnath/include/pjnath/config.h b/pjnath/include/pjnath/config.h
new file mode 100644
index 0000000..fc3e004
--- /dev/null
+++ b/pjnath/include/pjnath/config.h
@@ -0,0 +1,65 @@
+/* $Id$ */
+/* 
+ * Copyright (C) 2003-2007 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 __PJNATH_CONFIG_H__
+#define __PJNATH_CONFIG_H__
+
+
+/**
+ * @file config.h
+ * @brief Compile time settings
+ */
+
+/**
+ * @defgroup PJNATH_CONFIG Configuration
+ * @ingroup PJNATH
+ * @{
+ */
+
+/* **************************************************************************
+ * STUN CLIENT CONFIGURATION
+ */
+
+/**
+ * Maximum number of attributes in the STUN packet (for the old STUN
+ * library).
+ *
+ * Default: 16
+ */
+#ifndef PJSTUN_MAX_ATTR
+#   define PJSTUN_MAX_ATTR			    16
+#endif
+
+
+/**
+ * Maximum number of attributes in the STUN packet (for the new STUN
+ * library).
+ *
+ * Default: 16
+ */
+#ifndef PJ_STUN_MAX_ATTR
+#   define PJ_STUN_MAX_ATTR			    16
+#endif
+
+
+/**
+ * @}
+ */
+
+#endif	/* __PJNATH_CONFIG_H__ */
+
diff --git a/pjnath/include/pjnath/errno.h b/pjnath/include/pjnath/errno.h
new file mode 100644
index 0000000..cbefee8
--- /dev/null
+++ b/pjnath/include/pjnath/errno.h
@@ -0,0 +1,152 @@
+/* $Id$ */
+/* 
+ * Copyright (C)2003-2007 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 __PJNATH_ERRNO_H__
+#define __PJNATH_ERRNO_H__
+
+
+#include <pj/errno.h>
+
+/**
+ * @defgroup PJNATH_ERROR NAT Helper Error Codes
+ * @ingroup PJNATH
+ * @{
+ */
+
+/**
+ * Start of error code relative to PJ_ERRNO_START_USER.
+ * This value is 370000.
+ */
+#define PJNATH_ERRNO_START    (PJ_ERRNO_START_USER + PJ_ERRNO_SPACE_SIZE*4)
+
+
+
+/************************************************************
+ * NEW STUN ERROR
+ ***********************************************************/
+/* Messaging errors */
+#define PJNATH_ESTUNINATTRLEN	    -1
+#define PJNATH_ESTUNINMSGLEN	    -1
+#define	PJNATH_ESTUNINMSGTYPE	    -1
+#define PJNATH_ESTUNFINGERPRINT	    -1
+#define PJNATH_ESTUNNOTRESPOND	    -1
+
+/**
+ * @hideinitializer
+ * Too many STUN attributes.
+ */
+#define PJNATH_ESTUNTOOMANYATTR	    (PJNATH_ERRNO_START+110)/* 370110 */
+/**
+ * @hideinitializer
+ * Unknown STUN attribute. This error happens when the decoder encounters
+ * mandatory attribute type which it doesn't understand.
+ */
+#define PJNATH_ESTUNUNKNOWNATTR	    (PJNATH_ERRNO_START+111)/* 370111 */
+/**
+ * @hideinitializer
+ * Invalid STUN socket address length.
+ */
+#define PJNATH_ESTUNINADDRLEN	    (PJNATH_ERRNO_START+112)/* 370112 */
+/**
+ * @hideinitializer
+ * STUN IPv6 attribute not supported
+ */
+#define PJNATH_ESTUNIPV6NOTSUPP	    (PJNATH_ERRNO_START+113)/* 370113 */
+/**
+ * @hideinitializer
+ * Expecting STUN response message.
+ */
+#define PJNATH_ESTUNNOTRESPONSE	    (PJNATH_ERRNO_START+114)/* 370114 */
+/**
+ * @hideinitializer
+ * STUN transaction ID mismatch.
+ */
+#define PJNATH_ESTUNINVALIDID	    (PJNATH_ERRNO_START+115)/* 370115 */
+/**
+ * @hideinitializer
+ * Unable to find handler for the request.
+ */
+#define PJNATH_ESTUNNOHANDLER	    (PJNATH_ERRNO_START+116)/* 370116 */
+/**
+ * @hideinitializer
+ * Found non-FINGERPRINT attribute after MESSAGE-INTEGRITY. This is not
+ * valid since MESSAGE-INTEGRITY MUST be the last attribute or the
+ * attribute right before FINGERPRINT before the message.
+ */
+#define PJNATH_ESTUNMSGINTPOS	    (PJNATH_ERRNO_START+118)/* 370118 */
+/**
+ * @hideinitializer
+ * Found attribute after FINGERPRINT. This is not valid since FINGERPRINT
+ * MUST be the last attribute in the message.
+ */
+#define PJNATH_ESTUNFINGERPOS	    (PJNATH_ERRNO_START+119)/* 370119 */
+/**
+ * @hideinitializer
+ * Missing STUN USERNAME attribute.
+ * When credential is included in the STUN message (MESSAGE-INTEGRITY is
+ * present), the USERNAME attribute must be present in the message.
+ */
+#define PJNATH_ESTUNNOUSERNAME	    (PJNATH_ERRNO_START+120)/* 370120 */
+/**
+ * @hideinitializer
+ * Unknown STUN username/credential.
+ */
+#define PJNATH_ESTUNUSERNAME	    (PJNATH_ERRNO_START+121)/* 370121 */
+/**
+ * @hideinitializer
+ * Missing/invalidSTUN MESSAGE-INTEGRITY attribute.
+ */
+#define PJNATH_ESTUNMSGINT	    (PJNATH_ERRNO_START+122)/* 370122 */
+/**
+ * @hideinitializer
+ * Found duplicate STUN attribute.
+ */
+#define PJNATH_ESTUNDUPATTR	    (PJNATH_ERRNO_START+123)/* 370123 */
+/**
+ * @hideinitializer
+ * Missing STUN REALM attribute.
+ */
+#define PJNATH_ESTUNNOREALM	    (PJNATH_ERRNO_START+124)/* 370124 */
+/**
+ * @hideinitializer
+ * Missing/stale STUN NONCE attribute value.
+ */
+#define PJNATH_ESTUNNONCE	    (PJNATH_ERRNO_START+125)/* 370125 */
+/**
+ * @hideinitializer
+ * STUN transaction terminates with failure.
+ */
+#define PJNATH_ESTUNTSXFAILED	    (PJNATH_ERRNO_START+126)/* 370126 */
+
+
+//#define PJ_STATUS_FROM_STUN_CODE(code)	(PJNATH_ERRNO_START+code)
+
+
+/**
+ * @hideinitializer
+ * No ICE checklist is formed.
+ */
+#define PJ_EICENOCHECKLIST	    -1
+
+
+
+/**
+ * @}
+ */
+
+#endif	/* __PJNATH_ERRNO_H__ */
diff --git a/pjnath/include/pjnath/ice.h b/pjnath/include/pjnath/ice.h
new file mode 100644
index 0000000..3277dc7
--- /dev/null
+++ b/pjnath/include/pjnath/ice.h
@@ -0,0 +1,253 @@
+/* $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 __PJNATH_ICE_SOCK_H__
+#define __PJNATH_ICE_SOCK_H__
+
+/**
+ * @file ice_sock.h
+ * @brief ICE socket.
+ */
+#include <pjnath/types.h>
+#include <pjnath/stun_endpoint.h>
+#include <pjlib-util/resolver.h>
+#include <pj/sock.h>
+
+PJ_BEGIN_DECL
+
+
+/* **************************************************************************/
+/**
+ * @defgroup PJNATH_ICE_SOCK ICE Socket
+ * @brief High level ICE socket abstraction.
+ * @ingroup PJNATH
+ * @{
+ */
+
+/**
+ * This enumeration describes the type of an ICE candidate.
+ */
+typedef enum pj_ice_cand_type
+{
+    PJ_ICE_CAND_TYPE_HOST,
+    PJ_ICE_CAND_TYPE_MAPPED,
+    PJ_ICE_CAND_TYPE_PEER_MAPPED,
+    PJ_ICE_CAND_TYPE_RELAYED
+} pj_ice_cand_type;
+
+/**
+ *
+ */
+enum pj_ice_type_pref
+{
+    PJ_ICE_HOST_PREF	    = 126,
+    PJ_ICE_MAPPED_PREF	    = 100,
+    PJ_ICE_PEER_MAPPED_PREF = 110,
+    PJ_ICE_RELAYED_PREF	    = 0
+};
+
+typedef struct pj_ice pj_ice;
+
+
+#define PJ_ICE_MAX_CAND	    32
+#define PJ_ICE_MAX_COMP	    8
+
+
+/**
+ * ICE component
+ */
+typedef struct pj_ice_comp
+{
+    unsigned	    comp_id;
+    pj_sock_t	    sock;
+} pj_ice_comp;
+
+
+/**
+ * This structure describes an ICE candidate.
+ */
+typedef struct pj_ice_cand
+{
+    pj_uint32_t		 comp_id;
+    pj_ice_cand_type	 type;
+    pj_str_t		 foundation;
+    pj_uint32_t		 prio;
+    pj_sockaddr		 addr;
+    pj_sockaddr		 base_addr;
+    pj_sockaddr		 srv_addr;
+} pj_ice_cand;
+
+typedef enum pj_ice_check_state
+{
+    PJ_ICE_CHECK_STATE_FROZEN,
+    PJ_ICE_CHECK_STATE_WAITING,
+    PJ_ICE_CHECK_STATE_IN_PROGRESS,
+    PJ_ICE_CHECK_STATE_SUCCEEDED,
+    PJ_ICE_CHECK_STATE_FAILED
+} pj_ice_check_state;
+
+
+typedef struct pj_ice_check
+{
+    unsigned		local_cand_id;
+    pj_uint64_t		check_prio;
+    pj_ice_check_state	check_state;
+
+    pj_ice_cand_type	rem_type;
+    pj_str_t		rem_foundation;
+    pj_uint32_t		rem_prio;
+    pj_sockaddr		rem_addr;
+    pj_sockaddr		rem_base_addr;
+} pj_ice_check;
+
+
+typedef enum pj_ice_checklist_state
+{
+    PJ_ICE_CHECKLIST_ST_IDLE,
+    PJ_ICE_CHECKLIST_ST_RUNNING,
+    PJ_ICE_CHECKLIST_ST_COMPLETED
+} pj_ice_checklist_state;
+
+typedef struct pj_ice_checklist
+{
+    pj_ice_checklist_state   state;
+    unsigned		     count;
+    pj_ice_check	    *checks;
+} pj_ice_checklist;
+
+
+/**
+ * ICE sock callback.
+ */
+typedef struct pj_ice_cb
+{
+    pj_bool_t (*on_found_cand)(pj_ice *sock,
+			       pj_ice_cand_type type,
+			       const pj_sockaddr_t *addr,
+			       int addr_len);
+} pj_ice_cb;
+
+
+typedef enum pj_ice_state
+{
+    PJ_ICE_STATE_INIT,
+    PJ_ICE_STATE_GATHERING,
+    PJ_ICE_STATE_CAND_COMPLETE,
+    PJ_ICE_STATE_CHECKING,
+    PJ_ICE_STATE_COMPLETE,
+    PJ_ICE_STATE_RESV_ERROR
+} pj_ice_state;
+
+/**
+ * ICE structure.
+ */
+struct pj_ice
+{
+    char		obj_name[PJ_MAX_OBJ_NAME];
+
+    pj_pool_t		*pool;
+    pj_mutex_t		*mutex;
+    int			 af;
+    int			 sock_type;
+
+    pj_ice_state	 state;
+
+    /* Components */
+    unsigned		 comp_cnt;
+    pj_ice_comp		 comp[PJ_ICE_MAX_COMP];
+
+    /* Local candidates */
+    unsigned		 cand_cnt;
+    pj_ice_cand		 cand[PJ_ICE_MAX_CAND];
+
+    /* Checklist */
+    pj_ice_checklist	 cklist;
+
+    /* STUN servers */
+    pj_dns_resolver	*resv;
+    pj_dns_async_query	*resv_q;
+    pj_bool_t		 relay_enabled;
+    pj_sockaddr		 stun_srv;
+};
+
+
+PJ_DECL(pj_status_t) pj_ice_create(pj_stun_config *cfg,
+				   const char *name,
+				   int af,
+				   int sock_type,
+				   pj_ice **p_ice);
+PJ_DECL(pj_status_t) pj_ice_destroy(pj_ice *ice);
+PJ_DECL(pj_status_t) pj_ice_set_srv(pj_ice *ice,
+				    pj_bool_t enable_relay,
+				    pj_dns_resolver *resolver,
+				    const pj_str_t *domain);
+PJ_DECL(pj_status_t) pj_ice_set_srv_addr(pj_ice *ice,
+					 pj_bool_t enable_relay,
+					 const pj_sockaddr_t *srv_addr,
+					 unsigned addr_len);
+PJ_DECL(pj_status_t) pj_ice_add_comp(pj_ice *ice,
+				     unsigned comp_id,
+				     const pj_sockaddr_t *local_addr,
+				     unsigned addr_len);
+PJ_DECL(pj_status_t) pj_ice_add_sock_comp(pj_ice *ice,
+					  unsigned comp_id,
+					  pj_sock_t sock);
+
+PJ_DECL(pj_status_t) pj_ice_start_gather(pj_ice *ice,
+					 unsigned flags);
+
+PJ_DECL(pj_status_t) pj_ice_add_cand(pj_ice *ice,
+				     unsigned comp_id,
+				     pj_ice_cand_type type,
+				     pj_uint16_t local_pref,
+				     const pj_str_t *foundation,
+				     const pj_sockaddr_t *addr,
+				     const pj_sockaddr_t *base_addr,
+				     const pj_sockaddr_t *srv_addr,
+				     int addr_len,
+				     unsigned *cand_id);
+
+PJ_DECL(unsigned) pj_ice_get_cand_cnt(pj_ice *ice);
+PJ_DECL(pj_status_t) pj_ice_enum_cands(pj_ice *ice,
+				       unsigned sort_by,
+				       unsigned *p_count,
+				       unsigned cand_ids[]);
+PJ_DECL(unsigned) pj_ice_get_default_cand(pj_ice *ice,
+					  int *cand_id);
+PJ_DECL(pj_status_t) pj_ice_get_cand(pj_ice *ice,
+				     unsigned cand_id,
+				     pj_ice_cand **p_cand);
+
+PJ_DECL(pj_status_t) pj_ice_create_check_list(pj_ice *ice,
+					      pj_bool_t is_remote_offer,
+					      unsigned rem_cand_cnt,
+					      const pj_ice_cand rem_cand[]);
+
+PJ_DECL(pj_status_t) pj_ice_start_check(pj_ice *ice);
+
+
+/**
+ * @}
+ */
+
+
+PJ_END_DECL
+
+
+#endif	/* __PJNATH_ICE_SOCK_H__ */
+
diff --git a/pjnath/include/pjnath/stun_auth.h b/pjnath/include/pjnath/stun_auth.h
index 49b2acb..e30ebc9 100644
--- a/pjnath/include/pjnath/stun_auth.h
+++ b/pjnath/include/pjnath/stun_auth.h
@@ -16,15 +16,15 @@
  * 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__
+#ifndef __PJNATH_STUN_AUTH_H__
+#define __PJNATH_STUN_AUTH_H__
 
 /**
  * @file stun_auth.h
  * @brief STUN authentication.
  */
 
-#include <pjlib-util/stun_msg.h>
+#include <pjnath/stun_msg.h>
 
 
 PJ_BEGIN_DECL
@@ -32,8 +32,8 @@
 
 /* **************************************************************************/
 /**
- * @defgroup PJLIB_UTIL_STUN_AUTH STUN Authentication
- * @ingroup PJLIB_UTIL_STUN
+ * @defgroup PJNATH_STUN_AUTH STUN Authentication
+ * @ingroup PJNATH_STUN
  * @{
  */
 
@@ -271,5 +271,5 @@
 PJ_END_DECL
 
 
-#endif	/* __PJLIB_UTIL_STUN_AUTH_H__ */
+#endif	/* __PJNATH_STUN_AUTH_H__ */
 
diff --git a/pjnath/include/pjnath/stun_doc.h b/pjnath/include/pjnath/stun_doc.h
index 612bf1a..7b5e651 100644
--- a/pjnath/include/pjnath/stun_doc.h
+++ b/pjnath/include/pjnath/stun_doc.h
@@ -24,8 +24,8 @@
  */
 
 /**
- * @defgroup PJLIB_UTIL_STUN STUN and TURN
- * @ingroup PJLIB_UTIL
+ * @defgroup PJNATH_STUN STUN and TURN
+ * @ingroup PJNATH
 
  This is the implementation of STUN/TURN in PJLIB-UTIL library.
 
@@ -54,7 +54,7 @@
 
  @subsection stun_msg_sec Messaging and Parsing
 
- The lowest layer of the STUN implementation is the @ref PJLIB_UTIL_STUN_MSG
+ The lowest layer of the STUN implementation is the @ref PJNATH_STUN_MSG
  component. This part is responsible for encoding and decoding STUN messages.
 
  This layer only implements message representation and parsing. In particular,
@@ -65,7 +65,7 @@
 
  @subsection stun_endpt_sec Endpoint
 
- The @ref PJLIB_UTIL_STUN_ENDPOINT is used by the library to put together
+ The @ref PJNATH_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
@@ -74,11 +74,11 @@
 
  @subsection stun_clt_tsx_sec Client Transaction
 
- The @ref PJLIB_UTIL_STUN_TRANSACTION is used to manage outgoing STUN request,
+ The @ref PJNATH_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,
+ The @ref PJNATH_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
@@ -88,7 +88,7 @@
 
  @subsection stun_srv_sec Server Components
 
- The @ref PJLIB_UTIL_STUN_SERVER is used for:
+ The @ref PJNATH_STUN_SERVER is used for:
  - implementing STUN servers, and/or
  - implementing server side STUN handling (for example for ICE).
 
diff --git a/pjnath/include/pjnath/stun_endpoint.h b/pjnath/include/pjnath/stun_endpoint.h
index b341309..d9a32b5 100644
--- a/pjnath/include/pjnath/stun_endpoint.h
+++ b/pjnath/include/pjnath/stun_endpoint.h
@@ -16,15 +16,15 @@
  * 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__
+#ifndef __PJNATH_STUN_CONFIG_H__
+#define __PJNATH_STUN_CONFIG_H__
 
 /**
- * @file stun_endpoint.h
+ * @file stun_config.h
  * @brief STUN endpoint.
  */
 
-#include <pjlib-util/stun_msg.h>
+#include <pjnath/stun_msg.h>
 
 
 PJ_BEGIN_DECL
@@ -32,9 +32,9 @@
 
 /* **************************************************************************/
 /**
- * @defgroup PJLIB_UTIL_STUN_ENDPOINT STUN Endpoint
+ * @defgroup PJNATH_STUN_ENDPOINT STUN Endpoint
  * @brief Management of incoming and outgoing STUN transactions.
- * @ingroup PJLIB_UTIL_STUN
+ * @ingroup PJNATH_STUN
  * @{
  */
 
@@ -43,7 +43,7 @@
  * server STUN transactions, and it needs to be initialized before application
  * can send or receive STUN messages.
  */
-typedef struct pj_stun_endpoint
+typedef struct pj_stun_config
 {
     /**
      * Pool factory to be used by the STUN endpoint and all objects created
@@ -86,23 +86,23 @@
      */
     unsigned		 res_cache_msec;
 
-} pj_stun_endpoint;
+} pj_stun_config;
 
 
 
 /**
  * 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);
+PJ_DECL(pj_status_t) pj_stun_config_create(pj_pool_factory *factory,
+					   unsigned options,
+					   pj_ioqueue_t *ioqueue,
+					   pj_timer_heap_t *timer_heap,
+					   pj_stun_config **p_endpt);
 
 /**
  * Destroy STUN endpoint instance.
  */
-PJ_DECL(pj_status_t) pj_stun_endpoint_destroy(pj_stun_endpoint *endpt);
+PJ_DECL(pj_status_t) pj_stun_config_destroy(pj_stun_config *endpt);
 
 
 /**
@@ -113,5 +113,5 @@
 PJ_END_DECL
 
 
-#endif	/* __PJLIB_UTIL_STUN_ENDPOINT_H__ */
+#endif	/* __PJNATH_STUN_CONFIG_H__ */
 
diff --git a/pjnath/include/pjnath/stun_msg.h b/pjnath/include/pjnath/stun_msg.h
index ae66c2d..ae07629 100644
--- a/pjnath/include/pjnath/stun_msg.h
+++ b/pjnath/include/pjnath/stun_msg.h
@@ -16,15 +16,15 @@
  * 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__
+#ifndef __PJNATH_STUN_MSG_H__
+#define __PJNATH_STUN_MSG_H__
 
 /**
  * @file stun_msg.h
  * @brief STUN message components.
  */
 
-#include <pjlib-util/types.h>
+#include <pjnath/types.h>
 #include <pj/sock.h>
 
 
@@ -33,9 +33,9 @@
 
 /* **************************************************************************/
 /**
- * @defgroup PJLIB_UTIL_STUN_MSG STUN Message Representation and Parsing
+ * @defgroup PJNATH_STUN_MSG STUN Message Representation and Parsing
  * @brief Low-level representation and parsing of STUN messages.
- * @ingroup PJLIB_UTIL_STUN
+ * @ingroup PJNATH_STUN
  * @{
  */
 
@@ -529,13 +529,9 @@
     pj_bool_t		xor_ed;
 
     /**
-     * The socket address (as a union)
+     * The socket address
      */
-    union {
-	pj_sockaddr	    addr;   /**< Generic socket address.    */
-	pj_sockaddr_in	    ipv4;   /**< IPv4 socket address.	    */
-	pj_sockaddr_in6	    ipv6;   /**< IPv6 socket address.	    */
-    } addr;
+    pj_sockaddr		sockaddr;
 
 } pj_stun_sockaddr_attr;
 
@@ -1535,5 +1531,5 @@
 PJ_END_DECL
 
 
-#endif	/* __PJLIB_UTIL_STUN_MSG_H__ */
+#endif	/* __PJNATH_STUN_MSG_H__ */
 
diff --git a/pjnath/include/pjnath/stun_session.h b/pjnath/include/pjnath/stun_session.h
index fa18dc3..5f5bda3 100644
--- a/pjnath/include/pjnath/stun_session.h
+++ b/pjnath/include/pjnath/stun_session.h
@@ -16,13 +16,13 @@
  * 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__
+#ifndef __PJNATH_STUN_SESSION_H__
+#define __PJNATH_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 <pjnath/stun_msg.h>
+#include <pjnath/stun_auth.h>
+#include <pjnath/stun_endpoint.h>
+#include <pjnath/stun_transaction.h>
 #include <pj/list.h>
 #include <pj/timer.h>
 
@@ -31,9 +31,9 @@
 
 /* **************************************************************************/
 /**
- * @defgroup PJLIB_UTIL_STUN_SESSION STUN Client/Server Session
+ * @defgroup PJNATH_STUN_SESSION STUN Client/Server Session
  * @brief STUN client and server session
- * @ingroup PJLIB_UTIL_STUN
+ * @ingroup PJNATH_STUN
  * @{
  */
 
@@ -156,7 +156,7 @@
 /**
  * Create a STUN session.
  *
- * @param endpt		The STUN endpoint, to be used to register timers etc.
+ * @param cfg		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.
@@ -165,7 +165,7 @@
  *
  * @return	    PJ_SUCCESS on success, or the appropriate error code.
  */
-PJ_DECL(pj_status_t) pj_stun_session_create(pj_stun_endpoint *endpt,
+PJ_DECL(pj_status_t) pj_stun_session_create(pj_stun_config *cfg,
 					    const char *name,
 					    const pj_stun_session_cb *cb,
 					    pj_bool_t fingerprint,
@@ -368,5 +368,5 @@
 
 PJ_END_DECL
 
-#endif	/* __PJLIB_UTIL_STUN_SESSION_H__ */
+#endif	/* __PJNATH_STUN_SESSION_H__ */
 
diff --git a/pjnath/include/pjnath/stun_transaction.h b/pjnath/include/pjnath/stun_transaction.h
index c7a5bf9..f485886 100644
--- a/pjnath/include/pjnath/stun_transaction.h
+++ b/pjnath/include/pjnath/stun_transaction.h
@@ -16,16 +16,16 @@
  * 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__
+#ifndef __PJNATH_STUN_TRANSACTION_H__
+#define __PJNATH_STUN_TRANSACTION_H__
 
 /**
  * @file stun_transaction.h
  * @brief STUN transaction
  */
 
-#include <pjlib-util/stun_msg.h>
-#include <pjlib-util/stun_endpoint.h>
+#include <pjnath/stun_msg.h>
+#include <pjnath/stun_endpoint.h>
 
 
 PJ_BEGIN_DECL
@@ -33,16 +33,16 @@
 
 /* **************************************************************************/
 /**
- * @defgroup PJLIB_UTIL_STUN_TRANSACTION STUN Client Transaction
+ * @defgroup PJNATH_STUN_TRANSACTION STUN Client Transaction
  * @brief STUN client transaction
- * @ingroup PJLIB_UTIL_STUN
+ * @ingroup PJNATH_STUN
  * @{
  *
- The @ref PJLIB_UTIL_STUN_TRANSACTION is used to manage outgoing STUN request,
+ The @ref PJNATH_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,
+ The @ref PJNATH_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
@@ -100,7 +100,7 @@
  * ensure the reliability of the request by periodically retransmitting
  * the request, if necessary.
  *
- * @param endpt		The STUN endpoint, which will be used to retrieve
+ * @param cfg		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
@@ -110,7 +110,7 @@
  *
  * @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_DECL(pj_status_t) pj_stun_client_tsx_create(	pj_stun_config *cfg,
 					        pj_pool_t *pool,
 						const pj_stun_tsx_cb *cb,
 						pj_stun_client_tsx **p_tsx);
@@ -213,5 +213,5 @@
 PJ_END_DECL
 
 
-#endif	/* __PJLIB_UTIL_STUN_TRANSACTION_H__ */
+#endif	/* __PJNATH_STUN_TRANSACTION_H__ */
 
diff --git a/pjnath/include/pjnath/turn_client.h b/pjnath/include/pjnath/turn_client.h
index 83d8d2d..b9cfacc 100644
--- a/pjnath/include/pjnath/turn_client.h
+++ b/pjnath/include/pjnath/turn_client.h
@@ -16,24 +16,24 @@
  * 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__
+#ifndef __PJNATH_TURN_CLIENT_H__
+#define __PJNATH_TURN_CLIENT_H__
 
 /**
  * @file turn_client.h
  * @brief TURN client session.
  */
 
-#include <pjlib-util/stun_msg.h>
+#include <pjnath/stun_msg.h>
 
 
 PJ_BEGIN_DECL
 
 
 /**
- * @defgroup PJLIB_UTIL_TURN_CLIENT TURN Client Session
+ * @defgroup PJNATH_TURN_CLIENT TURN Client Session
  * @brief Management of STUN/TURN client session
- * @ingroup PJLIB_UTIL_STUN
+ * @ingroup PJNATH_STUN
  * @{
  */
 
@@ -128,5 +128,5 @@
 PJ_END_DECL
 
 
-#endif	/* __PJLIB_UTIL_TURN_CLIENT_H__ */
+#endif	/* __PJNATH_TURN_CLIENT_H__ */
 
diff --git a/pjnath/include/pjnath/types.h b/pjnath/include/pjnath/types.h
new file mode 100644
index 0000000..d39da89
--- /dev/null
+++ b/pjnath/include/pjnath/types.h
@@ -0,0 +1,63 @@
+/* $Id$ */
+/* 
+ * Copyright (C) 2003-2007 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 __PJNATH_TYPES_H__
+#define __PJNATH_TYPES_H__
+
+/**
+ * @file types.h
+ * @brief PJNATH types.
+ */
+
+#include <pj/types.h>
+#include <pjnath/config.h>
+
+/**
+ * @defgroup PJNATH NAT Helper Library
+ */
+
+/**
+ * @mainpage NAT Helper Library
+ *
+ * \n
+ * \n
+ * \n
+ * This is the documentation of PJNATH, an auxiliary library providing
+ * NAT helper functionalities such as STUN and ICE.
+ * 
+ * Please go to the <A HREF="modules.htm"><B>Modules</B></A> page for list
+ * of modules.
+ *
+ *
+ * \n
+ * \n
+ * \n
+ * \n
+ * \n
+ * \n
+ * \n
+ * \n
+ * \n
+ * \n
+ * \n
+ * \n
+ * \n
+ */
+
+#endif	/* __PJNATH_TYPES_H__ */
+
diff --git a/pjnath/src/pjnath/errno.c b/pjnath/src/pjnath/errno.c
new file mode 100644
index 0000000..bfde1bc
--- /dev/null
+++ b/pjnath/src/pjnath/errno.c
@@ -0,0 +1,121 @@
+/* $Id$ */
+/* 
+ * Copyright (C) 2003-2007 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 <pjnath/errno.h>
+#include <pj/string.h>
+
+
+
+/* PJNATH's own error codes/messages 
+ * MUST KEEP THIS ARRAY SORTED!!
+ * Message must be limited to 64 chars!
+ */
+#if defined(PJ_HAS_ERROR_STRING) && PJ_HAS_ERROR_STRING!=0
+static const struct 
+{
+    int code;
+    const char *msg;
+} err_str[] = 
+{
+    /* STUN */
+    PJ_BUILD_ERR( PJNATH_ESTUNTOOMANYATTR,  "Too many STUN attributes"),
+    PJ_BUILD_ERR( PJNATH_ESTUNUNKNOWNATTR,  "Unknown STUN attribute"),
+    PJ_BUILD_ERR( PJNATH_ESTUNINADDRLEN,    "Invalid STUN socket address length"),
+    PJ_BUILD_ERR( PJNATH_ESTUNIPV6NOTSUPP,  "STUN IPv6 attribute not supported"),
+    PJ_BUILD_ERR( PJNATH_ESTUNNOTRESPONSE,  "Expecting STUN response message"),
+    PJ_BUILD_ERR( PJNATH_ESTUNINVALIDID,    "STUN transaction ID mismatch"),
+    PJ_BUILD_ERR( PJNATH_ESTUNNOHANDLER,    "Unable to find STUN handler for the request"),
+    PJ_BUILD_ERR( PJNATH_ESTUNMSGINTPOS,    "Found non-FINGERPRINT attr. after MESSAGE-INTEGRITY"),
+    PJ_BUILD_ERR( PJNATH_ESTUNFINGERPOS,    "Found STUN attribute after FINGERPRINT"),
+    PJ_BUILD_ERR( PJNATH_ESTUNNOUSERNAME,   "Missing STUN USERNAME attribute"),
+    PJ_BUILD_ERR( PJNATH_ESTUNMSGINT,	    "Missing/invalid STUN MESSAGE-INTEGRITY attribute"),
+    PJ_BUILD_ERR( PJNATH_ESTUNDUPATTR,	    "Found duplicate STUN attribute"),
+    PJ_BUILD_ERR( PJNATH_ESTUNNOREALM,	    "Missing STUN REALM attribute"),
+    PJ_BUILD_ERR( PJNATH_ESTUNNONCE,	    "Missing/stale STUN NONCE attribute value"),
+    PJ_BUILD_ERR( PJNATH_ESTUNTSXFAILED,    "STUN transaction terminates with failure"),
+};
+#endif	/* PJ_HAS_ERROR_STRING */
+
+
+/*
+ * pjnath_strerror()
+ */
+PJ_DEF(pj_str_t) pjnath_strerror( pj_status_t statcode, 
+				  char *buf, pj_size_t bufsize )
+{
+    pj_str_t errstr;
+
+#if defined(PJ_HAS_ERROR_STRING) && (PJ_HAS_ERROR_STRING != 0)
+
+    if (statcode >= PJNATH_ERRNO_START && 
+	statcode < PJNATH_ERRNO_START + PJ_ERRNO_SPACE_SIZE)
+    {
+	/* Find the error in the table.
+	 * Use binary search!
+	 */
+	int first = 0;
+	int n = PJ_ARRAY_SIZE(err_str);
+
+	while (n > 0) {
+	    int half = n/2;
+	    int mid = first + half;
+
+	    if (err_str[mid].code < statcode) {
+		first = mid+1;
+		n -= (half+1);
+	    } else if (err_str[mid].code > statcode) {
+		n = half;
+	    } else {
+		first = mid;
+		break;
+	    }
+	}
+
+
+	if (PJ_ARRAY_SIZE(err_str) && err_str[first].code == statcode) {
+	    pj_str_t msg;
+	    
+	    msg.ptr = (char*)err_str[first].msg;
+	    msg.slen = pj_ansi_strlen(err_str[first].msg);
+
+	    errstr.ptr = buf;
+	    pj_strncpy_with_null(&errstr, &msg, bufsize);
+	    return errstr;
+
+	} 
+    }
+
+#endif	/* PJ_HAS_ERROR_STRING */
+
+
+    /* Error not found. */
+    errstr.ptr = buf;
+    errstr.slen = pj_ansi_snprintf(buf, bufsize, 
+				   "Unknown pjlib-util error %d",
+				   statcode);
+
+    return errstr;
+}
+
+
+PJ_DEF(pj_status_t) pjnath_init(void)
+{
+    return pj_register_strerror(PJNATH_ERRNO_START, 
+				PJ_ERRNO_SPACE_SIZE, 
+				&pjnath_strerror);
+}
diff --git a/pjnath/src/pjnath/ice.c b/pjnath/src/pjnath/ice.c
new file mode 100644
index 0000000..c92ceb5
--- /dev/null
+++ b/pjnath/src/pjnath/ice.c
@@ -0,0 +1,566 @@
+/* $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 <pjnath/ice.h>
+#include <pjnath/errno.h>
+#include <pj/assert.h>
+#include <pj/os.h>
+#include <pj/pool.h>
+#include <pj/string.h>
+
+
+static void destroy_ice(pj_ice *ice,
+			pj_status_t reason);
+static void ice_set_state(pj_ice *ice,
+			  pj_ice_state new_state);
+
+
+PJ_DEF(pj_status_t) pj_ice_create(pj_stun_config *cfg,
+				  const char *name,
+				  int af,
+				  int sock_type,
+				  pj_ice **p_ice)
+{
+    pj_pool_t *pool;
+    pj_ice *ice;
+    pj_status_t status;
+
+    PJ_ASSERT_RETURN(cfg && p_ice, PJ_EINVAL);
+    PJ_ASSERT_RETURN(sock_type==PJ_SOCK_DGRAM || sock_type==PJ_SOCK_STREAM,
+		     PJ_EINVAL);
+
+    if (!name)
+	name = "ice%p";
+
+    pool = pj_pool_create(cfg->pf, name, 4000, 4000, NULL);
+    ice = PJ_POOL_ZALLOC_T(pool, pj_ice);
+    ice->pool = pool;
+    ice->af = af;
+    ice->sock_type = sock_type;
+
+    pj_ansi_snprintf(ice->obj_name, sizeof(ice->obj_name),
+		     name, ice);
+
+    status = pj_mutex_create_recursive(pool, ice->obj_name, 
+				       &ice->mutex);
+    if (status != PJ_SUCCESS) {
+	destroy_ice(ice, status);
+	return status;
+    }
+
+    *p_ice = ice;
+
+    return PJ_SUCCESS;
+}
+
+
+static void destroy_ice(pj_ice *ice,
+			pj_status_t reason)
+{
+    if (ice->resv_q) {
+	pj_dns_resolver_cancel_query(ice->resv_q, PJ_FALSE);
+	ice->resv_q = NULL;
+    }
+
+    if (ice->mutex) {
+	pj_mutex_destroy(ice->mutex);
+	ice->mutex = NULL;
+    }
+
+    if (ice->pool) {
+	pj_pool_t *pool = ice->pool;
+	ice->pool = NULL;
+	pj_pool_release(pool);
+    }
+}
+
+
+PJ_DEF(pj_status_t) pj_ice_destroy(pj_ice *ice)
+{
+    destroy_ice(ice, PJ_SUCCESS);
+    return PJ_SUCCESS;
+}
+
+
+static void ice_set_state(pj_ice *ice,
+			  pj_ice_state new_state)
+{
+    ice->state = new_state;
+}
+
+static void resolver_cb(void *user_data,
+			pj_status_t status,
+			pj_dns_parsed_packet *response)
+{
+    pj_assert(!"Not implemented yet!");
+}
+
+PJ_DEF(pj_status_t) pj_ice_set_srv(pj_ice *ice,
+				   pj_bool_t enable_relay,
+				   pj_dns_resolver *resolver,
+				   const pj_str_t *domain)
+{
+    char namebuf[128];
+    char *tp_name;
+    pj_str_t name;
+    pj_status_t status;
+
+
+    /* Not implemented yet! */
+    return PJ_ENOTSUP;
+
+
+    PJ_ASSERT_RETURN(ice && resolver && domain, PJ_EINVAL);
+
+    /* Must not have a running resolver. This is because we couldn't
+     * safely cancel the query (there is a race condition situation
+     * between the callback acquiring the mutex and this function
+     * acquiring the mutex)
+     */
+    PJ_ASSERT_RETURN(ice->resv_q==NULL, PJ_EBUSY);
+
+    pj_mutex_lock(ice->mutex);
+
+    /* Reset resolver and server addresses */
+    ice->relay_enabled = enable_relay;
+    ice->resv = resolver;
+    pj_bzero(&ice->stun_srv, sizeof(ice->stun_srv));
+
+    /* Build SRV record name */
+    if (ice->sock_type == PJ_SOCK_DGRAM) {
+	tp_name = "_udp";
+    } else if (ice->sock_type == PJ_SOCK_STREAM) {
+	tp_name = "_tcp";
+    } else {
+	pj_assert(!"Invalid sock_type");
+	pj_mutex_unlock(ice->mutex);
+	return PJ_EBUG;
+    }
+
+    if (enable_relay) {
+	name.ptr = namebuf;
+	name.slen = pj_ansi_snprintf(namebuf, sizeof(namebuf),
+				     "_stun-relay.%s.%.*s",
+				     tp_name,
+				     (int)domain->slen,
+				     domain->ptr);
+    } else {
+	name.ptr = namebuf;
+	name.slen = pj_ansi_snprintf(namebuf, sizeof(namebuf),
+				     "_stun.%s.%.*s",
+				     tp_name,
+				     (int)domain->slen,
+				     domain->ptr);
+    }
+
+    if (name.slen < 1 || name.slen >= sizeof(namebuf)) {
+	pj_mutex_unlock(ice->mutex);
+	return PJ_ENAMETOOLONG;
+    }
+
+    /* Start DNS query */
+    status = pj_dns_resolver_start_query(ice->resv, &name, 
+					 PJ_DNS_TYPE_SRV, 0, 
+					 &resolver_cb, 
+					 ice, &ice->resv_q);
+    if (status != PJ_SUCCESS) {
+	pj_mutex_unlock(ice->mutex);
+	return status;
+    }
+
+    pj_mutex_unlock(ice->mutex);
+
+    return PJ_SUCCESS;
+}
+
+
+PJ_DEF(pj_status_t) pj_ice_set_srv_addr(pj_ice *ice,
+					pj_bool_t enable_relay,
+					const pj_sockaddr_t *srv_addr,
+					unsigned addr_len)
+{
+    PJ_ASSERT_RETURN(ice && srv_addr, PJ_EINVAL);
+    /* Must not have a running resolver. This is because we couldn't
+     * safely cancel the query (there is a race condition situation
+     * between the callback acquiring the mutex and this function
+     * acquiring the mutex)
+     */
+    PJ_ASSERT_RETURN(ice->resv_q==NULL, PJ_EBUSY);
+
+    pj_mutex_lock(ice->mutex);
+
+    ice->relay_enabled = enable_relay;
+    pj_memcpy(&ice->stun_srv, srv_addr, addr_len);
+
+    pj_mutex_unlock(ice->mutex);
+
+    return PJ_SUCCESS;
+
+}
+
+
+PJ_DEF(pj_status_t) pj_ice_add_comp(pj_ice *ice,
+				    unsigned comp_id,
+				    const pj_sockaddr_t *local_addr,
+				    unsigned addr_len)
+{
+    pj_status_t status;
+    pj_sock_t sock;
+
+    PJ_ASSERT_RETURN(ice && local_addr && addr_len, PJ_EINVAL);
+
+    status = pj_sock_socket(ice->af, ice->sock_type, 0, &sock);
+    if (status != PJ_SUCCESS)
+	return status;
+
+    status = pj_sock_bind(sock, local_addr, addr_len);
+    if (status != PJ_SUCCESS)
+	return status;
+
+    status = pj_ice_add_sock_comp(ice, comp_id, sock);
+    if (status != PJ_SUCCESS) {
+	pj_sock_close(sock);
+	return status;
+    }
+
+    return PJ_SUCCESS;
+}
+
+
+PJ_DEF(pj_status_t) pj_ice_add_sock_comp( pj_ice *ice,
+					  unsigned comp_id,
+					  pj_sock_t sock)
+{
+    PJ_ASSERT_RETURN(ice && sock != PJ_INVALID_SOCKET, PJ_EINVAL);
+    PJ_ASSERT_RETURN(ice->comp_cnt < PJ_ARRAY_SIZE(ice->comp), PJ_ETOOMANY);
+
+    pj_mutex_lock(ice->mutex);
+    ice->comp[ice->comp_cnt].comp_id = comp_id;
+    ice->comp[ice->comp_cnt].sock = sock;
+    ++ice->comp_cnt;
+    pj_mutex_unlock(ice->mutex);
+
+    return PJ_SUCCESS;
+}
+
+
+static pj_status_t gather_host_cands(pj_ice *ice)
+{
+    unsigned i;
+    pj_status_t status;
+
+    for (i=0; i<ice->comp_cnt; ++i) {
+	pj_ice_comp *comp = &ice->comp[i];
+	pj_sockaddr addr;
+	int addr_len;
+
+	addr_len = sizeof(addr);
+	status = pj_sock_getsockname(comp->sock, &addr, &addr_len);
+	if (status != PJ_SUCCESS)
+	    return status;
+
+	if (addr.ipv4.sin_addr.s_addr == 0) {
+	    status = pj_gethostip(&addr.ipv4.sin_addr);
+	    if (status != PJ_SUCCESS)
+		return status;
+	}
+
+	status = pj_ice_add_cand(ice, i, PJ_ICE_CAND_TYPE_HOST, 65535,
+				 NULL, &addr, &addr, NULL,
+    				 sizeof(pj_sockaddr_in), NULL);
+	if (status != PJ_SUCCESS)
+	    return status;
+    }
+
+    return PJ_SUCCESS;
+}
+
+static pj_status_t gather_mapped_cands(pj_ice *ice)
+{
+    return PJ_ENOTSUP;
+}
+
+static pj_status_t gather_relayed_cands(pj_ice *ice)
+{
+    return PJ_ENOTSUP;
+}
+
+PJ_DEF(pj_status_t) pj_ice_start_gather(pj_ice *ice,
+					unsigned flags)
+{
+    pj_status_t status;
+
+    /* Gather host candidate */
+    status = gather_host_cands(ice);
+    if (status != PJ_SUCCESS)
+	return status;
+
+    PJ_TODO(GATHER_MAPPED_AND_RELAYED_CANDIDATES);
+
+    ice_set_state(ice, PJ_ICE_STATE_CAND_COMPLETE);
+
+    return PJ_SUCCESS;
+}
+
+
+static pj_uint32_t CALC_CAND_PRIO(pj_ice_cand_type type,
+				  pj_uint32_t local_pref,
+				  pj_uint32_t comp_id)
+{
+    static pj_uint32_t type_pref[] =
+    {
+	PJ_ICE_HOST_PREF,
+	PJ_ICE_MAPPED_PREF,
+	PJ_ICE_PEER_MAPPED_PREF,
+	PJ_ICE_RELAYED_PREF
+    };
+
+    return ((1 << 24) * type_pref[type]) + 
+	   ((1 << 8) * local_pref) +
+	   (256 - comp_id);
+}
+
+
+PJ_DEF(pj_status_t) pj_ice_add_cand(pj_ice *ice,
+				    unsigned comp_id,
+				    pj_ice_cand_type type,
+				    pj_uint16_t local_pref,
+				    const pj_str_t *foundation,
+				    const pj_sockaddr_t *addr,
+				    const pj_sockaddr_t *base_addr,
+				    const pj_sockaddr_t *srv_addr,
+				    int addr_len,
+				    unsigned *p_cand_id)
+{
+    pj_ice_cand *cand;
+    pj_status_t status = PJ_SUCCESS;
+
+    pj_mutex_lock(ice->mutex);
+
+    if (ice->cand_cnt >= PJ_ARRAY_SIZE(ice->cand)) {
+	status = PJ_ETOOMANY;
+	goto on_error;
+    }
+
+    cand = &ice->cand[ice->cand_cnt];
+    cand->comp_id = comp_id;
+    cand->type = type;
+    pj_strdup(ice->pool, &cand->foundation, foundation);
+    cand->prio = CALC_CAND_PRIO(type, local_pref, cand->comp_id);
+    pj_memcpy(&cand->addr, addr, addr_len);
+    pj_memcpy(&cand->base_addr, base_addr, addr_len);
+    if (srv_addr)
+	pj_memcpy(&cand->srv_addr, srv_addr, addr_len);
+    else
+	pj_bzero(&cand->srv_addr, sizeof(cand->srv_addr));
+
+    if (p_cand_id)
+	*p_cand_id = ice->cand_cnt;
+
+    ++ice->cand_cnt;
+
+on_error:
+    pj_mutex_unlock(ice->mutex);
+    return status;
+}
+
+
+PJ_DEF(unsigned) pj_ice_get_cand_cnt(pj_ice *ice)
+{
+    return ice->cand_cnt;
+}
+
+
+PJ_DEF(pj_status_t) pj_ice_enum_cands(pj_ice *ice,
+				      unsigned sort_by,
+				      unsigned *p_count,
+				      unsigned cand_ids[])
+{
+    unsigned i, count;
+
+    pj_mutex_lock(ice->mutex);
+
+    count = (*p_count < ice->cand_cnt) ? *p_count : ice->cand_cnt;
+    for (i=0; i<count; ++i)
+	cand_ids[i] = i;
+
+    *p_count = count;
+    pj_mutex_unlock(ice->mutex);
+
+    return PJ_SUCCESS;
+}
+
+
+PJ_DEF(pj_status_t) pj_ice_get_cand(pj_ice *ice,
+				    unsigned cand_id,
+				    pj_ice_cand **p_cand)
+{
+    PJ_ASSERT_RETURN(ice && p_cand, PJ_EINVAL);
+    PJ_ASSERT_RETURN(cand_id <= ice->cand_cnt, PJ_EINVAL);
+
+    *p_cand = &ice->cand[cand_id];
+
+    return PJ_SUCCESS;
+}
+
+#ifndef MIN
+#   define MIN(a,b) (a < b ? a : b)
+#endif
+
+#ifndef MAX
+#   define MAX(a,b) (a > b ? a : b)
+#endif
+
+static pj_uint64_t CALC_CHECK_PRIO(pj_uint32_t O, pj_uint32_t A)
+{
+    return ((pj_uint64_t)1 << 32) * MIN(O, A) +
+	   (pj_uint64_t)2 * MAX(O, A) + (O>A ? 1 : 0);
+}
+
+
+PJ_DEF(pj_status_t) pj_ice_create_check_list(pj_ice *ice,
+					     pj_bool_t is_remote_offer,
+					     unsigned rem_cand_cnt,
+					     const pj_ice_cand rem_cand[])
+{
+    pj_ice_checklist *clist;
+    unsigned i, j, count;
+
+    PJ_ASSERT_RETURN(ice && rem_cand_cnt && rem_cand, PJ_EINVAL);
+
+    pj_mutex_lock(ice->mutex);
+
+    /* Create checklist */
+    clist = &ice->cklist;
+    clist->checks = pj_pool_calloc(ice->pool, 
+				   ice->cand_cnt * rem_cand_cnt,
+				   sizeof(pj_ice_check));
+    for (i=0, count=0; i<ice->cand_cnt; ++i) {
+	for (j=0; j<rem_cand_cnt; ++j) {
+
+	    pj_ice_check *c = &clist->checks[count++];
+
+	    /* A local candidate is paired with a remote candidate if
+	     * and only if the two candidates have the same component ID 
+	     * and have the same IP address version. 
+	     */
+	    if (ice->cand[i].comp_id != rem_cand[j].comp_id ||
+		pj_strcmp(&ice->cand[i].foundation,&rem_cand[j].foundation)==0)
+	    {
+		continue;
+	    }
+
+	    c->local_cand_id = i;
+
+	    if (is_remote_offer) {
+		c->check_prio = CALC_CHECK_PRIO(rem_cand[j].prio,
+						ice->cand[i].prio);
+	    } else {
+		c->check_prio = CALC_CHECK_PRIO(ice->cand[i].prio, 
+						rem_cand[j].prio);
+	    }
+
+	    c->rem_type = rem_cand[j].type;
+	    pj_strdup(ice->pool, &c->rem_foundation, &rem_cand[j].foundation);
+	    c->rem_prio = rem_cand[j].prio;
+	    pj_memcpy(&c->rem_addr, &rem_cand[j].addr, 
+		      sizeof(rem_cand[j].addr));
+	    pj_memcpy(&c->rem_base_addr, &rem_cand[j].base_addr, 
+		      sizeof(rem_cand[j].addr));
+	}
+    }
+
+    clist->count = count;
+
+    /* Sort checklist based on priority */
+    for (i=0; i<clist->count-1; ++i) {
+	unsigned highest = i;
+	for (j=i+1; j<clist->count; ++j) {
+	    if (clist->checks[j].check_prio > 
+		clist->checks[highest].check_prio) 
+	    {
+		highest = j;
+	    }
+	}
+
+	if (highest != i) {
+	    pj_ice_check tmp;
+
+	    pj_memcpy(&tmp, &clist->checks[i], sizeof(pj_ice_check));
+	    pj_memcpy(&clist->checks[i], &clist->checks[highest], 
+		      sizeof(pj_ice_check));
+	    pj_memcpy(&clist->checks[highest], &tmp, sizeof(pj_ice_check));
+	}
+    }
+
+    /* Prune the checklist */
+    for (i=0; i<clist->count; ++i) {
+	PJ_TODO(PRUNE_CHECKLIST);
+    }
+
+    pj_mutex_lock(ice->mutex);
+
+    return PJ_SUCCESS;
+}
+
+
+/* Start periodic check for the specified checklist */
+static pj_status_t start_periodic_check(pj_ice *ice, pj_ice_checklist *clist)
+{
+}
+
+
+/* Start ICE check */
+PJ_DEF(pj_status_t) pj_ice_start_check(pj_ice *ice)
+{
+    pj_ice_checklist *clist;
+    unsigned i, comp_id;
+    pj_str_t fnd;
+
+    PJ_ASSERT_RETURN(ice, PJ_EINVAL);
+
+    clist = &ice->cklist;
+
+    if (clist->count == 0)
+	return PJ_EICENOCHECKLIST;
+
+    /* Pickup the first pair and set the state to Waiting */
+    clist->checks[0].check_state = PJ_ICE_CHECK_STATE_WAITING;
+
+    /* Find all of the other pairs in that check list with the same
+     * component ID, but different foundations, and sets all of their
+     * states to Waiting as well.
+     */
+    comp_id = ice->cand[clist->checks[0].local_cand_id].comp_id;
+    fnd = ice->cand[clist->checks[0].local_cand_id].foundation;
+
+    for (i=1; i<clist->count; ++i) {
+	pj_ice_check *cki = &clist->checks[i];
+
+	if (ice->cand[cki->local_cand_id].comp_id != comp_id)
+	    continue;
+
+	if (pj_strcmp(&ice->cand[cki->local_cand_id].foundation, &fnd)==0)
+	    continue;
+
+	clist->checks[i].check_state = PJ_ICE_CHECK_STATE_WAITING;
+    }
+
+    /* Start periodic check */
+    return start_periodic_check(ice, clist);
+}
diff --git a/pjnath/src/pjnath/stun_auth.c b/pjnath/src/pjnath/stun_auth.c
index 9a94fe0..071019b 100644
--- a/pjnath/src/pjnath/stun_auth.c
+++ b/pjnath/src/pjnath/stun_auth.c
@@ -16,8 +16,8 @@
  * 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 <pjnath/stun_auth.h>
+#include <pjnath/errno.h>
 #include <pjlib-util/hmac_sha1.h>
 #include <pjlib-util/sha1.h>
 #include <pj/assert.h>
@@ -159,7 +159,7 @@
 	    create_challenge(pool, msg, PJ_STUN_SC_UNAUTHORIZED, NULL,
 			     &realm, &nonce, p_response);
 	}
-	return PJLIB_UTIL_ESTUNMSGINT;
+	return PJNATH_ESTUNMSGINT;
     }
 
     /* Next check that USERNAME is present */
@@ -170,7 +170,7 @@
 	    create_challenge(pool, msg, PJ_STUN_SC_MISSING_USERNAME, NULL,
 			     &realm, &nonce, p_response);
 	}
-	return PJLIB_UTIL_ESTUNNOUSERNAME;
+	return PJNATH_ESTUNNOUSERNAME;
     }
 
     /* Get REALM, if any */
@@ -201,7 +201,7 @@
 	    create_challenge(pool, msg, PJ_STUN_SC_UNKNOWN_USERNAME, NULL,
 			     &realm, &nonce, p_response);
 	}
-	return PJLIB_UTIL_ESTUNUSERNAME;
+	return PJNATH_ESTUNUSERNAME;
     }
 
 
@@ -216,7 +216,7 @@
 	    create_challenge(pool, msg, PJ_STUN_SC_MISSING_REALM, NULL,
 			     &realm, &nonce, p_response);
 	}
-	return PJLIB_UTIL_ESTUNNOREALM;
+	return PJNATH_ESTUNNOREALM;
 
     } else if (realm.slen != 0 && arealm != NULL) {
 	/* We want long term, and REALM is present */
@@ -227,7 +227,7 @@
 		create_challenge(pool, msg, PJ_STUN_SC_MISSING_NONCE, 
 				 NULL, &realm, &nonce, p_response);
 	    }
-	    return PJLIB_UTIL_ESTUNNONCE;
+	    return PJNATH_ESTUNNONCE;
 	}
 
 	/* Verify REALM matches */
@@ -237,7 +237,7 @@
 		create_challenge(pool, msg, PJ_STUN_SC_MISSING_REALM, 
 				 NULL, &realm, &nonce, p_response);
 	    }
-	    return PJLIB_UTIL_ESTUNNOREALM;
+	    return PJNATH_ESTUNNOREALM;
 	}
 
 	/* Valid case, will validate the message integrity later */
@@ -260,7 +260,7 @@
 		create_challenge(pool, msg, PJ_STUN_SC_MISSING_NONCE, 
 				 NULL, &realm, &nonce, p_response);
 	    }
-	    return PJLIB_UTIL_ESTUNNONCE;
+	    return PJNATH_ESTUNNONCE;
 	}
     }
 
@@ -286,7 +286,7 @@
 		create_challenge(pool, msg, PJ_STUN_SC_STALE_NONCE, 
 				 NULL, &realm, &nonce, p_response);
 	    }
-	    return PJLIB_UTIL_ESTUNNONCE;
+	    return PJNATH_ESTUNNONCE;
 	}
     }
 
@@ -331,7 +331,7 @@
 	    create_challenge(pool, msg, PJ_STUN_SC_INTEGRITY_CHECK_FAILURE,
 			     NULL, &realm, &nonce, p_response);
 	}
-	return PJLIB_UTIL_ESTUNMSGINT;
+	return PJNATH_ESTUNMSGINT;
     }
 
     /* Everything looks okay! */
diff --git a/pjnath/src/pjnath/stun_endpoint.c b/pjnath/src/pjnath/stun_endpoint.c
index 277e385..3be6407 100644
--- a/pjnath/src/pjnath/stun_endpoint.c
+++ b/pjnath/src/pjnath/stun_endpoint.c
@@ -16,8 +16,8 @@
  * 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 <pjnath/stun_endpoint.h>
+#include <pjnath/errno.h>
 #include <pj/assert.h>
 #include <pj/pool.h>
 
@@ -25,14 +25,14 @@
 /*
  * 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_DEF(pj_status_t) pj_stun_config_create( pj_pool_factory *factory,
+					   unsigned options,
+					   pj_ioqueue_t *ioqueue,
+					   pj_timer_heap_t *timer_heap,
+					   pj_stun_config **p_endpt)
 {
     pj_pool_t *pool;
-    pj_stun_endpoint *endpt;
+    pj_stun_config *endpt;
 
     PJ_ASSERT_RETURN(factory && p_endpt, PJ_EINVAL);
 
@@ -40,7 +40,7 @@
     if (!pool)
 	return PJ_ENOMEM;
     
-    endpt = PJ_POOL_ZALLOC_T(pool, pj_stun_endpoint);
+    endpt = PJ_POOL_ZALLOC_T(pool, pj_stun_config);
     endpt->pool = pool;
     endpt->pf = factory;
     endpt->options = options;
@@ -58,7 +58,7 @@
 /*
  * Destroy STUN endpoint instance.
  */
-PJ_DEF(pj_status_t) pj_stun_endpoint_destroy(pj_stun_endpoint *endpt)
+PJ_DEF(pj_status_t) pj_stun_config_destroy(pj_stun_config *endpt)
 {
     PJ_ASSERT_RETURN(endpt, PJ_EINVAL);
 
diff --git a/pjnath/src/pjnath/stun_msg.c b/pjnath/src/pjnath/stun_msg.c
index 1c750d8..b361898 100644
--- a/pjnath/src/pjnath/stun_msg.c
+++ b/pjnath/src/pjnath/stun_msg.c
@@ -16,9 +16,9 @@
  * 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 <pjnath/stun_msg.h>
+#include <pjnath/errno.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>
@@ -558,7 +558,7 @@
     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);
+    pj_memcpy(&attr->sockaddr, addr, addr_len);
     attr->xor_ed = xor_ed;
 
     *p_attr = attr;
@@ -606,19 +606,19 @@
 
     /* Check that the attribute length is valid */
     if (attr->hdr.length != STUN_GENERIC_IP_ADDR_LEN)
-	return PJLIB_UTIL_ESTUNINATTRLEN;
+	return PJNATH_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;
+	return PJNATH_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);
+    pj_sockaddr_in_init(&attr->sockaddr.ipv4, NULL, 0);
+    pj_memcpy(&attr->sockaddr.ipv4.sin_port, buf+ATTR_HDR_LEN+2, 2);
+    pj_memcpy(&attr->sockaddr.ipv4.sin_addr, buf+ATTR_HDR_LEN+4, 4);
 
     /* Done */
     *p_attr = attr;
@@ -644,22 +644,22 @@
 
     /* Check that the attribute length is valid */
     if (attr->hdr.length != STUN_GENERIC_IP_ADDR_LEN)
-	return PJLIB_UTIL_ESTUNINATTRLEN;
+	return PJNATH_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;
+	return PJNATH_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);
+    pj_sockaddr_in_init(&attr->sockaddr.ipv4, NULL, 0);
+    pj_memcpy(&attr->sockaddr.ipv4.sin_port, buf+ATTR_HDR_LEN+2, 2);
+    pj_memcpy(&attr->sockaddr.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);
+    attr->sockaddr.ipv4.sin_port ^= pj_htons(0x2112);
+    attr->sockaddr.ipv4.sin_addr.s_addr ^= pj_htonl(0x2112A442);
 
     /* Done */
     *p_attr = attr;
@@ -693,17 +693,17 @@
     *buf++ = '\0';
 
     /* Family (IPv4 only for now) */
-    PJ_ASSERT_RETURN(ca->addr.addr.sa_family == PJ_AF_INET, PJ_EINVAL);
+    PJ_ASSERT_RETURN(ca->sockaddr.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;
+	addr = ca->sockaddr.ipv4.sin_addr.s_addr;
+	port = ca->sockaddr.ipv4.sin_port;
 
-	port ^= 0x2112;
+	port ^= pj_htons(0x2112);
 	addr ^= pj_htonl(0x2112A442);
 
 	/* Port */
@@ -716,11 +716,11 @@
 
     } else {
 	/* Port */
-	pj_memcpy(buf, &ca->addr.ipv4.sin_port, 2);
+	pj_memcpy(buf, &ca->sockaddr.ipv4.sin_port, 2);
 	buf += 2;
 
 	/* Address */
-	pj_memcpy(buf, &ca->addr.ipv4.sin_addr, 4);
+	pj_memcpy(buf, &ca->sockaddr.ipv4.sin_addr, 4);
 	buf += 4;
     }
 
@@ -892,7 +892,7 @@
 
     /* Check that the attribute length is valid */
     if (attr->hdr.length != ATTR_HDR_LEN)
-	return PJLIB_UTIL_ESTUNINATTRLEN;
+	return PJNATH_ESTUNINATTRLEN;
 
     /* Done */
     *p_attr = attr;
@@ -992,7 +992,7 @@
 
     /* Check that the attribute length is valid */
     if (attr->hdr.length != STUN_UINT_LEN)
-	return PJLIB_UTIL_ESTUNINATTRLEN;
+	return PJNATH_ESTUNINATTRLEN;
 
     /* Done */
     *p_attr = attr;
@@ -1088,7 +1088,7 @@
 
     /* Check that the attribute length is valid */
     if (attr->hdr.length != STUN_MSG_INTEGRITY_LEN)
-	return PJLIB_UTIL_ESTUNINATTRLEN;
+	return PJNATH_ESTUNINATTRLEN;
 
     /* Done */
     *p_attr = attr;
@@ -1563,18 +1563,18 @@
     PJ_ASSERT_RETURN(pdu, PJ_EINVAL);
 
     if (pdu_len < sizeof(pj_stun_msg_hdr))
-	return PJLIB_UTIL_ESTUNINMSGLEN;
+	return PJNATH_ESTUNINMSGLEN;
 
     /* First byte of STUN message is always 0x00 or 0x01. */
     if (*pdu != 0x00 && *pdu != 0x01)
-	return PJLIB_UTIL_ESTUNINMSGTYPE;
+	return PJNATH_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;
+	return PJNATH_ESTUNINMSGLEN;
     }
 
     /* If magic is set, then there is great possibility that this is
@@ -1589,13 +1589,13 @@
 	    pj_uint32_t crc;
 
 	    if (attr_len != 4)
-		return PJLIB_UTIL_ESTUNINATTRLEN;
+		return PJNATH_ESTUNINATTRLEN;
 
 	    crc = pj_crc32_calc(pdu, msg_len + 20);
 	    crc ^= STUN_XOR_FINGERPRINT;
 
 	    if (crc != fingerprint)
-		return PJLIB_UTIL_ESTUNFINGERPRINT;
+		return PJNATH_ESTUNFINGERPRINT;
 	}
     }
 
@@ -1618,7 +1618,7 @@
     PJ_ASSERT_RETURN(pool && p_response, PJ_EINVAL);
 
     PJ_ASSERT_RETURN(PJ_STUN_IS_REQUEST(msg_type), 
-		     PJLIB_UTIL_ESTUNINMSGTYPE);
+		     PJNATH_ESTUNINMSGTYPE);
 
     /* Create response or error response */
     if (err_code)
@@ -1728,7 +1728,7 @@
 					    PJ_STUN_SC_BAD_REQUEST, 
 					    &err_msg, p_response);
 	    }
-	    return PJLIB_UTIL_ESTUNINATTRLEN;
+	    return PJNATH_ESTUNINATTRLEN;
 	}
 
 	/* Get the attribute descriptor */
@@ -1757,7 +1757,7 @@
 		    }
 		}
 
-		return PJLIB_UTIL_ESTUNUNKNOWNATTR;
+		return PJNATH_ESTUNUNKNOWNATTR;
 	    }
 
 	} else {
@@ -1805,7 +1805,7 @@
 						    PJ_STUN_SC_BAD_REQUEST,
 						    NULL, p_response);
 		    }
-		    return PJLIB_UTIL_ESTUNDUPATTR;
+		    return PJNATH_ESTUNDUPATTR;
 		}
 		has_msg_int = PJ_TRUE;
 
@@ -1819,7 +1819,7 @@
 						    PJ_STUN_SC_BAD_REQUEST,
 						    NULL, p_response);
 		    }
-		    return PJLIB_UTIL_ESTUNDUPATTR;
+		    return PJNATH_ESTUNDUPATTR;
 		}
 		has_fingerprint = PJ_TRUE;
 	    } else {
@@ -1833,8 +1833,8 @@
 						    PJ_STUN_SC_BAD_REQUEST,
 						    NULL, p_response);
 		    }
-		    return has_fingerprint ? PJLIB_UTIL_ESTUNFINGERPOS :
-					     PJLIB_UTIL_ESTUNMSGINTPOS;
+		    return has_fingerprint ? PJNATH_ESTUNFINGERPOS :
+					     PJNATH_ESTUNMSGINTPOS;
 		}
 	    }
 
@@ -1848,7 +1848,7 @@
 						PJ_STUN_SC_BAD_REQUEST,
 						&e, p_response);
 		}
-		return PJLIB_UTIL_ESTUNTOOMANYATTR;
+		return PJNATH_ESTUNTOOMANYATTR;
 	    }
 
 	    /* Add the attribute */
@@ -2027,12 +2027,12 @@
 	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);
+	PJ_ASSERT_RETURN(afingerprint == NULL, PJNATH_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);
+			     PJNATH_ESTUNMSGINTPOS);
 	    amsgint = (pj_stun_msgint_attr*) attr_hdr;
 
 	} else if (attr_hdr->type == PJ_STUN_ATTR_FINGERPRINT) {
@@ -2070,13 +2070,13 @@
 	if (i < msg->attr_count-2) {
 	    /* Should not happen for message generated by us */
 	    pj_assert(PJ_FALSE);
-	    return PJLIB_UTIL_ESTUNMSGINTPOS;
+	    return PJNATH_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;
+		return PJNATH_ESTUNMSGINTPOS;
 	    } else {
 		afingerprint = (pj_stun_fingerprint_attr*) msg->attr[i+1];
 	    }
@@ -2086,7 +2086,7 @@
 	if (auname == NULL) {
 	    /* Should not happen for message generated by us */
 	    pj_assert(PJ_FALSE);
-	    return PJLIB_UTIL_ESTUNNOUSERNAME;
+	    return PJNATH_ESTUNNOUSERNAME;
 	}
 
 	/* Password must be specified */
diff --git a/pjnath/src/pjnath/stun_msg_dump.c b/pjnath/src/pjnath/stun_msg_dump.c
index 0ee0ebe..5e83958 100644
--- a/pjnath/src/pjnath/stun_msg_dump.c
+++ b/pjnath/src/pjnath/stun_msg_dump.c
@@ -16,8 +16,8 @@
  * 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 <pjnath/stun_msg.h>
+#include <pjnath/errno.h>
 #include <pj/assert.h>
 #include <pj/string.h>
 
@@ -80,13 +80,13 @@
 
 	    attr = (const pj_stun_sockaddr_attr*)ahdr;
 
-	    if (attr->addr.addr.sa_family == PJ_AF_INET) {
+	    if (attr->sockaddr.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));
+				       pj_inet_ntoa(attr->sockaddr.ipv4.sin_addr),
+				       pj_ntohs(attr->sockaddr.ipv4.sin_port));
 
-	    } else if (attr->addr.addr.sa_family == PJ_AF_INET6) {
+	    } else if (attr->sockaddr.addr.sa_family == PJ_AF_INET6) {
 		len = pj_ansi_snprintf(p, end-p,
 				       ", IPv6 addr present\n");
 	    } else {
diff --git a/pjnath/src/pjnath/stun_session.c b/pjnath/src/pjnath/stun_session.c
index b4e7356..9bcff54 100644
--- a/pjnath/src/pjnath/stun_session.c
+++ b/pjnath/src/pjnath/stun_session.c
@@ -16,12 +16,12 @@
  * 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 <pjnath/stun_session.h>
 #include <pjlib.h>
 
 struct pj_stun_session
 {
-    pj_stun_endpoint	*endpt;
+    pj_stun_config	*cfg;
     pj_pool_t		*pool;
     pj_mutex_t		*mutex;
     pj_stun_session_cb	 cb;
@@ -119,7 +119,7 @@
     pj_stun_tx_data *tdata;
 
     /* Create pool and initialize basic tdata attributes */
-    pool = pj_pool_create(sess->endpt->pf, "tdata%p", 
+    pool = pj_pool_create(sess->cfg->pf, "tdata%p", 
 			  TDATA_POOL_SIZE, TDATA_POOL_INC, NULL);
     PJ_ASSERT_RETURN(pool, PJ_ENOMEM);
 
@@ -170,7 +170,7 @@
 	tdata->client_tsx = NULL;
     }
     if (tdata->res_timer.id != PJ_FALSE) {
-	pj_timer_heap_cancel(tdata->sess->endpt->timer_heap, 
+	pj_timer_heap_cancel(tdata->sess->cfg->timer_heap, 
 			     &tdata->res_timer);
 	tdata->res_timer.id = PJ_FALSE;
 	pj_list_erase(tdata);
@@ -223,8 +223,8 @@
     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)) 
+    if (sess->srv_name.slen && (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);
@@ -300,7 +300,7 @@
 
 /* **************************************************************************/
 
-PJ_DEF(pj_status_t) pj_stun_session_create( pj_stun_endpoint *endpt,
+PJ_DEF(pj_status_t) pj_stun_session_create( pj_stun_config *cfg,
 					    const char *name,
 					    const pj_stun_session_cb *cb,
 					    pj_bool_t fingerprint,
@@ -310,16 +310,16 @@
     pj_stun_session *sess;
     pj_status_t status;
 
-    PJ_ASSERT_RETURN(endpt && cb && p_sess, PJ_EINVAL);
+    PJ_ASSERT_RETURN(cfg && cb && p_sess, PJ_EINVAL);
 
     if (name==NULL)
 	name = "sess%p";
 
-    pool = pj_pool_create(endpt->pf, name, 4000, 4000, NULL);
+    pool = pj_pool_create(cfg->pf, name, 4000, 4000, NULL);
     PJ_ASSERT_RETURN(pool, PJ_ENOMEM);
 
     sess = PJ_POOL_ZALLOC_T(pool, pj_stun_session);
-    sess->endpt = endpt;
+    sess->cfg = cfg;
     sess->pool = pool;
     pj_memcpy(&sess->cb, cb, sizeof(*cb));
     sess->use_fingerprint = fingerprint;
@@ -383,8 +383,11 @@
 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);
+    PJ_ASSERT_RETURN(sess, PJ_EINVAL);
+    if (srv_name)
+	pj_strdup(sess->pool, &sess->srv_name, srv_name);
+    else
+	sess->srv_name.slen = 0;
     return PJ_SUCCESS;
 }
 
@@ -489,14 +492,12 @@
     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;
+    if (dst->addr.sa_family == PJ_AF_INET) {
+	dst_name = pj_inet_ntoa(dst->ipv4.sin_addr);
+	dst_port = pj_ntohs(dst->ipv4.sin_port);
+    } else if (dst->addr.sa_family == PJ_AF_INET6) {
 	dst_name = "IPv6";
-	dst_port = pj_ntohs(dst6->sin6_port);
+	dst_port = pj_ntohs(dst->ipv6.sin6_port);
     } else {
 	LOG_ERR_(sess, "Invalid address family", PJ_EINVAL);
 	return;
@@ -558,7 +559,7 @@
     if (PJ_STUN_IS_REQUEST(tdata->msg->hdr.type)) {
 
 	/* Create STUN client transaction */
-	status = pj_stun_client_tsx_create(sess->endpt, tdata->pool, 
+	status = pj_stun_client_tsx_create(sess->cfg, 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);
@@ -592,10 +593,10 @@
 	    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;
+	    timeout.sec = sess->cfg->res_cache_msec / 1000;
+	    timeout.msec = sess->cfg->res_cache_msec % 1000;
 
-	    status = pj_timer_heap_schedule(sess->endpt->timer_heap, 
+	    status = pj_timer_heap_schedule(sess->cfg->timer_heap, 
 					    &tdata->res_timer,
 					    &timeout);
 	    if (status != PJ_SUCCESS) {
@@ -829,7 +830,7 @@
 
     PJ_ASSERT_RETURN(sess && packet && pkt_size, PJ_EINVAL);
 
-    tmp_pool = pj_pool_create(sess->endpt->pf, "tmpstun", 1024, 1024, NULL);
+    tmp_pool = pj_pool_create(sess->cfg->pf, "tmpstun", 1024, 1024, NULL);
     if (!tmp_pool)
 	return PJ_ENOMEM;
 
diff --git a/pjnath/src/pjnath/stun_transaction.c b/pjnath/src/pjnath/stun_transaction.c
index 0000e3a..2813f7e 100644
--- a/pjnath/src/pjnath/stun_transaction.c
+++ b/pjnath/src/pjnath/stun_transaction.c
@@ -16,8 +16,8 @@
  * 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 <pjnath/stun_transaction.h>
+#include <pjnath/errno.h>
 #include <pj/assert.h>
 #include <pj/log.h>
 #include <pj/pool.h>
@@ -31,7 +31,7 @@
 struct pj_stun_client_tsx
 {
     char		 obj_name[PJ_MAX_OBJ_NAME];
-    pj_stun_endpoint	*endpt;
+    pj_stun_config	*cfg;
     pj_stun_tsx_cb	 cb;
     void		*user_data;
 
@@ -63,18 +63,18 @@
 /*
  * Create a STUN client transaction.
  */
-PJ_DEF(pj_status_t) pj_stun_client_tsx_create(pj_stun_endpoint *endpt,
+PJ_DEF(pj_status_t) pj_stun_client_tsx_create(pj_stun_config *cfg,
 					      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(cfg && 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;
+    tsx->cfg = cfg;
     pj_memcpy(&tsx->cb, cb, sizeof(*cb));
 
     tsx->timer.cb = &retransmit_timer_callback;
@@ -97,7 +97,7 @@
     PJ_ASSERT_RETURN(tsx, PJ_EINVAL);
 
     if (tsx->timer.id != 0) {
-	pj_timer_heap_cancel(tsx->endpt->timer_heap, &tsx->timer);
+	pj_timer_heap_cancel(tsx->cfg->timer_heap, &tsx->timer);
 	tsx->timer.id = 0;
     }
     return PJ_SUCCESS;
@@ -149,7 +149,7 @@
 	/* Calculate retransmit/timeout delay */
 	if (tsx->transmit_count == 0) {
 	    tsx->retransmit_time.sec = 0;
-	    tsx->retransmit_time.msec = tsx->endpt->rto_msec;
+	    tsx->retransmit_time.msec = tsx->cfg->rto_msec;
 
 	} else if (tsx->transmit_count < PJ_STUN_MAX_RETRANSMIT_COUNT-1) {
 	    unsigned msec;
@@ -168,7 +168,7 @@
 	 * cancel it (as opposed to when schedule_timer() failed we cannot
 	 * cancel transmission).
 	 */;
-	status = pj_timer_heap_schedule(tsx->endpt->timer_heap, &tsx->timer,
+	status = pj_timer_heap_schedule(tsx->cfg->timer_heap, &tsx->timer,
 					&tsx->retransmit_time);
 	if (status != PJ_SUCCESS) {
 	    tsx->timer.id = 0;
@@ -182,7 +182,7 @@
     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);
+	    pj_timer_heap_cancel(tsx->cfg->timer_heap, &tsx->timer);
 	    tsx->timer.id = 0;
 	}
 	stun_perror(tsx, "STUN error sending message", status);
@@ -235,7 +235,7 @@
 	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);
+	    tsx->cb.on_complete(tsx, PJNATH_ESTUNNOTRESPOND, NULL);
 	}
 	return;
     }
@@ -268,7 +268,7 @@
     {
 	PJ_LOG(4,(tsx->obj_name, 
 		  "STUN rx_msg() error: not response message"));
-	return PJLIB_UTIL_ESTUNNOTRESPONSE;
+	return PJNATH_ESTUNNOTRESPONSE;
     }
 
 
@@ -276,7 +276,7 @@
      * We can cancel retransmit timer now.
      */
     if (tsx->timer.id) {
-	pj_timer_heap_cancel(tsx->endpt->timer_heap, &tsx->timer);
+	pj_timer_heap_cancel(tsx->cfg->timer_heap, &tsx->timer);
 	tsx->timer.id = 0;
     }
 
@@ -300,7 +300,7 @@
     if (err_attr == NULL) {
 	status = PJ_SUCCESS;
     } else {
-	status = PJLIB_UTIL_ESTUNTSXFAILED;
+	status = PJNATH_ESTUNTSXFAILED;
     }
 
     /* Call callback */
diff --git a/pjnath/src/pjstun-client/client_main.c b/pjnath/src/pjstun-client/client_main.c
index be65b51..9bb249f 100644
--- a/pjnath/src/pjstun-client/client_main.c
+++ b/pjnath/src/pjstun-client/client_main.c
@@ -16,6 +16,7 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA 
  */
+#include <pjnath.h>
 #include <pjlib-util.h>
 #include <pjlib.h>
 
diff --git a/pjnath/src/pjstun-srv-test/bind_usage.c b/pjnath/src/pjstun-srv-test/bind_usage.c
index fc10fb9..3c1825f 100644
--- a/pjnath/src/pjstun-srv-test/bind_usage.c
+++ b/pjnath/src/pjstun-srv-test/bind_usage.c
@@ -85,7 +85,7 @@
     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,
+    status = pj_stun_session_create(si->cfg, "bind%p", &sess_cb, PJ_FALSE,
 				    &bu->session);
     if (status != PJ_SUCCESS) {
 	pj_stun_usage_destroy(bu->usage);
diff --git a/pjnath/src/pjstun-srv-test/server.c b/pjnath/src/pjstun-srv-test/server.c
index 5fdb233..d0fe426 100644
--- a/pjnath/src/pjstun-srv-test/server.c
+++ b/pjnath/src/pjstun-srv-test/server.c
@@ -83,8 +83,8 @@
     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);
+    status = pj_stun_config_create(srv->si.pf, 0, srv->si.ioqueue, 
+				     srv->si.timer_heap, &srv->si.cfg);
     if (status != PJ_SUCCESS)
 	goto on_error;
 
@@ -174,7 +174,7 @@
 	srv->threads[i] = NULL;
     }
 
-    pj_stun_endpoint_destroy(srv->si.endpt);
+    pj_stun_config_destroy(srv->si.cfg);
     pj_timer_heap_destroy(srv->si.timer_heap);
     pj_ioqueue_destroy(srv->si.ioqueue);
     pj_pool_release(srv->pool);
diff --git a/pjnath/src/pjstun-srv-test/server.h b/pjnath/src/pjstun-srv-test/server.h
index a88d87c..6c61da3 100644
--- a/pjnath/src/pjstun-srv-test/server.h
+++ b/pjnath/src/pjstun-srv-test/server.h
@@ -19,6 +19,7 @@
 #ifndef __STUN_SERVER_H__
 #define __STUN_SERVER_H__
 
+#include <pjnath.h>
 #include <pjlib-util.h>
 #include <pjlib.h>
 
@@ -30,7 +31,7 @@
 typedef struct pj_stun_server_info
 {
     pj_pool_factory	*pf;
-    pj_stun_endpoint	*endpt;
+    pj_stun_config	*cfg;
     pj_ioqueue_t	*ioqueue;
     pj_timer_heap_t	*timer_heap;
     unsigned		 thread_cnt;
diff --git a/pjnath/src/pjstun-srv-test/turn_usage.c b/pjnath/src/pjstun-srv-test/turn_usage.c
index e3d2e59..c1f83d1 100644
--- a/pjnath/src/pjstun-srv-test/turn_usage.c
+++ b/pjnath/src/pjstun-srv-test/turn_usage.c
@@ -69,7 +69,7 @@
 struct turn_usage
 {
     pj_pool_factory	*pf;
-    pj_stun_endpoint	*endpt;
+    pj_stun_config	*cfg;
     pj_ioqueue_t	*ioqueue;
     pj_timer_heap_t	*timer_heap;
     pj_pool_t		*pool;
@@ -165,7 +165,7 @@
     tu->pool = pool;
     tu->type = type;
     tu->pf = si->pf;
-    tu->endpt = si->endpt;
+    tu->cfg = si->cfg;
     tu->ioqueue = si->ioqueue;
     tu->timer_heap = si->timer_heap;
     tu->next_port = START_PORT;
@@ -197,7 +197,7 @@
     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,
+    status = pj_stun_session_create(si->cfg, "turns%p", &sess_cb, PJ_FALSE,
 				    &tu->default_session);
     if (status != PJ_SUCCESS) {
 	pj_stun_usage_destroy(tu->usage);
@@ -208,6 +208,8 @@
     sd->tu = tu;
     pj_stun_session_set_user_data(tu->default_session, sd);
 
+    pj_stun_session_set_server_name(tu->default_session, NULL);
+
     /* Create mutex */
     status = pj_mutex_create_recursive(pool, "turn%p", &tu->mutex);
     if (status != PJ_SUCCESS) {
@@ -620,7 +622,7 @@
     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, 
+    status = pj_stun_session_create(tu->cfg, client->obj_name, 
 				    &sess_cb, PJ_FALSE,
 				    &client->session);
     if (status != PJ_SUCCESS) {
diff --git a/pjsip/src/pjsip/sip_transport.c b/pjsip/src/pjsip/sip_transport.c
index 2229a2b..6238216 100644
--- a/pjsip/src/pjsip/sip_transport.c
+++ b/pjsip/src/pjsip/sip_transport.c
@@ -567,7 +567,7 @@
     tdata->tp_info.transport = tr;
     pj_memcpy(&tdata->tp_info.dst_addr, addr, addr_len);
     tdata->tp_info.dst_addr_len = addr_len;
-    if (((pj_sockaddr*)addr)->sa_family == PJ_AF_INET) {
+    if (((pj_sockaddr*)addr)->addr.sa_family == PJ_AF_INET) {
 	const char *str_addr;
 	str_addr = pj_inet_ntoa(((pj_sockaddr_in*)addr)->sin_addr);
 	pj_ansi_strcpy(tdata->tp_info.dst_name, str_addr);
@@ -1361,7 +1361,7 @@
 	    /* For datagram INET transports, try lookup with zero address.
 	     */
 	    else if ((flag & PJSIP_TRANSPORT_DATAGRAM) && 
-		     (remote_addr->sa_family == PJ_AF_INET)) 
+		     (remote_addr->addr.sa_family == PJ_AF_INET)) 
 	    {
 		pj_sockaddr_in *addr = (pj_sockaddr_in*)&key.addr;
 
diff --git a/pjsip/src/pjsip/sip_transport_tcp.c b/pjsip/src/pjsip/sip_transport_tcp.c
index 8aa679d..481387c 100644
--- a/pjsip/src/pjsip/sip_transport_tcp.c
+++ b/pjsip/src/pjsip/sip_transport_tcp.c
@@ -786,7 +786,7 @@
 		     addr_len && p_transport, PJ_EINVAL);
 
     /* Check that address is a sockaddr_in */
-    PJ_ASSERT_RETURN(rem_addr->sa_family == PJ_AF_INET &&
+    PJ_ASSERT_RETURN(rem_addr->addr.sa_family == PJ_AF_INET &&
 		     addr_len == sizeof(pj_sockaddr_in), PJ_EINVAL);
 
 
diff --git a/pjsip/src/pjsip/sip_transport_udp.c b/pjsip/src/pjsip/sip_transport_udp.c
index 216f2cf..48d2b2d 100644
--- a/pjsip/src/pjsip/sip_transport_udp.c
+++ b/pjsip/src/pjsip/sip_transport_udp.c
@@ -469,7 +469,7 @@
     tp->base.key.type = PJSIP_TRANSPORT_UDP;
 
     /* Remote address is left zero (except the family) */
-    tp->base.key.rem_addr.sa_family = PJ_AF_INET;
+    tp->base.key.rem_addr.addr.sa_family = PJ_AF_INET;
 
     /* Type name. */
     tp->base.type_name = "UDP";