Index: pjproject/branches/iceproject/pjlib-util/build/pjlib_util.dsp
===================================================================
--- pjproject/branches/iceproject/pjlib-util/build/pjlib_util.dsp	(revision 928)
+++ pjproject/branches/iceproject/pjlib-util/build/pjlib_util.dsp	(revision 929)
@@ -208,4 +208,8 @@
 # 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
@@ -213,4 +217,8 @@
 
 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
Index: pjproject/branches/iceproject/pjlib-util/include/pjlib-util/stun_doc.h
===================================================================
--- pjproject/branches/iceproject/pjlib-util/include/pjlib-util/stun_doc.h	(revision 929)
+++ pjproject/branches/iceproject/pjlib-util/include/pjlib-util/stun_doc.h	(revision 929)
@@ -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/branches/iceproject/pjlib-util/include/pjlib-util/stun_endpoint.h
===================================================================
--- pjproject/branches/iceproject/pjlib-util/include/pjlib-util/stun_endpoint.h	(revision 928)
+++ pjproject/branches/iceproject/pjlib-util/include/pjlib-util/stun_endpoint.h	(revision 929)
@@ -1,3 +1,3 @@
-/* $Id */
+/* $Id$ */
 /* 
  * Copyright (C) 2003-2005 Benny Prijono <benny@prijono.org>
@@ -21,6 +21,6 @@
 
 /**
- * @file stun_msg.h
- * @brief STUN message components.
+ * @file stun_endpoint.h
+ * @brief STUN endpoint.
  */
 
Index: pjproject/branches/iceproject/pjlib-util/include/pjlib-util/stun_msg.h
===================================================================
--- pjproject/branches/iceproject/pjlib-util/include/pjlib-util/stun_msg.h	(revision 928)
+++ pjproject/branches/iceproject/pjlib-util/include/pjlib-util/stun_msg.h	(revision 929)
@@ -1,3 +1,3 @@
-/* $Id */
+/* $Id$ */
 /* 
  * Copyright (C) 2003-2005 Benny Prijono <benny@prijono.org>
@@ -28,8 +28,4 @@
 #include <pj/sock.h>
 
-/**
- * @defgroup PJLIB_UTIL_STUN Simple Traversal Underneath NAT (STUN)
- * @ingroup PJLIB_UTIL
- */
 
 PJ_BEGIN_DECL
Index: pjproject/branches/iceproject/pjlib-util/include/pjlib-util/stun_server.h
===================================================================
--- pjproject/branches/iceproject/pjlib-util/include/pjlib-util/stun_server.h	(revision 929)
+++ pjproject/branches/iceproject/pjlib-util/include/pjlib-util/stun_server.h	(revision 929)
@@ -0,0 +1,104 @@
+/* $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__
+
+/**
+ * @file stun_server.h
+ * @brief STUN server side services.
+ */
+
+#include <pjlib-util/stun_msg.h>
+#include <pjlib-util/stun_endpoint.h>
+
+
+PJ_BEGIN_DECL
+
+
+/* **************************************************************************/
+/**
+ * @defgroup PJLIB_UTIL_STUN_SERVER STUN Server Side Services
+ * @brief STUN server side services
+ * @ingroup PJLIB_UTIL_STUN
+ * @{
+ */
+
+typedef struct pj_stun_service pj_stun_service;
+
+
+/**
+ * STUN service handler.
+ */
+typedef struct pj_stun_service_handler
+{
+    /**
+     * The STUN message type.
+     */
+    int	     msg_type;
+
+    /** 
+     * Callback to be called to handle this STUN message type.
+     *
+     * @param svc   The service.
+     * @param msg   The STUN message.
+     */
+    void    (*handle_msg)(pj_stun_service *svc, const pj_stun_msg *msg);
+
+} pj_stun_service_handler;
+
+
+/**
+ * Create STUN service.
+ */
+PJ_DECL(pj_status_t) pj_stun_service_create(pj_pool_t *pool,
+					    unsigned handler_cnt,
+					    pj_stun_service_handler cb[],
+					    void *user_data,
+					    pj_stun_service **p_svc);
+
+/**
+ * Destroy STUN service
+ */
+PJ_DECL(pj_status_t) pj_stun_service_destroy(pj_stun_service *svc);
+
+
+/**
+ * Get user data associated with the STUN service.
+ */
+PJ_DECL(void*) pj_stun_service_get_user_data(pj_stun_service *svc);
+
+
+/**
+ * Instruct the STUN service to handle incoming STUN message.
+ */
+PJ_DECL(pj_status_t) pj_stun_service_handle_msg(pj_stun_service *svc,
+						const pj_stun_msg *msg);
+
+
+
+/**
+ * @}
+ */
+
+
+PJ_END_DECL
+
+
+#endif	/* __PJ_STUN_SERVER_H__ */
+
Index: pjproject/branches/iceproject/pjlib-util/include/pjlib-util/stun_simple.h
===================================================================
--- pjproject/branches/iceproject/pjlib-util/include/pjlib-util/stun_simple.h	(revision 928)
+++ pjproject/branches/iceproject/pjlib-util/include/pjlib-util/stun_simple.h	(revision 929)
@@ -1,3 +1,3 @@
-/* $Id */
+/* $Id$ */
 /* 
  * Copyright (C) 2003-2005 Benny Prijono <benny@prijono.org>
@@ -28,13 +28,8 @@
 #include <pj/sock.h>
 
-/**
- * @defgroup PJLIB_UTIL_STUN_CLIENT Mini/Tiny STUN Client
- * @ingroup PJLIB_UTIL
- * @{
- */
 
 PJ_BEGIN_DECL
 
