Index: pjproject/branches/users/nanang/pjmedia/build/pjmedia.vcproj
===================================================================
--- pjproject/branches/users/nanang/pjmedia/build/pjmedia.vcproj	(revision 1697)
+++ pjproject/branches/users/nanang/pjmedia/build/pjmedia.vcproj	(revision 1698)
@@ -44,5 +44,5 @@
 				Optimization="2"
 				InlineFunctionExpansion="1"
-				AdditionalIncludeDirectories="../include,../../pjlib/include,../../pjlib-util/include,../../pjnath/include,../../third_party/portaudio/include,../../third_party/speex/include,../.."
+				AdditionalIncludeDirectories="../include;../../pjlib/include;&quot;../../pjlib-util/include&quot;;../../pjnath/include;../../third_party/portaudio/include;../../third_party/speex/include;../../third_party/build/srtp;../../third_party/srtp/include;../../third_party/srtp/crypto/include;../.."
 				PreprocessorDefinitions="NDEBUG;WIN32;_LIB;PJ_WIN32=1;PJ_M_I386=1"
 				StringPooling="true"
@@ -120,5 +120,5 @@
 				Name="VCCLCompilerTool"
 				Optimization="0"
-				AdditionalIncludeDirectories="../include,../../pjlib/include,../../pjlib-util/include,../../pjnath/include,../../third_party/portaudio/include,../../third_party/speex/include,../.."
+				AdditionalIncludeDirectories="../include;../../pjlib/include;&quot;../../pjlib-util/include&quot;;../../pjnath/include;../../third_party/portaudio/include;../../third_party/speex/include;../../third_party/build/srtp;../../third_party/srtp/include;../../third_party/srtp/crypto/include;../.."
 				PreprocessorDefinitions="_DEBUG;WIN32;_LIB;PJ_WIN32=1;PJ_M_I386=1"
 				MinimalRebuild="true"
@@ -967,4 +967,8 @@
 			</File>
 			<File
+				RelativePath="..\src\pjmedia\transport_srtp.c"
+				>
+			</File>
+			<File
 				RelativePath="..\src\pjmedia\transport_udp.c"
 				>
@@ -1218,4 +1222,8 @@
 			</File>
 			<File
+				RelativePath="..\include\pjmedia\transport_srtp.h"
+				>
+			</File>
+			<File
 				RelativePath="..\include\pjmedia\transport_udp.h"
 				>
Index: pjproject/branches/users/nanang/pjmedia/include/pjmedia.h
===================================================================
--- pjproject/branches/users/nanang/pjmedia/include/pjmedia.h	(revision 1697)
+++ pjproject/branches/users/nanang/pjmedia/include/pjmedia.h	(revision 1698)
@@ -55,4 +55,5 @@
 #include <pjmedia/transport.h>
 #include <pjmedia/transport_ice.h>
+#include <pjmedia/transport_srtp.h>
 #include <pjmedia/transport_udp.h>
 #include <pjmedia/wav_playlist.h>
Index: pjproject/branches/users/nanang/pjmedia/include/pjmedia/transport.h
===================================================================
--- pjproject/branches/users/nanang/pjmedia/include/pjmedia/transport.h	(revision 1697)
+++ pjproject/branches/users/nanang/pjmedia/include/pjmedia/transport.h	(revision 1698)
@@ -172,4 +172,5 @@
  */
 typedef struct pjmedia_transport pjmedia_transport;
+typedef struct pjmedia_sdp_session pjmedia_sdp_session;
 
 
@@ -243,4 +244,47 @@
 			     const void *pkt,
 			     pj_size_t size);
+
+    /**
+     * This function is called by application to generate the SDP parts
+     * related to transport type, e.g: ICE, SRTP.
+     *
+     * Application should call #pjmedia_transport_media_create() instead of 
+     * calling this function directly.
+     */
+    pj_status_t (*media_create)(pjmedia_transport *tp,
+				pj_pool_t *pool,
+				pjmedia_sdp_session *sdp_local,
+				const pjmedia_sdp_session *sdp_remote);
+
+    /**
+     * This function is called by application to start the transport
+     * based on SDP negotiation result.
+     *
+     * Application should call #pjmedia_transport_media_start() instead of 
+     * calling this function directly.
+     */
+    pj_status_t (*media_start) (pjmedia_transport *tp,
+			        pj_pool_t *pool,
+			        pjmedia_sdp_session *sdp_local,
+			        const pjmedia_sdp_session *sdp_remote,
+				unsigned media_index);
+
+    /**
+     * This function is called by application to stop the transport.
+     *
+     * Application should call #pjmedia_transport_media_stop() instead of 
+     * calling this function directly.
+     */
+    pj_status_t (*media_stop)  (pjmedia_transport *tp);
+
+    /**
+     * This function can be called to simulate packet lost.
+     *
+     * Application should call #pjmedia_transport_simulate_lost() instead of 
+     * calling this function directly.
+     */
+    pj_status_t (*simulate_lost)(pjmedia_transport *tp,
+				 pjmedia_dir dir,
+				 unsigned pct_lost);
 
     /**
@@ -411,4 +455,63 @@
 
 /**
+ * Generate local SDP parts that are related to the specified media transport.
+ * Remote SDP might be needed as reference when application is in deciding
+ * side of negotiation (callee side), otherwise it should be NULL.
+ * This is just a simple wrapper which calls <tt>media_create()</tt> member 
+ * of the transport.
+ *
+ * @param tp		The media transport.
+ * @param pool		The memory pool.
+ * @param sdp_local	Local SDP.
+ * @param sdp_remote	Remote SDP.
+ *
+ * @return		PJ_SUCCESS on success, or the appropriate error code.
+ */
+PJ_INLINE(pj_status_t) pjmedia_transport_media_create(pjmedia_transport *tp,
+				    pj_pool_t *pool,
+				    pjmedia_sdp_session *sdp_local,
+				    const pjmedia_sdp_session *sdp_remote)
+{
+    return (*tp->op->media_create)(tp, pool, sdp_local, sdp_remote);
+}
+
+/**
+ * Start the transport with regards to SDP negotiation result. 
+ * This is just a simple wrapper which calls <tt>media_start()</tt> member 
+ * of the transport.
+ *
+ * @param tp		The media transport.
+ * @param pool		The memory pool.
+ * @param sdp_local	Local SDP.
+ * @param sdp_remote	Remote SDP.
+ * @param media_index	Media index to start.
+ *
+ * @return		PJ_SUCCESS on success, or the appropriate error code.
+ */
+PJ_INLINE(pj_status_t) pjmedia_transport_media_start(pjmedia_transport *tp,
+				    pj_pool_t *pool,
+				    pjmedia_sdp_session *sdp_local,
+				    const pjmedia_sdp_session *sdp_remote,
+				    unsigned media_index)
+{
+    return (*tp->op->media_start)(tp, pool, sdp_local, sdp_remote, media_index);
+}
+
+
+/**
+ * Stop the transport. 
+ * This is just a simple wrapper which calls <tt>media_stop()</tt> member 
+ * of the transport.
+ *
+ * @param tp		The media transport.
+ *
+ * @return		PJ_SUCCESS on success, or the appropriate error code.
+ */
+PJ_INLINE(pj_status_t) pjmedia_transport_media_stop(pjmedia_transport *tp)
+{
+    return (*tp->op->media_stop)(tp);
+}
+
+/**
  * Close media transport. This is just a simple wrapper which calls 
  * <tt>destroy()</tt> member of the transport. This function will free
@@ -427,4 +530,23 @@
 }
 
+/**
+ * Simulate packet lost in the specified direction (for testing purposes).
+ * When enabled, the transport will randomly drop packets to the specified
+ * direction.
+ *
+ * @param tp	    The media transport.
+ * @param dir	    Media direction to which packets will be randomly dropped.
+ * @param pct_lost  Percent lost (0-100). Set to zero to disable packet
+ *		    lost simulation.
+ *
+ * @return	    PJ_SUCCESS on success.
+ */
+PJ_INLINE(pj_status_t) pjmedia_transport_simulate_lost(pjmedia_transport *tp,
+						       pjmedia_dir dir,
+						       unsigned pct_lost)
+{
+    return (*tp->op->simulate_lost)(tp, dir, pct_lost);
+}
+
 
 PJ_END_DECL
Index: pjproject/branches/users/nanang/pjmedia/include/pjmedia/transport_ice.h
===================================================================
--- pjproject/branches/users/nanang/pjmedia/include/pjmedia/transport_ice.h	(revision 1697)
+++ pjproject/branches/users/nanang/pjmedia/include/pjmedia/transport_ice.h	(revision 1698)
@@ -17,6 +17,6 @@
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA 
  */
-#ifndef __pjmedia_ice_H__
-#define __pjmedia_ice_H__
+#ifndef __PJMEDIA_TRANSPORT_ICE_H__
+#define __PJMEDIA_TRANSPORT_ICE_H__
 
 
@@ -75,13 +75,4 @@
 					const pjmedia_ice_cb *cb,
 					pjmedia_transport **p_tp);
-
-/**
- * Destroy the media transport.
- *
- * @param tp		The media transport.
- *
- * @return		PJ_SUCCESS.
- */
-PJ_DECL(pj_status_t) pjmedia_ice_destroy(pjmedia_transport *tp);
 
 
@@ -170,69 +161,4 @@
 					  const pj_str_t *local_passwd);
 
-/**
- * Modify the SDP to add ICE specific SDP attributes before sending
- * the SDP to remote host.
- *
- * @param tp		The media transport.
- * @param pool		Pool to allocate memory for the SDP elements.
- * @param sdp		The SDP descriptor to be modified.
- *
- * @return		PJ_SUCCESS, or the appropriate error code.
- */
-PJ_DECL(pj_status_t) pjmedia_ice_modify_sdp(pjmedia_transport *tp,
-					    pj_pool_t *pool,
-					    pjmedia_sdp_session *sdp);
-
-/**
- * Start ICE connectivity checks.
- *
- * This function will pair the local and remote candidates to create 
- * check list. Once the check list is created and sorted based on the
- * priority, ICE periodic checks will be started. This function will 
- * return immediately, and application will be notified about the 
- * connectivity check status in the callback.
- *
- * @param tp		The media transport.
- * @param pool		Memory pool to parse the SDP.
- * @param rem_sdp	The SDP received from remote agent.
- * @param media_index	The media index (in SDP) to process.
- *
- * @return		PJ_SUCCESS, or the appropriate error code.
- */
-PJ_DECL(pj_status_t) pjmedia_ice_start_ice(pjmedia_transport *tp,
-					   pj_pool_t *pool,
-					   const pjmedia_sdp_session *rem_sdp,
-					   unsigned media_index);
-
-/**
- * Stop the ICE session (typically when the call is terminated). Application
- * may restart the ICE session again by calling #pjmedia_ice_init_ice(),
- * for example to use this media transport for the next call.
- *
- * @param tp		The media transport.
- *
- * @return		PJ_SUCCESS, or the appropriate error code.
- */
-PJ_DECL(pj_status_t) pjmedia_ice_stop_ice(pjmedia_transport *tp);
-
-
-/**
- * Simulate packet lost in the specified direction (for testing purposes).
- * When enabled, the transport will randomly drop packets to the specified
- * direction.
- *
- * @param tp	    The ICE media transport.
- * @param dir	    Media direction to which packets will be randomly dropped.
- * @param pct_lost  Percent lost (0-100). Set to zero to disable packet
- *		    lost simulation.
- *
- * @return	    PJ_SUCCESS on success.
- */
-PJ_DECL(pj_status_t) pjmedia_ice_simulate_lost(pjmedia_transport *tp,
-					       pjmedia_dir dir,
-					       unsigned pct_lost);
-
-
-
 
 PJ_END_DECL
@@ -244,5 +170,5 @@
 
 
-#endif	/* __pjmedia_ice_H__ */
+#endif	/* __PJMEDIA_TRANSPORT_ICE_H__ */
 
 
Index: pjproject/branches/users/nanang/pjmedia/include/pjmedia/transport_srtp.h
===================================================================
--- pjproject/branches/users/nanang/pjmedia/include/pjmedia/transport_srtp.h	(revision 1698)
+++ pjproject/branches/users/nanang/pjmedia/include/pjmedia/transport_srtp.h	(revision 1698)
@@ -0,0 +1,119 @@
+/* $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 __PJMEDIA_TRANSPORT_SRTP_H__
+#define __PJMEDIA_TRANSPORT_SRTP_H__
+
+/**
+ * @file srtp.h
+ * @brief transport SRTP encapsulates secure media transport.
+ */
+
+#include <pjmedia/transport.h>
+
+
+PJ_BEGIN_DECL
+
+/**
+ * Options that can be specified when creating SRTP transport.
+ */
+enum pjmedia_transport_srtp_options
+{
+    /**
+     * This option will make the underlying transport to be closed whenever
+     * the SRTP transport is closed.
+     */
+    PJMEDIA_SRTP_AUTO_CLOSE_UNDERLYING_TRANSPORT = 1
+};
+
+/**
+ * SRTP session parameters.
+ */
+typedef struct pjmedia_srtp_stream_policy
+{
+    pj_str_t key;	     /**< Key string.		    */
+    pj_str_t crypto_suite;   /**< SRTP parameter for RTP.   */
+} pjmedia_srtp_stream_policy;
+
+
+/**
+ * Create an SRTP media transport.
+ *
+ * @param endpt		    The media endpoint instance.
+ * @param tp		    The actual media transport 
+ *			    to send and receive RTP/RTCP packets.
+ * @param p_tp_srtp	    Pointer to receive the transport SRTP instance.
+ *
+ * @return		    PJ_SUCCESS on success.
+ */
+PJ_DECL(pj_status_t) pjmedia_transport_srtp_create(pjmedia_endpt *endpt,
+					 pjmedia_transport *tp,
+					 unsigned options,
+					 pjmedia_transport **p_tp_srtp);
+
+/**
+ * Initialize and start SRTP session with the given parameters.
+ * Please note:
+ * 1. pjmedia_transport_srtp_init_session() and 
+ *    pjmedia_transport_srtp_deinit_session() is automatic called by 
+ *    SRTP pjmedia_transport_media_start() and pjmedia_transport_media_stop(),
+ *    application needs to call these functions directly only if the application
+ *    is not intended to call SRTP pjmedia_transport_media_start.
+ * 2. Even if an RTP stream is only one direction, you might need to provide 
+ *    both policies, because it is needed by RTCP, which is usually two 
+ *    directions.
+ * 3. Key for transmit and receive direction MUST be different, this is
+ *    specified by libsrtp.
+ *
+ * @param srtp	    The SRTP transport.
+ * @param prm	    Session parameters.
+ *
+ * @return	    PJ_SUCCESS on success.
+ */
+PJ_DECL(pj_status_t) pjmedia_transport_srtp_init_session(
+		       pjmedia_transport *srtp,
+		       const pjmedia_srtp_stream_policy *policy_tx,
+		       const pjmedia_srtp_stream_policy *policy_rx);
+
+/**
+ * Stop SRTP seession.
+ *
+ * @param srtp	    The SRTP media transport.
+ *
+ * @return	    PJ_SUCCESS on success.
+ *
+ * @see pjmedia_transport_srtp_init_session() 
+ */
+PJ_DECL(pj_status_t) pjmedia_transport_srtp_deinit_session(
+		       pjmedia_transport *srtp);
+
+
+/**
+ * Query real transport of SRTP.
+ *
+ * @param srtp		    The SRTP media transport.
+ *
+ * @return		    real media transport.
+ */
+PJ_DECL(pjmedia_transport*) pjmedia_transport_srtp_get_real_transport(
+				pjmedia_transport *srtp);
+
+
+PJ_END_DECL
+
+#endif /* __PJMEDIA_TRANSPORT_SRTP_H__ */
Index: pjproject/branches/users/nanang/pjmedia/include/pjmedia/transport_udp.h
===================================================================
--- pjproject/branches/users/nanang/pjmedia/include/pjmedia/transport_udp.h	(revision 1697)
+++ pjproject/branches/users/nanang/pjmedia/include/pjmedia/transport_udp.h	(revision 1698)
@@ -54,17 +54,4 @@
     PJMEDIA_UDP_NO_SRC_ADDR_CHECKING = 1
 };
-
-
-/**
- * UDP transport info.
- */
-typedef struct pjmedia_transport_udp_info
-{
-    /**
-     * Media socket info.
-     */
-    pjmedia_sock_info	skinfo;
-
-} pjmedia_transport_udp_info;
 
 
@@ -138,16 +125,4 @@
 						   pjmedia_transport **p_tp);
 
