* #36737: switch back to svn repo, remove assert in sip_transaction.c
diff --git a/jni/pjproject-android/.svn/pristine/ca/ca07fd5202b28664016550b1f86a3811421e8c3b.svn-base b/jni/pjproject-android/.svn/pristine/ca/ca07fd5202b28664016550b1f86a3811421e8c3b.svn-base
new file mode 100644
index 0000000..00d8fe7
--- /dev/null
+++ b/jni/pjproject-android/.svn/pristine/ca/ca07fd5202b28664016550b1f86a3811421e8c3b.svn-base
@@ -0,0 +1,350 @@
+/* $Id$ */
+/* 
+ * Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com)
+ * Copyright (C) 2003-2008 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 __PJSIP_TRANSPORT_TLS_H__
+#define __PJSIP_TRANSPORT_TLS_H__
+
+/**
+ * @file sip_transport_tls.h
+ * @brief SIP TLS Transport.
+ */
+
+#include <pjsip/sip_transport.h>
+#include <pj/pool.h>
+#include <pj/ssl_sock.h>
+#include <pj/string.h>
+#include <pj/sock_qos.h>
+
+
+PJ_BEGIN_DECL
+
+/**
+ * @defgroup PJSIP_TRANSPORT_TLS TLS Transport
+ * @ingroup PJSIP_TRANSPORT
+ * @brief API to create and register TLS transport.
+ * @{
+ * The functions below are used to create TLS transport and register 
+ * the transport to the framework.
+ */
+
+/**
+ * The default SSL method to be used by PJSIP.
+ * Default is PJSIP_TLSV1_METHOD
+ */
+#ifndef PJSIP_SSL_DEFAULT_METHOD
+#   define PJSIP_SSL_DEFAULT_METHOD	PJSIP_TLSV1_METHOD
+#endif
+
+/** SSL protocol method constants. */
+typedef enum pjsip_ssl_method
+{
+    PJSIP_SSL_UNSPECIFIED_METHOD= 0,	/**< Default protocol method.	*/
+    PJSIP_TLSV1_METHOD		= 31,	/**< Use SSLv1 method.		*/
+    PJSIP_SSLV2_METHOD		= 20,	/**< Use SSLv2 method.		*/
+    PJSIP_SSLV3_METHOD		= 30,	/**< Use SSLv3 method.		*/
+    PJSIP_SSLV23_METHOD		= 23	/**< Use SSLv23 method.		*/
+} pjsip_ssl_method;
+
+
+
+
+/**
+ * TLS transport settings.
+ */
+typedef struct pjsip_tls_setting
+{
+    /**
+     * Certificate of Authority (CA) list file.
+     */
+    pj_str_t	ca_list_file;
+
+    /**
+     * Public endpoint certificate file, which will be used as client-
+     * side  certificate for outgoing TLS connection, and server-side
+     * certificate for incoming TLS connection.
+     */
+    pj_str_t	cert_file;
+
+    /**
+     * Optional private key of the endpoint certificate to be used.
+     */
+    pj_str_t	privkey_file;
+
+    /**
+     * Password to open private key.
+     */
+    pj_str_t	password;
+
+    /**
+     * TLS protocol method from #pjsip_ssl_method, which can be:
+     *	- PJSIP_SSL_UNSPECIFIED_METHOD(0): default (which will use 
+     *                                     PJSIP_SSL_DEFAULT_METHOD)
+     *	- PJSIP_TLSV1_METHOD(1):	   TLSv1
+     *	- PJSIP_SSLV2_METHOD(2):	   SSLv2
+     *	- PJSIP_SSLV3_METHOD(3):	   SSL3
+     *	- PJSIP_SSLV23_METHOD(23):	   SSL23
+     *
+     * Default is PJSIP_SSL_UNSPECIFIED_METHOD (0), which in turn will
+     * use PJSIP_SSL_DEFAULT_METHOD, which default value is 
+     * PJSIP_TLSV1_METHOD.
+     */
+    int		method;
+
+    /**
+     * Number of ciphers contained in the specified cipher preference. 
+     * If this is set to zero, then default cipher list of the backend 
+     * will be used.
+     *
+     * Default: 0 (zero).
+     */
+    unsigned ciphers_num;
+
+    /**
+     * Ciphers and order preference. The #pj_ssl_cipher_get_availables()
+     * can be used to check the available ciphers supported by backend.
+     */
+    pj_ssl_cipher *ciphers;
+
+    /**
+     * Specifies TLS transport behavior on the server TLS certificate 
+     * verification result:
+     * - If \a verify_server is disabled (set to PJ_FALSE), TLS transport 
+     *   will just notify the application via #pjsip_tp_state_callback with
+     *   state PJSIP_TP_STATE_CONNECTED regardless TLS verification result.
+     * - If \a verify_server is enabled (set to PJ_TRUE), TLS transport 
+     *   will be shutdown and application will be notified with state
+     *   PJSIP_TP_STATE_DISCONNECTED whenever there is any TLS verification
+     *   error, otherwise PJSIP_TP_STATE_CONNECTED will be notified.
+     *
+     * In any cases, application can inspect #pjsip_tls_state_info in the
+     * callback to see the verification detail.
+     *
+     * Default value is PJ_FALSE.
+     */
+    pj_bool_t	verify_server;
+
+    /**
+     * Specifies TLS transport behavior on the client TLS certificate 
+     * verification result:
+     * - If \a verify_client is disabled (set to PJ_FALSE), TLS transport 
+     *   will just notify the application via #pjsip_tp_state_callback with
+     *   state PJSIP_TP_STATE_CONNECTED regardless TLS verification result.
+     * - If \a verify_client is enabled (set to PJ_TRUE), TLS transport 
+     *   will be shutdown and application will be notified with state
+     *   PJSIP_TP_STATE_DISCONNECTED whenever there is any TLS verification
+     *   error, otherwise PJSIP_TP_STATE_CONNECTED will be notified.
+     *
+     * In any cases, application can inspect #pjsip_tls_state_info in the
+     * callback to see the verification detail.
+     *
+     * Default value is PJ_FALSE.
+     */
+    pj_bool_t	verify_client;
+
+    /**
+     * When acting as server (incoming TLS connections), reject inocming
+     * connection if client doesn't supply a TLS certificate.
+     *
+     * This setting corresponds to SSL_VERIFY_FAIL_IF_NO_PEER_CERT flag.
+     * Default value is PJ_FALSE.
+     */
+    pj_bool_t	require_client_cert;
+
+    /**
+     * TLS negotiation timeout to be applied for both outgoing and
+     * incoming connection. If both sec and msec member is set to zero,
+     * the SSL negotiation doesn't have a timeout.
+     */
+    pj_time_val	timeout;
+
+    /**
+     * Should SO_REUSEADDR be used for the listener socket.
+     * Default value is PJSIP_TLS_TRANSPORT_REUSEADDR.
+     */
+    pj_bool_t reuse_addr;
+
+    /**
+     * QoS traffic type to be set on this transport. When application wants
+     * to apply QoS tagging to the transport, it's preferable to set this
+     * field rather than \a qos_param fields since this is more portable.
+     *
+     * Default value is PJ_QOS_TYPE_BEST_EFFORT.
+     */
+    pj_qos_type qos_type;
+
+    /**
+     * Set the low level QoS parameters to the transport. This is a lower
+     * level operation than setting the \a qos_type field and may not be
+     * supported on all platforms.
+     *
+     * By default all settings in this structure are disabled.
+     */
+    pj_qos_params qos_params;
+
+    /**
+     * Specify if the transport should ignore any errors when setting the QoS
+     * traffic type/parameters.
+     *
+     * Default: PJ_TRUE
+     */
+    pj_bool_t qos_ignore_error;
+
+} pjsip_tls_setting;
+
+
+/**
+ * This structure defines TLS transport extended info in <tt>ext_info</tt>
+ * field of #pjsip_transport_state_info for the transport state notification
+ * callback #pjsip_tp_state_callback.
+ */
+typedef struct pjsip_tls_state_info
+{
+    /**
+     * SSL socket info.
+     */
+    pj_ssl_sock_info	*ssl_sock_info;
+
+} pjsip_tls_state_info;
+
+
+/**
+ * Initialize TLS setting with default values.
+ *
+ * @param tls_opt   The TLS setting to be initialized.
+ */
+PJ_INLINE(void) pjsip_tls_setting_default(pjsip_tls_setting *tls_opt)
+{
+    pj_memset(tls_opt, 0, sizeof(*tls_opt));
+    tls_opt->reuse_addr = PJSIP_TLS_TRANSPORT_REUSEADDR;
+    tls_opt->qos_type = PJ_QOS_TYPE_BEST_EFFORT;
+    tls_opt->qos_ignore_error = PJ_TRUE;
+}
+
+
+/**
+ * Copy TLS setting.
+ *
+ * @param pool	    The pool to duplicate strings etc.
+ * @param dst	    Destination structure.
+ * @param src	    Source structure.
+ */
+PJ_INLINE(void) pjsip_tls_setting_copy(pj_pool_t *pool,
+				       pjsip_tls_setting *dst,
+				       const pjsip_tls_setting *src)
+{
+    pj_memcpy(dst, src, sizeof(*dst));
+    pj_strdup_with_null(pool, &dst->ca_list_file, &src->ca_list_file);
+    pj_strdup_with_null(pool, &dst->cert_file, &src->cert_file);
+    pj_strdup_with_null(pool, &dst->privkey_file, &src->privkey_file);
+    pj_strdup_with_null(pool, &dst->password, &src->password);
+    if (src->ciphers_num) {
+	unsigned i;
+	dst->ciphers = (pj_ssl_cipher*) pj_pool_calloc(pool, src->ciphers_num,
+						       sizeof(pj_ssl_cipher));
+	for (i=0; i<src->ciphers_num; ++i)
+	    dst->ciphers[i] = src->ciphers[i];
+    }
+}
+
+
+/**
+ * Register support for SIP TLS transport by creating TLS listener on
+ * the specified address and port. This function will create an
+ * instance of SIP TLS transport factory and register it to the
+ * transport manager.
+ *
+ * See also #pjsip_tls_transport_start2() which supports IPv6.
+ *
+ * @param endpt		The SIP endpoint.
+ * @param opt		Optional TLS settings.
+ * @param local		Optional local address to bind, or specify the
+ *			address to bind the server socket to. Both IP 
+ *			interface address and port fields are optional.
+ *			If IP interface address is not specified, socket
+ *			will be bound to PJ_INADDR_ANY. If port is not
+ *			specified, socket will be bound to any port
+ *			selected by the operating system.
+ * @param a_name	Optional published address, which is the address to be
+ *			advertised as the address of this SIP transport. 
+ *			If this argument is NULL, then the bound address
+ *			will be used as the published address.
+ * @param async_cnt	Number of simultaneous asynchronous accept()
+ *			operations to be supported. It is recommended that
+ *			the number here corresponds to the number of
+ *			processors in the system (or the number of SIP
+ *			worker threads).
+ * @param p_factory	Optional pointer to receive the instance of the
+ *			SIP TLS transport factory just created.
+ *
+ * @return		PJ_SUCCESS when the transport has been successfully
+ *			started and registered to transport manager, or
+ *			the appropriate error code.
+ */
+PJ_DECL(pj_status_t) pjsip_tls_transport_start(pjsip_endpoint *endpt,
+					       const pjsip_tls_setting *opt,
+					       const pj_sockaddr_in *local,
+					       const pjsip_host_port *a_name,
+					       unsigned async_cnt,
+					       pjsip_tpfactory **p_factory);
+
+/**
+ * Variant of #pjsip_tls_transport_start() that supports IPv6. To instantiate
+ * IPv6 listener, set the address family of the "local" argument to IPv6
+ * (the host and port part may be left unspecified if not desired, i.e. by
+ * filling them with zeroes).
+ *
+ * @param endpt		The SIP endpoint.
+ * @param opt		Optional TLS settings.
+ * @param local		Optional local address to bind, or specify the
+ *			address to bind the server socket to. Both IP
+ *			interface address and port fields are optional.
+ *			If IP interface address is not specified, socket
+ *			will be bound to any address. If port is not
+ *			specified, socket will be bound to any port
+ *			selected by the operating system.
+ * @param a_name	Optional published address, which is the address to be
+ *			advertised as the address of this SIP transport.
+ *			If this argument is NULL, then the bound address
+ *			will be used as the published address.
+ * @param async_cnt	Number of simultaneous asynchronous accept()
+ *			operations to be supported. It is recommended that
+ *			the number here corresponds to the number of
+ *			processors in the system (or the number of SIP
+ *			worker threads).
+ * @param p_factory	Optional pointer to receive the instance of the
+ *			SIP TLS transport factory just created.
+ *
+ * @return		PJ_SUCCESS when the transport has been successfully
+ *			started and registered to transport manager, or
+ *			the appropriate error code.
+ */
+PJ_DECL(pj_status_t) pjsip_tls_transport_start2(pjsip_endpoint *endpt,
+ 					        const pjsip_tls_setting *opt,
+					        const pj_sockaddr *local,
+					        const pjsip_host_port *a_name,
+					        unsigned async_cnt,
+					        pjsip_tpfactory **p_factory);
+
+PJ_END_DECL
+
+/**
+ * @}
+ */
+
+#endif	/* __PJSIP_TRANSPORT_TLS_H__ */
diff --git a/jni/pjproject-android/.svn/pristine/ca/ca190bf85e4606f5441953f95f736b8e574f75fc.svn-base b/jni/pjproject-android/.svn/pristine/ca/ca190bf85e4606f5441953f95f736b8e574f75fc.svn-base
new file mode 100644
index 0000000..1b7f072
--- /dev/null
+++ b/jni/pjproject-android/.svn/pristine/ca/ca190bf85e4606f5441953f95f736b8e574f75fc.svn-base
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="ISO-8859-1" ?>
+<!DOCTYPE scenario SYSTEM "sipp.dtd">
+
+<scenario name="MESSAGE request without message body">
+  <send retrans="500">
+    <![CDATA[
+
+      MESSAGE sip:[service]@[remote_ip]:[remote_port] SIP/2.0
+      Via: SIP/2.0/[transport] [local_ip]:[local_port];branch=[branch]
+      From: sipp <sip:sipp@[local_ip]:[local_port]>;tag=[call_number]
+      To: sut <sip:[service]@[remote_ip]:[remote_port]>
+      Call-ID: [call_id]
+      CSeq: 1 MESSAGE
+      Contact: sip:sipp@[local_ip]:[local_port]
+      Max-Forwards: 70
+      Subject: Message without body
+      Content-Length: 0
+
+    ]]>
+  </send>
+
+  <recv response="200" rtd="true">
+  </recv>
+
+  <!-- definition of the response time repartition table (unit is ms)   -->
+  <ResponseTimeRepartition value="10, 20, 30, 40, 50, 100, 150, 200"/>
+
+  <!-- definition of the call length repartition table (unit is ms)     -->
+  <CallLengthRepartition value="10, 50, 100, 500, 1000, 5000, 10000"/>
+
+</scenario>
+
diff --git a/jni/pjproject-android/.svn/pristine/ca/ca2e6ad9c79bb056bf05afbc3e16f6d26c648359.svn-base b/jni/pjproject-android/.svn/pristine/ca/ca2e6ad9c79bb056bf05afbc3e16f6d26c648359.svn-base
new file mode 100644
index 0000000..44238c5
--- /dev/null
+++ b/jni/pjproject-android/.svn/pristine/ca/ca2e6ad9c79bb056bf05afbc3e16f6d26c648359.svn-base
@@ -0,0 +1,436 @@
+/* $Id$ */
+/* 
+ * Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com)
+ * Copyright (C) 2003-2008 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_SESSION_H__
+#define __PJMEDIA_SESSION_H__
+
+
+/**
+ * @file session.h
+ * @brief Media Session.
+ */
+
+#include <pjmedia/endpoint.h>
+#include <pjmedia/stream.h>
+#include <pjmedia/sdp.h>
+
+PJ_BEGIN_DECL 
+
+/**
+ * @defgroup PJMEDIA_SESSION Media Sessions
+ * @brief Management of media sessions
+ * @{
+ *
+ * A media session represents multimedia communication between two
+ * parties. A media session represents the multimedia session that
+ * is described by SDP session descriptor. A media session consists 
+ * of one or more media streams (pjmedia_stream), where each stream 
+ * represents one media line (m= line) in SDP.
+ *
+ * This module provides functions to create and manage multimedia
+ * sessions.
+ *
+ * Application creates the media session by calling #pjmedia_session_create(),
+ * normally after it has completed negotiating both SDP offer and answer.
+ * The session creation function creates the media session (including
+ * media streams) based on the content of local and remote SDP.
+ */
+
+
+/**
+ * Session info, retrieved from a session by calling
+ * #pjmedia_session_get_info().
+ */
+struct pjmedia_session_info
+{
+    /** Number of streams. */
+    unsigned		stream_cnt;
+
+    /** Individual stream info. */
+    pjmedia_stream_info	stream_info[PJMEDIA_MAX_SDP_MEDIA];
+};
+
+
+/** 
+ * Opaque declaration of media session. 
+ */
+typedef struct pjmedia_session pjmedia_session;
+
+
+/**
+ * @see pjmedia_session_info.
+ */
+typedef struct pjmedia_session_info pjmedia_session_info;
+
+
+/**
+ * This function will initialize the session info based on information
+ * in both SDP session descriptors. The remaining information will be
+ * taken from default codec parameters. If socket info array is specified,
+ * the socket will be copied to the session info as well.
+ *
+ * @param pool		Pool to allocate memory.
+ * @param endpt		Pjmedia endpoint.
+ * @param max_streams	Maximum number of stream infos to be created.
+ * @param si		Session info structure to be initialized.
+ * @param local		Local SDP session descriptor.
+ * @param remote	Remote SDP session descriptor.
+ *
+ * @return		PJ_SUCCESS if stream info is successfully initialized.
+ */
+PJ_DECL(pj_status_t)
+pjmedia_session_info_from_sdp( pj_pool_t *pool,
+			       pjmedia_endpt *endpt,
+			       unsigned max_streams,
+			       pjmedia_session_info *si,
+			       const pjmedia_sdp_session *local,
+			       const pjmedia_sdp_session *remote);
+
+
+/**
+ * This function will initialize the stream info based on information
+ * in both SDP session descriptors for the specified stream index. 
+ * The remaining information will be taken from default codec parameters. 
+ * If socket info array is specified, the socket will be copied to the 
+ * session info as well.
+ *
+ * @param si		Stream info structure to be initialized.
+ * @param pool		Pool to allocate memory.
+ * @param endpt		PJMEDIA endpoint instance.
+ * @param local		Local SDP session descriptor.
+ * @param remote	Remote SDP session descriptor.
+ * @param stream_idx	Media stream index in the session descriptor.
+ *
+ * @return		PJ_SUCCESS if stream info is successfully initialized.
+ */
+PJ_DECL(pj_status_t)
+pjmedia_stream_info_from_sdp( pjmedia_stream_info *si,
+			      pj_pool_t *pool,
+			      pjmedia_endpt *endpt,
+			      const pjmedia_sdp_session *local,
+			      const pjmedia_sdp_session *remote,
+			      unsigned stream_idx);
+
+/**
+ * Create media session based on the local and remote SDP. After the session
+ * has been created, application normally would want to get the media port 
+ * interface of each streams, by calling #pjmedia_session_get_port(). The 
+ * media port interface exports put_frame() and get_frame() function, used
+ * to transmit and receive media frames from the stream.
+ *
+ * Without application calling put_frame() and get_frame(), there will be 
+ * no media frames transmitted or received by the session.
+ * 
+ * @param endpt		The PJMEDIA endpoint instance.
+ * @param si		Session info containing stream count and array of
+ *			stream info. The stream count indicates how many
+ *			streams to be created in the session.
+ * @param transports	Array of media stream transports, with 
+ *			sufficient number of elements (one for each stream).
+ * @param user_data	Arbitrary user data to be kept in the session.
+ * @param p_session	Pointer to receive the media session.
+ *
+ * @return		PJ_SUCCESS if media session can be created 
+ *			successfully.
+ */
+PJ_DECL(pj_status_t) 
+pjmedia_session_create( pjmedia_endpt *endpt, 
+			const pjmedia_session_info *si,
+			pjmedia_transport *transports[],
+			void *user_data,
+			pjmedia_session **p_session );
+
+
+/**
+ * Get media session info of the session.
+ *
+ * @param session	The session which info is being queried.
+ * @param info		Pointer to receive session info.
+ *
+ * @return		PJ_SUCCESS on success.
+ */
+PJ_DECL(pj_status_t) pjmedia_session_get_info( pjmedia_session *session,
+					       pjmedia_session_info *info );
+
+/**
+ * Get user data of the session.
+ *
+ * @param session	The session being queried.
+ *
+ * @return		User data of the session.
+ */
+PJ_DECL(void*) pjmedia_session_get_user_data( pjmedia_session *session);
+
+
+/**
+ * Activate all streams in media session for the specified direction.
+ * Application only needs to call this function if it previously paused
+ * the session.
+ *
+ * @param session	The media session.
+ * @param dir		The direction to activate.
+ *
+ * @return		PJ_SUCCESS if success.
+ */
+PJ_DECL(pj_status_t) pjmedia_session_resume(pjmedia_session *session,
+					    pjmedia_dir dir);
+
+
+/**
+ * Suspend receipt and transmission of all streams in media session
+ * for the specified direction.
+ *
+ * @param session	The media session.
+ * @param dir		The media direction to suspend.
+ *
+ * @return		PJ_SUCCESS if success.
+ */
+PJ_DECL(pj_status_t) pjmedia_session_pause(pjmedia_session *session,
+					   pjmedia_dir dir);
+
+/**
+ * Suspend receipt and transmission of individual stream in media session
+ * for the specified direction.
+ *
+ * @param session	The media session.
+ * @param index		The stream index.
+ * @param dir		The media direction to pause.
+ *
+ * @return		PJ_SUCCESS on success.
+ */
+PJ_DECL(pj_status_t) pjmedia_session_pause_stream( pjmedia_session *session,
+						   unsigned index,
+						   pjmedia_dir dir);
+
+/**
+ * Activate individual stream in media session for the specified direction.
+ *
+ * @param session	The media session.
+ * @param index		The stream index.
+ * @param dir		The media direction to activate.
+ *
+ * @return		PJ_SUCCESS on success.
+ */
+PJ_DECL(pj_status_t) pjmedia_session_resume_stream(pjmedia_session *session,
+						   unsigned index,
+						   pjmedia_dir dir);
+
+/**
+ * Send RTCP SDES for the session.
+ *
+ * @param session	The media session.
+ *
+ * @return		PJ_SUCCESS on success.
+ */
+PJ_DECL(pj_status_t) 
+pjmedia_session_send_rtcp_sdes( const pjmedia_session *session );
+
+/**
+ * Send RTCP BYE for the session.
+ *
+ * @param session	The media session.
+ *
+ * @return		PJ_SUCCESS on success.
+ */
+PJ_DECL(pj_status_t) 
+pjmedia_session_send_rtcp_bye( const pjmedia_session *session );
+
+/**
+ * Enumerate media streams in the session.
+ *
+ * @param session	The media session.
+ * @param count		On input, specifies the number of elements in
+ *			the array. On output, the number will be filled
+ *			with number of streams in the session.
+ * @param strm_info	Array of stream info.
+ *
+ * @return		PJ_SUCCESS on success.
+ */
+PJ_DECL(pj_status_t) 
+pjmedia_session_enum_streams( const pjmedia_session *session,
+			      unsigned *count, 
+			      pjmedia_stream_info strm_info[]);
+
+
+/**
+ * Get the media port interface of the specified stream. The media port
+ * interface declares put_frame() and get_frame() function, which is the 
+ * only  way for application to transmit and receive media frames from the
+ * stream.
+ *
+ * @param session	The media session.
+ * @param index		Stream index.
+ * @param p_port	Pointer to receive the media port interface for
+ *			the specified stream.
+ *
+ * @return		PJ_SUCCESS on success.
+ */
+PJ_DECL(pj_status_t) pjmedia_session_get_port( pjmedia_session *session,
+					       unsigned index,
+					       pjmedia_port **p_port);
+
+
+/**
+ * Get session statistics. The stream statistic shows various
+ * indicators such as packet count, packet lost, jitter, delay, etc.
+ * See also #pjmedia_session_get_stream_stat_jbuf()
+ *
+ * @param session	The media session.
+ * @param index		Stream index.
+ * @param stat		Stream statistic.
+ *
+ * @return		PJ_SUCCESS on success.
+ */
+PJ_DECL(pj_status_t) pjmedia_session_get_stream_stat(pjmedia_session *session,
+						     unsigned index,
+						     pjmedia_rtcp_stat *stat);
+
+
+/**
+ * Reset session statistics.
+ *
+ * @param session	The media session.
+ * @param index		Stream index.
+ *
+ * @return		PJ_SUCCESS on success.
+ */
+PJ_DECL(pj_status_t) pjmedia_session_reset_stream_stat(pjmedia_session *session,
+						       unsigned index);
+
+
+#if defined(PJMEDIA_HAS_RTCP_XR) && (PJMEDIA_HAS_RTCP_XR != 0)
+/**
+ * Get extended session statistics. The extended statistic shows reports
+ * from RTCP XR, such as per interval statistics summary (packet count, 
+ * packet lost, jitter, etc), VoIP metrics (delay, quality, etc)
+ *
+ * @param session	The media session.
+ * @param index		Stream index.
+ * @param stat_xr	Stream extended statistics.
+ *
+ * @return		PJ_SUCCESS on success.
+ */
+PJ_DECL(pj_status_t) pjmedia_session_get_stream_stat_xr(
+					     pjmedia_session *session,
+					     unsigned index,
+					     pjmedia_rtcp_xr_stat *stat_xr);
+#endif
+
+
+/**
+ * Get current jitter buffer state for the specified stream.
+ * See also #pjmedia_session_get_stream_stat()
+ *
+ * @param session	The media session.
+ * @param index		Stream index.
+ * @param state		Jitter buffer state.
+ *
+ * @return		PJ_SUCCESS on success.
+ */
+PJ_DECL(pj_status_t) pjmedia_session_get_stream_stat_jbuf(
+					    pjmedia_session *session,
+					    unsigned index,
+					    pjmedia_jb_state *state);
+
+/**
+ * Dial DTMF digit to the stream, using RFC 2833 mechanism.
+ *
+ * @param session	The media session.
+ * @param index		The stream index.
+ * @param ascii_digits	String of ASCII digits (i.e. 0-9*##A-B).
+ *
+ * @return		PJ_SUCCESS on success.
+ */
+PJ_DECL(pj_status_t) pjmedia_session_dial_dtmf( pjmedia_session *session,
+					        unsigned index,
+						const pj_str_t *ascii_digits );
+
+
+/**
+ * Check if the specified stream has received DTMF digits.
+ *
+ * @param session	The media session.
+ * @param index		The stream index.
+ *
+ * @return		Non-zero (PJ_TRUE) if the stream has DTMF digits.
+ */
+PJ_DECL(pj_status_t) pjmedia_session_check_dtmf( pjmedia_session *session,
+					         unsigned index);
+
+
+/**
+ * Retrieve DTMF digits from the specified stream.
+ *
+ * @param session	The media session.
+ * @param index		The stream index.
+ * @param ascii_digits	Buffer to receive the digits. The length of this
+ *			buffer is indicated in the "size" argument.
+ * @param size		On input, contains the maximum digits to be copied
+ *			to the buffer.
+ *			On output, it contains the actual digits that has
+ *			been copied to the buffer.
+ *
+ * @return		PJ_SUCCESS on success.
+ */
+PJ_DECL(pj_status_t) pjmedia_session_get_dtmf( pjmedia_session *session,
+					       unsigned index,
+					       char *ascii_digits,
+					       unsigned *size );
+
+/**
+ * Set callback to be called upon receiving DTMF digits. If callback is
+ * registered, the stream will not buffer incoming DTMF but rather call
+ * the callback as soon as DTMF digit is received completely.
+ *
+ * @param session	The media session.
+ * @param index		The stream index.
+ * @param cb		Callback to be called upon receiving DTMF digits.
+ *			The DTMF digits will be given to the callback as
+ *			ASCII digits.
+ * @param user_data	User data to be returned back when the callback
+ *			is called.
+ *
+ * @return		PJ_SUCCESS on success.
+ */
+PJ_DECL(pj_status_t)
+pjmedia_session_set_dtmf_callback(pjmedia_session *session,
+				  unsigned index,
+				  void (*cb)(pjmedia_stream*, 
+				 	     void *user_data, 
+					     int digit), 
+				  void *user_data);
+
+/**
+ * Destroy media session.
+ *
+ * @param session	The media session.
+ *
+ * @return		PJ_SUCCESS if success.
+ */
+PJ_DECL(pj_status_t) pjmedia_session_destroy(pjmedia_session *session);
+
+
+
+/**
+ * @}
+ */
+
+PJ_END_DECL
+
+#endif	/* __PJMEDIA_SESSION_H__ */
diff --git a/jni/pjproject-android/.svn/pristine/ca/ca5bae41da676fd67c8e8e432641e16fc4d53b07.svn-base b/jni/pjproject-android/.svn/pristine/ca/ca5bae41da676fd67c8e8e432641e16fc4d53b07.svn-base
new file mode 100644
index 0000000..782beba
--- /dev/null
+++ b/jni/pjproject-android/.svn/pristine/ca/ca5bae41da676fd67c8e8e432641e16fc4d53b07.svn-base
@@ -0,0 +1,26 @@
+# $Id$
+import inc_sip as sip
+import inc_sdp as sdp
+
+sdp = \
+"""
+v=0
+o=- 0 0 IN IP4 127.0.0.1
+s=tester
+c=IN IP4 127.0.0.1
+t=0 0
+m=audio 4000 RTP/SAVP 0 101
+a=rtpmap:0 PCMU/8000
+a=sendrecv
+a=rtpmap:101 telephone-event/8000
+a=fmtp:101 0-15
+a=crypto:1 CRYPTO_X inline:WnD7c1ksDGs+dIefCEo8omPg4uO8DYIinNGL5yxQ
+"""
+
+args = "--null-audio --auto-answer 200 --max-calls 1 --use-srtp 2 --srtp-secure 0"
+include = []
+exclude = []
+
+sendto_cfg = sip.SendtoCfg( "caller has used unsupported crypto, callee (SRTP mandatory) must reject the call", 
+			    pjsua_args=args, sdp=sdp, resp_code=406, 
+			    resp_inc=include, resp_exc=exclude)
diff --git a/jni/pjproject-android/.svn/pristine/ca/ca660114d57a9e8d7b1f6194ab71d1384508884b.svn-base b/jni/pjproject-android/.svn/pristine/ca/ca660114d57a9e8d7b1f6194ab71d1384508884b.svn-base
new file mode 100644
index 0000000..dd5ee69
--- /dev/null
+++ b/jni/pjproject-android/.svn/pristine/ca/ca660114d57a9e8d7b1f6194ab71d1384508884b.svn-base
@@ -0,0 +1,6 @@
+<resources>
+
+    <string name="app_name">pjsua</string>
+    <string name="title_activity_main">MainActivity</string>
+
+</resources>
\ No newline at end of file
diff --git a/jni/pjproject-android/.svn/pristine/ca/caa0f2d219373ed57dd63818cfa2d9e8eaf9b9af.svn-base b/jni/pjproject-android/.svn/pristine/ca/caa0f2d219373ed57dd63818cfa2d9e8eaf9b9af.svn-base
new file mode 100644
index 0000000..25f6bd0
--- /dev/null
+++ b/jni/pjproject-android/.svn/pristine/ca/caa0f2d219373ed57dd63818cfa2d9e8eaf9b9af.svn-base
@@ -0,0 +1,61 @@
+/* $Id$ */
+/* 
+ * Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com)
+ * Copyright (C) 2003-2008 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 __PJSIP_H__
+#define __PJSIP_H__
+
+/* Base types. */
+#include <pjsip/sip_types.h>
+#include <pjsip/sip_errno.h>
+
+/* Messaging and parsing. */
+#include <pjsip/sip_uri.h>
+#include <pjsip/sip_tel_uri.h>
+#include <pjsip/sip_msg.h>
+#include <pjsip/sip_multipart.h>
+#include <pjsip/sip_parser.h>
+
+/* Core */
+#include <pjsip/sip_event.h>
+#include <pjsip/sip_module.h>
+#include <pjsip/sip_endpoint.h>
+#include <pjsip/sip_util.h>
+
+/* Transport layer */
+#include <pjsip/sip_transport.h>
+#include <pjsip/sip_transport_udp.h>
+#include <pjsip/sip_transport_loop.h>
+#include <pjsip/sip_transport_tcp.h>
+#include <pjsip/sip_transport_tls.h>
+#include <pjsip/sip_resolve.h>
+
+/* Authentication. */
+#include <pjsip/sip_auth.h>
+#include <pjsip/sip_auth_aka.h>
+
+/* Transaction layer. */
+#include <pjsip/sip_transaction.h>
+
+/* UA Layer. */
+#include <pjsip/sip_ua_layer.h>
+#include <pjsip/sip_dialog.h>
+
+
+#endif	/* __PJSIP_H__ */
+
diff --git a/jni/pjproject-android/.svn/pristine/ca/caca4a7739b50580380edcdc248ef4864249374b.svn-base b/jni/pjproject-android/.svn/pristine/ca/caca4a7739b50580380edcdc248ef4864249374b.svn-base
new file mode 100644
index 0000000..62eb1c0
--- /dev/null
+++ b/jni/pjproject-android/.svn/pristine/ca/caca4a7739b50580380edcdc248ef4864249374b.svn-base
@@ -0,0 +1,76 @@
+/* $Id$ */
+/* 
+ * Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com)
+ * Copyright (C) 2003-2008 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_ADAPTER_SAMPLE_H__
+#define __PJMEDIA_TRANSPORT_ADAPTER_SAMPLE_H__
+
+
+/**
+ * @file transport_adapter_sample.h
+ * @brief Sample Media Transport Adapter
+ */
+
+#include <pjmedia/transport.h>
+
+
+/**
+ * @defgroup PJMEDIA_TRANSPORT_ADAPTER_SAMPLE Sample Transport Adapter
+ * @ingroup PJMEDIA_TRANSPORT
+ * @brief Example on how to create transport adapter.
+ * @{
+ *
+ * This describes a sample implementation of transport adapter, similar to
+ * the way the SRTP transport adapter works.
+ */
+
+PJ_BEGIN_DECL
+
+
+/**
+ * Create the transport adapter, specifying the underlying transport to be
+ * used to send and receive RTP/RTCP packets.
+ *
+ * @param endpt		The media endpoint.
+ * @param name		Optional name to identify this media transport
+ *			for logging purposes.
+ * @param base_tp	The base/underlying media transport to send and
+ * 			receive RTP/RTCP packets.
+ * @param del_base	Specify whether the base transport should also be
+ * 			destroyed when destroy() is called upon us.
+ * @param p_tp		Pointer to receive the media transport instance.
+ *
+ * @return		PJ_SUCCESS on success, or the appropriate error code.
+ */
+PJ_DECL(pj_status_t) pjmedia_tp_adapter_create( pjmedia_endpt *endpt,
+					        const char *name,
+					        pjmedia_transport *base_tp,
+					        pj_bool_t del_base,
+						pjmedia_transport **p_tp);
+
+PJ_END_DECL
+
+
+/**
+ * @}
+ */
+
+
+#endif	/* __PJMEDIA_TRANSPORT_ADAPTER_SAMPLE_H__ */
+
+
diff --git a/jni/pjproject-android/.svn/pristine/ca/cad7fbac0b5b2a12ce84e61a5e565993dba716d4.svn-base b/jni/pjproject-android/.svn/pristine/ca/cad7fbac0b5b2a12ce84e61a5e565993dba716d4.svn-base
new file mode 100644
index 0000000..bdc2046
--- /dev/null
+++ b/jni/pjproject-android/.svn/pristine/ca/cad7fbac0b5b2a12ce84e61a5e565993dba716d4.svn-base
@@ -0,0 +1,2085 @@
+/* $Id$ */
+/* 
+ * Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com)
+ * Copyright (C) 2003-2008 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 "test.h"
+#include <pjsip.h>
+#include <pjlib.h>
+
+#define POOL_SIZE	8000
+#if defined(PJ_DEBUG) && PJ_DEBUG!=0
+#   define LOOP		10000
+#else
+#   define LOOP		100000
+#endif
+#define AVERAGE_MSG_LEN	800
+#define THIS_FILE	"msg_test.c"
+
+static pjsip_msg *create_msg0(pj_pool_t *pool);
+static pjsip_msg *create_msg1(pj_pool_t *pool);
+
+#define STATUS_PARTIAL		1
+#define STATUS_SYNTAX_ERROR	2
+
+#define FLAG_DETECT_ONLY	1
+#define FLAG_PARSE_ONLY		4
+#define FLAG_PRINT_ONLY		8
+
+struct test_msg
+{
+    char	 msg[1024];
+    pjsip_msg *(*creator)(pj_pool_t *pool);
+    pj_size_t	 len;
+    int		 expected_status;
+} test_array[] = 
+{
+{
+    /* 'Normal' message with all headers. */
+    "INVITE sip:user@foo SIP/2.0\n"
+    "from: Hi I'm Joe <sip:joe.user@bar.otherdomain.com>;tag=123457890123456\r"
+    "To: Fellow User <sip:user@foo.bar.domain.com>\r\n"
+    "Call-ID: 12345678901234567890@bar\r\n"
+    "Content-Length: 0\r\n"
+    "CSeq: 123456 INVITE\n"
+    "Contact: <sip:joe@bar> ; q=0.5;expires=3600,sip:user@host;q=0.500\r"
+    "  ,sip:user2@host2\n"
+    "Content-Type: text/html ; charset=ISO-8859-4\r"
+    "Route: <sip:bigbox3.site3.atlanta.com;lr>,\r\n"
+    "  <sip:server10.biloxi.com;lr>\r"
+    "Record-Route: <sip:server10.biloxi.com>,\r\n" /* multiple routes+folding*/
+    "  <sip:bigbox3.site3.atlanta.com;lr>\n"
+    "v: SIP/2.0/SCTP bigbox3.site3.atlanta.com;branch=z9hG4bK77ef4c230\n"
+    "Via: SIP/2.0/UDP pc33.atlanta.com;branch=z9hG4bKnashds8\n" /* folding. */
+    " ;received=192.0.2.1\r\n"
+    "Via: SIP/2.0/UDP 10.2.1.1, SIP/2.0/TCP 192.168.1.1\n"
+    "Organization: \r"
+    "Max-Forwards: 70\n"
+    "X-Header: \r\n"	    /* empty header */
+    "P-Associated-URI:\r\n" /* empty header without space */
+    "\r\n",
+    &create_msg0,
+    0,
+    PJ_SUCCESS
+},
+{
+    /* Typical response message. */
+    "SIP/2.0 200 OK\r\n"
+    "Via: SIP/2.0/SCTP server10.biloxi.com;branch=z9hG4bKnashds8;rport;received=192.0.2.1\r\n"
+    "Via: SIP/2.0/UDP bigbox3.site3.atlanta.com;branch=z9hG4bK77ef4c2312983.1;received=192.0.2.2\r\n"
+    "Via: SIP/2.0/UDP pc33.atlanta.com;branch=z9hG4bK776asdhds ;received=192.0.2.3\r\n"
+    "Route: <sip:proxy.sipprovider.com>\r\n"
+    "Route: <sip:proxy.supersip.com:5060>\r\n"
+    "Max-Forwards: 70\r\n"
+    "To: Bob <sip:bob@biloxi.com>;tag=a6c85cf\r\n"
+    "From: Alice <sip:alice@atlanta.com>;tag=1928301774\r\n"
+    "Call-ID: a84b4c76e66710@pc33.atlanta.com\r\n"
+    "CSeq: 314159 INVITE\r\n"
+    "Contact: <sips:bob@192.0.2.4>\r\n"
+    "Content-Type: application/sdp\r\n"
+    "Content-Length: 150\r\n"
+    "\r\n"
+    "v=0\r\n"
+    "o=alice 53655765 2353687637 IN IP4 pc33.atlanta.com\r\n"
+    "s=-\r\n"
+    "t=0 0\r\n"
+    "c=IN IP4 pc33.atlanta.com\r\n"
+    "m=audio 3456 RTP/AVP 0 1 3 99\r\n"
+    "a=rtpmap:0 PCMU/8000\r\n",
+    &create_msg1,
+    0,
+    PJ_SUCCESS
+},
+{
+    /* Torture message from RFC 4475
+     * 3.1.1.1 A short tortuous INVITE
+     */
+    "INVITE sip:vivekg@chair-dnrc.example.com;unknownparam SIP/2.0\n"
+    "TO :\n"
+    " sip:vivekg@chair-dnrc.example.com ;   tag    = 1918181833n\n"
+    "from   : \"J Rosenberg \\\\\\\"\"       <sip:jdrosen@example.com>\n"
+    "  ;\n"
+    "  tag = 98asjd8\n"
+    "MaX-fOrWaRdS: 0068\n"
+    "Call-ID: wsinv.ndaksdj@192.0.2.1\n"
+    "Content-Length   : 150\n"
+    "cseq: 0009\n"
+    "  INVITE\n"
+    "Via  : SIP  /   2.0\n"
+    " /UDP\n"
+    "    192.0.2.2;rport;branch=390skdjuw\n"
+    "s :\n"
+    "NewFangledHeader:   newfangled value\n"
+    " continued newfangled value\n"
+    "UnknownHeaderWithUnusualValue: ;;,,;;,;\n"
+    "Content-Type: application/sdp\n"
+    "Route:\n"
+    " <sip:services.example.com;lr;unknownwith=value;unknown-no-value>\n"
+    "v:  SIP  / 2.0  / TCP     spindle.example.com   ;\n"
+    "  branch  =   z9hG4bK9ikj8  ,\n"
+    " SIP  /    2.0   / UDP  192.168.255.111   ; branch=\n"
+    " z9hG4bK30239\n"
+    "m:\"Quoted string \\\"\\\"\" <sip:jdrosen@example.com> ; newparam =\n"
+    "      newvalue ;\n"
+    "  secondparam ; q = 0.33\r\n"
+    "\r\n"
+    "v=0\r\n"
+    "o=mhandley 29739 7272939 IN IP4 192.0.2.3\r\n"
+    "s=-\r\n"
+    "c=IN IP4 192.0.2.4\r\n"
+    "t=0 0\r\n"
+    "m=audio 49217 RTP/AVP 0 12\r\n"
+    "m=video 3227 RTP/AVP 31\r\n"
+    "a=rtpmap:31 LPC\r\n",
+    NULL,
+    0,
+    PJ_SUCCESS
+},
+{
+    /* Torture message from RFC 4475
+     * 3.1.1.2 Wide Range of Valid Characters
+     */
+    "!interesting-Method0123456789_*+`.%indeed'~ sip:1_unusual.URI~(to-be!sure)&isn't+it$/crazy?,/;;*:&it+has=1,weird!*pas$wo~d_too.(doesn't-it)@example.com SIP/2.0\n"
+    "Via: SIP/2.0/UDP host1.example.com;rport;branch=z9hG4bK-.!%66*_+`'~\n"
+    "To: \"BEL:\\\x07 NUL:\\\x00 DEL:\\\x7F\" <sip:1_unusual.URI~(to-be!sure)&isn't+it$/crazy?,/;;*@example.com>\n"
+    "From: token1~` token2'+_ token3*%!.- <sip:mundane@example.com> ;fromParam''~+*_!.-%=\"\xD1\x80\xD0\xB0\xD0\xB1\xD0\xBE\xD1\x82\xD0\xB0\xD1\x8E\xD1\x89\xD0\xB8\xD0\xB9\";tag=_token~1'+`*%!-.\n"
+    "Call-ID: intmeth.word%ZK-!.*_+'@word`~)(><:\\/\"][?}{\n"
+    "CSeq: 139122385 !interesting-Method0123456789_*+`.%indeed'~\n"
+    "Max-Forwards: 255\n"
+    "extensionHeader-!.%*+_`'~: \xEF\xBB\xBF\xE5\xA4\xA7\xE5\x81\x9C\xE9\x9B\xBB\n"
+    "Content-Length: 0\r\n\r\n",
+    NULL,
+    641,
+    PJ_SUCCESS
+},
+{
+    /* Torture message from RFC 4475
+     * 3.1.1.3 Valid Use of the % Escaping Mechanism
+     */
+    "INVITE sip:sips%3Auser%40example.com@example.net SIP/2.0\n"
+    "To: sip:%75se%72@example.com\n"
+    "From: <sip:I%20have%20spaces@example.net>;tag=1234\n"
+    "Max-Forwards: 87\n"
+    "i: esc01.239409asdfakjkn23onasd0-3234\n"
+    "CSeq: 234234 INVITE\n"
+    "Via: SIP/2.0/UDP host5.example.net;rport;branch=z9hG4bKkdjuw\n"
+    "C: application/sdp\n"
+    "Contact:\n"
+    "  <sip:cal%6Cer@192.168.0.2:5060;%6C%72;n%61me=v%61lue%25%34%31>\n"
+    "Content-Length: 150\r\n"
+    "\r\n"
+    "v=0\r\n"
+    "o=mhandley 29739 7272939 IN IP4 192.0.2.1\r\n"
+    "s=-\r\n"
+    "c=IN IP4 192.0.2.1\r\n"
+    "t=0 0\r\n"
+    "m=audio 49217 RTP/AVP 0 12\r\n"
+    "m=video 3227 RTP/AVP 31\r\n"
+    "a=rtpmap:31 LPC\r\n",
+    NULL,
+    0,
+    PJ_SUCCESS
+},
+{
+    /* Torture message from RFC 4475
+     * 3.1.1.4 Escaped Nulls in URIs
+     */
+    "REGISTER sip:example.com SIP/2.0\r\n"
+    "To: sip:null-%00-null@example.com\r\n"
+    "From: sip:null-%00-null@example.com;tag=839923423\r\n"
+    "Max-Forwards: 70\r\n"
+    "Call-ID: escnull.39203ndfvkjdasfkq3w4otrq0adsfdfnavd\r\n"
+    "CSeq: 14398234 REGISTER\r\n"
+    "Via: SIP/2.0/UDP host5.example.com;rport;branch=z9hG4bKkdjuw\r\n"
+    "Contact: <sip:%00@host5.example.com>\r\n"
+    "Contact: <sip:%00%00@host5.example.com>\r\n"
+    "L:0\r\n"
+    "\r\n",
+    NULL,
+    0,
+    PJ_SUCCESS
+},
+{
+    /* Torture message from RFC 4475
+     * 3.1.1.5 Use of % When It Is Not an Escape
+     */
+    "RE%47IST%45R sip:registrar.example.com SIP/2.0\r\n"
+    "To: \"%Z%45\" <sip:resource@example.com>\r\n"
+    "From: \"%Z%45\" <sip:resource@example.com>;tag=f232jadfj23\r\n"
+    "Call-ID: esc02.asdfnqwo34rq23i34jrjasdcnl23nrlknsdf\r\n"
+    "Via: SIP/2.0/TCP host.example.com;rport;branch=z9hG4bK209%fzsnel234\r\n"
+    "CSeq: 29344 RE%47IST%45R\r\n"
+    "Max-Forwards: 70\r\n"
+    "Contact: <sip:alias1@host1.example.com>\r\n"
+    "C%6Fntact: <sip:alias2@host2.example.com>\r\n"
+    "Contact: <sip:alias3@host3.example.com>\r\n"
+    "l: 0\r\n"
+    "\r\n",
+    NULL,
+    0,
+    PJ_SUCCESS
+}
+};
+
+static struct
+{
+    int flag;
+    pj_highprec_t detect_len, parse_len, print_len;
+    pj_timestamp  detect_time, parse_time, print_time;
+} var;
+
+static pj_status_t test_entry( pj_pool_t *pool, struct test_msg *entry )
+{
+    pjsip_msg *parsed_msg, *ref_msg = NULL;
+    static pjsip_msg *print_msg;
+    pj_status_t status = PJ_SUCCESS;
+    pj_ssize_t len;
+    pj_str_t str1, str2;
+    pjsip_hdr *hdr1, *hdr2;
+    pj_timestamp t1, t2;
+    pjsip_parser_err_report err_list;
+    pj_size_t msg_size;
+    char msgbuf1[PJSIP_MAX_PKT_LEN];
+    char msgbuf2[PJSIP_MAX_PKT_LEN];
+    enum { BUFLEN = 512 };
+
+    if (entry->len==0)
+	entry->len = pj_ansi_strlen(entry->msg);
+
+    if (var.flag & FLAG_PARSE_ONLY)
+	goto parse_msg;
+
+    if (var.flag & FLAG_PRINT_ONLY) {
+	if (print_msg == NULL)
+	    print_msg = entry->creator(pool);
+	goto print_msg;
+    }
+
+    /* Detect message. */
+    var.detect_len = var.detect_len + entry->len;
+    pj_get_timestamp(&t1);
+    status = pjsip_find_msg(entry->msg, entry->len, PJ_FALSE, &msg_size);
+    if (status != PJ_SUCCESS) {
+	if (status!=PJSIP_EPARTIALMSG || 
+	    entry->expected_status!=STATUS_PARTIAL)
+	{
+	    app_perror("   error: unable to detect message", status);
+	    return -5;
+	}
+    }
+    if (msg_size != entry->len) {
+	PJ_LOG(3,(THIS_FILE, "   error: size mismatch"));
+	return -6;
+    }
+    pj_get_timestamp(&t2);
+    pj_sub_timestamp(&t2, &t1);
+    pj_add_timestamp(&var.detect_time, &t2);
+
+    if (var.flag & FLAG_DETECT_ONLY)
+	return PJ_SUCCESS;
+    
+    /* Parse message. */
+parse_msg:
+    var.parse_len = var.parse_len + entry->len;
+    pj_get_timestamp(&t1);
+    pj_list_init(&err_list);
+    parsed_msg = pjsip_parse_msg(pool, entry->msg, entry->len, &err_list);
+    if (parsed_msg == NULL) {
+	if (entry->expected_status != STATUS_SYNTAX_ERROR) {
+	    status = -10;
+	    if (err_list.next != &err_list) {
+		PJ_LOG(3,(THIS_FILE, "   Syntax error in line %d col %d",
+			      err_list.next->line, err_list.next->col));
+	    }
+	    goto on_return;
+	}
+    }
+    pj_get_timestamp(&t2);
+    pj_sub_timestamp(&t2, &t1);
+    pj_add_timestamp(&var.parse_time, &t2);
+
+    if ((var.flag & FLAG_PARSE_ONLY) || entry->creator==NULL)
+	return PJ_SUCCESS;
+
+    /* Create reference message. */
+    ref_msg = entry->creator(pool);
+
+    /* Create buffer for comparison. */
+    str1.ptr = (char*)pj_pool_alloc(pool, BUFLEN);
+    str2.ptr = (char*)pj_pool_alloc(pool, BUFLEN);
+
+    /* Compare message type. */
+    if (parsed_msg->type != ref_msg->type) {
+	status = -20;
+	goto on_return;
+    }
+
+    /* Compare request or status line. */
+    if (parsed_msg->type == PJSIP_REQUEST_MSG) {
+	pjsip_method *m1 = &parsed_msg->line.req.method;
+	pjsip_method *m2 = &ref_msg->line.req.method;
+
+	if (pjsip_method_cmp(m1, m2) != 0) {
+	    status = -30;
+	    goto on_return;
+	}
+	status = pjsip_uri_cmp(PJSIP_URI_IN_REQ_URI,
+			       parsed_msg->line.req.uri, 
+			       ref_msg->line.req.uri);
+	if (status != PJ_SUCCESS) {
+	    app_perror("   error: request URI mismatch", status);
+	    status = -31;
+	    goto on_return;
+	}
+    } else {
+	if (parsed_msg->line.status.code != ref_msg->line.status.code) {
+	    PJ_LOG(3,(THIS_FILE, "   error: status code mismatch"));
+	    status = -32;
+	    goto on_return;
+	}
+	if (pj_strcmp(&parsed_msg->line.status.reason, 
+		      &ref_msg->line.status.reason) != 0) 
+	{
+	    PJ_LOG(3,(THIS_FILE, "   error: status text mismatch"));
+	    status = -33;
+	    goto on_return;
+	}
+    }
+
+    /* Compare headers. */
+    hdr1 = parsed_msg->hdr.next;
+    hdr2 = ref_msg->hdr.next;
+
+    while (hdr1 != &parsed_msg->hdr && hdr2 != &ref_msg->hdr) {
+	len = pjsip_hdr_print_on(hdr1, str1.ptr, BUFLEN);
+	if (len < 0) {
+	    status = -40;
+	    goto on_return;
+	}
+	str1.ptr[len] = '\0';
+	str1.slen = len;
+
+	len = pjsip_hdr_print_on(hdr2, str2.ptr, BUFLEN);
+	if (len < 0) {
+	    status = -50;
+	    goto on_return;
+	}
+	str2.ptr[len] = '\0';
+	str2.slen = len;
+
+	if (pj_strcmp(&str1, &str2) != 0) {
+	    status = -60;
+	    PJ_LOG(3,(THIS_FILE, "   error: header string mismatch:\n"
+		          "   h1='%s'\n"
+			  "   h2='%s'\n",
+			  str1.ptr, str2.ptr));
+	    goto on_return;
+	}
+
+	hdr1 = hdr1->next;
+	hdr2 = hdr2->next;
+    }
+
+    if (hdr1 != &parsed_msg->hdr || hdr2 != &ref_msg->hdr) {
+	status = -70;
+	goto on_return;
+    }
+
+    /* Compare body? */
+    if (parsed_msg->body==NULL && ref_msg->body==NULL)
+	goto print_msg;
+
+    /* Compare msg body length. */
+    if (parsed_msg->body->len != ref_msg->body->len) {
+	status = -80;
+	goto on_return;
+    }
+
+    /* Compare msg body content type. */
+    if (pj_strcmp(&parsed_msg->body->content_type.type,
+	          &ref_msg->body->content_type.type) != 0) {
+	status = -90;
+	goto on_return;
+    }
+    if (pj_strcmp(&parsed_msg->body->content_type.subtype,
+	          &ref_msg->body->content_type.subtype) != 0) {
+	status = -100;
+	goto on_return;
+    }
+
+    /* Compare body content. */
+    str1.slen = parsed_msg->body->print_body(parsed_msg->body,
+					     msgbuf1, sizeof(msgbuf1));
+    if (str1.slen < 1) {
+	status = -110;
+	goto on_return;
+    }
+    str1.ptr = msgbuf1;
+
+    str2.slen = ref_msg->body->print_body(ref_msg->body,
+					  msgbuf2, sizeof(msgbuf2));
+    if (str2.slen < 1) {
+	status = -120;
+	goto on_return;
+    }
+    str2.ptr = msgbuf2;
+
+    if (pj_strcmp(&str1, &str2) != 0) {
+	status = -140;
+	goto on_return;
+    }
+    
+    /* Print message. */
+print_msg:
+    var.print_len = var.print_len + entry->len;
+    pj_get_timestamp(&t1);
+    if (var.flag & FLAG_PRINT_ONLY)
+	ref_msg = print_msg;
+    len = pjsip_msg_print(ref_msg, msgbuf1, PJSIP_MAX_PKT_LEN);
+    if (len < 1) {
+	status = -150;
+	goto on_return;
+    }
+    pj_get_timestamp(&t2);
+    pj_sub_timestamp(&t2, &t1);
+    pj_add_timestamp(&var.print_time, &t2);
+
+
+    status = PJ_SUCCESS;
+
+on_return:
+    return status;
+}
+
+
+static pjsip_msg *create_msg0(pj_pool_t *pool)
+{
+
+    pjsip_msg *msg;
+    pjsip_name_addr *name_addr;
+    pjsip_sip_uri *url;
+    pjsip_fromto_hdr *fromto;
+    pjsip_cid_hdr *cid;
+    pjsip_clen_hdr *clen;
+    pjsip_cseq_hdr *cseq;
+    pjsip_contact_hdr *contact;
+    pjsip_ctype_hdr *ctype;
+    pjsip_routing_hdr *routing;
+    pjsip_via_hdr *via;
+    pjsip_generic_string_hdr *generic;
+    pjsip_param *prm;
+    pj_str_t str;
+
+    msg = pjsip_msg_create(pool, PJSIP_REQUEST_MSG);
+
+    /* "INVITE sip:user@foo SIP/2.0\n" */
+    pjsip_method_set(&msg->line.req.method, PJSIP_INVITE_METHOD);
+    url = pjsip_sip_uri_create(pool, 0);
+    msg->line.req.uri = (pjsip_uri*)url;
+    pj_strdup2(pool, &url->user, "user");
+    pj_strdup2(pool, &url->host, "foo");
+
+    /* "From: Hi I'm Joe <sip:joe.user@bar.otherdomain.com>;tag=123457890123456\r" */
+    fromto = pjsip_from_hdr_create(pool);
+    pjsip_msg_add_hdr(msg, (pjsip_hdr*)fromto);
+    pj_strdup2(pool, &fromto->tag, "123457890123456");
+    name_addr = pjsip_name_addr_create(pool);
+    fromto->uri = (pjsip_uri*)name_addr;
+    pj_strdup2(pool, &name_addr->display, "Hi I'm Joe");
+    url = pjsip_sip_uri_create(pool, 0);
+    name_addr->uri = (pjsip_uri*)url;
+    pj_strdup2(pool, &url->user, "joe.user");
+    pj_strdup2(pool, &url->host, "bar.otherdomain.com");
+
+    /* "To: Fellow User <sip:user@foo.bar.domain.com>\r\n" */
+    fromto = pjsip_to_hdr_create(pool);
+    pjsip_msg_add_hdr(msg, (pjsip_hdr*)fromto);
+    name_addr = pjsip_name_addr_create(pool);
+    fromto->uri = (pjsip_uri*)name_addr;
+    pj_strdup2(pool, &name_addr->display, "Fellow User");
+    url = pjsip_sip_uri_create(pool, 0);
+    name_addr->uri = (pjsip_uri*)url;
+    pj_strdup2(pool, &url->user, "user");
+    pj_strdup2(pool, &url->host, "foo.bar.domain.com");
+
+    /* "Call-ID: 12345678901234567890@bar\r\n" */
+    cid = pjsip_cid_hdr_create(pool);
+    pjsip_msg_add_hdr(msg, (pjsip_hdr*)cid);
+    pj_strdup2(pool, &cid->id, "12345678901234567890@bar");
+
+    /* "Content-Length: 0\r\n" */
+    clen = pjsip_clen_hdr_create(pool);
+    pjsip_msg_add_hdr(msg, (pjsip_hdr*)clen);
+    clen->len = 0;
+
+    /* "CSeq: 123456 INVITE\n" */
+    cseq = pjsip_cseq_hdr_create(pool);
+    pjsip_msg_add_hdr(msg, (pjsip_hdr*)cseq);
+    cseq->cseq = 123456;
+    pjsip_method_set(&cseq->method, PJSIP_INVITE_METHOD);
+
+    /* "Contact: <sip:joe@bar>;q=0.5;expires=3600*/
+    contact = pjsip_contact_hdr_create(pool);
+    pjsip_msg_add_hdr(msg, (pjsip_hdr*)contact);
+    contact->q1000 = 500;
+    contact->expires = 3600;
+    name_addr = pjsip_name_addr_create(pool);
+    contact->uri = (pjsip_uri*)name_addr;
+    url = pjsip_sip_uri_create(pool, 0);
+    name_addr->uri = (pjsip_uri*)url;
+    pj_strdup2(pool, &url->user, "joe");
+    pj_strdup2(pool, &url->host, "bar");
+
+    /*, sip:user@host;q=0.500\r" */
+    contact = pjsip_contact_hdr_create(pool);
+    pjsip_msg_add_hdr(msg, (pjsip_hdr*)contact);
+    contact->q1000 = 500;
+    name_addr = pjsip_name_addr_create(pool);
+    contact->uri = (pjsip_uri*)name_addr;
+    url = pjsip_sip_uri_create(pool, 0);
+    name_addr->uri = (pjsip_uri*)url;
+    pj_strdup2(pool, &url->user, "user");
+    pj_strdup2(pool, &url->host, "host");
+
+    /* "  ,sip:user2@host2\n" */
+    contact = pjsip_contact_hdr_create(pool);
+    pjsip_msg_add_hdr(msg, (pjsip_hdr*)contact);
+    name_addr = pjsip_name_addr_create(pool);
+    contact->uri = (pjsip_uri*)name_addr;
+    url = pjsip_sip_uri_create(pool, 0);
+    name_addr->uri = (pjsip_uri*)url;
+    pj_strdup2(pool, &url->user, "user2");
+    pj_strdup2(pool, &url->host, "host2");
+
+    /* "Content-Type: text/html; charset=ISO-8859-4\r" */
+    ctype = pjsip_ctype_hdr_create(pool);
+    pjsip_msg_add_hdr(msg, (pjsip_hdr*)ctype);
+    pj_strdup2(pool, &ctype->media.type, "text");
+    pj_strdup2(pool, &ctype->media.subtype, "html");
+    prm = PJ_POOL_ALLOC_T(pool, pjsip_param);
+    prm->name = pj_str("charset");
+    prm->value = pj_str("ISO-8859-4");
+    pj_list_push_back(&ctype->media.param, prm);
+
+    /* "Route: <sip:bigbox3.site3.atlanta.com;lr>,\r\n" */
+    routing = pjsip_route_hdr_create(pool);
+    pjsip_msg_add_hdr(msg, (pjsip_hdr*)routing);
+    url = pjsip_sip_uri_create(pool, 0);
+    routing->name_addr.uri = (pjsip_uri*)url;
+    pj_strdup2(pool, &url->host, "bigbox3.site3.atlanta.com");
+    url->lr_param = 1;
+
+    /* "  <sip:server10.biloxi.com;lr>\r" */
+    routing = pjsip_route_hdr_create(pool);
+    pjsip_msg_add_hdr(msg, (pjsip_hdr*)routing);
+    url = pjsip_sip_uri_create(pool, 0);
+    routing->name_addr.uri = (pjsip_uri*)url;
+    pj_strdup2(pool, &url->host, "server10.biloxi.com");
+    url->lr_param = 1;
+
+    /* "Record-Route: <sip:server10.biloxi.com>,\r\n" */
+    routing = pjsip_rr_hdr_create(pool);
+    pjsip_msg_add_hdr(msg, (pjsip_hdr*)routing);
+    url = pjsip_sip_uri_create(pool, 0);
+    routing->name_addr.uri = (pjsip_uri*)url;
+    pj_strdup2(pool, &url->host, "server10.biloxi.com");
+    url->lr_param = 0;
+
+    /* "  <sip:bigbox3.site3.atlanta.com;lr>\n" */
+    routing = pjsip_rr_hdr_create(pool);
+    pjsip_msg_add_hdr(msg, (pjsip_hdr*)routing);
+    url = pjsip_sip_uri_create(pool, 0);
+    routing->name_addr.uri = (pjsip_uri*)url;
+    pj_strdup2(pool, &url->host, "bigbox3.site3.atlanta.com");
+    url->lr_param = 1;
+
+    /* "Via: SIP/2.0/SCTP bigbox3.site3.atlanta.com;branch=z9hG4bK77ef4c230\n" */
+    via = pjsip_via_hdr_create(pool);
+    pjsip_msg_add_hdr(msg, (pjsip_hdr*)via);
+    pj_strdup2(pool, &via->transport, "SCTP");
+    pj_strdup2(pool, &via->sent_by.host, "bigbox3.site3.atlanta.com");
+    pj_strdup2(pool, &via->branch_param, "z9hG4bK77ef4c230");
+
+    /* "Via: SIP/2.0/UDP pc33.atlanta.com;branch=z9hG4bKnashds8\n"
+	" ;received=192.0.2.1\r\n" */
+    via = pjsip_via_hdr_create(pool);
+    pjsip_msg_add_hdr(msg, (pjsip_hdr*)via);
+    pj_strdup2(pool, &via->transport, "UDP");
+    pj_strdup2(pool, &via->sent_by.host, "pc33.atlanta.com");
+    pj_strdup2(pool, &via->branch_param, "z9hG4bKnashds8");
+    pj_strdup2(pool, &via->recvd_param, "192.0.2.1");
+
+
+    /* "Via: SIP/2.0/UDP 10.2.1.1, */ 
+    via = pjsip_via_hdr_create(pool);
+    pjsip_msg_add_hdr(msg, (pjsip_hdr*)via);
+    pj_strdup2(pool, &via->transport, "UDP");
+    pj_strdup2(pool, &via->sent_by.host, "10.2.1.1");
+    
+    
+    /*SIP/2.0/TCP 192.168.1.1\n" */
+    via = pjsip_via_hdr_create(pool);
+    pjsip_msg_add_hdr(msg, (pjsip_hdr*)via);
+    pj_strdup2(pool, &via->transport, "TCP");
+    pj_strdup2(pool, &via->sent_by.host, "192.168.1.1");
+
+    /* "Organization: \r" */
+    str.ptr = "Organization";
+    str.slen = 12;
+    generic = pjsip_generic_string_hdr_create(pool, &str, NULL);
+    pjsip_msg_add_hdr(msg, (pjsip_hdr*)generic);
+    generic->hvalue.ptr = NULL;
+    generic->hvalue.slen = 0;
+
+    /* "Max-Forwards: 70\n" */
+    str.ptr = "Max-Forwards";
+    str.slen = 12;
+    generic = pjsip_generic_string_hdr_create(pool, &str, NULL);
+    pjsip_msg_add_hdr(msg, (pjsip_hdr*)generic);
+    str.ptr = "70";
+    str.slen = 2;
+    generic->hvalue = str;
+
+    /* "X-Header: \r\n" */
+    str.ptr = "X-Header";
+    str.slen = 8;
+    generic = pjsip_generic_string_hdr_create(pool, &str, NULL);
+    pjsip_msg_add_hdr(msg, (pjsip_hdr*)generic);
+    str.ptr = NULL;
+    str.slen = 0;
+    generic->hvalue = str;
+
+    /* P-Associated-URI:\r\n */
+    str.ptr = "P-Associated-URI";
+    str.slen = 16;
+    generic = pjsip_generic_string_hdr_create(pool, &str, NULL);
+    pjsip_msg_add_hdr(msg, (pjsip_hdr*)generic);
+    str.ptr = NULL;
+    str.slen = 0;
+    generic->hvalue = str;
+
+    return msg;
+}
+
+static pjsip_msg *create_msg1(pj_pool_t *pool)
+{
+    pjsip_via_hdr *via;
+    pjsip_route_hdr *route;
+    pjsip_name_addr *name_addr;
+    pjsip_sip_uri *url;
+    pjsip_max_fwd_hdr *max_fwd;
+    pjsip_to_hdr *to;
+    pjsip_from_hdr *from;
+    pjsip_contact_hdr *contact;
+    pjsip_ctype_hdr *ctype;
+    pjsip_cid_hdr *cid;
+    pjsip_clen_hdr *clen;
+    pjsip_cseq_hdr *cseq;
+    pjsip_msg *msg = pjsip_msg_create(pool, PJSIP_RESPONSE_MSG);
+    pjsip_msg_body *body;
+
+    //"SIP/2.0 200 OK\r\n"
+    msg->line.status.code = 200;
+    msg->line.status.reason = pj_str("OK");
+
+    //"Via: SIP/2.0/SCTP server10.biloxi.com;branch=z9hG4bKnashds8;rport;received=192.0.2.1\r\n"
+    via = pjsip_via_hdr_create(pool);
+    pjsip_msg_add_hdr(msg, (pjsip_hdr*)via);
+    via->transport = pj_str("SCTP");
+    via->sent_by.host = pj_str("server10.biloxi.com");
+    via->branch_param = pj_str("z9hG4bKnashds8");
+    via->rport_param = 0;
+    via->recvd_param = pj_str("192.0.2.1");
+
+    //"Via: SIP/2.0/UDP bigbox3.site3.atlanta.com;branch=z9hG4bK77ef4c2312983.1;received=192.0.2.2\r\n"
+    via = pjsip_via_hdr_create(pool);
+    pjsip_msg_add_hdr(msg, (pjsip_hdr*)via);
+    via->transport = pj_str("UDP");
+    via->sent_by.host = pj_str("bigbox3.site3.atlanta.com");
+    via->branch_param = pj_str("z9hG4bK77ef4c2312983.1");
+    via->recvd_param = pj_str("192.0.2.2");
+
+    //"Via: SIP/2.0/UDP pc33.atlanta.com;branch=z9hG4bK776asdhds ;received=192.0.2.3\r\n"
+    via = pjsip_via_hdr_create(pool);
+    pjsip_msg_add_hdr(msg, (pjsip_hdr*)via);
+    via->transport = pj_str("UDP");
+    via->sent_by.host = pj_str("pc33.atlanta.com");
+    via->branch_param = pj_str("z9hG4bK776asdhds");
+    via->recvd_param = pj_str("192.0.2.3");
+
+    //"Route: <sip:proxy.sipprovider.com>\r\n"
+    route = pjsip_route_hdr_create(pool);
+    pjsip_msg_add_hdr(msg, (pjsip_hdr*)route);
+    url = pjsip_sip_uri_create(pool, PJ_FALSE);
+    route->name_addr.uri = (pjsip_uri*)url;
+    url->host = pj_str("proxy.sipprovider.com");
+    
+    //"Route: <sip:proxy.supersip.com:5060>\r\n"
+    route = pjsip_route_hdr_create(pool);
+    pjsip_msg_add_hdr(msg, (pjsip_hdr*)route);
+    url = pjsip_sip_uri_create(pool, PJ_FALSE);
+    route->name_addr.uri = (pjsip_uri*)url;
+    url->host = pj_str("proxy.supersip.com");
+    url->port = 5060;
+
+    //"Max-Forwards: 70\r\n"
+    max_fwd = pjsip_max_fwd_hdr_create(pool, 70);
+    pjsip_msg_add_hdr(msg, (pjsip_hdr*)max_fwd);
+
+    //"To: Bob <sip:bob@biloxi.com>;tag=a6c85cf\r\n"
+    to = pjsip_to_hdr_create(pool);
+    pjsip_msg_add_hdr(msg, (pjsip_hdr*)to);
+    name_addr = pjsip_name_addr_create(pool);
+    name_addr->display = pj_str("Bob");
+    to->uri = (pjsip_uri*)name_addr;
+    url = pjsip_sip_uri_create(pool, PJ_FALSE);
+    name_addr->uri = (pjsip_uri*)url;
+    url->user = pj_str("bob");
+    url->host = pj_str("biloxi.com");
+    to->tag = pj_str("a6c85cf");
+
+    //"From: Alice <sip:alice@atlanta.com>;tag=1928301774\r\n"
+    from = pjsip_from_hdr_create(pool);
+    pjsip_msg_add_hdr(msg, (pjsip_hdr*)from);
+    name_addr = pjsip_name_addr_create(pool);
+    name_addr->display = pj_str("Alice");
+    from->uri = (pjsip_uri*)name_addr;
+    url = pjsip_sip_uri_create(pool, PJ_FALSE);
+    name_addr->uri = (pjsip_uri*)url;
+    url->user = pj_str("alice");
+    url->host = pj_str("atlanta.com");
+    from->tag = pj_str("1928301774");
+
+    //"Call-ID: a84b4c76e66710@pc33.atlanta.com\r\n"
+    cid = pjsip_cid_hdr_create(pool);
+    pjsip_msg_add_hdr(msg, (pjsip_hdr*)cid);
+    cid->id = pj_str("a84b4c76e66710@pc33.atlanta.com");
+
+    //"CSeq: 314159 INVITE\r\n"
+    cseq = pjsip_cseq_hdr_create(pool);
+    pjsip_msg_add_hdr(msg, (pjsip_hdr*)cseq);
+    cseq->cseq = 314159;
+    pjsip_method_set(&cseq->method, PJSIP_INVITE_METHOD);
+
+    //"Contact: <sips:bob@192.0.2.4>\r\n"
+    contact = pjsip_contact_hdr_create(pool);
+    pjsip_msg_add_hdr(msg, (pjsip_hdr*)contact);
+    name_addr = pjsip_name_addr_create(pool);
+    contact->uri = (pjsip_uri*)name_addr;
+    url = pjsip_sip_uri_create(pool, PJ_TRUE);
+    name_addr->uri = (pjsip_uri*)url;
+    url->user = pj_str("bob");
+    url->host = pj_str("192.0.2.4");
+
+    //"Content-Type: application/sdp\r\n"
+    ctype = pjsip_ctype_hdr_create(pool);
+    pjsip_msg_add_hdr(msg, (pjsip_hdr*)ctype);
+    ctype->media.type = pj_str("application");
+    ctype->media.subtype = pj_str("sdp");
+
+    //"Content-Length: 150\r\n"
+    clen = pjsip_clen_hdr_create(pool);
+    pjsip_msg_add_hdr(msg, (pjsip_hdr*)clen);
+    clen->len = 150;
+
+    // Body
+    body = PJ_POOL_ZALLOC_T(pool, pjsip_msg_body);
+    msg->body = body;
+    body->content_type.type = pj_str("application");
+    body->content_type.subtype = pj_str("sdp");
+    body->data = (void*)
+	"v=0\r\n"
+	"o=alice 53655765 2353687637 IN IP4 pc33.atlanta.com\r\n"
+	"s=-\r\n"
+	"t=0 0\r\n"
+	"c=IN IP4 pc33.atlanta.com\r\n"
+	"m=audio 3456 RTP/AVP 0 1 3 99\r\n"
+	"a=rtpmap:0 PCMU/8000\r\n";
+    body->len = (unsigned)pj_ansi_strlen((const char*) body->data);
+    body->print_body = &pjsip_print_text_body;
+
+    return msg;
+}
+
+/*****************************************************************************/
+
+static pj_status_t simple_test(void)
+{
+    char stbuf[] = "SIP/2.0 180 Ringing like it never rings before";
+    unsigned i;
+    pjsip_status_line st_line;
+    pj_status_t status;
+
+    PJ_LOG(3,(THIS_FILE, "  simple test.."));
+    
+    status = pjsip_parse_status_line(stbuf, pj_ansi_strlen(stbuf), &st_line);
+    if (status != PJ_SUCCESS)
+	return status;
+
+    for (i=0; i<PJ_ARRAY_SIZE(test_array); ++i) {
+	pj_pool_t *pool;
+	pool = pjsip_endpt_create_pool(endpt, NULL, POOL_SIZE, POOL_SIZE);
+	status = test_entry( pool, &test_array[i] );
+	pjsip_endpt_release_pool(endpt, pool);
+
+	if (status != PJ_SUCCESS)
+	    return status;
+    }
+
+    return PJ_SUCCESS;
+}
+
+
+#if INCLUDE_BENCHMARKS
+static int msg_benchmark(unsigned *p_detect, unsigned *p_parse, 
+			 unsigned *p_print)
+{
+    pj_pool_t *pool;
+    int i, loop;
+    pj_timestamp zero;
+    pj_time_val elapsed;
+    pj_highprec_t avg_detect, avg_parse, avg_print, kbytes;
+    pj_status_t status = PJ_SUCCESS;
+
+    pj_bzero(&var, sizeof(var));
+    zero.u64 = 0;
+
+    for (loop=0; loop<LOOP; ++loop) {
+	for (i=0; i<(int)PJ_ARRAY_SIZE(test_array); ++i) {
+	    pool = pjsip_endpt_create_pool(endpt, NULL, POOL_SIZE, POOL_SIZE);
+	    status = test_entry( pool, &test_array[i] );
+	    pjsip_endpt_release_pool(endpt, pool);
+
+	    if (status != PJ_SUCCESS)
+		return status;
+	}
+    }
+
+    kbytes = var.detect_len;
+    pj_highprec_mod(kbytes, 1000000);
+    pj_highprec_div(kbytes, 100000);
+    elapsed = pj_elapsed_time(&zero, &var.detect_time);
+    avg_detect = pj_elapsed_usec(&zero, &var.detect_time);
+    pj_highprec_mul(avg_detect, AVERAGE_MSG_LEN);
+    pj_highprec_div(avg_detect, var.detect_len);
+    avg_detect = 1000000 / avg_detect;
+
+    PJ_LOG(3,(THIS_FILE, 
+	      "    %u.%u MB detected in %d.%03ds (avg=%d msg detection/sec)", 
+	      (unsigned)(var.detect_len/1000000), (unsigned)kbytes,
+	      elapsed.sec, elapsed.msec,
+	      (unsigned)avg_detect));
+    *p_detect = (unsigned)avg_detect;
+
+    kbytes = var.parse_len;
+    pj_highprec_mod(kbytes, 1000000);
+    pj_highprec_div(kbytes, 100000);
+    elapsed = pj_elapsed_time(&zero, &var.parse_time);
+    avg_parse = pj_elapsed_usec(&zero, &var.parse_time);
+    pj_highprec_mul(avg_parse, AVERAGE_MSG_LEN);
+    pj_highprec_div(avg_parse, var.parse_len);
+    avg_parse = 1000000 / avg_parse;
+
+    PJ_LOG(3,(THIS_FILE, 
+	      "    %u.%u MB parsed in %d.%03ds (avg=%d msg parsing/sec)", 
+	      (unsigned)(var.parse_len/1000000), (unsigned)kbytes,
+	      elapsed.sec, elapsed.msec,
+	      (unsigned)avg_parse));
+    *p_parse = (unsigned)avg_parse;
+
+    kbytes = var.print_len;
+    pj_highprec_mod(kbytes, 1000000);
+    pj_highprec_div(kbytes, 100000);
+    elapsed = pj_elapsed_time(&zero, &var.print_time);
+    avg_print = pj_elapsed_usec(&zero, &var.print_time);
+    pj_highprec_mul(avg_print, AVERAGE_MSG_LEN);
+    pj_highprec_div(avg_print, var.print_len);
+    avg_print = 1000000 / avg_print;
+
+    PJ_LOG(3,(THIS_FILE, 
+	      "    %u.%u MB printed in %d.%03ds (avg=%d msg print/sec)", 
+	      (unsigned)(var.print_len/1000000), (unsigned)kbytes,
+	      elapsed.sec, elapsed.msec,
+	      (unsigned)avg_print));
+
+    *p_print = (unsigned)avg_print;
+    return status;
+}
+#endif	/* INCLUDE_BENCHMARKS */
+
+/*****************************************************************************/
+/* Test various header parsing and production */
+static int hdr_test_success(pjsip_hdr *h);
+static int hdr_test_accept0(pjsip_hdr *h);
+static int hdr_test_accept1(pjsip_hdr *h);
+static int hdr_test_accept2(pjsip_hdr *h);
+static int hdr_test_allow0(pjsip_hdr *h);
+static int hdr_test_authorization(pjsip_hdr *h);
+static int hdr_test_cid(pjsip_hdr *h);
+static int hdr_test_contact0(pjsip_hdr *h);
+static int hdr_test_contact1(pjsip_hdr *h);
+static int hdr_test_contact_q0(pjsip_hdr *h);
+static int hdr_test_contact_q1(pjsip_hdr *h);
+static int hdr_test_contact_q2(pjsip_hdr *h);
+static int hdr_test_contact_q3(pjsip_hdr *h);
+static int hdr_test_contact_q4(pjsip_hdr *h);
+static int hdr_test_content_length(pjsip_hdr *h);
+static int hdr_test_content_type(pjsip_hdr *h);
+static int hdr_test_from(pjsip_hdr *h);
+static int hdr_test_proxy_authenticate(pjsip_hdr *h);
+static int hdr_test_record_route(pjsip_hdr *h);
+static int hdr_test_supported(pjsip_hdr *h);
+static int hdr_test_to(pjsip_hdr *h);
+static int hdr_test_via(pjsip_hdr *h);
+static int hdr_test_via_ipv6_1(pjsip_hdr *h);
+static int hdr_test_via_ipv6_2(pjsip_hdr *h);
+static int hdr_test_via_ipv6_3(pjsip_hdr *h);
+static int hdr_test_retry_after1(pjsip_hdr *h);
+static int hdr_test_subject_utf(pjsip_hdr *h);
+
+
+#define GENERIC_PARAM	     "p0=a;p1=\"ab:;cd\";p2=ab%3acd;p3"
+#define GENERIC_PARAM_PARSED "p0=a;p1=\"ab:;cd\";p2=ab:cd;p3"
+#define PARAM_CHAR	     "][/:&+$"
+#define SIMPLE_ADDR_SPEC     "sip:host"
+#define ADDR_SPEC	     SIMPLE_ADDR_SPEC ";"PARAM_CHAR"="PARAM_CHAR ";p1=\";\""
+#define NAME_ADDR	     "<" ADDR_SPEC ">"
+
+#define HDR_FLAG_PARSE_FAIL 1
+#define HDR_FLAG_DONT_PRINT 2
+
+struct hdr_test_t
+{
+    char *hname;
+    char *hshort_name;
+    char *hcontent;
+    int  (*test)(pjsip_hdr*);
+    unsigned flags;
+} hdr_test_data[] =
+{
+    {
+	/* Empty Accept */
+	"Accept", NULL,
+	"",
+	&hdr_test_accept0
+    },
+
+    {
+	/* Overflowing generic string header */
+	"Accept", NULL,
+	"a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, " \
+	"a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, " \
+	"a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, " \
+	"a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, " \
+	"a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, " \
+	"a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, " \
+	"a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, " \
+	"a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a",
+	&hdr_test_success,
+	HDR_FLAG_PARSE_FAIL
+    },
+
+    {
+	/* Normal Accept */
+	"Accept", NULL,
+	"application/*, text/plain",
+	&hdr_test_accept1
+    },
+
+    {
+	/* Accept with params */
+	"Accept", NULL,
+	"application/*;p1=v1, text/plain",
+	&hdr_test_accept2
+    },
+
+    {
+	/* Empty Allow */
+	"Allow", NULL,
+	"",
+	&hdr_test_allow0,
+    },
+
+    {
+	/* Authorization, testing which params should be quoted */
+	"Authorization", NULL,
+	"Digest username=\"username\", realm=\"realm\", nonce=\"nonce\", "  \
+		"uri=\"sip:domain\", response=\"RESPONSE\", algorithm=MD5, "    \
+		"cnonce=\"CNONCE\", opaque=\"OPAQUE\", qop=auth, nc=00000001",
+	&hdr_test_authorization
+    },
+
+    {
+	/* Call ID */
+	"Call-ID", "i",
+	"-.!%*_+`'~()<>:\\\"/[]?{}",
+	&hdr_test_cid,
+    },
+
+    {
+	/* Parameter belong to hparam */
+	"Contact", "m",
+	SIMPLE_ADDR_SPEC ";p1=v1",
+	&hdr_test_contact0,
+	HDR_FLAG_DONT_PRINT
+    },
+
+    {
+	/* generic-param in Contact header */
+	"Contact", "m",
+	NAME_ADDR ";" GENERIC_PARAM,
+	&hdr_test_contact1
+    },
+
+    {
+	/* q=0 parameter in Contact header */
+	"Contact", "m",
+	NAME_ADDR ";q=0",
+	&hdr_test_contact_q0,
+	HDR_FLAG_DONT_PRINT
+    },
+
+    {
+	/* q=0.5 parameter in Contact header */
+	"Contact", "m",
+	NAME_ADDR ";q=0.5",
+	&hdr_test_contact_q1
+    },
+
+    {
+	/* q=1 parameter in Contact header */
+	"Contact", "m",
+	NAME_ADDR ";q=1",
+	&hdr_test_contact_q2
+    },
+
+    {
+	/* q=1.0 parameter in Contact header */
+	"Contact", "m",
+	NAME_ADDR ";q=1.0",
+	&hdr_test_contact_q3,
+	HDR_FLAG_DONT_PRINT
+    },
+
+    {
+	/* q=1.1 parameter in Contact header */
+	"Contact", "m",
+	NAME_ADDR ";q=1.15",
+	&hdr_test_contact_q4
+    },
+
+    {
+	/* Content-Length */
+	"Content-Length", "l",
+	"10",
+	&hdr_test_content_length
+    },
+
+    {
+	/* Content-Type, with generic-param */
+	"Content-Type", "c",
+	"application/sdp" ";" GENERIC_PARAM,
+	&hdr_test_content_type,
+	HDR_FLAG_DONT_PRINT
+    },
+
+    {
+	/* From, testing parameters and generic-param */
+	"From", "f",
+	NAME_ADDR ";" GENERIC_PARAM,
+	&hdr_test_from
+    },
+
+    {
+	/* Proxy-Authenticate, testing which params should be quoted */
+	"Proxy-Authenticate", NULL,
+	"Digest  realm=\"realm\",domain=\"sip:domain\",nonce=\"nonce\","  \
+	        "opaque=\"opaque\",stale=true,algorithm=MD5,qop=\"auth\"",
+	&hdr_test_proxy_authenticate
+    },
+
+    {
+	/* Record-Route, param belong to header */
+	"Record-Route", NULL,
+	NAME_ADDR ";" GENERIC_PARAM,
+	&hdr_test_record_route
+    },
+
+    {
+	/* Empty Supported */
+	"Supported", "k",
+	"",
+	&hdr_test_supported,
+    },
+
+    {
+	/* To */
+	"To", "t",
+	NAME_ADDR ";" GENERIC_PARAM,
+	&hdr_test_to
+    },
+
+    {
+	/* Via */
+	"Via", "v",
+	"SIP/2.0/XYZ host" ";" GENERIC_PARAM,
+	&hdr_test_via
+    },
+
+    {
+	/* Via with IPv6 */
+	"Via", "v",
+	"SIP/2.0/UDP [::1]",
+	&hdr_test_via_ipv6_1
+    },
+
+    {
+	/* Via with IPv6 */
+	"Via", "v",
+	"SIP/2.0/UDP [::1]:5061",
+	&hdr_test_via_ipv6_2
+    },
+
+    {
+	/* Via with IPv6 */
+	"Via", "v",
+	"SIP/2.0/UDP [::1];rport=5061;received=::2",
+	&hdr_test_via_ipv6_3
+    },
+
+    {
+	/* Retry-After header with comment */
+	"Retry-After", NULL,
+	"10(Already Pending Register)",
+	&hdr_test_retry_after1
+    },
+
+    {
+	/* Non-ASCII UTF-8 characters in Subject */
+	"Subject", NULL,
+	"\xC0\x81",
+	&hdr_test_subject_utf
+    }
+};
+
+static int hdr_test_success(pjsip_hdr *h)
+{
+    PJ_UNUSED_ARG(h);
+    return 0;
+}
+
+/* "" */
+static int hdr_test_accept0(pjsip_hdr *h)
+{
+    pjsip_accept_hdr *hdr = (pjsip_accept_hdr*)h;
+
+    if (h->type != PJSIP_H_ACCEPT)
+	return -1010;
+
+    if (hdr->count != 0)
+	return -1020;
+
+    return 0;
+}
+
+/* "application/ *, text/plain\r\n" */
+static int hdr_test_accept1(pjsip_hdr *h)
+{
+    pjsip_accept_hdr *hdr = (pjsip_accept_hdr*)h;
+
+    if (h->type != PJSIP_H_ACCEPT)
+	return -1110;
+
+    if (hdr->count != 2)
+	return -1120;
+
+    if (pj_strcmp2(&hdr->values[0], "application/*"))
+	return -1130;
+
+    if (pj_strcmp2(&hdr->values[1], "text/plain"))
+	return -1140;
+
+    return 0;
+}
+
+/* "application/ *;p1=v1, text/plain\r\n" */
+static int hdr_test_accept2(pjsip_hdr *h)
+{
+    pjsip_accept_hdr *hdr = (pjsip_accept_hdr*)h;
+
+    if (h->type != PJSIP_H_ACCEPT)
+	return -1210;
+
+    if (hdr->count != 2)
+	return -1220;
+
+    if (pj_strcmp2(&hdr->values[0], "application/*;p1=v1"))
+	return -1230;
+
+    if (pj_strcmp2(&hdr->values[1], "text/plain"))
+	return -1240;
+
+    return 0;
+}
+
+/* "" */
+static int hdr_test_allow0(pjsip_hdr *h)
+{
+    pjsip_allow_hdr *hdr = (pjsip_allow_hdr*)h;
+
+    if (h->type != PJSIP_H_ALLOW)
+	return -1310;
+
+    if (hdr->count != 0)
+	return -1320;
+
+    return 0;
+
+}
+
+
+/*
+	"Digest username=\"username\", realm=\"realm\", nonce=\"nonce\", "  \
+		"uri=\"sip:domain\", response=\"RESPONSE\", algorithm=MD5, "    \
+		"cnonce=\"CNONCE\", opaque=\"OPAQUE\", qop=auth, nc=00000001",
+ */
+static int hdr_test_authorization(pjsip_hdr *h)
+{
+    pjsip_authorization_hdr *hdr = (pjsip_authorization_hdr*)h;
+
+    if (h->type != PJSIP_H_AUTHORIZATION)
+	return -1410;
+
+    if (pj_strcmp2(&hdr->scheme, "Digest"))
+	return -1420;
+
+    if (pj_strcmp2(&hdr->credential.digest.username, "username"))
+	return -1421;
+
+    if (pj_strcmp2(&hdr->credential.digest.realm, "realm"))
+	return -1422;
+
+    if (pj_strcmp2(&hdr->credential.digest.nonce, "nonce"))
+	return -1423;
+
+    if (pj_strcmp2(&hdr->credential.digest.uri, "sip:domain"))
+	return -1424;
+
+    if (pj_strcmp2(&hdr->credential.digest.response, "RESPONSE"))
+	return -1425;
+
+    if (pj_strcmp2(&hdr->credential.digest.algorithm, "MD5"))
+	return -1426;
+
+    if (pj_strcmp2(&hdr->credential.digest.cnonce, "CNONCE"))
+	return -1427;
+
+    if (pj_strcmp2(&hdr->credential.digest.opaque, "OPAQUE"))
+	return -1428;
+
+    if (pj_strcmp2(&hdr->credential.digest.qop, "auth"))
+	return -1429;
+
+    if (pj_strcmp2(&hdr->credential.digest.nc, "00000001"))
+	return -1430;
+
+    return 0;
+}
+
+
+/*
+    "-.!%*_+`'~()<>:\\\"/[]?{}\r\n"
+ */
+static int hdr_test_cid(pjsip_hdr *h)
+{
+    pjsip_cid_hdr *hdr = (pjsip_cid_hdr*)h;
+
+    if (h->type != PJSIP_H_CALL_ID)
+	return -1510;
+
+    if (pj_strcmp2(&hdr->id, "-.!%*_+`'~()<>:\\\"/[]?{}"))
+	return -1520;
+
+    return 0;
+}
+
+/*
+ #define SIMPLE_ADDR_SPEC    "sip:host"
+ */
+static int test_simple_addr_spec(pjsip_uri *uri)
+{
+    pjsip_sip_uri *sip_uri = (pjsip_sip_uri *)pjsip_uri_get_uri(uri);
+
+    if (!PJSIP_URI_SCHEME_IS_SIP(uri))
+	return -900;
+
+    if (pj_strcmp2(&sip_uri->host, "host"))
+	return -910;
+
+    if (sip_uri->port != 0)
+	return -920;
+
+    return 0;
+}
+
+/* 
+#define PARAM_CHAR	    "][/:&+$"
+#define SIMPLE_ADDR_SPEC    "sip:host"
+#define ADDR_SPEC	     SIMPLE_ADDR_SPEC ";"PARAM_CHAR"="PARAM_CHAR ";p1=\";\""
+#define NAME_ADDR	    "<" ADDR_SPEC ">"
+ */
+static int nameaddr_test(void *uri)
+{
+    pjsip_sip_uri *sip_uri=(pjsip_sip_uri *)pjsip_uri_get_uri((pjsip_uri*)uri);
+    pjsip_param *param;
+    int rc;
+
+    if (!PJSIP_URI_SCHEME_IS_SIP(uri))
+	return -930;
+
+    rc = test_simple_addr_spec((pjsip_uri*)sip_uri);
+    if (rc != 0)
+	return rc;
+
+    if (pj_list_size(&sip_uri->other_param) != 2)
+	return -940;
+
+    param = sip_uri->other_param.next;
+
+    if (pj_strcmp2(&param->name, PARAM_CHAR))
+	return -942;
+
+    if (pj_strcmp2(&param->value, PARAM_CHAR))
+	return -943;
+
+    param = param->next;
+    if (pj_strcmp2(&param->name, "p1"))
+	return -942;
+    if (pj_strcmp2(&param->value, "\";\""))
+	return -943;
+
+    return 0;
+}
+
+/*
+#define GENERIC_PARAM  "p0=a;p1=\"ab:;cd\";p2=ab%3acd;p3"
+ */
+static int generic_param_test(pjsip_param *param_head)
+{
+    pjsip_param *param;
+
+    if (pj_list_size(param_head) != 4)
+	return -950;
+
+    param = param_head->next;
+
+    if (pj_strcmp2(&param->name, "p0"))
+	return -952;
+    if (pj_strcmp2(&param->value, "a"))
+	return -953;
+
+    param = param->next;
+    if (pj_strcmp2(&param->name, "p1"))
+	return -954;
+    if (pj_strcmp2(&param->value, "\"ab:;cd\""))
+	return -955;
+
+    param = param->next;
+    if (pj_strcmp2(&param->name, "p2"))
+	return -956;
+    if (pj_strcmp2(&param->value, "ab:cd"))
+	return -957;
+
+    param = param->next;
+    if (pj_strcmp2(&param->name, "p3"))
+	return -958;
+    if (pj_strcmp2(&param->value, ""))
+	return -959;
+
+    return 0;
+}
+
+
+
+/*
+    SIMPLE_ADDR_SPEC ";p1=v1\r\n"
+ */
+static int hdr_test_contact0(pjsip_hdr *h)
+{
+    pjsip_contact_hdr *hdr = (pjsip_contact_hdr*)h;
+    pjsip_param *param;
+    int rc;
+
+    if (h->type != PJSIP_H_CONTACT)
+	return -1610;
+
+    rc = test_simple_addr_spec(hdr->uri);
+    if (rc != 0)
+	return rc;
+
+    if (pj_list_size(&hdr->other_param) != 1)
+	return -1620;
+
+    param = hdr->other_param.next;
+
+    if (pj_strcmp2(&param->name, "p1"))
+	return -1630;
+
+    if (pj_strcmp2(&param->value, "v1"))
+	return -1640;
+
+    return 0;
+}
+
+/*
+    NAME_ADDR GENERIC_PARAM "\r\n",    
+ */
+static int hdr_test_contact1(pjsip_hdr *h)
+{
+    pjsip_contact_hdr *hdr = (pjsip_contact_hdr*)h;
+    int rc;
+
+    if (h->type != PJSIP_H_CONTACT)
+	return -1710;
+
+    rc = nameaddr_test(hdr->uri);
+    if (rc != 0)
+	return rc;
+
+    rc = generic_param_test(&hdr->other_param);
+    if (rc != 0)
+	return rc;
+
+    return 0;
+}
+
+/*
+    NAME_ADDR ";q=0"
+ */
+static int hdr_test_contact_q0(pjsip_hdr *h)
+{
+    pjsip_contact_hdr *hdr = (pjsip_contact_hdr*)h;
+    int rc;
+
+    if (h->type != PJSIP_H_CONTACT)
+	return -1710;
+
+    rc = nameaddr_test(hdr->uri);
+    if (rc != 0)
+	return rc;
+
+    if (hdr->q1000 != 0)
+	return -1711;
+
+    return 0;
+}
+
+/*
+    NAME_ADDR ";q=0.5"
+ */
+static int hdr_test_contact_q1(pjsip_hdr *h)
+{
+    pjsip_contact_hdr *hdr = (pjsip_contact_hdr*)h;
+    int rc;
+
+    if (h->type != PJSIP_H_CONTACT)
+	return -1710;
+
+    rc = nameaddr_test(hdr->uri);
+    if (rc != 0)
+	return rc;
+
+    if (hdr->q1000 != 500)
+	return -1712;
+
+    return 0;
+}
+
+/*
+    NAME_ADDR ";q=1"
+ */
+static int hdr_test_contact_q2(pjsip_hdr *h)
+{
+    pjsip_contact_hdr *hdr = (pjsip_contact_hdr*)h;
+    int rc;
+
+    if (h->type != PJSIP_H_CONTACT)
+	return -1710;
+
+    rc = nameaddr_test(hdr->uri);
+    if (rc != 0)
+	return rc;
+
+    if (hdr->q1000 != 1000)
+	return -1713;
+
+    return 0;
+}
+
+/*
+    NAME_ADDR ";q=1.0"
+ */
+static int hdr_test_contact_q3(pjsip_hdr *h)
+{
+    pjsip_contact_hdr *hdr = (pjsip_contact_hdr*)h;
+    int rc;
+
+    if (h->type != PJSIP_H_CONTACT)
+	return -1710;
+
+    rc = nameaddr_test(hdr->uri);
+    if (rc != 0)
+	return rc;
+
+    if (hdr->q1000 != 1000)
+	return -1714;
+
+    return 0;
+}
+
+/*
+    NAME_ADDR ";q=1.15"
+ */
+static int hdr_test_contact_q4(pjsip_hdr *h)
+{
+    pjsip_contact_hdr *hdr = (pjsip_contact_hdr*)h;
+    int rc;
+
+    if (h->type != PJSIP_H_CONTACT)
+	return -1710;
+
+    rc = nameaddr_test(hdr->uri);
+    if (rc != 0)
+	return rc;
+
+    if (hdr->q1000 != 1150)
+	return -1715;
+
+    return 0;
+}
+
+/*
+    "10"
+ */
+static int hdr_test_content_length(pjsip_hdr *h)
+{
+    pjsip_clen_hdr *hdr = (pjsip_clen_hdr*)h;
+
+    if (h->type != PJSIP_H_CONTENT_LENGTH)
+	return -1810;
+
+    if (hdr->len != 10)
+	return -1820;
+
+    return 0;
+}
+
+/*
+    "application/sdp" GENERIC_PARAM,
+ */
+static int hdr_test_content_type(pjsip_hdr *h)
+{
+    pjsip_ctype_hdr *hdr = (pjsip_ctype_hdr*)h;
+    const pjsip_param *prm;
+
+    if (h->type != PJSIP_H_CONTENT_TYPE)
+	return -1910;
+
+    if (pj_strcmp2(&hdr->media.type, "application"))
+	return -1920;
+
+    if (pj_strcmp2(&hdr->media.subtype, "sdp"))
+	return -1930;
+
+    /* Currently, if the media parameter contains escaped characters,
+     * pjsip will print the parameter unescaped.
+     */
+    prm = hdr->media.param.next;
+    if (prm == &hdr->media.param) return -1940;
+    if (pj_strcmp2(&prm->name, "p0")) return -1941;
+    if (pj_strcmp2(&prm->value, "a")) return -1942;
+
+    prm = prm->next;
+    if (prm == &hdr->media.param) return -1950;
+    if (pj_strcmp2(&prm->name, "p1")) { PJ_LOG(3,("", "%.*s", (int)prm->name.slen, prm->name.ptr)); return -1951; }
+    if (pj_strcmp2(&prm->value, "\"ab:;cd\"")) { PJ_LOG(3,("", "%.*s", (int)prm->value.slen, prm->value.ptr)); return -1952; }
+
+    prm = prm->next;
+    if (prm == &hdr->media.param) return -1960;
+    if (pj_strcmp2(&prm->name, "p2")) return -1961;
+    if (pj_strcmp2(&prm->value, "ab:cd")) return -1962;
+
+    prm = prm->next;
+    if (prm == &hdr->media.param) return -1970;
+    if (pj_strcmp2(&prm->name, "p3")) return -1971;
+    if (pj_strcmp2(&prm->value, "")) return -1972;
+
+    return 0;
+}
+
+/*
+    NAME_ADDR GENERIC_PARAM,
+ */
+static int hdr_test_from(pjsip_hdr *h)
+{
+    pjsip_from_hdr *hdr = (pjsip_from_hdr*)h;
+    int rc;
+
+    if (h->type != PJSIP_H_FROM)
+	return -2010;
+
+    rc = nameaddr_test(hdr->uri);
+    if (rc != 0)
+	return rc;
+
+    rc = generic_param_test(&hdr->other_param);
+    if (rc != 0)
+	return rc;
+
+    return 0;
+}
+
+/*
+	"Digest realm=\"realm\", domain=\"sip:domain\", nonce=\"nonce\", "  \
+	        "opaque=\"opaque\", stale=true, algorithm=MD5, qop=\"auth\"",
+ */
+static int hdr_test_proxy_authenticate(pjsip_hdr *h)
+{
+    pjsip_proxy_authenticate_hdr *hdr = (pjsip_proxy_authenticate_hdr*)h;
+
+    if (h->type != PJSIP_H_PROXY_AUTHENTICATE)
+	return -2110;
+
+    if (pj_strcmp2(&hdr->scheme, "Digest"))
+	return -2120;
+
+    if (pj_strcmp2(&hdr->challenge.digest.realm, "realm"))
+	return -2130;
+
+    if (pj_strcmp2(&hdr->challenge.digest.domain, "sip:domain"))
+	return -2140;
+
+    if (pj_strcmp2(&hdr->challenge.digest.nonce, "nonce"))
+	return -2150;
+
+    if (pj_strcmp2(&hdr->challenge.digest.opaque, "opaque"))
+	return -2160;
+
+    if (hdr->challenge.digest.stale != 1)
+	return -2170;
+
+    if (pj_strcmp2(&hdr->challenge.digest.algorithm, "MD5"))
+	return -2180;
+
+    if (pj_strcmp2(&hdr->challenge.digest.qop, "auth"))
+	return -2190;
+
+    return 0;
+}
+
+/*
+    NAME_ADDR GENERIC_PARAM,
+ */
+static int hdr_test_record_route(pjsip_hdr *h)
+{
+    pjsip_rr_hdr *hdr = (pjsip_rr_hdr*)h;
+    int rc;
+
+    if (h->type != PJSIP_H_RECORD_ROUTE)
+	return -2210;
+
+    rc = nameaddr_test(&hdr->name_addr);
+    if (rc != 0)
+	return rc;
+
+    rc = generic_param_test(&hdr->other_param);
+    if (rc != 0)
+	return rc;
+
+    return 0;
+
+}
+
+/*
+    " \r\n"
+ */
+static int hdr_test_supported(pjsip_hdr *h)
+{
+    pjsip_supported_hdr *hdr = (pjsip_supported_hdr*)h;
+
+    if (h->type != PJSIP_H_SUPPORTED)
+	return -2310;
+
+    if (hdr->count != 0)
+	return -2320;
+
+    return 0;
+}
+
+/*
+    NAME_ADDR GENERIC_PARAM,
+ */
+static int hdr_test_to(pjsip_hdr *h)
+{
+    pjsip_to_hdr *hdr = (pjsip_to_hdr*)h;
+    int rc;
+
+    if (h->type != PJSIP_H_TO)
+	return -2410;
+
+    rc = nameaddr_test(hdr->uri);
+    if (rc != 0)
+	return rc;
+
+    rc = generic_param_test(&hdr->other_param);
+    if (rc != 0)
+	return rc;
+
+    return 0;
+}
+
+/*
+    "SIP/2.0 host" GENERIC_PARAM
+ */
+static int hdr_test_via(pjsip_hdr *h)
+{
+    pjsip_via_hdr *hdr = (pjsip_via_hdr*)h;
+    int rc;
+
+    if (h->type != PJSIP_H_VIA)
+	return -2510;
+
+    if (pj_strcmp2(&hdr->transport, "XYZ"))
+	return -2515;
+
+    if (pj_strcmp2(&hdr->sent_by.host, "host"))
+	return -2520;
+
+    if (hdr->sent_by.port != 0)
+	return -2530;
+
+    rc = generic_param_test(&hdr->other_param);
+    if (rc != 0)
+	return rc;
+
+    return 0;
+}
+
+
+/*
+    "SIP/2.0/UDP [::1]"
+ */
+static int hdr_test_via_ipv6_1(pjsip_hdr *h)
+{
+    pjsip_via_hdr *hdr = (pjsip_via_hdr*)h;
+
+    if (h->type != PJSIP_H_VIA)
+	return -2610;
+
+    if (pj_strcmp2(&hdr->transport, "UDP"))
+	return -2615;
+
+    if (pj_strcmp2(&hdr->sent_by.host, "::1"))
+	return -2620;
+
+    if (hdr->sent_by.port != 0)
+	return -2630;
+
+    return 0;
+}
+
+/* "SIP/2.0/UDP [::1]:5061" */
+static int hdr_test_via_ipv6_2(pjsip_hdr *h)
+{
+    pjsip_via_hdr *hdr = (pjsip_via_hdr*)h;
+
+    if (h->type != PJSIP_H_VIA)
+	return -2710;
+
+    if (pj_strcmp2(&hdr->transport, "UDP"))
+	return -2715;
+
+    if (pj_strcmp2(&hdr->sent_by.host, "::1"))
+	return -2720;
+
+    if (hdr->sent_by.port != 5061)
+	return -2730;
+
+    return 0;
+}
+
+/* "SIP/2.0/UDP [::1];rport=5061;received=::2" */
+static int hdr_test_via_ipv6_3(pjsip_hdr *h)
+{
+    pjsip_via_hdr *hdr = (pjsip_via_hdr*)h;
+
+    if (h->type != PJSIP_H_VIA)
+	return -2810;
+
+    if (pj_strcmp2(&hdr->transport, "UDP"))
+	return -2815;
+
+    if (pj_strcmp2(&hdr->sent_by.host, "::1"))
+	return -2820;
+
+    if (hdr->sent_by.port != 0)
+	return -2830;
+
+    if (pj_strcmp2(&hdr->recvd_param, "::2"))
+	return -2840;
+
+    if (hdr->rport_param != 5061)
+	return -2850;
+
+    return 0;
+}
+
+/* "10(Already Pending Register)" */
+static int hdr_test_retry_after1(pjsip_hdr *h)
+{
+    pjsip_retry_after_hdr *hdr = (pjsip_retry_after_hdr*)h;
+
+    if (h->type != PJSIP_H_RETRY_AFTER)
+	return -2910;
+
+    if (hdr->ivalue != 10)
+	return -2920;
+    
+    if (pj_strcmp2(&hdr->comment, "Already Pending Register"))
+	return -2930;
+
+    return 0;
+}
+
+/* Subject: \xC0\x81 */
+static int hdr_test_subject_utf(pjsip_hdr *h)
+{
+    pjsip_subject_hdr *hdr = (pjsip_subject_hdr*)h;
+
+    if (pj_strcmp2(&h->name, "Subject"))
+	return -2950;
+
+    if (pj_strcmp2(&hdr->hvalue, "\xC0\x81"))
+	return -2960;
+
+    return 0;
+}
+
+static int hdr_test(void)
+{
+    unsigned i;
+
+    PJ_LOG(3,(THIS_FILE, "  testing header parsing.."));
+
+    for (i=0; i<PJ_ARRAY_SIZE(hdr_test_data); ++i) {
+	struct hdr_test_t  *test = &hdr_test_data[i];
+	pj_str_t hname;
+	pj_ssize_t len;
+	int parsed_len;
+	pj_pool_t *pool;
+	pjsip_hdr *parsed_hdr1=NULL, *parsed_hdr2=NULL;
+	char *input, *output;
+#if defined(PJSIP_UNESCAPE_IN_PLACE) && PJSIP_UNESCAPE_IN_PLACE!=0
+	static char hcontent[1024];
+#else
+	char *hcontent;
+#endif
+	int rc;
+
+	pool = pjsip_endpt_create_pool(endpt, NULL, POOL_SIZE, POOL_SIZE);
+
+	/* Parse the header */
+	hname = pj_str(test->hname);
+	len = strlen(test->hcontent);
+#if defined(PJSIP_UNESCAPE_IN_PLACE) && PJSIP_UNESCAPE_IN_PLACE!=0
+	PJ_ASSERT_RETURN(len < sizeof(hcontent), PJSIP_EMSGTOOLONG);
+	strcpy(hcontent, test->hcontent);
+#else
+	hcontent = test->hcontent;
+#endif
+	
+	parsed_hdr1 = (pjsip_hdr*) pjsip_parse_hdr(pool, &hname, 
+						   hcontent, len, 
+						   &parsed_len);
+	if (parsed_hdr1 == NULL) {
+	    if (test->flags & HDR_FLAG_PARSE_FAIL) {
+		pj_pool_release(pool);
+		continue;
+	    }
+	    PJ_LOG(3,(THIS_FILE, "    error parsing header %s: %s", test->hname, test->hcontent));
+	    return -500;
+	}
+
+	/* Test the parsing result */
+	if (test->test && (rc=test->test(parsed_hdr1)) != 0) {
+	    PJ_LOG(3,(THIS_FILE, "    validation failed for header %s: %s", test->hname, test->hcontent));
+	    PJ_LOG(3,(THIS_FILE, "    error code is %d", rc));
+	    return -502;
+	}
+
+#if 1
+	/* Parse with hshortname, if present */
+	if (test->hshort_name) {
+	    hname = pj_str(test->hshort_name);
+	    len = strlen(test->hcontent);
+#if defined(PJSIP_UNESCAPE_IN_PLACE) && PJSIP_UNESCAPE_IN_PLACE!=0
+	    PJ_ASSERT_RETURN(len < sizeof(hcontent), PJSIP_EMSGTOOLONG);
+	    strcpy(hcontent, test->hcontent);
+#else
+	    hcontent = test->hcontent;
+#endif
+
+	    parsed_hdr2 = (pjsip_hdr*) pjsip_parse_hdr(pool, &hname, hcontent, len, &parsed_len);
+	    if (parsed_hdr2 == NULL) {
+		PJ_LOG(3,(THIS_FILE, "    error parsing header %s: %s", test->hshort_name, test->hcontent));
+		return -510;
+	    }
+	}
+#endif
+
+	if (test->flags & HDR_FLAG_DONT_PRINT) {
+	    pj_pool_release(pool);
+	    continue;
+	}
+
+	/* Print the original header */
+	input = (char*) pj_pool_alloc(pool, 1024);
+	len = pj_ansi_snprintf(input, 1024, "%s: %s", test->hname, test->hcontent);
+	if (len < 1 || len >= 1024)
+	    return -520;
+
+	/* Print the parsed header*/
+	output = (char*) pj_pool_alloc(pool, 1024);
+	len = pjsip_hdr_print_on(parsed_hdr1, output, 1024);
+	if (len < 0 || len >= 1024) {
+	    PJ_LOG(3,(THIS_FILE, "    header too long: %s: %s", test->hname, test->hcontent));
+	    return -530;
+	}
+	output[len] = 0;
+
+	if (strcmp(input, output) != 0) {
+	    PJ_LOG(3,(THIS_FILE, "    header character by character comparison failed."));
+	    PJ_LOG(3,(THIS_FILE, "    original header=|%s|", input));
+	    PJ_LOG(3,(THIS_FILE, "    parsed header  =|%s|", output));
+	    return -540;
+	}
+
+	pj_pool_release(pool);
+    }
+
+    return 0;
+}
+
+
+/*****************************************************************************/
+
+int msg_test(void)
+{
+    enum { COUNT = 1, DETECT=0, PARSE=1, PRINT=2 };
+    struct {
+	unsigned detect;
+	unsigned parse;
+	unsigned print;
+    } run[COUNT];
+    unsigned i, max, avg_len;
+    char desc[250];
+    pj_status_t status;
+
+    status = hdr_test();
+    if (status != 0)
+	return status;
+
+    status = simple_test();
+    if (status != PJ_SUCCESS)
+	return status;
+
+#if INCLUDE_BENCHMARKS
+    for (i=0; i<COUNT; ++i) {
+	PJ_LOG(3,(THIS_FILE, "  benchmarking (%d of %d)..", i+1, COUNT));
+	status = msg_benchmark(&run[i].detect, &run[i].parse, &run[i].print);
+	if (status != PJ_SUCCESS)
+	    return status;
+    }
+
+    /* Calculate average message length */
+    for (i=0, avg_len=0; i<PJ_ARRAY_SIZE(test_array); ++i) {
+	avg_len += (unsigned)test_array[i].len;
+    }
+    avg_len /= PJ_ARRAY_SIZE(test_array);
+
+
+    /* Print maximum detect/sec */
+    for (i=0, max=0; i<COUNT; ++i)
+	if (run[i].detect > max) max = run[i].detect;
+
+    PJ_LOG(3,("", "  Maximum message detection/sec=%u", max));
+
+    pj_ansi_sprintf(desc, "Number of SIP messages "
+			  "can be pre-parse by <tt>pjsip_find_msg()</tt> "
+			  "per second (tested with %d message sets with "
+			  "average message length of "
+			  "%d bytes)", (int)PJ_ARRAY_SIZE(test_array), avg_len);
+    report_ival("msg-detect-per-sec", max, "msg/sec", desc);
+
+    /* Print maximum parse/sec */
+    for (i=0, max=0; i<COUNT; ++i)
+	if (run[i].parse > max) max = run[i].parse;
+
+    PJ_LOG(3,("", "  Maximum message parsing/sec=%u", max));
+
+    pj_ansi_sprintf(desc, "Number of SIP messages "
+			  "can be <b>parsed</b> by <tt>pjsip_parse_msg()</tt> "
+			  "per second (tested with %d message sets with "
+			  "average message length of "
+			  "%d bytes)", (int)PJ_ARRAY_SIZE(test_array), avg_len);
+    report_ival("msg-parse-per-sec", max, "msg/sec", desc);
+
+    /* Msg parsing bandwidth */
+    report_ival("msg-parse-bandwidth-mb", avg_len*max/1000000, "MB/sec",
+	        "Message parsing bandwidth in megabytes (number of megabytes"
+		" worth of SIP messages that can be parsed per second). "
+		"The value is derived from msg-parse-per-sec above.");
+
+
+    /* Print maximum print/sec */
+    for (i=0, max=0; i<COUNT; ++i)
+	if (run[i].print > max) max = run[i].print;
+
+    PJ_LOG(3,("", "  Maximum message print/sec=%u", max));
+
+    pj_ansi_sprintf(desc, "Number of SIP messages "
+			  "can be <b>printed</b> by <tt>pjsip_msg_print()</tt>"
+			  " per second (tested with %d message sets with "
+			  "average message length of "
+			  "%d bytes)", (int)PJ_ARRAY_SIZE(test_array), avg_len);
+
+    report_ival("msg-print-per-sec", max, "msg/sec", desc);
+
+    /* Msg print bandwidth */
+    report_ival("msg-printed-bandwidth-mb", avg_len*max/1000000, "MB/sec",
+	        "Message print bandwidth in megabytes (total size of "
+		"SIP messages printed per second). "
+		"The value is derived from msg-print-per-sec above.");
+
+#endif	/* INCLUDE_BENCHMARKS */
+
+    return PJ_SUCCESS;
+}
+
+
+
+
diff --git a/jni/pjproject-android/.svn/pristine/ca/cadbc8133cd82b5e17f0d6f65522e7031d2d0810.svn-base b/jni/pjproject-android/.svn/pristine/ca/cadbc8133cd82b5e17f0d6f65522e7031d2d0810.svn-base
new file mode 100644
index 0000000..2ddcc59
--- /dev/null
+++ b/jni/pjproject-android/.svn/pristine/ca/cadbc8133cd82b5e17f0d6f65522e7031d2d0810.svn-base
@@ -0,0 +1,392 @@
+/* $Id$ */
+/* 
+ * Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com)
+ * Copyright (C) 2003-2008 Benny Prijono <benny@prijono.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA 
+ */
+#include <pjlib-util/pcap.h>
+#include <pj/assert.h>
+#include <pj/errno.h>
+#include <pj/file_io.h>
+#include <pj/log.h>
+#include <pj/pool.h>
+#include <pj/sock.h>
+#include <pj/string.h>
+
+#if 0
+#   define TRACE_(x)	PJ_LOG(5,x)
+#else
+#   define TRACE_(x)
+#endif
+
+
+#pragma pack(1)
+
+typedef struct pj_pcap_hdr 
+{
+    pj_uint32_t magic_number;   /* magic number */
+    pj_uint16_t version_major;  /* major version number */
+    pj_uint16_t version_minor;  /* minor version number */
+    pj_int32_t  thiszone;       /* GMT to local correction */
+    pj_uint32_t sigfigs;        /* accuracy of timestamps */
+    pj_uint32_t snaplen;        /* max length of captured packets, in octets */
+    pj_uint32_t network;        /* data link type */
+} pj_pcap_hdr;
+
+typedef struct pj_pcap_rec_hdr 
+{
+    pj_uint32_t ts_sec;         /* timestamp seconds */
+    pj_uint32_t ts_usec;        /* timestamp microseconds */
+    pj_uint32_t incl_len;       /* number of octets of packet saved in file */
+    pj_uint32_t orig_len;       /* actual length of packet */
+} pj_pcap_rec_hdr;
+
+#if 0
+/* gcc insisted on aligning this struct to 32bit on ARM */
+typedef struct pj_pcap_eth_hdr 
+{
+    pj_uint8_t  dest[6];
+    pj_uint8_t  src[6];
+    pj_uint8_t  len[2];
+} pj_pcap_eth_hdr;
+#else
+typedef pj_uint8_t pj_pcap_eth_hdr[14];
+#endif
+
+typedef struct pj_pcap_ip_hdr 
+{
+    pj_uint8_t	v_ihl;
+    pj_uint8_t	tos;
+    pj_uint16_t	len;
+    pj_uint16_t	id;
+    pj_uint16_t	flags_fragment;
+    pj_uint8_t	ttl;
+    pj_uint8_t	proto;
+    pj_uint16_t	csum;
+    pj_uint32_t	ip_src;
+    pj_uint32_t	ip_dst;
+} pj_pcap_ip_hdr;
+
+/* Implementation of pcap file */
+struct pj_pcap_file
+{
+    char	    obj_name[PJ_MAX_OBJ_NAME];
+    pj_oshandle_t   fd;
+    pj_bool_t	    swap;
+    pj_pcap_hdr	    hdr;
+    pj_pcap_filter  filter;
+};
+
+/* Init default filter */
+PJ_DEF(void) pj_pcap_filter_default(pj_pcap_filter *filter)
+{
+    pj_bzero(filter, sizeof(*filter));
+}
+
+/* Open pcap file */
+PJ_DEF(pj_status_t) pj_pcap_open(pj_pool_t *pool,
+				 const char *path,
+				 pj_pcap_file **p_file)
+{
+    pj_pcap_file *file;
+    pj_ssize_t sz;
+    pj_status_t status;
+
+    PJ_ASSERT_RETURN(pool && path && p_file, PJ_EINVAL);
+
+    /* More sanity checks */
+    TRACE_(("pcap", "sizeof(pj_pcap_eth_hdr)=%d",
+	    sizeof(pj_pcap_eth_hdr)));
+    PJ_ASSERT_RETURN(sizeof(pj_pcap_eth_hdr)==14, PJ_EBUG);
+    TRACE_(("pcap", "sizeof(pj_pcap_ip_hdr)=%d",
+	    sizeof(pj_pcap_ip_hdr)));
+    PJ_ASSERT_RETURN(sizeof(pj_pcap_ip_hdr)==20, PJ_EBUG);
+    TRACE_(("pcap", "sizeof(pj_pcap_udp_hdr)=%d",
+	    sizeof(pj_pcap_udp_hdr)));
+    PJ_ASSERT_RETURN(sizeof(pj_pcap_udp_hdr)==8, PJ_EBUG);
+    
+    file = PJ_POOL_ZALLOC_T(pool, pj_pcap_file);
+
+    pj_ansi_strcpy(file->obj_name, "pcap");
+
+    status = pj_file_open(pool, path, PJ_O_RDONLY, &file->fd);
+    if (status != PJ_SUCCESS)
+	return status;
+
+    /* Read file pcap header */
+    sz = sizeof(file->hdr);
+    status = pj_file_read(file->fd, &file->hdr, &sz);
+    if (status != PJ_SUCCESS) {
+	pj_file_close(file->fd);
+	return status;
+    }
+
+    /* Check magic number */
+    if (file->hdr.magic_number == 0xa1b2c3d4) {
+	file->swap = PJ_FALSE;
+    } else if (file->hdr.magic_number == 0xd4c3b2a1) {
+	file->swap = PJ_TRUE;
+	file->hdr.network = pj_ntohl(file->hdr.network);
+    } else {
+	/* Not PCAP file */
+	pj_file_close(file->fd);
+	return PJ_EINVALIDOP;
+    }
+
+    TRACE_((file->obj_name, "PCAP file %s opened", path));
+    
+    *p_file = file;
+    return PJ_SUCCESS;
+}
+
+/* Close pcap file */
+PJ_DEF(pj_status_t) pj_pcap_close(pj_pcap_file *file)
+{
+    PJ_ASSERT_RETURN(file, PJ_EINVAL);
+    TRACE_((file->obj_name, "PCAP file closed"));
+    return pj_file_close(file->fd);
+}
+
+/* Setup filter */
+PJ_DEF(pj_status_t) pj_pcap_set_filter(pj_pcap_file *file,
+				       const pj_pcap_filter *fil)
+{
+    PJ_ASSERT_RETURN(file && fil, PJ_EINVAL);
+    pj_memcpy(&file->filter, fil, sizeof(pj_pcap_filter));
+    return PJ_SUCCESS;
+}
+
+/* Read file */
+static pj_status_t read_file(pj_pcap_file *file,
+			     void *buf,
+			     pj_ssize_t *sz)
+{
+    pj_status_t status;
+    status = pj_file_read(file->fd, buf, sz);
+    if (status != PJ_SUCCESS)
+	return status;
+    if (*sz == 0)
+	return PJ_EEOF;
+    return PJ_SUCCESS;
+}
+
+static pj_status_t skip(pj_oshandle_t fd, pj_off_t bytes)
+{
+    pj_status_t status;
+    status = pj_file_setpos(fd, bytes, PJ_SEEK_CUR);
+    if (status != PJ_SUCCESS)
+	return status; 
+    return PJ_SUCCESS;
+}
+
+
+#define SKIP_PKT()  \
+	if (rec_incl > sz_read) { \
+	    status = skip(file->fd, rec_incl-sz_read);\
+	    if (status != PJ_SUCCESS) \
+		return status; \
+	}
+
+/* Read UDP packet */
+PJ_DEF(pj_status_t) pj_pcap_read_udp(pj_pcap_file *file,
+				     pj_pcap_udp_hdr *udp_hdr,
+				     pj_uint8_t *udp_payload,
+				     pj_size_t *udp_payload_size)
+{
+    PJ_ASSERT_RETURN(file && udp_payload && udp_payload_size, PJ_EINVAL);
+    PJ_ASSERT_RETURN(*udp_payload_size, PJ_EINVAL);
+
+    /* Check data link type in PCAP file header */
+    if ((file->filter.link && 
+	    file->hdr.network != (pj_uint32_t)file->filter.link) ||
+	file->hdr.network != PJ_PCAP_LINK_TYPE_ETH)
+    {
+	/* Link header other than Ethernet is not supported for now */
+	return PJ_ENOTSUP;
+    }
+
+    /* Loop until we have the packet */
+    for (;;) {
+	union {
+	    pj_pcap_rec_hdr rec;
+	    pj_pcap_eth_hdr eth;
+	    pj_pcap_ip_hdr ip;
+	    pj_pcap_udp_hdr udp;
+	} tmp;
+	unsigned rec_incl;
+	pj_ssize_t sz;
+	pj_size_t sz_read = 0;
+	pj_status_t status;
+
+	TRACE_((file->obj_name, "Reading packet.."));
+
+	/* Read PCAP packet header */
+	sz = sizeof(tmp.rec);
+	status = read_file(file, &tmp.rec, &sz); 
+	if (status != PJ_SUCCESS) {
+	    TRACE_((file->obj_name, "read_file() error: %d", status));
+	    return status;
+	}
+
+	rec_incl = tmp.rec.incl_len;
+
+	/* Swap byte ordering */
+	if (file->swap) {
+	    tmp.rec.incl_len = pj_ntohl(tmp.rec.incl_len);
+	    tmp.rec.orig_len = pj_ntohl(tmp.rec.orig_len);
+	    tmp.rec.ts_sec = pj_ntohl(tmp.rec.ts_sec);
+	    tmp.rec.ts_usec = pj_ntohl(tmp.rec.ts_usec);
+	}
+
+	/* Read link layer header */
+	switch (file->hdr.network) {
+	case PJ_PCAP_LINK_TYPE_ETH:
+	    sz = sizeof(tmp.eth);
+	    status = read_file(file, &tmp.eth, &sz);
+	    break;
+	default:
+	    TRACE_((file->obj_name, "Error: link layer not Ethernet"));
+	    return PJ_ENOTSUP;
+	}
+
+	if (status != PJ_SUCCESS) {
+	    TRACE_((file->obj_name, "Error reading Eth header: %d", status));
+	    return status;
+	}
+
+	sz_read += sz;
+	    
+	/* Read IP header */
+	sz = sizeof(tmp.ip);
+	status = read_file(file, &tmp.ip, &sz);
+	if (status != PJ_SUCCESS) {
+	    TRACE_((file->obj_name, "Error reading IP header: %d", status));
+	    return status;
+	}
+
+	sz_read += sz;
+
+	/* Skip if IP source mismatch */
+	if (file->filter.ip_src && tmp.ip.ip_src != file->filter.ip_src) {
+	    TRACE_((file->obj_name, "IP source %s mismatch, skipping", 
+		    pj_inet_ntoa(*(pj_in_addr*)&tmp.ip.ip_src)));
+	    SKIP_PKT();
+	    continue;
+	}
+
+	/* Skip if IP destination mismatch */
+	if (file->filter.ip_dst && tmp.ip.ip_dst != file->filter.ip_dst) {
+	    TRACE_((file->obj_name, "IP detination %s mismatch, skipping", 
+		    pj_inet_ntoa(*(pj_in_addr*)&tmp.ip.ip_dst)));
+	    SKIP_PKT();
+	    continue;
+	}
+
+	/* Skip if proto mismatch */
+	if (file->filter.proto && tmp.ip.proto != file->filter.proto) {
+	    TRACE_((file->obj_name, "IP proto %d mismatch, skipping", 
+		    tmp.ip.proto));
+	    SKIP_PKT();
+	    continue;
+	}
+
+	/* Read transport layer header */
+	switch (tmp.ip.proto) {
+	case PJ_PCAP_PROTO_TYPE_UDP:
+	    sz = sizeof(tmp.udp);
+	    status = read_file(file, &tmp.udp, &sz);
+	    if (status != PJ_SUCCESS) {
+		TRACE_((file->obj_name, "Error reading UDP header: %d",status));
+		return status;
+	    }
+
+	    sz_read += sz;
+
+	    /* Skip if source port mismatch */
+	    if (file->filter.src_port && 
+	        tmp.udp.src_port != file->filter.src_port) 
+	    {
+		TRACE_((file->obj_name, "UDP src port %d mismatch, skipping", 
+			pj_ntohs(tmp.udp.src_port)));
+		SKIP_PKT();
+		continue;
+	    }
+
+	    /* Skip if destination port mismatch */
+	    if (file->filter.dst_port && 
+		tmp.udp.dst_port != file->filter.dst_port) 
+	    {
+		TRACE_((file->obj_name, "UDP dst port %d mismatch, skipping", 
+			pj_ntohs(tmp.udp.dst_port)));
+		SKIP_PKT();
+		continue;
+	    }
+
+	    /* Copy UDP header if caller wants it */
+	    if (udp_hdr) {
+		pj_memcpy(udp_hdr, &tmp.udp, sizeof(*udp_hdr));
+	    }
+
+	    /* Calculate payload size */
+	    sz = pj_ntohs(tmp.udp.len) - sizeof(tmp.udp);
+	    break;
+	default:
+	    TRACE_((file->obj_name, "Not UDP, skipping"));
+	    SKIP_PKT();
+	    continue;
+	}
+
+	/* Check if payload fits the buffer */
+	if (sz > (pj_ssize_t)*udp_payload_size) {
+	    TRACE_((file->obj_name, 
+		    "Error: packet too large (%d bytes required)", sz));
+	    SKIP_PKT();
+	    return PJ_ETOOSMALL;
+	}
+
+	/* Read the payload */
+	status = read_file(file, udp_payload, &sz);
+	if (status != PJ_SUCCESS) {
+	    TRACE_((file->obj_name, "Error reading payload: %d", status));
+	    return status;
+	}
+
+	sz_read += sz;
+
+	*udp_payload_size = sz;
+
+	// Some layers may have trailer, e.g: link eth2.
+	/* Check that we've read all the packets */
+	//PJ_ASSERT_RETURN(sz_read == rec_incl, PJ_EBUG);
+
+	/* Skip trailer */
+	while (sz_read < rec_incl) {
+	    sz = rec_incl - sz_read;
+	    status = read_file(file, &tmp.eth, &sz);
+	    if (status != PJ_SUCCESS) {
+		TRACE_((file->obj_name, "Error reading trailer: %d", status));
+		return status;
+	    }
+	    sz_read += sz;
+	}
+
+	return PJ_SUCCESS;
+    }
+
+    /* Does not reach here */
+}
+
+