-/**
+/*
  * This enumeration describes STUN message types.
  */
@@ -50,5 +45,5 @@
 
 
-/**
+/*
  * This enumeration describes STUN attribute types.
  */
@@ -69,5 +64,5 @@
 
 
-/**
+/*
  * This structre describes STUN message header.
  */
@@ -80,5 +75,5 @@
 
 
-/**
+/*
  * This structre describes STUN attribute header.
  */
@@ -90,5 +85,5 @@
 
 
-/**
+/*
  * This structre describes STUN MAPPED-ADDR attribute.
  */
@@ -147,4 +142,15 @@
 PJ_DECL(void*) pj_stun_msg_find_attr( pj_stun_msg *msg, pj_stun_attr_type t);
 
+
+/**
+ * @defgroup PJLIB_UTIL_STUN_CLIENT Simple STUN Helper
+ * @ingroup PJLIB_UTIL_STUN
+ * @brief A simple and small footprint STUN resolution helper
+ * @{
+ *
+ * This is the older implementation of STUN client, with only one function
+ * provided (pj_stun_get_mapped_addr()) to retrieve the public IP address
+ * of multiple sockets.
+ */
 
 /**
Index: pjproject/branches/iceproject/pjlib-util/include/pjlib-util/stun_transaction.h
===================================================================
--- pjproject/branches/iceproject/pjlib-util/include/pjlib-util/stun_transaction.h	(revision 928)
+++ pjproject/branches/iceproject/pjlib-util/include/pjlib-util/stun_transaction.h	(revision 929)
@@ -1,3 +1,3 @@
-/* $Id */
+/* $Id$ */
 /* 
  * Copyright (C) 2003-2005 Benny Prijono <benny@prijono.org>
@@ -38,4 +38,16 @@
  * @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.
+
+
  */
 
@@ -50,7 +62,29 @@
 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, 
 			       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,