-/**
- * Get media socket info from the specified UDP transport.
- *
- * @param tp	    The UDP transport interface.
- * @param info	    Media socket info to be initialized.
- *
- * @return	    PJ_SUCCESS on success.
- */
-PJ_DECL(pj_status_t) 
-pjmedia_transport_udp_get_info( pjmedia_transport *tp,
-				pjmedia_transport_udp_info *info);
-
 
 /**
@@ -170,34 +145,4 @@
 
 
-/**
- * Simulate packet lost in the specified direction (for testing purposes).
- * When enabled, the transport will randomly drop packets to the specified
- * direction.
- *
- * @param tp	    The UDP media transport.
- * @param dir	    Media direction to which packets will be randomly dropped.
- * @param pct_lost  Percent lost (0-100). Set to zero to disable packet
- *		    lost simulation.
- *
- * @return	    PJ_SUCCESS on success.
- */
-PJ_DECL(pj_status_t) pjmedia_transport_udp_simulate_lost(pjmedia_transport *tp,
-							 pjmedia_dir dir,
-							 unsigned pct_lost);
-
-
-
-/**
- * Close UDP transport. Application can also use the "destroy" member of
- * media transport interface to close the UDP transport.
- *
- * @param tp	    The UDP media transport.
- *
- * @return	    PJ_SUCCESS on success.
- */
-PJ_DECL(pj_status_t) pjmedia_transport_udp_close(pjmedia_transport *tp);
-
-
-
 PJ_END_DECL
 
Index: pjproject/branches/users/nanang/pjmedia/src/pjmedia/transport_ice.c
===================================================================
--- pjproject/branches/users/nanang/pjmedia/src/pjmedia/transport_ice.c	(revision 1697)
+++ pjproject/branches/users/nanang/pjmedia/src/pjmedia/transport_ice.c	(revision 1698)
@@ -52,25 +52,39 @@
  * These are media transport operations.
  */
-static pj_status_t tp_get_info(pjmedia_transport *tp,
-			       pjmedia_sock_info *info);
-static pj_status_t tp_attach( pjmedia_transport *tp,
-			      void *stream,
-			      const pj_sockaddr_t *rem_addr,
-			      const pj_sockaddr_t *rem_rtcp,
-			      unsigned addr_len,
-			      void (*rtp_cb)(void*,
-					     const void*,
-					     pj_ssize_t),
-			      void (*rtcp_cb)(void*,
-					      const void*,
-					      pj_ssize_t));
-static void	   tp_detach( pjmedia_transport *tp,
-			      void *strm);
-static pj_status_t tp_send_rtp( pjmedia_transport *tp,
-			        const void *pkt,
-			        pj_size_t size);
-static pj_status_t tp_send_rtcp( pjmedia_transport *tp,
-			         const void *pkt,
-			         pj_size_t size);
+static pj_status_t transport_get_info (pjmedia_transport *tp,
+				       pjmedia_sock_info *info);
+static pj_status_t transport_attach   (pjmedia_transport *tp,
+				       void *user_data,
+				       const pj_sockaddr_t *rem_addr,
+				       const pj_sockaddr_t *rem_rtcp,
+				       unsigned addr_len,
+				       void (*rtp_cb)(void*,
+						      const void*,
+						      pj_ssize_t),
+				       void (*rtcp_cb)(void*,
+						       const void*,
+						       pj_ssize_t));
+static void	   transport_detach   (pjmedia_transport *tp,
+				       void *strm);
+static pj_status_t transport_send_rtp( pjmedia_transport *tp,
+				       const void *pkt,
+				       pj_size_t size);
+static pj_status_t transport_send_rtcp(pjmedia_transport *tp,
+				       const void *pkt,
+				       pj_size_t size);
+static pj_status_t transport_media_create(pjmedia_transport *tp,
+				       pj_pool_t *pool,
+				       pjmedia_sdp_session *sdp_local,
+				       const pjmedia_sdp_session *sdp_remote);
+static pj_status_t transport_media_start (pjmedia_transport *tp,
+				       pj_pool_t *pool,
+				       pjmedia_sdp_session *sdp_local,
+				       const pjmedia_sdp_session *sdp_remote,
+				       unsigned media_index);
+static pj_status_t transport_media_stop(pjmedia_transport *tp);
+static pj_status_t transport_simulate_lost(pjmedia_transport *tp,
+				       pjmedia_dir dir,
+				       unsigned pct_lost);
+static pj_status_t transport_destroy  (pjmedia_transport *tp);
 
 /*
@@ -85,12 +99,16 @@
 
 
-static pjmedia_transport_op tp_ice_op = 
-{
-    &tp_get_info,
-    &tp_attach,
-    &tp_detach,
-    &tp_send_rtp,
-    &tp_send_rtcp,
-    &pjmedia_ice_destroy
+static pjmedia_transport_op transport_ice_op = 
+{
+    &transport_get_info,
+    &transport_attach,
+    &transport_detach,
+    &transport_send_rtp,
+    &transport_send_rtcp,
+    &transport_media_create,
+    &transport_media_start,
+    &transport_media_stop,
+    &transport_simulate_lost,
+    &transport_destroy
 };
 
@@ -133,5 +151,5 @@
     tp_ice->ice_st = ice_st;
     pj_ansi_strcpy(tp_ice->base.name, ice_st->obj_name);
-    tp_ice->base.op = &tp_ice_op;
+    tp_ice->base.op = &transport_ice_op;
     tp_ice->base.type = PJMEDIA_TRANSPORT_TYPE_ICE;
 
@@ -144,23 +162,4 @@
     if (p_tp)
 	*p_tp = &tp_ice->base;
-
-    return PJ_SUCCESS;
-}
-
-
-/*
- * Destroy ICE media transport.
- */
-PJ_DEF(pj_status_t) pjmedia_ice_destroy(pjmedia_transport *tp)
-{
-    struct transport_ice *tp_ice = (struct transport_ice*)tp;
-
-    if (tp_ice->ice_st) {
-	pj_ice_strans_destroy(tp_ice->ice_st);
-	/*Must not touch tp_ice after ice_st is destroyed!
-	 (it has the pool)
-	 tp_ice->ice_st = NULL;
-	 */
-    }
 
     return PJ_SUCCESS;
@@ -231,5 +230,6 @@
 		     comp, PJ_EINVAL);
 
-    pj_memcpy(comp, tp_ice->ice_st->comp[comp_id-1], sizeof(pj_ice_strans_comp));
+    pj_memcpy(comp, tp_ice->ice_st->comp[comp_id-1], 
+	      sizeof(pj_ice_strans_comp));
     return PJ_SUCCESS;		    
 }
@@ -247,5 +247,6 @@
 {
     struct transport_ice *tp_ice = (struct transport_ice*)tp;
-    return pj_ice_strans_init_ice(tp_ice->ice_st, role, local_ufrag, local_passwd);
+    return pj_ice_strans_init_ice(tp_ice->ice_st, role, local_ufrag, 
+				  local_passwd);
 }
 
@@ -255,7 +256,8 @@
  * This will add ICE attributes to the SDP.
  */
-PJ_DEF(pj_status_t) pjmedia_ice_modify_sdp(pjmedia_transport *tp,
-					   pj_pool_t *pool,
-					   pjmedia_sdp_session *sdp)
+static pj_status_t transport_media_create(pjmedia_transport *tp,
+				       pj_pool_t *pool,
+				       pjmedia_sdp_session *sdp_local,
+				       const pjmedia_sdp_session *sdp_remote)
 {
     struct transport_ice *tp_ice = (struct transport_ice*)tp;
@@ -265,4 +267,6 @@
     unsigned i, cand_cnt;
 
+    PJ_UNUSED_ARG(sdp_remote);
+
     buffer = (char*) pj_pool_alloc(pool, MAXLEN);
 
@@ -270,10 +274,10 @@
     attr = pjmedia_sdp_attr_create(pool, "ice-ufrag", 
 				   &tp_ice->ice_st->ice->rx_ufrag);
-    sdp->attr[sdp->attr_count++] = attr;
+    sdp_local->attr[sdp_local->attr_count++] = attr;
 
     /* Create ice-pwd attribute */
     attr = pjmedia_sdp_attr_create(pool, "ice-pwd", 
 				   &tp_ice->ice_st->ice->rx_pass);
-    sdp->attr[sdp->attr_count++] = attr;
+    sdp_local->attr[sdp_local->attr_count++] = attr;
 
     /* Add all candidates (to media level) */
@@ -330,5 +334,5 @@
 	value = pj_str(buffer);
 	attr = pjmedia_sdp_attr_create(pool, "candidate", &value);
-	sdp->media[0]->attr[sdp->media[0]->attr_count++] = attr;
+	sdp_local->media[0]->attr[sdp_local->media[0]->attr_count++] = attr;
     }
 
@@ -457,5 +461,5 @@
     PJ_LOG(4,(tp_ice->ice_st->obj_name, 
 	      "Disabling local ICE, reason=%s", reason));
-    pjmedia_ice_stop_ice(&tp_ice->base);
+    transport_media_stop(&tp_ice->base);
 }
 
@@ -464,8 +468,9 @@
  * Start ICE checks when both offer and answer are available.
  */
-PJ_DEF(pj_status_t) pjmedia_ice_start_ice(pjmedia_transport *tp,
-					  pj_pool_t *pool,
-					  const pjmedia_sdp_session *rem_sdp,
-					  unsigned media_index)
+static pj_status_t transport_media_start(pjmedia_transport *tp,
+				         pj_pool_t *pool,
+				         pjmedia_sdp_session *sdp_local,
+				         const pjmedia_sdp_session *sdp_remote,
+				         unsigned media_index)
 {
     struct transport_ice *tp_ice = (struct transport_ice*)tp;
@@ -482,8 +487,10 @@
     pj_status_t status;
 
-    PJ_ASSERT_RETURN(tp && pool && rem_sdp, PJ_EINVAL);
-    PJ_ASSERT_RETURN(media_index < rem_sdp->media_count, PJ_EINVAL);
-
-    sdp_med = rem_sdp->media[media_index];
+    PJ_UNUSED_ARG(sdp_local);
+
+    PJ_ASSERT_RETURN(tp && pool && sdp_remote, PJ_EINVAL);
+    PJ_ASSERT_RETURN(media_index < sdp_remote->media_count, PJ_EINVAL);
+
+    sdp_med = sdp_remote->media[media_index];
 
     /* Get the SDP connection for the media stream.
@@ -493,5 +500,5 @@
     conn = sdp_med->conn;
     if (conn == NULL)
-	conn = rem_sdp->conn;
+	conn = sdp_remote->conn;
 
     if (conn == NULL) {
@@ -508,5 +515,5 @@
     if (attr == NULL) {
 	/* Find ice-ufrag attribute in session descriptor */
-	attr = pjmedia_sdp_attr_find2(rem_sdp->attr_count, rem_sdp->attr,
+	attr = pjmedia_sdp_attr_find2(sdp_remote->attr_count, sdp_remote->attr,
 				      "ice-ufrag", NULL);
 	if (attr == NULL) {
@@ -522,5 +529,5 @@
     if (attr == NULL) {
 	/* Find ice-pwd attribute in session descriptor */
-	attr = pjmedia_sdp_attr_find2(rem_sdp->attr_count, rem_sdp->attr,
+	attr = pjmedia_sdp_attr_find2(sdp_remote->attr_count, sdp_remote->attr,
 				      "ice-pwd", NULL);
 	if (attr == NULL) {
@@ -609,5 +616,5 @@
 
 
-PJ_DEF(pj_status_t) pjmedia_ice_stop_ice(pjmedia_transport *tp)
+static pj_status_t transport_media_stop(pjmedia_transport *tp)
 {
     struct transport_ice *tp_ice = (struct transport_ice*)tp;
@@ -616,6 +623,6 @@
 
 
-static pj_status_t tp_get_info(pjmedia_transport *tp,
-			       pjmedia_sock_info *info)
+static pj_status_t transport_get_info(pjmedia_transport *tp,
+				      pjmedia_sock_info *info)
 {
     struct transport_ice *tp_ice = (struct transport_ice*)tp;
@@ -649,15 +656,15 @@
 
 
-static pj_status_t tp_attach( pjmedia_transport *tp,
-			      void *stream,
-			      const pj_sockaddr_t *rem_addr,
-			      const pj_sockaddr_t *rem_rtcp,
-			      unsigned addr_len,
-			      void (*rtp_cb)(void*,
-					     const void*,
-					     pj_ssize_t),
-			      void (*rtcp_cb)(void*,
-					      const void*,
-					      pj_ssize_t))
+static pj_status_t transport_attach  (pjmedia_transport *tp,
+				      void *stream,
+				      const pj_sockaddr_t *rem_addr,
+				      const pj_sockaddr_t *rem_rtcp,
+				      unsigned addr_len,
+				      void (*rtp_cb)(void*,
+						     const void*,
+						     pj_ssize_t),
+				      void (*rtcp_cb)(void*,
+						      const void*,
+						      pj_ssize_t))
 {
     struct transport_ice *tp_ice = (struct transport_ice*)tp;
@@ -674,6 +681,6 @@
 
 
-static void tp_detach(pjmedia_transport *tp,
-		      void *strm)
+static void transport_detach(pjmedia_transport *tp,
+			     void *strm)
 {
     struct transport_ice *tp_ice = (struct transport_ice*)tp;
@@ -687,7 +694,7 @@
 
 
-static pj_status_t tp_send_rtp(pjmedia_transport *tp,
-			       const void *pkt,
-			       pj_size_t size)
+static pj_status_t transport_send_rtp(pjmedia_transport *tp,
+				      const void *pkt,
+				      pj_size_t size)
 {
     struct transport_ice *tp_ice = (struct transport_ice*)tp;
@@ -709,7 +716,7 @@
 
 
-static pj_status_t tp_send_rtcp(pjmedia_transport *tp,
-			        const void *pkt,
-			        pj_size_t size)
+static pj_status_t transport_send_rtcp(pjmedia_transport *tp,
+				       const void *pkt,
+				       pj_size_t size)
 {
     struct transport_ice *tp_ice = (struct transport_ice*)tp;
@@ -799,7 +806,7 @@
 
 /* Simulate lost */
-PJ_DEF(pj_status_t) pjmedia_ice_simulate_lost( pjmedia_transport *tp,
-					       pjmedia_dir dir,
-					       unsigned pct_lost)
+static pj_status_t transport_simulate_lost(pjmedia_transport *tp,
+					   pjmedia_dir dir,
+					   unsigned pct_lost)
 {
     struct transport_ice *ice = (struct transport_ice*) tp;
@@ -816,2 +823,21 @@
 }
 
+
+/*
+ * Destroy ICE media transport.
+ */
+static pj_status_t transport_destroy(pjmedia_transport *tp)
+{
+    struct transport_ice *tp_ice = (struct transport_ice*)tp;
+
+    if (tp_ice->ice_st) {
+	pj_ice_strans_destroy(tp_ice->ice_st);
+	/*Must not touch tp_ice after ice_st is destroyed!
+	 (it has the pool)
+	 tp_ice->ice_st = NULL;
+	 */
+    }
+
+    return PJ_SUCCESS;
+}
+
Index: pjproject/branches/users/nanang/pjmedia/src/pjmedia/transport_srtp.c
===================================================================
--- pjproject/branches/users/nanang/pjmedia/src/pjmedia/transport_srtp.c	(revision 1698)
+++ pjproject/branches/users/nanang/pjmedia/src/pjmedia/transport_srtp.c	(revision 1698)
@@ -0,0 +1,997 @@
+/* $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 <pjmedia/transport_srtp.h>
+#include <pjmedia/endpoint.h>
+#include <pjlib-util/base64.h>
+#include <pj/assert.h>
+#include <pj/log.h>
+#include <pj/os.h>
+#include <pj/pool.h>
+#include <srtp.h>
+
+#define THIS_FILE   "transport_srtp.c"
+
+/* Maximum size of packet */
+#define MAX_BUFFER_LEN	1500
+#define MAX_KEY_LEN	32
+#define SRTP_ERROR(e)	-1
+
+static const pj_str_t ID_RTP_AVP = { "RTP/AVP", 7 };
+static const pj_str_t ID_RTP_SAVP = { "RTP/SAVP", 8 };
+
+typedef struct crypto_suite
+{
+    char		*name;
+    cipher_type_id_t	 cipher_type;
+    unsigned		 cipher_key_len;
+    auth_type_id_t	 auth_type;
+    unsigned		 auth_key_len;
+    unsigned		 srtp_auth_tag_len;
+    unsigned		 srtcp_auth_tag_len;
+    sec_serv_t		 service;
+} crypto_suite;
+
+/* Crypto suites as defined on RFC 4568 */
+static crypto_suite crypto_suites[] = {
+    /* plain RTP/RTCP (no cipher & no auth) */
+    {"NULL", NULL_CIPHER, 0, NULL_AUTH, 0, 0, 0, sec_serv_none},
+
+    /* cipher AES_CM, auth HMAC_SHA1, auth tag len = 10 octets */
+    {"AES_CM_128_HMAC_SHA1_80", AES_128_ICM, 30, HMAC_SHA1, 20, 10, 10, 
+	sec_serv_conf_and_auth},
+
+    /* cipher AES_CM, auth HMAC_SHA1, auth tag len = 4 octets */
+    {"AES_CM_128_HMAC_SHA1_32", AES_128_ICM, 30, HMAC_SHA1, 20, 4, 10,
+	sec_serv_conf_and_auth},
+
+    /* 
+     * F8_128_HMAC_SHA1_8 not supported by libsrtp?
+     * {"F8_128_HMAC_SHA1_8", NULL_CIPHER, 0, NULL_AUTH, 0, 0, 0, sec_serv_none}
+     */
+};
+
+typedef struct transport_srtp
+{
+    pjmedia_transport	 base;	    /**< Base transport interface. */
+    pj_pool_t		*pool;
+    pj_mutex_t		*mutex;
+    char		 tx_buffer[MAX_BUFFER_LEN];
+    char		 rx_buffer[MAX_BUFFER_LEN];
+    unsigned		 options;   /**< Transport options.	   */
+
+    /* SRTP policy */
+    pj_bool_t		 session_inited;
+    pj_bool_t		 offerer_side;
+    char		 tx_key[MAX_KEY_LEN];
+    char		 rx_key[MAX_KEY_LEN];
+    pjmedia_srtp_stream_policy tx_policy;
+    pjmedia_srtp_stream_policy rx_policy;
+
+    /* libSRTP contexts */
+    srtp_t		 srtp_tx_ctx;
+    srtp_t		 srtp_rx_ctx;
+
+    /* Stream information */
+    void		*user_data;
+    void		(*rtp_cb)( void *user_data,
+				   const void *pkt,
+				   pj_ssize_t size);
+    void		(*rtcp_cb)(void *user_data,
+				   const void *pkt,
+				   pj_ssize_t size);
+        
+    /* Transport information */
+    pjmedia_transport	*real_tp; /**< Underlying transport.       */
+
+} transport_srtp;
+
+
+/*
+ * This callback is called by transport when incoming rtp is received
+ */
+static void srtp_rtp_cb( void *user_data, const void *pkt, pj_ssize_t size);
+
+/*
+ * This callback is called by transport when incoming rtcp is received
+ */
+static void srtp_rtcp_cb( void *user_data, const void *pkt, pj_ssize_t size);
+
+
+/*
+ * These are media transport operations.
+ */
+static pj_status_t transport_get_info (pjmedia_transport *tp,
+				       pjmedia_sock_info *info);
+static pj_status_t transport_attach   (pjmedia_transport *tp,
+				       void *user_data,
+				       const pj_sockaddr_t *rem_addr,
+				       const pj_sockaddr_t *rem_rtcp,
+				       unsigned addr_len,
+				       void (*rtp_cb)(void*,
+						      const void*,
+						      pj_ssize_t),
+				       void (*rtcp_cb)(void*,
+						       const void*,
+						       pj_ssize_t));
+static void	   transport_detach   (pjmedia_transport *tp,
+				       void *strm);
+static pj_status_t transport_send_rtp( pjmedia_transport *tp,
+				       const void *pkt,
+				       pj_size_t size);
+static pj_status_t transport_send_rtcp(pjmedia_transport *tp,
+				       const void *pkt,
+				       pj_size_t size);
+static pj_status_t transport_media_create(pjmedia_transport *tp,
+				       pj_pool_t *pool,
+				       pjmedia_sdp_session *sdp_local,
+				       const pjmedia_sdp_session *sdp_remote);
+static pj_status_t transport_media_start (pjmedia_transport *tp,
+				       pj_pool_t *pool,
+				       pjmedia_sdp_session *sdp_local,
+				       const pjmedia_sdp_session *sdp_remote,
+				       unsigned media_index);
+static pj_status_t transport_media_stop(pjmedia_transport *tp);
+static pj_status_t transport_simulate_lost(pjmedia_transport *tp,
+				       pjmedia_dir dir,
+				       unsigned pct_lost);
+static pj_status_t transport_destroy  (pjmedia_transport *tp);
+
+
+
+static pjmedia_transport_op transport_srtp_op = 
+{
+    &transport_get_info,
+    &transport_attach,
+    &transport_detach,
+    &transport_send_rtp,
+    &transport_send_rtcp,
+    &transport_media_create,
+    &transport_media_start,
+    &transport_media_stop,
+    &transport_simulate_lost,
+    &transport_destroy
+};
+
+char * octet_string_hex_string(const void *s, int length);
+
+static pj_status_t pjmedia_srtp_init_lib(void)
+{
+    err_status_t err;
+    static pj_bool_t initialized = PJ_FALSE;
+
+    if (initialized == PJ_FALSE) {
+	err = srtp_init();
+	if (err != err_status_ok) { 
+	    return SRTP_ERROR(err);
+	}
+
+	initialized = PJ_TRUE;
+
+	PJ_TODO(REGISTER_LIBSRTP_ERROR_CODES_AND_MESSAGES);
+    }
+    
+    return PJ_SUCCESS;
+}
+
+
+/*
+ * Create an SRTP media transport.
+ */
+PJ_DEF(pj_status_t) pjmedia_transport_srtp_create( pjmedia_endpt *endpt, 
+					 pjmedia_transport *tp,
+					 unsigned options,
+					 pjmedia_transport **p_srtp)
+{
+    pj_pool_t *pool;
+    transport_srtp *srtp;
+    pj_status_t status;
+
+    PJ_ASSERT_RETURN(endpt && p_srtp, PJ_EINVAL);
+
+    /* Init libsrtp. */
+    status = pjmedia_srtp_init_lib();
+    if (status != PJ_SUCCESS) {
+	return status;
+    }
+
+    pool = pjmedia_endpt_create_pool(endpt, "srtp%p", 1000, 1000);
+    srtp = PJ_POOL_ZALLOC_T(pool, transport_srtp);
+
+    srtp->pool = pool;
+    srtp->session_inited = PJ_FALSE;
+    srtp->offerer_side = PJ_TRUE;
+    srtp->options = options;
+
+    status = pj_mutex_create_recursive(pool, pool->obj_name, &srtp->mutex);
+    if (status != PJ_SUCCESS) {
+	pj_pool_release(pool);
+	return status;
+    }
+
+    /* Initialize base pjmedia_transport */
+    pj_memcpy(srtp->base.name, pool->obj_name, PJ_MAX_OBJ_NAME);
+    srtp->base.type = tp->type;
+    srtp->base.op = &transport_srtp_op;
+
+    /* Set underlying transport */
+    srtp->real_tp = tp;
+
+    /* Done */
+    *p_srtp = &srtp->base;
+
+    return PJ_SUCCESS;
+}
+
+
+/*
+ * Initialize and start SRTP session with the given parameters.
+ */
+PJ_DEF(pj_status_t) pjmedia_transport_srtp_init_session(
+			   pjmedia_transport *srtp, 
+			   const pjmedia_srtp_stream_policy *policy_tx,
+			   const pjmedia_srtp_stream_policy *policy_rx)
+{
+    transport_srtp  *p_srtp = (transport_srtp*) srtp;
+    srtp_policy_t    policy_tx_;
+    srtp_policy_t    policy_rx_;
+    err_status_t     err;
+    int		     i;
+    int		     cs_tx_idx = -1;
+    int		     cs_rx_idx = -1;
+    int		     crypto_suites_cnt;
+
+    if (p_srtp->session_inited) {
+	return PJ_EEXISTS;
+    }
+
+    crypto_suites_cnt = sizeof(crypto_suites)/sizeof(crypto_suites[0]);
+
+    /* Check whether the crypto-suite requested is supported */
+    for (i=0; i<crypto_suites_cnt; ++i) {
+	if ((cs_rx_idx == -1) && 
+	    !pj_stricmp2(&policy_rx->crypto_suite, crypto_suites[i].name))
+	    cs_rx_idx = i;
+	
+	if ((cs_tx_idx == -1) && 
+	    !pj_stricmp2(&policy_tx->crypto_suite, crypto_suites[i].name))
+	    cs_tx_idx = i;
+    }
+
+    if ((cs_tx_idx == -1) || (cs_rx_idx == -1)) {
+	return PJ_ENOTSUP;
+    }
+
+    /* Init transmit direction */
+    pj_bzero(&policy_tx_, sizeof(srtp_policy_t));
+    pj_memmove(p_srtp->tx_key, policy_tx->key.ptr, policy_tx->key.slen);
+    policy_tx_.key		  = (uint8_t*)p_srtp->tx_key;
+    policy_tx_.ssrc.type	  = ssrc_any_outbound;
+    policy_tx_.ssrc.value	  = 0;
+    policy_tx_.rtp.sec_serv	  = crypto_suites[cs_tx_idx].service;
+    policy_tx_.rtp.cipher_type	  = crypto_suites[cs_tx_idx].cipher_type;
+    policy_tx_.rtp.cipher_key_len = crypto_suites[cs_tx_idx].cipher_key_len;
+    policy_tx_.rtp.auth_type	  = crypto_suites[cs_tx_idx].auth_type;
+    policy_tx_.rtp.auth_key_len	  = crypto_suites[cs_tx_idx].auth_key_len;
+    policy_tx_.rtp.auth_tag_len	  = crypto_suites[cs_tx_idx].srtp_auth_tag_len;
+    policy_tx_.rtcp		  = policy_tx_.rtp;
+    policy_tx_.rtcp.auth_tag_len  = crypto_suites[cs_tx_idx].srtcp_auth_tag_len;
+    policy_tx_.next		  = NULL;
+    err = srtp_create(&p_srtp->srtp_tx_ctx, &policy_tx_);
+    if (err != err_status_ok) {
+	return SRTP_ERROR(err);
+    }
+
+    pj_strset(&p_srtp->tx_policy.key,  p_srtp->tx_key, policy_tx->key.slen);
+    p_srtp->tx_policy.crypto_suite = pj_str(crypto_suites[cs_tx_idx].name);
+
+
+    /* Init receive direction */
+    pj_bzero(&policy_rx_, sizeof(srtp_policy_t));
+    pj_memmove(p_srtp->rx_key, policy_rx->key.ptr, policy_rx->key.slen);
+    policy_rx_.key		  = (uint8_t*)p_srtp->rx_key;
+    policy_rx_.ssrc.type	  = ssrc_any_inbound;
+    policy_rx_.ssrc.value	  = 0;
+    policy_rx_.rtp.sec_serv	  = crypto_suites[cs_rx_idx].service;
+    policy_rx_.rtp.cipher_type	  = crypto_suites[cs_rx_idx].cipher_type;
+    policy_rx_.rtp.cipher_key_len = crypto_suites[cs_rx_idx].cipher_key_len;
+    policy_rx_.rtp.auth_type	  = crypto_suites[cs_rx_idx].auth_type;
+    policy_rx_.rtp.auth_key_len	  = crypto_suites[cs_rx_idx].auth_key_len;
+    policy_rx_.rtp.auth_tag_len	  = crypto_suites[cs_rx_idx].srtp_auth_tag_len;
+    policy_rx_.rtcp		  = policy_rx_.rtp;
+    policy_rx_.rtcp.auth_tag_len  = crypto_suites[cs_rx_idx].srtcp_auth_tag_len;
+    policy_rx_.next		  = NULL;
+    err = srtp_create(&p_srtp->srtp_rx_ctx, &policy_rx_);
+    if (err != err_status_ok) {
+	srtp_dealloc(p_srtp->srtp_tx_ctx);
+	return SRTP_ERROR(err);
+    }
+
+    pj_strset(&p_srtp->rx_policy.key,  p_srtp->rx_key, policy_rx->key.slen);
+    p_srtp->rx_policy.crypto_suite = pj_str(crypto_suites[i].name);
+
+    /* Declare SRTP session initialized */
+    p_srtp->session_inited = PJ_TRUE;
+
+    PJ_LOG(3, (THIS_FILE, "TX %s key=%s", crypto_suites[cs_tx_idx].name,
+	   octet_string_hex_string(policy_tx->key.ptr, policy_tx->key.slen)));
+    PJ_LOG(3, (THIS_FILE, "RX %s key=%s", crypto_suites[cs_rx_idx].name,
+	   octet_string_hex_string(policy_rx->key.ptr, policy_rx->key.slen)));
+
+    return PJ_SUCCESS;
+}
+
+/*
+ * Stop SRTP session.
+ */
+PJ_DEF(pj_status_t) pjmedia_transport_srtp_deinit_session(
+					    pjmedia_transport *srtp)
+{
+    transport_srtp *p_srtp = (transport_srtp*) srtp;
+    err_status_t err;
+
+    if (!p_srtp->session_inited)
+	return PJ_SUCCESS;
+
+    err = srtp_dealloc(p_srtp->srtp_rx_ctx);
+    if (err != err_status_ok) {
+	PJ_TODO(LOG_ERROR_DEALLOC_RX);
+	//return SRTP_ERROR(err);
+    }
+    err = srtp_dealloc(p_srtp->srtp_tx_ctx);
+    if (err != err_status_ok) {
+	PJ_TODO(LOG_ERROR_DEALLOC_TX);
+	//return SRTP_ERROR(err);
+    }
+
+    p_srtp->session_inited = PJ_FALSE;
+
+    return PJ_SUCCESS;
+}
+
+PJ_DEF(pjmedia_transport *) pjmedia_transport_srtp_get_real_transport(
+				    pjmedia_transport *tp)
+{
+    transport_srtp *srtp = (transport_srtp*) tp;
+
+    PJ_ASSERT_RETURN(tp, NULL);
+
+    return srtp->real_tp;
+}
+
+
+static pj_status_t transport_get_info(pjmedia_transport *tp,
+				      pjmedia_sock_info *info)
+{
+    transport_srtp *srtp = (transport_srtp*) tp;
+
+    /* put SRTP info as well? */
+    return pjmedia_transport_get_info(srtp->real_tp, info);
+}
+
+static pj_status_t transport_attach(pjmedia_transport *tp,
+				    void *user_data,
+				    const pj_sockaddr_t *rem_addr,
+				    const pj_sockaddr_t *rem_rtcp,
+				    unsigned addr_len,
+				    void (*rtp_cb) (void*, const void*,
+						    pj_ssize_t),
+				    void (*rtcp_cb)(void*, const void*,
+						    pj_ssize_t))
+{
+    transport_srtp *srtp = (transport_srtp*) tp;
+    pj_status_t status;
+
+    /* Attach itself to transport */
+    status = pjmedia_transport_attach(srtp->real_tp, srtp, rem_addr, rem_rtcp,
+				      addr_len, &srtp_rtp_cb, &srtp_rtcp_cb);
+    if (status != PJ_SUCCESS) {
+	PJ_TODO(HANDLE_FAILURE);
+    }
+
+    /* Save the callbacks */
+    srtp->rtp_cb = rtp_cb;
+    srtp->rtcp_cb = rtcp_cb;
+    srtp->user_data = user_data;
+
+    return status;
+}
+
+static void transport_detach(pjmedia_transport *tp, void *strm)
+{
+    transport_srtp *srtp = (transport_srtp*) tp;
+
+    PJ_ASSERT_ON_FAIL(tp && srtp->real_tp, return);
+
+    PJ_UNUSED_ARG(strm);
+    pjmedia_transport_detach(srtp->real_tp, srtp);
+
+    /* Clear up application infos from transport */
+    srtp->rtp_cb = NULL;
+    srtp->rtcp_cb = NULL;
+    srtp->user_data = NULL;
+}
+
+static pj_status_t transport_send_rtp( pjmedia_transport *tp,
+				       const void *pkt,
+				       pj_size_t size)
+{
+    pj_status_t status;
+    transport_srtp *srtp = (transport_srtp*) tp;
+    int len = size;
+    err_status_t err;
+
+    if (!srtp->session_inited)
+	return PJ_SUCCESS;
+
+    PJ_ASSERT_RETURN(size < sizeof(srtp->tx_buffer), PJ_ETOOBIG);
+
+    pj_mutex_lock(srtp->mutex);
+    pj_memcpy(srtp->tx_buffer, pkt, size);
+    
+    err = srtp_protect(srtp->srtp_tx_ctx, srtp->tx_buffer, &len);
+    if (err == err_status_ok) {
+	status = pjmedia_transport_send_rtp(srtp->real_tp, srtp->tx_buffer, len);
+    } else {
+	status = SRTP_ERROR(err);
+    }
+    
+    pj_mutex_unlock(srtp->mutex);
+
+    return status;
+}
+
+static pj_status_t transport_send_rtcp(pjmedia_transport *tp,
+				       const void *pkt,
+				       pj_size_t size)
+{
+    pj_status_t status;
+    transport_srtp *srtp = (transport_srtp*) tp;
+    int len = size;
+    err_status_t err;
+
+    if (!srtp->session_inited)
+	return PJ_SUCCESS;
+
+    PJ_ASSERT_RETURN((size) < sizeof(srtp->tx_buffer), PJ_ETOOBIG);
+
+    pj_mutex_lock(srtp->mutex);
+    pj_memcpy(srtp->tx_buffer, pkt, size);
+
+    err = srtp_protect_rtcp(srtp->srtp_tx_ctx, srtp->tx_buffer, &len);
+    
+    if (err == err_status_ok) {
+	status = pjmedia_transport_send_rtcp(srtp->real_tp, srtp->tx_buffer, len);
+    } else {
+	status = SRTP_ERROR(err);
+    }
+
+    pj_mutex_unlock(srtp->mutex);
+
+    return status;
+}
+
+static pj_status_t transport_simulate_lost(pjmedia_transport *tp,
+					   pjmedia_dir dir,
+					   unsigned pct_lost)
+{
+    transport_srtp *srtp = (transport_srtp *) tp;
+
+    return pjmedia_transport_simulate_lost(srtp->real_tp, dir, pct_lost);
+}
+
+static pj_status_t transport_destroy  (pjmedia_transport *tp)
+{
+    transport_srtp *srtp = (transport_srtp *) tp;
+    pj_status_t status;
+
+    pjmedia_transport_detach(tp, NULL);
+    
+    if (srtp->options && PJMEDIA_SRTP_AUTO_CLOSE_UNDERLYING_TRANSPORT) {
+	pjmedia_transport_close(srtp->real_tp);
+    }
+
+    status = pjmedia_transport_srtp_deinit_session(tp);
+    if (status != PJ_SUCCESS)
+	return status;
+
+    pj_mutex_destroy(srtp->mutex);
+    pj_pool_release(srtp->pool);
+
+    return PJ_SUCCESS;
+}
+
+/*
+ * This callback is called by transport when incoming rtp is received
+ */
+static void srtp_rtp_cb( void *user_data, const void *pkt, pj_ssize_t size)
+{
+    transport_srtp *srtp = (transport_srtp *) user_data;
+    int len = size;
+    err_status_t err;
+
+    if (size < 0 || size > sizeof(srtp->rx_buffer) || !srtp->session_inited) {
+	return;
+    }
+
+    pj_mutex_lock(srtp->mutex);
+    pj_memcpy(srtp->rx_buffer, pkt, size);
+
+    err = srtp_unprotect(srtp->srtp_rx_ctx, srtp->rx_buffer, &len);
+    
+    /* unprotect should returns less (or same, if auth disabled) size */
+    PJ_TODO(CHECK_SIZE_AFTER_UNPROTECT);
+
+    if (err == err_status_ok) {
+	srtp->rtp_cb(srtp->user_data, srtp->rx_buffer, len);
+    } else {
+	PJ_TODO(LOG_ERROR_UNPROTECT);
+    }
+
+    pj_mutex_unlock(srtp->mutex);
+}
+
+/*
+ * This callback is called by transport when incoming rtcp is received
+ */
+static void srtp_rtcp_cb( void *user_data, const void *pkt, pj_ssize_t size)
+{
+    transport_srtp *srtp = (transport_srtp *) user_data;
+    int len = size;
+    err_status_t err;
+
+    if (size < 0 || size > sizeof(srtp->rx_buffer) || !srtp->session_inited) {
+	return;
+    }
+
+    pj_mutex_lock(srtp->mutex);
+    pj_memcpy(srtp->rx_buffer, pkt, size);
+
+    err = srtp_unprotect_rtcp(srtp->srtp_rx_ctx, srtp->rx_buffer, &len);
+
+    /* unprotect should returns less (or same, if auth disabled) size */
+    PJ_TODO(CHECK_SIZE_AFTER_UNPROTECT);
+
+    if (err == err_status_ok) {
+	srtp->rtcp_cb(srtp->user_data, srtp->rx_buffer, len);
+    } else {
+	PJ_TODO(LOG_ERROR_UNPROTECT);
+    }
+    
+    pj_mutex_unlock(srtp->mutex);
+}
+
+/* Generate crypto attribute, including crypto key.
+ * If crypto-suite chosen is crypto NULL, just return PJ_SUCCESS,
+ * and set buffer_len = 0.
+ */
+static pj_status_t generate_crypto_attr_value(char *buffer, int *buffer_len, 
+					      int cs_idx, int cs_tag)
+{
+    pj_uint8_t key[MAX_KEY_LEN];
+    char b64_key[PJ_BASE256_TO_BASE64_LEN(MAX_KEY_LEN)+1];
+    int b64_key_len = sizeof(b64_key);
+    err_status_t err;
+    pj_status_t status;
+    pj_bool_t key_ok;
+
+    PJ_ASSERT_RETURN(MAX_KEY_LEN >= crypto_suites[cs_idx].cipher_key_len,
+		     PJ_ETOOSMALL);
+
+    /* Crypto-suite NULL. */
+    if (cs_idx == 0) {
+	*buffer_len = 0;
+	return PJ_SUCCESS;
+    }
+
+    /* Generate key. */
+    do {
+	unsigned i;
+	key_ok = PJ_TRUE;
+
+	err = crypto_get_random(key, crypto_suites[cs_idx].cipher_key_len);
+	if (err != err_status_ok) {
+	    PJ_LOG(5,(THIS_FILE, "Failed generating random key"));
+	    return SRTP_ERROR(err);
+	}
+	for (i=0; i<crypto_suites[cs_idx].cipher_key_len && key_ok; ++i)
+	    if (key[i] == 0) key_ok = PJ_FALSE;
+
+    } while (!key_ok);
+
+    /* Key transmitted via SDP should be base64 encoded. */
+    status = pj_base64_encode(key, crypto_suites[cs_idx].cipher_key_len,
+			      b64_key, &b64_key_len);
+    if (status != PJ_SUCCESS) {
+	PJ_LOG(5,(THIS_FILE, "Failed encoding plain key to base64"));
+	return status;
+    }
+
+    b64_key[b64_key_len] = '\0';
+
+    
+    PJ_ASSERT_RETURN((unsigned)*buffer_len >= 
+		     (pj_ansi_strlen(crypto_suites[cs_idx].name) +
+		     b64_key_len + 16), PJ_ETOOSMALL);
+
+    /* Print the crypto attribute value. */
+    *buffer_len = pj_ansi_snprintf(buffer, *buffer_len, "%d %s inline:%s",
+				   cs_tag, 
+				   crypto_suites[cs_idx].name,
+				   b64_key);
+
+    return PJ_SUCCESS;
+}
+
+static pj_status_t transport_media_create(pjmedia_transport *tp,
+				          pj_pool_t *pool,
+				          pjmedia_sdp_session *sdp_local,
+				          const pjmedia_sdp_session *sdp_remote)
+{
+    struct transport_srtp *srtp = (struct transport_srtp*) tp;
+    enum { MAXLEN = 512 };
+    char buffer[MAXLEN];
+    pj_status_t status;
+    unsigned i, j;
+    unsigned cs_cnt = sizeof(crypto_suites)/sizeof(crypto_suites[0]);
+
+    /* If we are the answerer side, skip generating crypto-suites offer */
+    if (sdp_remote) {
+	srtp->offerer_side = PJ_FALSE;
+	return PJ_SUCCESS;
+    }
+    
+    srtp->offerer_side = PJ_TRUE;
+
+    for (i=0; i<sdp_local->media_count; ++i) {
+	/* Change "RTP/AVP" transport to "RTP/SAVP" */
+	if (pj_stricmp(&sdp_local->media[i]->desc.transport, &ID_RTP_AVP) == 0) {
+	    sdp_local->media[i]->desc.transport = ID_RTP_SAVP;
+
+	/* Skip media transport that is not appropriate for SRTP */
+	} else if (pj_stricmp(&sdp_local->media[i]->desc.transport, 
+		   &ID_RTP_SAVP) != 0)
+	{
+	    continue;
+	}
+
+	/* Generate "crypto" attribute(s) */
+	for (j=1; j<cs_cnt; ++j) {
+	    /* Offer all our crypto-suites. */
+	    pj_str_t attr_value;
+	    int buffer_len = MAXLEN;
+	    pjmedia_sdp_attr *attr;
+
+	    status = generate_crypto_attr_value(buffer, &buffer_len, j, j);
+	    if (status != PJ_SUCCESS)
+		return status;
+
+	    /* If buffer_len==0, just skip the crypto attribute. */
+	    if (buffer_len) {
+		pj_strset(&attr_value, buffer, buffer_len);
+		attr = pjmedia_sdp_attr_create(pool, "crypto", &attr_value);
+		sdp_local->media[i]->attr[sdp_local->media[i]->attr_count++] = attr;
+	    }
+	}
+    }
+
+    return pjmedia_transport_media_create(srtp->real_tp, pool, sdp_local, 
+					   sdp_remote);
+}
+
+/* Parse crypto attribute line */
+static pj_status_t parse_attr_crypto(pj_pool_t *pool,
+				     const pjmedia_sdp_attr *attr,
+				     pjmedia_srtp_stream_policy *policy,
+				     int *tag)
+{
+    pj_str_t input;
+    char *token;
+
+    pj_bzero(policy, sizeof(*policy));
+    pj_strdup_with_null(pool, &input, &attr->value);
+
+    /* Tag */
+    token = strtok(input.ptr, " ");
+    if (!token) {
+	PJ_LOG(5,(THIS_FILE, "Expecting tag"));
+	return PJMEDIA_SDP_EINATTR;
+    }
+    *tag = atoi(token);
+
+    /* Crypto-suite */
+    token = strtok(NULL, " ");
+    if (!token) {
+	PJ_LOG(5,(THIS_FILE, "Expecting crypto suite"));
+	return PJMEDIA_SDP_EINATTR;
+    }
+    policy->crypto_suite = pj_str(token);
+
+    /* Key method */
+    token = strtok(NULL, ":");
+    if (!token) {
+	PJ_LOG(5,(THIS_FILE, "Expecting key method"));
+	return PJMEDIA_SDP_EINATTR;
+    }
+    if (pj_ansi_stricmp(token, "inline")) {
+	PJ_LOG(5,(THIS_FILE, "Key method %s not supported!", token));
+	return PJMEDIA_SDP_EINATTR;
+    }
+
+    /* Key */
+    token = strtok(NULL, "| ");
+    if (!token) {
+	PJ_LOG(5,(THIS_FILE, "Expecting key"));
+	return PJMEDIA_SDP_EINATTR;
+    }
+    policy->key = pj_str(token);
+
+    return PJ_SUCCESS;
+}
+
+static pj_status_t transport_media_start(pjmedia_transport *tp,
+				         pj_pool_t *pool,
+				         pjmedia_sdp_session *sdp_local,
+				         const pjmedia_sdp_session *sdp_remote,
+				         unsigned media_index)
+{
+    struct transport_srtp *srtp = (struct transport_srtp*) tp;
+    pjmedia_sdp_media *media_remote = sdp_remote->media[media_index];
+    pjmedia_sdp_media *media_local  = sdp_local->media[media_index];
+    pjmedia_sdp_attr *attr;
+    pjmedia_srtp_stream_policy policy_remote;
+    pjmedia_srtp_stream_policy policy_local;
+    pj_status_t status;
+    unsigned cs_cnt = sizeof(crypto_suites)/sizeof(crypto_suites[0]);
+    int cs_tag = -1;
+    unsigned i, j;
+
+    /* If the media is inactive, do nothing. */
+    if (pjmedia_sdp_media_find_attr2(media_remote, "inactive", NULL) ||
+	pjmedia_sdp_media_find_attr2(media_local, "inactive", NULL))
+    {
+	return PJ_SUCCESS;
+    }
+
+    /* default crypto-suite = crypto 'NULL' */
+    pj_bzero(&policy_remote, sizeof(policy_remote));
+    policy_remote.crypto_suite = pj_str(crypto_suites[0].name);
+    pj_bzero(&policy_local, sizeof(policy_local));
+    policy_remote.crypto_suite = pj_str(crypto_suites[0].name);
+
+    /* If the media transport is not RTP/SAVP, just apply crypto default */
+    if (pj_stricmp(&media_local->desc.transport, &ID_RTP_SAVP) ||
+	pj_stricmp(&media_remote->desc.transport, &ID_RTP_SAVP))
+    {
+	return PJMEDIA_SDP_EINPROTO;
+    }
+
+    /*
+     * In this stage, we need to make sure the crypto-suite negotiation
+     * is completed, and also parse the key from SDP.
+     */
+    if (srtp->offerer_side) {
+	/* If we are at the offerer side: 
+	 * 1. Get what crypto-suite selected by remote, we use the same one.
+	 * 2. Get what key we offered in the offering stage for 
+	 *    the selected crypto-suite.
+	 * 3. If no crypto-suite answered, assume the answerer want plain RTP.
+	 *    (perhaps this will abuse RFC 4568)
+	 */
+
+	/* Make sure only thera is ONLY ONE crypto attribute in the answer. */
+	attr = NULL;
+	for (i=0; i<media_remote->attr_count; ++i) {
+	    if (!pj_stricmp2(&media_local->attr[i]->name, "crypto")) {
+		if (attr)
+		    return PJMEDIA_ERROR;
+
+		attr = media_local->attr[i];
+	    }
+	}
+	if (!attr) {
+	    /* the answer got no crypto-suite attribute, huh! */
+	    PJ_LOG(5,(THIS_FILE, "Crypto attribute cannot be found in" \
+				 "remote SDP, using NULL crypto."));
+	} else {
+
+	    /* get policy_remote */
+	    status = parse_attr_crypto(pool, attr, &policy_remote, &cs_tag);
+	    if (status != PJ_SUCCESS)
+		return status;
+
+	    /* lets see what crypto-suite chosen, we will use the same one */
+	    for (i=1; i<cs_cnt; ++i) {
+		if (!pj_stricmp2(&policy_remote.crypto_suite, 
+				 crypto_suites[i].name))
+    		    break;
+	    }
+
+	    /* The crypto-suite answered is not supported,
+	     * this SHOULD NEVER happen, since we only offer what we support,
+	     * except the answerer is trying to force us use his crypto-suite!
+	     * Let's return non-PJ_SUCCESS and cancel the call.
+	     */
+	    if (i == cs_cnt) {
+		return PJ_ENOTSUP;
+	    }
+
+	    /* check whether the answer is match to our offers,
+	     * then get our own offered key along with the crypto-suite
+	     * and put it in policy_local.
+	     */
+	    for (i=0; i<media_local->attr_count; ++i) {
+		int tmp_cs_tag;
+    	    
+		if (pj_stricmp2(&media_local->attr[i]->name, "crypto"))
+		    continue;
+
+		status = parse_attr_crypto(pool, media_local->attr[i], 
+					   &policy_local, &tmp_cs_tag);
+		if (status != PJ_SUCCESS)
+		    return status;
+
+		/* Selected crypto-suite is marked by same crypto attr tag */
+		if (tmp_cs_tag == cs_tag)
+		    break;
+	    }
+	    /* This SHOULD NEVER happen. */
+	    if (i == media_local->attr_count) {
+		return PJMEDIA_SDPNEG_ENOMEDIA;
+	    }
+
+	    /* Check if crypto-suite name match, crypto tag was ensured same */
+	    if (pj_stricmp(&policy_local.crypto_suite, 
+			   &policy_remote.crypto_suite))
+	    {
+		return PJMEDIA_ERROR;
+	    }
+	}
+    } else {
+	/* If we are at the answerer side: 
+	 * 1. Negotiate: check if any offered crypto-suite matches 
+	 *    our capability.
+	 * 2. If there is one, generate key and media attribute.
+	 * 3. If there isn't, return error.
+	 * 4. If no crypto-suite offered, apply NULL crypto-suite.
+	 *    (perhaps this will abuse RFC 4568)
+	 *
+	 * Please note that we need to consider the existance of other media,
+	 * so instead of returning non-PJ_SUCCESS on failed negotiation,
+	 * which will cancel the call, perhaps it is wiser to mark the media 
+	 * as inactive.
+	 */
+
+	enum { MAXLEN = 512 };
+	char buffer[MAXLEN];
+	int  buffer_len = MAXLEN;
+	pj_str_t attr_value;
+	pj_bool_t no_crypto_attr = PJ_TRUE;
+	int cs_idx = -1;
+
+	/* find supported crypto-suite, get the tag, and assign policy_local */
+	for (i=0; (i<media_remote->attr_count) && (cs_idx == -1); ++i) {
+	    if (pj_stricmp2(&media_remote->attr[i]->name, "crypto"))
+		continue;
+
+	    no_crypto_attr = PJ_FALSE;
+
+	    status = parse_attr_crypto(pool, media_remote->attr[i], 
+				       &policy_remote, &cs_tag);
+	    if (status != PJ_SUCCESS)
+		return status;
+	 
+	    /* lets see if the crypto-suite offered is supported */
+	    for (j=1; j<cs_cnt; ++j) {
+		if (!pj_stricmp2(&policy_remote.crypto_suite, 
+				 crypto_suites[j].name))
+		{
+		    cs_idx = j;
+    		    break;
+		}
+	    }
+	}
+
+	if (!no_crypto_attr) {
+	    /* No crypto-suites offered is supported by us.
+	     * What should we do?
+	     * By now, let's just deactivate the media.
+	     */
+	    if (i == media_remote->attr_count) {
+		attr = pjmedia_sdp_attr_create(pool, "inactive", NULL);
+		media_local->attr[media_local->attr_count++] = attr;
+		media_local->desc.port = 0;
+
+		return PJ_SUCCESS;
+	    }
+
+	    /* there is crypto-suite supported
+	     * let's generate crypto attribute and also the key,
+	     * dont forget to use offerer cs_tag.
+	     */
+	    status = generate_crypto_attr_value(buffer, &buffer_len, cs_idx, cs_tag);
+	    if (status != PJ_SUCCESS)
+		return status;
+
+	    /* If buffer_len==0, just skip the crypto attribute. */
+	    if (buffer_len) {
+		pj_strset(&attr_value, buffer, buffer_len);
+		attr = pjmedia_sdp_attr_create(pool, "crypto", &attr_value);
+		media_local->attr[media_local->attr_count++] = attr;
+
+		/* put our key & crypto-suite name to policy_local */
+		status = parse_attr_crypto(pool, attr, &policy_local, &cs_tag);
+		if (status != PJ_SUCCESS)
+		    return status;
+	    }
+	}
+    }
+
+    /* in the SDP, all keys are in base64, they have to be decoded back
+     * to base256 before used.
+     */
+    if (policy_local.key.slen) {
+	char key[MAX_KEY_LEN];
+	int  key_len = MAX_KEY_LEN;
+	
+	status = pj_base64_decode(&policy_local.key, 
+	                          (pj_uint8_t*)key, &key_len);
+	if (status != PJ_SUCCESS)
+	    return status;
+
+	pj_memcpy(policy_local.key.ptr, key, key_len);
+	policy_local.key.slen = key_len;
+    }
+
+    if (policy_remote.key.slen) {
+	char key[MAX_KEY_LEN];
+	int  key_len = MAX_KEY_LEN;
+	
+	status = pj_base64_decode(&policy_remote.key, 
+	                          (pj_uint8_t*)key, &key_len);
+	if (status != PJ_SUCCESS)
+	    return status;
+
+	pj_memcpy(policy_remote.key.ptr, key, key_len);
+	policy_remote.key.slen = key_len;
+    }
+
+    /* Got policy_local & policy_remote, let's initalize the SRTP */
+    status = pjmedia_transport_srtp_init_session(tp, 
+						 &policy_local, &policy_remote);
+    if (status != PJ_SUCCESS)
+	return status;
+
+    return pjmedia_transport_media_start(srtp->real_tp, pool, 
+					 sdp_local, sdp_remote,
+				         media_index);
+}
+
+static pj_status_t transport_media_stop(pjmedia_transport *tp)
+{
+    struct transport_srtp *srtp = (struct transport_srtp*) tp;
+    pj_status_t status;
+
+    status = pjmedia_transport_srtp_deinit_session(tp);
+    if (status != PJ_SUCCESS) {
+	PJ_TODO(LOG_ERROR_DEINIT_SRTP);
+    }
+
+    return pjmedia_transport_media_stop(srtp->real_tp);
+}
Index: pjproject/branches/users/nanang/pjmedia/src/pjmedia/transport_udp.c
===================================================================
--- pjproject/branches/users/nanang/pjmedia/src/pjmedia/transport_udp.c	(revision 1697)
+++ pjproject/branches/users/nanang/pjmedia/src/pjmedia/transport_udp.c	(revision 1698)
@@ -95,7 +95,10 @@
                        pj_ssize_t bytes_read);
 
-static pj_status_t transport_get_info(pjmedia_transport *tp,
-				      pjmedia_sock_info *info);
-static pj_status_t transport_attach(   pjmedia_transport *tp,
+/*
+ * These are media transport operations.
+ */
+static pj_status_t transport_get_info (pjmedia_transport *tp,
+				       pjmedia_sock_info *info);
+static pj_status_t transport_attach   (pjmedia_transport *tp,
 				       void *user_data,
 				       const pj_sockaddr_t *rem_addr,
@@ -108,5 +111,5 @@
 						       const void*,
 						       pj_ssize_t));
-static void	   transport_detach(   pjmedia_transport *tp,
+static void	   transport_detach   (pjmedia_transport *tp,
 				       void *strm);
 static pj_status_t transport_send_rtp( pjmedia_transport *tp,
@@ -116,4 +119,18 @@
 				       const void *pkt,
 				       pj_size_t size);
+static pj_status_t transport_media_create(pjmedia_transport *tp,
+				       pj_pool_t *pool,
+				       pjmedia_sdp_session *sdp_local,
+				       const pjmedia_sdp_session *sdp_remote);
+static pj_status_t transport_media_start (pjmedia_transport *tp,
+				       pj_pool_t *pool,
+				       pjmedia_sdp_session *sdp_local,
+				       const pjmedia_sdp_session *sdp_remote,
+				       unsigned media_index);
+static pj_status_t transport_media_stop(pjmedia_transport *tp);
+static pj_status_t transport_simulate_lost(pjmedia_transport *tp,
+				       pjmedia_dir dir,
+				       unsigned pct_lost);
+static pj_status_t transport_destroy  (pjmedia_transport *tp);
 
 
@@ -125,5 +142,9 @@
     &transport_send_rtp,
     &transport_send_rtcp,
-    &pjmedia_transport_udp_close
+    &transport_media_create,
+    &transport_media_start,
+    &transport_media_stop,
+    &transport_simulate_lost,
+    &transport_destroy
 };
 
@@ -342,16 +363,6 @@
 
 on_error:
-    pjmedia_transport_udp_close(&tp->base);
+    transport_destroy(&tp->base);
     return status;
-}
-
-
-/*
- * Get media socket info.
- */
-PJ_DEF(pj_status_t) pjmedia_transport_udp_get_info( pjmedia_transport *tp,
-				pjmedia_transport_udp_info *inf)
-{
-    return transport_get_info(tp, &inf->skinfo);
 }
 
@@ -360,5 +371,5 @@
  * Close UDP transport.
  */
-PJ_DEF(pj_status_t) pjmedia_transport_udp_close(pjmedia_transport *tp)
+static pj_status_t transport_destroy(pjmedia_transport *tp)
 {
     struct transport_udp *udp = (struct transport_udp*) tp;
@@ -727,7 +738,42 @@
 
 
-PJ_DEF(pj_status_t) pjmedia_transport_udp_simulate_lost(pjmedia_transport *tp,
-							pjmedia_dir dir,
-							unsigned pct_lost)
+static pj_status_t transport_media_create(pjmedia_transport *tp,
+				  pj_pool_t *pool,
+				  pjmedia_sdp_session *sdp_local,
+				  const pjmedia_sdp_session *sdp_remote)
+{
+    PJ_UNUSED_ARG(tp);
+    PJ_UNUSED_ARG(pool);
+    PJ_UNUSED_ARG(sdp_local);
+    PJ_UNUSED_ARG(sdp_remote);
+
+    return PJ_SUCCESS;
+}
+
+static pj_status_t transport_media_start(pjmedia_transport *tp,
+				  pj_pool_t *pool,
+				  pjmedia_sdp_session *sdp_local,
+				  const pjmedia_sdp_session *sdp_remote,
+				  unsigned media_index)
+{
+    PJ_UNUSED_ARG(tp);
+    PJ_UNUSED_ARG(pool);
+    PJ_UNUSED_ARG(sdp_local);
+    PJ_UNUSED_ARG(sdp_remote);
+    PJ_UNUSED_ARG(media_index);
+
+    return PJ_SUCCESS;
+}
+
+static pj_status_t transport_media_stop(pjmedia_transport *tp)
+{
+    PJ_UNUSED_ARG(tp);
+
+    return PJ_SUCCESS;
+}
+
+static pj_status_t transport_simulate_lost(pjmedia_transport *tp,
+					   pjmedia_dir dir,
+					   unsigned pct_lost)
 {
     struct transport_udp *udp = (struct transport_udp*)tp;
Index: pjproject/branches/users/nanang/pjproject-vs8.sln
===================================================================
--- pjproject/branches/users/nanang/pjproject-vs8.sln	(revision 1697)
+++ pjproject/branches/users/nanang/pjproject-vs8.sln	(revision 1698)
@@ -1,5 +1,5 @@
 ﻿
 Microsoft Visual Studio Solution File, Format Version 9.00
-# Visual C++ Express 2005
+# Visual Studio 2005
 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "pjlib", "pjlib\build\pjlib.vcproj", "{DA0E03ED-53A7-4050-8A85-90541C5509F8}"
 EndProject
@@ -13,6 +13,6 @@
 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "pjlib_util_test", "pjlib-util\build\pjlib_util_test.vcproj", "{ED02BE13-8297-4770-8097-27DC2CCABF9A}"
 	ProjectSection(ProjectDependencies) = postProject
-		{DA0E03ED-53A7-4050-8A85-90541C5509F8} = {DA0E03ED-53A7-4050-8A85-90541C5509F8}
-		{FE07F272-AE7F-4549-9E9F-EF9B80CB1693} = {FE07F272-AE7F-4549-9E9F-EF9B80CB1693}
+		{FE07F272-AE7F-4549-9E9F-EF9B80CB1693} = {FE07F272-AE7F-4549-9E9F-EF9B80CB1693}
+		{DA0E03ED-53A7-4050-8A85-90541C5509F8} = {DA0E03ED-53A7-4050-8A85-90541C5509F8}
 	EndProjectSection
 EndProject
@@ -29,63 +29,65 @@
 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "pjsua", "pjsip-apps\build\pjsua.vcproj", "{8310649E-A25E-4AF0-91E8-9E3CC659BB89}"
 	ProjectSection(ProjectDependencies) = postProject
+		{F0DBAA03-1BA3-4E3B-A2CA-727E3D3AB858} = {F0DBAA03-1BA3-4E3B-A2CA-727E3D3AB858}
 		{2BB84911-C1B4-4747-B93D-36AA82CC5031} = {2BB84911-C1B4-4747-B93D-36AA82CC5031}
 		{4BF51C21-5A30-423B-82FE-1ED410E5769D} = {4BF51C21-5A30-423B-82FE-1ED410E5769D}
+		{A5D9AA24-08ED-48B9-BD65-F0A25E96BFC4} = {A5D9AA24-08ED-48B9-BD65-F0A25E96BFC4}
+		{FE07F272-AE7F-4549-9E9F-EF9B80CB1693} = {FE07F272-AE7F-4549-9E9F-EF9B80CB1693}
+		{6794B975-4E84-4F49-B2DC-C31F2224E03E} = {6794B975-4E84-4F49-B2DC-C31F2224E03E}
+		{7FDE3880-A4AB-49E3-B439-EBEF0A0C7A65} = {7FDE3880-A4AB-49E3-B439-EBEF0A0C7A65}
+		{3CF9FFA9-8387-4635-9D1B-E7944CBEFEAA} = {3CF9FFA9-8387-4635-9D1B-E7944CBEFEAA}
+		{4B059DBA-CD9C-4D0F-BE8C-FFB4EFD498E9} = {4B059DBA-CD9C-4D0F-BE8C-FFB4EFD498E9}
+		{855DC8C0-D3E9-4A2E-AE47-116605A7BC9B} = {855DC8C0-D3E9-4A2E-AE47-116605A7BC9B}
+		{4B5945CD-0CB3-49AA-A7FF-7612D93F82C0} = {4B5945CD-0CB3-49AA-A7FF-7612D93F82C0}
+		{B8719FD5-E8A6-4A36-943C-891D07F5DD21} = {B8719FD5-E8A6-4A36-943C-891D07F5DD21}
+		{DA0E03ED-53A7-4050-8A85-90541C5509F8} = {DA0E03ED-53A7-4050-8A85-90541C5509F8}
+		{B5FE16F8-3EDB-4110-BD80-B4238CC01E8D} = {B5FE16F8-3EDB-4110-BD80-B4238CC01E8D}
+		{9CA0FDFB-2172-41FC-B7F1-5CE915EDCB37} = {9CA0FDFB-2172-41FC-B7F1-5CE915EDCB37}
 		{E53AA5FF-B737-40AA-BD13-387EFA99023D} = {E53AA5FF-B737-40AA-BD13-387EFA99023D}
-		{9CA0FDFB-2172-41FC-B7F1-5CE915EDCB37} = {9CA0FDFB-2172-41FC-B7F1-5CE915EDCB37}
+	EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "pjsua_lib", "pjsip\build\pjsua_lib.vcproj", "{9CA0FDFB-2172-41FC-B7F1-5CE915EDCB37}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "sample_debug", "pjsip-apps\build\sample_debug.vcproj", "{A0F1AA62-0F6F-420D-B09A-AC04B6862821}"
+	ProjectSection(ProjectDependencies) = postProject
+		{A5D9AA24-08ED-48B9-BD65-F0A25E96BFC4} = {A5D9AA24-08ED-48B9-BD65-F0A25E96BFC4}
+		{FE07F272-AE7F-4549-9E9F-EF9B80CB1693} = {FE07F272-AE7F-4549-9E9F-EF9B80CB1693}
+		{6794B975-4E84-4F49-B2DC-C31F2224E03E} = {6794B975-4E84-4F49-B2DC-C31F2224E03E}
+		{7FDE3880-A4AB-49E3-B439-EBEF0A0C7A65} = {7FDE3880-A4AB-49E3-B439-EBEF0A0C7A65}
+		{3CF9FFA9-8387-4635-9D1B-E7944CBEFEAA} = {3CF9FFA9-8387-4635-9D1B-E7944CBEFEAA}
+		{4B059DBA-CD9C-4D0F-BE8C-FFB4EFD498E9} = {4B059DBA-CD9C-4D0F-BE8C-FFB4EFD498E9}
+		{855DC8C0-D3E9-4A2E-AE47-116605A7BC9B} = {855DC8C0-D3E9-4A2E-AE47-116605A7BC9B}
+		{4B5945CD-0CB3-49AA-A7FF-7612D93F82C0} = {4B5945CD-0CB3-49AA-A7FF-7612D93F82C0}
+		{B8719FD5-E8A6-4A36-943C-891D07F5DD21} = {B8719FD5-E8A6-4A36-943C-891D07F5DD21}
+		{DA0E03ED-53A7-4050-8A85-90541C5509F8} = {DA0E03ED-53A7-4050-8A85-90541C5509F8}
 		{B5FE16F8-3EDB-4110-BD80-B4238CC01E8D} = {B5FE16F8-3EDB-4110-BD80-B4238CC01E8D}
-		{DA0E03ED-53A7-4050-8A85-90541C5509F8} = {DA0E03ED-53A7-4050-8A85-90541C5509F8}
-		{B8719FD5-E8A6-4A36-943C-891D07F5DD21} = {B8719FD5-E8A6-4A36-943C-891D07F5DD21}
-		{4B5945CD-0CB3-49AA-A7FF-7612D93F82C0} = {4B5945CD-0CB3-49AA-A7FF-7612D93F82C0}
-		{855DC8C0-D3E9-4A2E-AE47-116605A7BC9B} = {855DC8C0-D3E9-4A2E-AE47-116605A7BC9B}
-		{4B059DBA-CD9C-4D0F-BE8C-FFB4EFD498E9} = {4B059DBA-CD9C-4D0F-BE8C-FFB4EFD498E9}
-		{3CF9FFA9-8387-4635-9D1B-E7944CBEFEAA} = {3CF9FFA9-8387-4635-9D1B-E7944CBEFEAA}
-		{7FDE3880-A4AB-49E3-B439-EBEF0A0C7A65} = {7FDE3880-A4AB-49E3-B439-EBEF0A0C7A65}
-		{6794B975-4E84-4F49-B2DC-C31F2224E03E} = {6794B975-4E84-4F49-B2DC-C31F2224E03E}
-		{FE07F272-AE7F-4549-9E9F-EF9B80CB1693} = {FE07F272-AE7F-4549-9E9F-EF9B80CB1693}
-		{A5D9AA24-08ED-48B9-BD65-F0A25E96BFC4} = {A5D9AA24-08ED-48B9-BD65-F0A25E96BFC4}
-	EndProjectSection
-EndProject
-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "pjsua_lib", "pjsip\build\pjsua_lib.vcproj", "{9CA0FDFB-2172-41FC-B7F1-5CE915EDCB37}"
-EndProject
-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "sample_debug", "pjsip-apps\build\sample_debug.vcproj", "{A0F1AA62-0F6F-420D-B09A-AC04B6862821}"
-	ProjectSection(ProjectDependencies) = postProject
+		{9CA0FDFB-2172-41FC-B7F1-5CE915EDCB37} = {9CA0FDFB-2172-41FC-B7F1-5CE915EDCB37}
 		{E53AA5FF-B737-40AA-BD13-387EFA99023D} = {E53AA5FF-B737-40AA-BD13-387EFA99023D}
-		{9CA0FDFB-2172-41FC-B7F1-5CE915EDCB37} = {9CA0FDFB-2172-41FC-B7F1-5CE915EDCB37}
-		{B5FE16F8-3EDB-4110-BD80-B4238CC01E8D} = {B5FE16F8-3EDB-4110-BD80-B4238CC01E8D}
-		{DA0E03ED-53A7-4050-8A85-90541C5509F8} = {DA0E03ED-53A7-4050-8A85-90541C5509F8}
-		{B8719FD5-E8A6-4A36-943C-891D07F5DD21} = {B8719FD5-E8A6-4A36-943C-891D07F5DD21}
-		{4B5945CD-0CB3-49AA-A7FF-7612D93F82C0} = {4B5945CD-0CB3-49AA-A7FF-7612D93F82C0}
-		{855DC8C0-D3E9-4A2E-AE47-116605A7BC9B} = {855DC8C0-D3E9-4A2E-AE47-116605A7BC9B}
-		{4B059DBA-CD9C-4D0F-BE8C-FFB4EFD498E9} = {4B059DBA-CD9C-4D0F-BE8C-FFB4EFD498E9}
-		{3CF9FFA9-8387-4635-9D1B-E7944CBEFEAA} = {3CF9FFA9-8387-4635-9D1B-E7944CBEFEAA}
-		{7FDE3880-A4AB-49E3-B439-EBEF0A0C7A65} = {7FDE3880-A4AB-49E3-B439-EBEF0A0C7A65}
-		{6794B975-4E84-4F49-B2DC-C31F2224E03E} = {6794B975-4E84-4F49-B2DC-C31F2224E03E}
-		{FE07F272-AE7F-4549-9E9F-EF9B80CB1693} = {FE07F272-AE7F-4549-9E9F-EF9B80CB1693}
-		{A5D9AA24-08ED-48B9-BD65-F0A25E96BFC4} = {A5D9AA24-08ED-48B9-BD65-F0A25E96BFC4}
-		{2BB84911-C1B4-4747-B93D-36AA82CC5031} = {2BB84911-C1B4-4747-B93D-36AA82CC5031}
+		{2BB84911-C1B4-4747-B93D-36AA82CC5031} = {2BB84911-C1B4-4747-B93D-36AA82CC5031}
+		{F0DBAA03-1BA3-4E3B-A2CA-727E3D3AB858} = {F0DBAA03-1BA3-4E3B-A2CA-727E3D3AB858}
 	EndProjectSection
 EndProject
 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "samples", "pjsip-apps\build\samples.vcproj", "{E378A1FC-0C9C-4462-860F-7E60BC1BF84E}"
 	ProjectSection(ProjectDependencies) = postProject
-		{9CA0FDFB-2172-41FC-B7F1-5CE915EDCB37} = {9CA0FDFB-2172-41FC-B7F1-5CE915EDCB37}
-		{DA0E03ED-53A7-4050-8A85-90541C5509F8} = {DA0E03ED-53A7-4050-8A85-90541C5509F8}
-		{B8719FD5-E8A6-4A36-943C-891D07F5DD21} = {B8719FD5-E8A6-4A36-943C-891D07F5DD21}
-		{4B5945CD-0CB3-49AA-A7FF-7612D93F82C0} = {4B5945CD-0CB3-49AA-A7FF-7612D93F82C0}
-		{855DC8C0-D3E9-4A2E-AE47-116605A7BC9B} = {855DC8C0-D3E9-4A2E-AE47-116605A7BC9B}
-		{7FDE3880-A4AB-49E3-B439-EBEF0A0C7A65} = {7FDE3880-A4AB-49E3-B439-EBEF0A0C7A65}
-		{FE07F272-AE7F-4549-9E9F-EF9B80CB1693} = {FE07F272-AE7F-4549-9E9F-EF9B80CB1693}
-		{2BB84911-C1B4-4747-B93D-36AA82CC5031} = {2BB84911-C1B4-4747-B93D-36AA82CC5031}
+		{2BB84911-C1B4-4747-B93D-36AA82CC5031} = {2BB84911-C1B4-4747-B93D-36AA82CC5031}
+		{FE07F272-AE7F-4549-9E9F-EF9B80CB1693} = {FE07F272-AE7F-4549-9E9F-EF9B80CB1693}
+		{7FDE3880-A4AB-49E3-B439-EBEF0A0C7A65} = {7FDE3880-A4AB-49E3-B439-EBEF0A0C7A65}
+		{855DC8C0-D3E9-4A2E-AE47-116605A7BC9B} = {855DC8C0-D3E9-4A2E-AE47-116605A7BC9B}
+		{4B5945CD-0CB3-49AA-A7FF-7612D93F82C0} = {4B5945CD-0CB3-49AA-A7FF-7612D93F82C0}
+		{B8719FD5-E8A6-4A36-943C-891D07F5DD21} = {B8719FD5-E8A6-4A36-943C-891D07F5DD21}
+		{DA0E03ED-53A7-4050-8A85-90541C5509F8} = {DA0E03ED-53A7-4050-8A85-90541C5509F8}
+		{9CA0FDFB-2172-41FC-B7F1-5CE915EDCB37} = {9CA0FDFB-2172-41FC-B7F1-5CE915EDCB37}
 	EndProjectSection
 EndProject
 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "test_pjsip", "pjsip\build\test_pjsip.vcproj", "{B3F7D4E9-702F-4EB4-ADA8-098D0A83D770}"
 	ProjectSection(ProjectDependencies) = postProject
-		{9CA0FDFB-2172-41FC-B7F1-5CE915EDCB37} = {9CA0FDFB-2172-41FC-B7F1-5CE915EDCB37}
-		{DA0E03ED-53A7-4050-8A85-90541C5509F8} = {DA0E03ED-53A7-4050-8A85-90541C5509F8}
-		{B8719FD5-E8A6-4A36-943C-891D07F5DD21} = {B8719FD5-E8A6-4A36-943C-891D07F5DD21}
-		{4B5945CD-0CB3-49AA-A7FF-7612D93F82C0} = {4B5945CD-0CB3-49AA-A7FF-7612D93F82C0}
-		{855DC8C0-D3E9-4A2E-AE47-116605A7BC9B} = {855DC8C0-D3E9-4A2E-AE47-116605A7BC9B}
-		{7FDE3880-A4AB-49E3-B439-EBEF0A0C7A65} = {7FDE3880-A4AB-49E3-B439-EBEF0A0C7A65}
-		{FE07F272-AE7F-4549-9E9F-EF9B80CB1693} = {FE07F272-AE7F-4549-9E9F-EF9B80CB1693}
-		{2BB84911-C1B4-4747-B93D-36AA82CC5031} = {2BB84911-C1B4-4747-B93D-36AA82CC5031}
+		{2BB84911-C1B4-4747-B93D-36AA82CC5031} = {2BB84911-C1B4-4747-B93D-36AA82CC5031}
+		{FE07F272-AE7F-4549-9E9F-EF9B80CB1693} = {FE07F272-AE7F-4549-9E9F-EF9B80CB1693}
+		{7FDE3880-A4AB-49E3-B439-EBEF0A0C7A65} = {7FDE3880-A4AB-49E3-B439-EBEF0A0C7A65}
+		{855DC8C0-D3E9-4A2E-AE47-116605A7BC9B} = {855DC8C0-D3E9-4A2E-AE47-116605A7BC9B}
+		{4B5945CD-0CB3-49AA-A7FF-7612D93F82C0} = {4B5945CD-0CB3-49AA-A7FF-7612D93F82C0}
+		{B8719FD5-E8A6-4A36-943C-891D07F5DD21} = {B8719FD5-E8A6-4A36-943C-891D07F5DD21}
+		{DA0E03ED-53A7-4050-8A85-90541C5509F8} = {DA0E03ED-53A7-4050-8A85-90541C5509F8}
+		{9CA0FDFB-2172-41FC-B7F1-5CE915EDCB37} = {9CA0FDFB-2172-41FC-B7F1-5CE915EDCB37}
 	EndProjectSection
 EndProject
@@ -105,4 +107,6 @@
 EndProject
 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libmilenage", "third_party\build\milenage\libmilenage.vcproj", "{4BF51C21-5A30-423B-82FE-1ED410E5769D}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libsrtp", "third_party\build\srtp\libsrtp.vcproj", "{F0DBAA03-1BA3-4E3B-A2CA-727E3D3AB858}"
 EndProject
 Global
@@ -200,4 +204,8 @@
 		{4BF51C21-5A30-423B-82FE-1ED410E5769D}.Release|Win32.ActiveCfg = Release|Win32
 		{4BF51C21-5A30-423B-82FE-1ED410E5769D}.Release|Win32.Build.0 = Release|Win32
+		{F0DBAA03-1BA3-4E3B-A2CA-727E3D3AB858}.Debug|Win32.ActiveCfg = Debug|Win32
+		{F0DBAA03-1BA3-4E3B-A2CA-727E3D3AB858}.Debug|Win32.Build.0 = Debug|Win32
+		{F0DBAA03-1BA3-4E3B-A2CA-727E3D3AB858}.Release|Win32.ActiveCfg = Release|Win32
+		{F0DBAA03-1BA3-4E3B-A2CA-727E3D3AB858}.Release|Win32.Build.0 = Release|Win32
 	EndGlobalSection
 	GlobalSection(SolutionProperties) = preSolution
Index: pjproject/branches/users/nanang/pjsip-apps/build/Samples-vc.mak
===================================================================
--- pjproject/branches/users/nanang/pjsip-apps/build/Samples-vc.mak	(revision 1697)
+++ pjproject/branches/users/nanang/pjsip-apps/build/Samples-vc.mak	(revision 1698)
@@ -24,7 +24,8 @@
 RESAMPLE_LIB = ..\..\third_party\lib\libresample-$(TARGET)$(LIBEXT)
 SPEEX_LIB = ..\..\third_party\lib\libspeex-$(TARGET)$(LIBEXT)
+SRTP_LIB = ..\..\third_party\lib\libsrtp-$(TARGET)$(LIBEXT)
 
 THIRD_PARTY_LIBS = $(GSM_LIB) $(ILBC_LIB) $(PORTAUDIO_LIB) $(RESAMPLE_LIB) \
-				   $(SPEEX_LIB)
+				   $(SPEEX_LIB) $(SRTP_LIB)
 
 LIBS = $(PJSUA_LIB_LIB) $(PJSIP_UA_LIB) $(PJSIP_SIMPLE_LIB) \
Index: pjproject/branches/users/nanang/pjsip-apps/src/pjsua/pjsua_app.c
===================================================================
--- pjproject/branches/users/nanang/pjsip-apps/src/pjsua/pjsua_app.c	(revision 1697)
+++ pjproject/branches/users/nanang/pjsip-apps/src/pjsua/pjsua_app.c	(revision 1698)
@@ -166,4 +166,5 @@
     puts  ("Media Options:");
     puts  ("  --use-ice           Enable ICE (default:no)");
+    puts  ("  --use-srtp          Enable SRTP (default:no)");
     puts  ("  --add-codec=name    Manually add codec (default is to enable all)");
     puts  ("  --dis-codec=name    Disable codec (can be specified multiple times)");
@@ -383,5 +384,5 @@
 	   OPT_ADD_BUDDY, OPT_OFFER_X_MS_MSG, OPT_NO_PRESENCE,
 	   OPT_AUTO_ANSWER, OPT_AUTO_HANGUP, OPT_AUTO_PLAY, OPT_AUTO_LOOP,
-	   OPT_AUTO_CONF, OPT_CLOCK_RATE, OPT_USE_ICE,
+	   OPT_AUTO_CONF, OPT_CLOCK_RATE, OPT_USE_ICE, OPT_USE_SRTP,
 	   OPT_PLAY_FILE, OPT_PLAY_TONE, OPT_RTP_PORT, OPT_ADD_CODEC, 
 	   OPT_ILBC_MODE, OPT_REC_FILE, OPT_AUTO_REC,
@@ -442,4 +443,5 @@
 	{ "rtp-port",	1, 0, OPT_RTP_PORT},
 	{ "use-ice",    0, 0, OPT_USE_ICE},
+	{ "use-srtp",   0, 0, OPT_USE_SRTP},
 	{ "add-codec",  1, 0, OPT_ADD_CODEC},
 	{ "dis-codec",  1, 0, OPT_DIS_CODEC},
@@ -797,4 +799,8 @@
 	    break;
 
+	case OPT_USE_SRTP:
+	    cfg->media_cfg.enable_srtp = PJ_TRUE;
+	    break;
+
 	case OPT_RTP_PORT:
 	    cfg->rtp_cfg.port = my_atoi(pj_optarg);
Index: pjproject/branches/users/nanang/pjsip-apps/src/samples/simpleua.c
===================================================================
--- pjproject/branches/users/nanang/pjsip-apps/src/samples/simpleua.c	(revision 1697)
+++ pjproject/branches/users/nanang/pjsip-apps/src/samples/simpleua.c	(revision 1698)
@@ -286,11 +286,5 @@
      * the SDP).
      */
-    {
-	pjmedia_transport_udp_info udp_info;
-
-	pjmedia_transport_udp_get_info(g_med_transport, &udp_info);
-	pj_memcpy(&g_med_skinfo, &udp_info.skinfo, 
-		  sizeof(pjmedia_sock_info));
-    }
+    pjmedia_transport_get_info(g_med_transport, &g_med_skinfo);
 
 
Index: pjproject/branches/users/nanang/pjsip-apps/src/samples/siprtp.c
===================================================================
--- pjproject/branches/users/nanang/pjsip-apps/src/samples/siprtp.c	(revision 1697)
+++ pjproject/branches/users/nanang/pjsip-apps/src/samples/siprtp.c	(revision 1698)
@@ -1006,5 +1006,5 @@
     pjmedia_sdp_media *m;
     pjmedia_sdp_attr *attr;
-    pjmedia_transport_udp_info tpinfo;
+    pjmedia_sock_info tpinfo;
     struct media_stream *audio = &call->media[0];
 
@@ -1013,5 +1013,5 @@
 
     /* Get transport info */
-    pjmedia_transport_udp_get_info(audio->transport, &tpinfo);
+    pjmedia_transport_get_info(audio->transport, &tpinfo);
 
     /* Create and initialize basic SDP session */
@@ -1047,5 +1047,5 @@
     /* Standard media info: */
     m->desc.media = pj_str("audio");
-    m->desc.port = pj_ntohs(tpinfo.skinfo.rtp_addr_name.ipv4.sin_port);
+    m->desc.port = pj_ntohs(tpinfo.rtp_addr_name.ipv4.sin_port);
     m->desc.port_count = 1;
     m->desc.transport = pj_str("RTP/AVP");
Index: pjproject/branches/users/nanang/pjsip-apps/src/samples/streamutil.c
===================================================================
--- pjproject/branches/users/nanang/pjsip-apps/src/samples/streamutil.c	(revision 1697)
+++ pjproject/branches/users/nanang/pjsip-apps/src/samples/streamutil.c	(revision 1698)
@@ -56,4 +56,11 @@
  "  --send-only           Set stream direction to send only		\n"
  "  --recv-only           Set stream direction to recv only (default)   \n"
+ "  --use-srtp[=NAME]     Enable SRTP with crypto suite NAME            \n"
+ "                        e.g: AES_CM_128_HMAC_SHA1_80 (default),       \n"
+ "                             AES_CM_128_HMAC_SHA1_32                  \n"
+ "                        Use this option along with the TX & RX keys,  \n"
+ "                        formated of 60 hex digits (e.g: E148DA..)      \n"
+ "  --srtp-tx-key         SRTP key for transmiting                      \n"
+ "  --srtp-rx-key         SRTP key for receiving                        \n"
  "\n"
 ;
@@ -65,4 +72,5 @@
 #include <pjmedia.h>
 #include <pjmedia-codec.h>
+#include <pjmedia/transport_srtp.h>
 
 #include <stdlib.h>	/* atoi() */
@@ -79,4 +87,6 @@
 static void print_stream_stat(pjmedia_stream *stream);
 
+/* Prototype for LIBSRTP utility in file datatypes.c */
+int hex_string_to_octet_string(char *raw, char *hex, int len);
 
 /* 
@@ -123,8 +133,13 @@
 				  pj_uint16_t local_port,
 				  const pj_sockaddr_in *rem_addr,
+				  pj_bool_t use_srtp,
+				  const pj_str_t *crypto_suite,
+				  const pj_str_t *srtp_tx_key,
+				  const pj_str_t *srtp_rx_key,
 				  pjmedia_stream **p_stream )
 {
     pjmedia_stream_info info;
-    pjmedia_transport *transport;
+    pjmedia_transport *transport = NULL;
+    pjmedia_transport *srtp_tp = NULL;
     pj_status_t status;
 
@@ -159,4 +174,26 @@
 	return status;
 
+    /* Check if SRTP enabled */
+    if (use_srtp) {
+	pjmedia_srtp_stream_policy tx_plc, rx_plc;
+
+	status = pjmedia_transport_srtp_create(med_endpt, transport, 
+			    PJMEDIA_SRTP_AUTO_CLOSE_UNDERLYING_TRANSPORT,
+			    &srtp_tp);
+	if (status != PJ_SUCCESS)
+	    return status;
+
+	pj_bzero(&tx_plc, sizeof(pjmedia_srtp_stream_policy));
+	pj_bzero(&rx_plc, sizeof(pjmedia_srtp_stream_policy));
+
+	tx_plc.key = *srtp_tx_key;
+	tx_plc.crypto_suite = *crypto_suite;
+	rx_plc.key = *srtp_rx_key;
+	rx_plc.crypto_suite = *crypto_suite;
+	
+	status = pjmedia_transport_srtp_init_session(srtp_tp, &tx_plc, &rx_plc);
+	if (status != PJ_SUCCESS)
+	    return status;
+    }
 
     /* Now that the stream info is initialized, we can create the 
@@ -165,9 +202,10 @@
 
     status = pjmedia_stream_create( med_endpt, pool, &info, 
-				    transport, NULL, p_stream);
+				    (use_srtp?srtp_tp:transport), 
+				    NULL, p_stream);
 
     if (status != PJ_SUCCESS) {
 	app_perror(THIS_FILE, "Error creating stream", status);
-	pjmedia_transport_udp_close(transport);
+	pjmedia_transport_close(transport);
 	return status;
     }
@@ -202,4 +240,12 @@
     pj_status_t status; 
 
+    /* SRTP variables */
+    pj_bool_t use_srtp = PJ_FALSE;
+    char tmp_tx_key[64];
+    char tmp_rx_key[64];
+    pj_str_t  srtp_tx_key = {NULL, 0};
+    pj_str_t  srtp_rx_key = {NULL, 0};
+    pj_str_t  srtp_crypto_suite = {NULL, 0};
+    int	tmp_key_len;
 
     /* Default values */
@@ -221,4 +267,7 @@
 	OPT_SEND_ONLY	= 's',
 	OPT_RECV_ONLY	= 'i',
+	OPT_USE_SRTP	= 'S',
+	OPT_SRTP_TX_KEY	= 'x',
+	OPT_SRTP_RX_KEY	= 'y',
 	OPT_HELP	= 'h',
     };
@@ -233,4 +282,7 @@
 	{ "send-only",      0, 0, OPT_SEND_ONLY },
 	{ "recv-only",      0, 0, OPT_RECV_ONLY },
+	{ "use-srtp",	    2, 0, OPT_USE_SRTP },
+	{ "srtp-tx-key",    1, 0, OPT_SRTP_TX_KEY },
+	{ "srtp-rx-key",    1, 0, OPT_SRTP_RX_KEY },
 	{ "help",	    0, 0, OPT_HELP },
 	{ NULL, 0, 0, 0 },
@@ -299,4 +351,23 @@
 	    break;
 
+	case OPT_USE_SRTP:
+	    use_srtp = PJ_TRUE;
+	    if (pj_optarg) {
+		pj_strset(&srtp_crypto_suite, pj_optarg, strlen(pj_optarg));
+	    } else {
+		srtp_crypto_suite = pj_str("AES_CM_128_HMAC_SHA1_80");
+	    }
+	    break;
+
+	case OPT_SRTP_TX_KEY:
+	    tmp_key_len = hex_string_to_octet_string(tmp_tx_key, pj_optarg, strlen(pj_optarg));
+	    pj_strset(&srtp_tx_key, tmp_tx_key, tmp_key_len/2);
+	    break;
+
+	case OPT_SRTP_RX_KEY:
+	    tmp_key_len = hex_string_to_octet_string(tmp_rx_key, pj_optarg, strlen(pj_optarg));
+	    pj_strset(&srtp_rx_key, tmp_rx_key, tmp_key_len/2);
+	    break;
+
 	case OPT_HELP:
 	    usage();
@@ -324,4 +395,12 @@
     }
 
+    if (use_srtp) {
+	if (((dir & PJMEDIA_DIR_ENCODING) && !srtp_tx_key.slen) ||
+	    ((dir & PJMEDIA_DIR_DECODING) && !srtp_rx_key.slen))
+	{
+	    printf("Error: Key for each SRTP stream direction must be set\n");
+	    return 1;
+	}
+    }
 
     /* Must create a pool factory before we can allocate any memory. */
@@ -369,5 +448,8 @@
     /* Create stream based on program arguments */
     status = create_stream(pool, med_endpt, codec_info, dir, local_port, 
-			   &remote_addr, &stream);
+			   &remote_addr, 
+			   use_srtp, &srtp_crypto_suite, 
+			   &srtp_tx_key, &srtp_rx_key,
+			   &stream);
     if (status != PJ_SUCCESS)
 	goto on_exit;
@@ -538,5 +620,6 @@
 	tp = pjmedia_stream_get_transport(stream);
 	pjmedia_stream_destroy(stream);
-	pjmedia_transport_udp_close(tp);
+	
+	pjmedia_transport_close(tp);
     }
 
Index: pjproject/branches/users/nanang/pjsip/include/pjsip-ua/sip_inv.h
===================================================================
--- pjproject/branches/users/nanang/pjsip/include/pjsip-ua/sip_inv.h	(revision 1697)
+++ pjproject/branches/users/nanang/pjsip/include/pjsip-ua/sip_inv.h	(revision 1698)
@@ -395,4 +395,6 @@
  *			(this is useful e.g. when application wants to send 
  *			the response statelessly).
+ *
+ * @see pjsip_inv_verify_request2()
  */
 PJ_DECL(pj_status_t) pjsip_inv_verify_request(	pjsip_rx_data *rdata,
@@ -403,4 +405,18 @@
 						pjsip_tx_data **tdata);
 
+/**
+ * Variant of #pjsip_inv_verify_request() which allows application to specify
+ * the parsed SDP in the \a offer argument. This is useful to avoid having to
+ * re-parse the SDP in the incoming request.
+ *
+ * @see pjsip_inv_verify_request()
+ */
+PJ_DECL(pj_status_t) pjsip_inv_verify_request2( pjsip_rx_data *rdata,
+						unsigned *options,
+						const pjmedia_sdp_session *offer,
+						const pjmedia_sdp_session *answer,
+						pjsip_dialog *dlg,
+						pjsip_endpoint *endpt,
+						pjsip_tx_data **tdata);
 
 /**
Index: pjproject/branches/users/nanang/pjsip/include/pjsua-lib/pjsua.h
===================================================================
--- pjproject/branches/users/nanang/pjsip/include/pjsua-lib/pjsua.h	(revision 1697)
+++ pjproject/branches/users/nanang/pjsip/include/pjsua-lib/pjsua.h	(revision 1698)
@@ -3769,4 +3769,9 @@
      */
     pj_bool_t		enable_relay;
+
+    /**
+     * Enable SRTP
+     */
+    pj_bool_t		enable_srtp;
 };
 
Index: pjproject/branches/users/nanang/pjsip/include/pjsua-lib/pjsua_internal.h
===================================================================
--- pjproject/branches/users/nanang/pjsip/include/pjsua-lib/pjsua_internal.h	(revision 1697)
+++ pjproject/branches/users/nanang/pjsip/include/pjsua-lib/pjsua_internal.h	(revision 1698)
@@ -316,7 +316,8 @@
 pj_status_t pjsua_media_channel_create_sdp(pjsua_call_id call_id, 
 					   pj_pool_t *pool,
+					   const pjmedia_sdp_session *rem_sdp,
 					   pjmedia_sdp_session **p_sdp);
 pj_status_t pjsua_media_channel_update(pjsua_call_id call_id,
-				       const pjmedia_sdp_session *local_sdp,
+				       pjmedia_sdp_session *local_sdp,
 				       const pjmedia_sdp_session *remote_sdp);
 pj_status_t pjsua_media_channel_deinit(pjsua_call_id call_id);
Index: pjproject/branches/users/nanang/pjsip/src/pjsip-ua/sip_inv.c
===================================================================
--- pjproject/branches/users/nanang/pjsip/src/pjsip-ua/sip_inv.c	(revision 1697)
+++ pjproject/branches/users/nanang/pjsip/src/pjsip-ua/sip_inv.c	(revision 1698)
@@ -677,10 +677,11 @@
  * Verify incoming INVITE request.
  */
-PJ_DEF(pj_status_t) pjsip_inv_verify_request(pjsip_rx_data *rdata,
-					     unsigned *options,
-					     const pjmedia_sdp_session *l_sdp,
-					     pjsip_dialog *dlg,
-					     pjsip_endpoint *endpt,
-					     pjsip_tx_data **p_tdata)
+PJ_DEF(pj_status_t) pjsip_inv_verify_request2(pjsip_rx_data *rdata,
+					      unsigned *options,
+					      const pjmedia_sdp_session *r_sdp,
+					      const pjmedia_sdp_session *l_sdp,
+					      pjsip_dialog *dlg,
+					      pjsip_endpoint *endpt,
+					      pjsip_tx_data **p_tdata)
 {
     pjsip_msg *msg;
@@ -723,8 +724,8 @@
     pj_list_init(&res_hdr_list);
 
-    /* Check the request body, see if it'inv something that we support
-     * (i.e. SDP). 
+    /* Check the request body, see if it's something that we support,
+     * only when the body hasn't been parsed before.
      */
-    if (msg->body) {
+    if (r_sdp==NULL && msg->body) {
 	pjsip_msg_body *body = msg->body;
 	pj_str_t str_application = {"application", 11};
@@ -778,4 +779,8 @@
 	}
 
+	r_sdp = sdp;
+    }
+
+    if (r_sdp) {
 	/* Negotiate with local SDP */
 	if (l_sdp) {
@@ -788,5 +793,5 @@
 	    /* Create SDP negotiator */
 	    status = pjmedia_sdp_neg_create_w_remote_offer(
-			    rdata->tp_info.pool, l_sdp, sdp, &neg);
+			    rdata->tp_info.pool, l_sdp, r_sdp, &neg);
 	    PJ_ASSERT_RETURN(status == PJ_SUCCESS, status);
 
@@ -1026,4 +1031,19 @@
 
     return status;
+}
+
+
+/*
+ * Verify incoming INVITE request.
+ */
+PJ_DEF(pj_status_t) pjsip_inv_verify_request( pjsip_rx_data *rdata,
+					      unsigned *options,
+					      const pjmedia_sdp_session *l_sdp,
+					      pjsip_dialog *dlg,
+					      pjsip_endpoint *endpt,
+					      pjsip_tx_data **p_tdata)
+{
+    return pjsip_inv_verify_request2(rdata, options, NULL, l_sdp, dlg, 
+				     endpt, p_tdata);
 }
 
Index: pjproject/branches/users/nanang/pjsip/src/pjsua-lib/pjsua_call.c
===================================================================
--- pjproject/branches/users/nanang/pjsip/src/pjsua-lib/pjsua_call.c	(revision 1697)
+++ pjproject/branches/users/nanang/pjsip/src/pjsua-lib/pjsua_call.c	(revision 1698)
@@ -335,5 +335,5 @@
     offer = NULL;
 #else
-    status = pjsua_media_channel_create_sdp(call->index, dlg->pool, &offer);
+    status = pjsua_media_channel_create_sdp(call->index, dlg->pool, NULL, &offer);
     if (status != PJ_SUCCESS) {
 	pjsua_perror(THIS_FILE, "pjmedia unable to create SDP", status);
@@ -482,5 +482,5 @@
     pjsua_call *call;
     int call_id = -1;
-    pjmedia_sdp_session *answer;
+    pjmedia_sdp_session *offer, *answer;
     pj_status_t status;
 
@@ -590,7 +590,24 @@
     }
 
+    /* Parse SDP from incoming request */
+    if (rdata->msg_info.msg->body) {
+	status = pjmedia_sdp_parse(rdata->tp_info.pool, 
+				   rdata->msg_info.msg->body->data,
+				   rdata->msg_info.msg->body->len, &offer);
+	if (status != PJ_SUCCESS) {
+	    pjsua_perror(THIS_FILE, "Error parsing SDP in incoming INVITE", status);
+	    pjsip_endpt_respond_stateless(pjsua_var.endpt, rdata, 400, NULL,
+					  NULL, NULL);
+	    pjsua_media_channel_deinit(call->index);
+	    PJSUA_UNLOCK();
+	    return PJ_TRUE;
+	}
+    } else {
+	offer = NULL;
+    }
 
     /* Get media capability from media endpoint: */
-    status = pjsua_media_channel_create_sdp(call->index, rdata->tp_info.pool, &answer);
+    status = pjsua_media_channel_create_sdp(call->index, rdata->tp_info.pool, 
+					    offer, &answer);
     if (status != PJ_SUCCESS) {
 	pjsip_endpt_respond_stateless(pjsua_var.endpt, rdata, 500, NULL,
@@ -613,6 +630,6 @@
 	options |= PJSIP_INV_REQUIRE_100REL;
 
-    status = pjsip_inv_verify_request(rdata, &options, answer, NULL,
-				      pjsua_var.endpt, &response);
+    status = pjsip_inv_verify_request2(rdata, &options, offer, answer, NULL,
+				       pjsua_var.endpt, &response);
     if (status != PJ_SUCCESS) {
 
@@ -1314,5 +1331,6 @@
     PJ_UNUSED_ARG(unhold);
     PJ_TODO(create_active_inactive_sdp_based_on_unhold_arg);
-    status = pjsua_media_channel_create_sdp(call->index, call->inv->pool, &sdp);
+    status = pjsua_media_channel_create_sdp(call->index, call->inv->pool, 
+					    NULL, &sdp);
     if (status != PJ_SUCCESS) {
 	pjsua_perror(THIS_FILE, "Unable to get SDP from media endpoint", 
@@ -1380,5 +1398,6 @@
 
     /* Create SDP */
-    status = pjsua_media_channel_create_sdp(call->index, call->inv->pool, &sdp);
+    status = pjsua_media_channel_create_sdp(call->index, call->inv->pool, 
+					    NULL, &sdp);
     if (status != PJ_SUCCESS) {
 	pjsua_perror(THIS_FILE, "Unable to get SDP from media endpoint", 
@@ -2321,5 +2340,5 @@
 {
     pjsua_call *call;
-    const pjmedia_sdp_session *local_sdp;
+    pjmedia_sdp_session *local_sdp;
     const pjmedia_sdp_session *remote_sdp;
 
@@ -2502,5 +2521,6 @@
 	}
 
-	status = pjsua_media_channel_create_sdp(call->index, call->inv->pool, &answer);
+	status = pjsua_media_channel_create_sdp(call->index, call->inv->pool, 
+					        offer, &answer);
     }
 
@@ -2554,5 +2574,6 @@
 	}
 
-	status = pjsua_media_channel_create_sdp(call->index, call->inv->pool, offer);
+	status = pjsua_media_channel_create_sdp(call->index, call->inv->pool, 
+					        NULL, offer);
     }
 
Index: pjproject/branches/users/nanang/pjsip/src/pjsua-lib/pjsua_media.c
===================================================================
--- pjproject/branches/users/nanang/pjsip/src/pjsua-lib/pjsua_media.c	(revision 1697)
+++ pjproject/branches/users/nanang/pjsip/src/pjsua-lib/pjsua_media.c	(revision 1698)
@@ -535,7 +535,20 @@
 	    goto on_error;
 	}
-	status = pjmedia_transport_udp_attach(pjsua_var.med_endpt, NULL,
-					      &skinfo, 0,
-					      &pjsua_var.calls[i].med_tp);
+
+	if (pjsua_var.media_cfg.enable_srtp) {
+	    pjmedia_transport *tp;
+	    unsigned srtp_options = 
+				PJMEDIA_SRTP_AUTO_CLOSE_UNDERLYING_TRANSPORT;
+
+	    status = pjmedia_transport_udp_attach(pjsua_var.med_endpt, NULL,
+						  &skinfo, 0, &tp);
+	    status = pjmedia_transport_srtp_create(pjsua_var.med_endpt, tp,
+						   srtp_options, 
+						   &pjsua_var.calls[i].med_tp);
+	} else {
+	    status = pjmedia_transport_udp_attach(pjsua_var.med_endpt, NULL,
+						  &skinfo, 0,
+						  &pjsua_var.calls[i].med_tp);
+	}
 	if (status != PJ_SUCCESS) {
 	    pjsua_perror(THIS_FILE, "Unable to create media transport",
@@ -544,11 +557,11 @@
 	}
 
-	pjmedia_transport_udp_simulate_lost(pjsua_var.calls[i].med_tp,
-					    PJMEDIA_DIR_ENCODING,
-					    pjsua_var.media_cfg.tx_drop_pct);
-
-	pjmedia_transport_udp_simulate_lost(pjsua_var.calls[i].med_tp,
-					    PJMEDIA_DIR_DECODING,
-					    pjsua_var.media_cfg.rx_drop_pct);
+	pjmedia_transport_simulate_lost(pjsua_var.calls[i].med_tp,
+					PJMEDIA_DIR_ENCODING,
+					pjsua_var.media_cfg.tx_drop_pct);
+
+	pjmedia_transport_simulate_lost(pjsua_var.calls[i].med_tp,
+					PJMEDIA_DIR_DECODING,
+					pjsua_var.media_cfg.rx_drop_pct);
 
     }
@@ -646,11 +659,11 @@
 	}
 
-	pjmedia_ice_simulate_lost(pjsua_var.calls[i].med_tp,
-				  PJMEDIA_DIR_ENCODING,
-				  pjsua_var.media_cfg.tx_drop_pct);
-
-	pjmedia_ice_simulate_lost(pjsua_var.calls[i].med_tp,
-				  PJMEDIA_DIR_DECODING,
-				  pjsua_var.media_cfg.rx_drop_pct);
+	pjmedia_transport_simulate_lost(pjsua_var.calls[i].med_tp,
+				        PJMEDIA_DIR_ENCODING,
+				        pjsua_var.media_cfg.tx_drop_pct);
+
+	pjmedia_transport_simulate_lost(pjsua_var.calls[i].med_tp,
+				        PJMEDIA_DIR_DECODING,
+				        pjsua_var.media_cfg.rx_drop_pct);
 
 	status = pjmedia_ice_start_init(pjsua_var.calls[i].med_tp, 0, &addr,
@@ -757,5 +770,5 @@
 
 	/* Restart ICE */
-	pjmedia_ice_stop_ice(call->med_tp);
+	pjmedia_transport_media_stop(call->med_tp);
 
 	status = pjmedia_ice_init_ice(call->med_tp, ice_role, NULL, NULL);
@@ -769,4 +782,5 @@
 pj_status_t pjsua_media_channel_create_sdp(pjsua_call_id call_id, 
 					   pj_pool_t *pool,
+					   const pjmedia_sdp_session *rem_sdp,
 					   pjmedia_sdp_session **p_sdp)
 {
@@ -816,9 +830,11 @@
     }
 
-    if (pjsua_var.media_cfg.enable_ice) {
-	status = pjmedia_ice_modify_sdp(call->med_tp, pool, sdp);
+    //if (pjsua_var.media_cfg.enable_ice) {
+	//status = pjmedia_transport_media_create(call->med_tp, pool, sdp, NULL);
+	status = pjmedia_transport_media_create(call->med_tp, pool, 
+						sdp, rem_sdp);
 	if (status != PJ_SUCCESS)
 	    goto on_error;
-    }
+    //}
 
     *p_sdp = sdp;
@@ -859,7 +875,7 @@
     stop_media_session(call_id);
 
-    if (pjsua_var.media_cfg.enable_ice) {
-	pjmedia_ice_stop_ice(call->med_tp);
-    }
+    //if (pjsua_var.media_cfg.enable_ice) {
+	pjmedia_transport_media_stop(call->med_tp);
+    //}
 
     return PJ_SUCCESS;
@@ -885,5 +901,5 @@
 
 pj_status_t pjsua_media_channel_update(pjsua_call_id call_id,
-				       const pjmedia_sdp_session *local_sdp,
+				       pjmedia_sdp_session *local_sdp,
 				       const pjmedia_sdp_session *remote_sdp)
 {
@@ -947,7 +963,7 @@
 
 	/* Shutdown ICE session */
-	if (pjsua_var.media_cfg.enable_ice) {
-	    pjmedia_ice_stop_ice(call->med_tp);
-	}
+	//if (pjsua_var.media_cfg.enable_ice) {
+	    pjmedia_transport_media_stop(call->med_tp);
+	//}
 
 	/* No need because we need keepalive? */
@@ -955,10 +971,11 @@
     } else {
 	/* Start ICE */
-	if (pjsua_var.media_cfg.enable_ice) {
-	    status = pjmedia_ice_start_ice(call->med_tp, call->inv->pool, 
-					   remote_sdp, 0);
+	//if (pjsua_var.media_cfg.enable_ice) {
+	    status = pjmedia_transport_media_start(call->med_tp, 
+						   call->inv->pool,
+						   local_sdp, remote_sdp, 0);
 	    if (status != PJ_SUCCESS)
 		return status;
-	}
+	//}
 
 	/* Override ptime, if this option is specified. */
Index: pjproject/branches/users/nanang/third_party/build/srtp/config.h
===================================================================
--- pjproject/branches/users/nanang/third_party/build/srtp/config.h	(revision 1698)
+++ pjproject/branches/users/nanang/third_party/build/srtp/config.h	(revision 1698)
@@ -0,0 +1,3 @@
+#ifdef _WIN32
+#include "../../srtp/config.hw"
+#endif
Index: pjproject/branches/users/nanang/third_party/build/srtp/libsrtp.vcproj
===================================================================
--- pjproject/branches/users/nanang/third_party/build/srtp/libsrtp.vcproj	(revision 1698)
+++ pjproject/branches/users/nanang/third_party/build/srtp/libsrtp.vcproj	(revision 1698)
@@ -0,0 +1,431 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+	ProjectType="Visual C++"
+	Version="8.00"
+	Name="libsrtp"
+	ProjectGUID="{F0DBAA03-1BA3-4E3B-A2CA-727E3D3AB858}"
+	RootNamespace="libsrtp"
+	Keyword="Win32Proj"
+	>
+	<Platforms>
+		<Platform
+			Name="Win32"
+		/>
+	</Platforms>
+	<ToolFiles>
+	</ToolFiles>
+	<Configurations>
+		<Configuration
+			Name="Debug|Win32"
+			OutputDirectory=".\output\libsrtp-i386-win32-vc8-debug"
+			IntermediateDirectory=".\output\libsrtp-i386-win32-vc8-debug"
+			ConfigurationType="4"
+			CharacterSet="2"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				AdditionalIncludeDirectories=".,../../srtp/include,../../srtp/crypto/include"
+				PreprocessorDefinitions="WIN32;_DEBUG;_LIB"
+				MinimalRebuild="true"
+				BasicRuntimeChecks="3"
+				RuntimeLibrary="1"
+				UsePrecompiledHeader="0"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="true"
+				DebugInformationFormat="4"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLibrarianTool"
+				OutputFile="..\..\lib\libsrtp-i386-win32-vc8-debug.lib"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCFxCopTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+			/>
+		</Configuration>
+		<Configuration
+			Name="Release|Win32"
+			OutputDirectory=".\output\libsrtp-i386-win32-vc8-release"
+			IntermediateDirectory=".\output\libsrtp-i386-win32-vc8-release"
+			ConfigurationType="4"
+			CharacterSet="2"
+			WholeProgramOptimization="1"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				AdditionalIncludeDirectories=".,../../srtp/include,../../srtp/crypto/include"
+				PreprocessorDefinitions="WIN32;NDEBUG;_LIB"
+				RuntimeLibrary="2"
+				UsePrecompiledHeader="0"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="true"
+				DebugInformationFormat="3"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLibrarianTool"
+				OutputFile="..\..\lib\libsrtp-i386-win32-vc8-release.lib"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCFxCopTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+			/>
+		</Configuration>
+	</Configurations>
+	<References>
+	</References>
+	<Files>
+		<Filter
+			Name="Source Files"
+			Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx"
+			UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
+			>
+			<File
+				RelativePath="..\..\srtp\srtp\srtp.c"
+				>
+			</File>
+		</Filter>
+		<Filter
+			Name="Header Files"
+			Filter="h;hpp;hxx;hm;inl;inc;xsd"
+			UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
+			>
+			<File
+				RelativePath="..\..\srtp\include\config.h"
+				>
+			</File>
+			<File
+				RelativePath=".\config_win32.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\srtp\include\rtp.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\srtp\include\srtp.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\srtp\include\ut_sim.h"
+				>
+			</File>
+		</Filter>
+		<Filter
+			Name="crypto"
+			>
+			<Filter
+				Name="ae_xfm"
+				>
+				<File
+					RelativePath="..\..\srtp\crypto\ae_xfm\xfm.c"
+					>
+				</File>
+			</Filter>
+			<Filter
+				Name="cipher"
+				>
+				<File
+					RelativePath="..\..\srtp\crypto\cipher\aes.c"
+					>
+				</File>
+				<File
+					RelativePath="..\..\srtp\crypto\cipher\aes_cbc.c"
+					>
+				</File>
+				<File
+					RelativePath="..\..\srtp\crypto\cipher\aes_icm.c"
+					>
+				</File>
+				<File
+					RelativePath="..\..\srtp\crypto\cipher\cipher.c"
+					>
+				</File>
+				<File
+					RelativePath="..\..\srtp\crypto\cipher\null_cipher.c"
+					>
+				</File>
+			</Filter>
+			<Filter
+				Name="hash"
+				>
+				<File
+					RelativePath="..\..\srtp\crypto\hash\auth.c"
+					>
+				</File>
+				<File
+					RelativePath="..\..\srtp\crypto\hash\hmac.c"
+					>
+				</File>
+				<File
+					RelativePath="..\..\srtp\crypto\hash\null_auth.c"
+					>
+				</File>
+				<File
+					RelativePath="..\..\srtp\crypto\hash\sha1.c"
+					>
+				</File>
+			</Filter>
+			<Filter
+				Name="kernel"
+				>
+				<File
+					RelativePath="..\..\srtp\crypto\kernel\alloc.c"
+					>
+				</File>
+				<File
+					RelativePath="..\..\srtp\crypto\kernel\crypto_kernel.c"
+					>
+				</File>
+				<File
+					RelativePath="..\..\srtp\crypto\kernel\err.c"
+					>
+				</File>
+				<File
+					RelativePath="..\..\srtp\crypto\kernel\key.c"
+					>
+				</File>
+			</Filter>
+			<Filter
+				Name="math"
+				>
+				<File
+					RelativePath="..\..\srtp\crypto\math\datatypes.c"
+					>
+				</File>
+				<File
+					RelativePath="..\..\srtp\crypto\math\gf2_8.c"
+					>
+				</File>
+				<File
+					RelativePath="..\..\srtp\crypto\math\stat.c"
+					>
+				</File>
+			</Filter>
+			<Filter
+				Name="replay"
+				>
+				<File
+					RelativePath="..\..\srtp\crypto\replay\rdb.c"
+					>
+				</File>
+				<File
+					RelativePath="..\..\srtp\crypto\replay\rdbx.c"
+					>
+				</File>
+				<File
+					RelativePath="..\..\srtp\crypto\replay\ut_sim.c"
+					>
+				</File>
+			</Filter>
+			<Filter
+				Name="include"
+				>
+				<File
+					RelativePath="..\..\srtp\crypto\include\aes.h"
+					>
+				</File>
+				<File
+					RelativePath="..\..\srtp\crypto\include\aes_cbc.h"
+					>
+				</File>
+				<File
+					RelativePath="..\..\srtp\crypto\include\aes_icm.h"
+					>
+				</File>
+				<File
+					RelativePath="..\..\srtp\crypto\include\alloc.h"
+					>
+				</File>
+				<File
+					RelativePath="..\..\srtp\crypto\include\auth.h"
+					>
+				</File>
+				<File
+					RelativePath="..\..\srtp\crypto\include\cipher.h"
+					>
+				</File>
+				<File
+					RelativePath="..\..\srtp\crypto\include\crypto.h"
+					>
+				</File>
+				<File
+					RelativePath="..\..\srtp\crypto\include\crypto_kernel.h"
+					>
+				</File>
+				<File
+					RelativePath="..\..\srtp\crypto\include\crypto_math.h"
+					>
+				</File>
+				<File
+					RelativePath="..\..\srtp\crypto\include\crypto_types.h"
+					>
+				</File>
+				<File
+					RelativePath="..\..\srtp\crypto\include\cryptoalg.h"
+					>
+				</File>
+				<File
+					RelativePath="..\..\srtp\crypto\include\datatypes.h"
+					>
+				</File>
+				<File
+					RelativePath="..\..\srtp\crypto\include\err.h"
+					>
+				</File>
+				<File
+					RelativePath="..\..\srtp\crypto\include\gf2_8.h"
+					>
+				</File>
+				<File
+					RelativePath="..\..\srtp\crypto\include\hmac.h"
+					>
+				</File>
+				<File
+					RelativePath="..\..\srtp\crypto\include\integers.h"
+					>
+				</File>
+				<File
+					RelativePath="..\..\srtp\crypto\include\kernel_compat.h"
+					>
+				</File>
+				<File
+					RelativePath="..\..\srtp\crypto\include\key.h"
+					>
+				</File>
+				<File
+					RelativePath="..\..\srtp\crypto\include\null_auth.h"
+					>
+				</File>
+				<File
+					RelativePath="..\..\srtp\crypto\include\null_cipher.h"
+					>
+				</File>
+				<File
+					RelativePath="..\..\srtp\crypto\include\prng.h"
+					>
+				</File>
+				<File
+					RelativePath="..\..\srtp\crypto\include\rand_source.h"
+					>
+				</File>
+				<File
+					RelativePath="..\..\srtp\crypto\include\rdb.h"
+					>
+				</File>
+				<File
+					RelativePath="..\..\srtp\crypto\include\rdbx.h"
+					>
+				</File>
+				<File
+					RelativePath="..\..\srtp\crypto\include\sha1.h"
+					>
+				</File>
+				<File
+					RelativePath="..\..\srtp\crypto\include\stat.h"
+					>
+				</File>
+				<File
+					RelativePath="..\..\srtp\crypto\include\xfm.h"
+					>
+				</File>
+			</Filter>
+			<Filter
+				Name="rng"
+				>
+				<File
+					RelativePath="..\..\srtp\crypto\rng\ctr_prng.c"
+					>
+				</File>
+				<File
+					RelativePath="..\..\srtp\crypto\rng\prng.c"
+					>
+				</File>
+				<File
+					RelativePath="..\..\srtp\crypto\rng\rand_source.c"
+					>
+				</File>
+			</Filter>
+		</Filter>
+		<Filter
+			Name="tables"
+			>
+			<File
+				RelativePath="..\..\srtp\tables\aes_tables.c"
+				>
+			</File>
+		</Filter>
+	</Files>
+	<Globals>
+	</Globals>
+</VisualStudioProject>