@@ -62,5 +96,17 @@
 
 /**
- * Create a STUN client transaction.
+ * 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 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,
@@ -69,5 +115,9 @@
 
 /**
- * .
+ * 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);
@@ -75,5 +125,13 @@
 
 /**
- * .
+ * 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,
@@ -82,5 +140,10 @@
 
 /**
- * .
+ * 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);
@@ -88,12 +151,39 @@
 
 /**
- * .
+ * 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 msg		The STUN message.
+ *
+ * @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,
 						 const pj_stun_msg *msg);
 
 
 /**
- * .
+ * 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,
Index: pjproject/branches/iceproject/pjlib-util/src/pjlib-util/stun_endpoint.c
===================================================================
--- pjproject/branches/iceproject/pjlib-util/src/pjlib-util/stun_endpoint.c	(revision 928)
+++ pjproject/branches/iceproject/pjlib-util/src/pjlib-util/stun_endpoint.c	(revision 929)
@@ -1,3 +1,3 @@
-/* $Id */
+/* $Id$ */
 /* 
  * Copyright (C) 2003-2005 Benny Prijono <benny@prijono.org>
Index: pjproject/branches/iceproject/pjlib-util/src/pjlib-util/stun_msg.c
===================================================================
--- pjproject/branches/iceproject/pjlib-util/src/pjlib-util/stun_msg.c	(revision 928)
+++ pjproject/branches/iceproject/pjlib-util/src/pjlib-util/stun_msg.c	(revision 929)
@@ -1,3 +1,3 @@
-/* $Id */
+/* $Id$ */
 /* 
  * Copyright (C) 2003-2005 Benny Prijono <benny@prijono.org>
Index: pjproject/branches/iceproject/pjlib-util/src/pjlib-util/stun_transaction.c
===================================================================
--- pjproject/branches/iceproject/pjlib-util/src/pjlib-util/stun_transaction.c	(revision 928)
+++ pjproject/branches/iceproject/pjlib-util/src/pjlib-util/stun_transaction.c	(revision 929)
@@ -1,3 +1,3 @@
-/* $Id */
+/* $Id$ */
 /* 
  * Copyright (C) 2003-2005 Benny Prijono <benny@prijono.org>
@@ -39,4 +39,5 @@
     pj_uint32_t		 tsx_id[4];
 
+    pj_bool_t		 require_retransmit;
     pj_timer_entry	 timer;
     unsigned		 transmit_count;
@@ -109,5 +110,5 @@
 
 /*
- * .
+ * Set user data.
  */
 PJ_DEF(pj_status_t) pj_stun_client_tsx_set_data(pj_stun_client_tsx *tsx,
@@ -121,5 +122,5 @@
 
 /*
- * .
+ * Get the user data
  */
 PJ_DEF(void*) pj_stun_client_tsx_get_data(pj_stun_client_tsx *tsx)
@@ -139,31 +140,33 @@
     PJ_ASSERT_RETURN(tsx->timer.id == 0, PJ_EBUSY);
 
-    /* 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) {
-	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 % 100;
-
-    } 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;
+    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) {
+	    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 % 100;
+
+	} 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;
+	}
     }
 
@@ -172,6 +175,8 @@
     status = tsx->cb.on_send_msg(tsx, tsx->last_pkt, tsx->last_pkt_size);
     if (status != PJ_SUCCESS) {
-	pj_timer_heap_cancel(tsx->endpt->timer_heap, &tsx->timer);
-	tsx->timer.id = 0;
+	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;
@@ -185,8 +190,10 @@
 }
 
-/*
- * .
+
+/*
+ * 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,
 						const pj_stun_msg *msg)
 {
@@ -208,4 +215,8 @@
     pj_memcpy(&tsx->tsx_id[1], msg->hdr.tsx_id, 12);
 
+    /* Update STUN retransmit flag */
+    tsx->require_retransmit = retransmit;
+
+    /* Send the message */
     return tsx_transmit_msg(tsx);
 }
@@ -243,5 +254,5 @@
 
 /*
- * 
+ * 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,
@@ -292,5 +303,10 @@
     err_attr = (pj_stun_error_code_attr*) 
 		pj_stun_msg_find_attr(msg, PJ_STUN_ATTR_ERROR_CODE, 0);
-    if (err_attr->err_class == 1) {
+
+    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)",
@@ -301,5 +317,5 @@
     }
 
-    if (err_attr==NULL || err_attr->err_class == 2) {
+    if (err_attr == NULL) {
 	status = PJ_SUCCESS;
     } else {
