Index: pjproject/branches/projects/pjsua2/pjsip/build/Makefile
===================================================================
--- pjproject/branches/projects/pjsua2/pjsip/build/Makefile	(revision 4643)
+++ pjproject/branches/projects/pjsua2/pjsip/build/Makefile	(revision 4644)
@@ -90,5 +90,6 @@
 export PJSUA2_LIB_SRCDIR = ../src/pjsua2
 export PJSUA2_LIB_OBJS += $(OS_OBJS) $(M_OBJS) $(CC_OBJS) $(HOST_OBJS) \
-			   account.o endpoint.o types.o
+			   account.o endpoint.o json.o persistent.o types.o \
+			   siptypes.o
 export PJSUA2_LIB_CFLAGS += $(_CFLAGS) $(PJ_VIDEO_CFLAGS)
 export PJSUA2_LIB_CXXFLAGS = $(PJSUA2_LIB_CFLAGS) 
Index: pjproject/branches/projects/pjsua2/pjsip/include/pjsua2.hpp
===================================================================
--- pjproject/branches/projects/pjsua2/pjsip/include/pjsua2.hpp	(revision 4643)
+++ pjproject/branches/projects/pjsua2/pjsip/include/pjsua2.hpp	(revision 4644)
@@ -22,4 +22,5 @@
 #include <pjsua2/endpoint.hpp>
 #include <pjsua2/account.hpp>
+#include <pjsua2/json.hpp>
 
 #endif
Index: pjproject/branches/projects/pjsua2/pjsip/include/pjsua2/account.hpp
===================================================================
--- pjproject/branches/projects/pjsua2/pjsip/include/pjsua2/account.hpp	(revision 4643)
+++ pjproject/branches/projects/pjsua2/pjsip/include/pjsua2/account.hpp	(revision 4644)
@@ -1,5 +1,5 @@
 /* $Id$ */
 /*
- * Copyright (C) 2008-2012 Teluu Inc. (http://www.teluu.com)
+ * Copyright (C) 2013 Teluu Inc. (http://www.teluu.com)
  *
  * This program is free software; you can redistribute it and/or modify
@@ -25,5 +25,6 @@
  */
 #include <pjsua-lib/pjsua.h>
-#include <pjsua2/types.hpp>
+#include <pjsua2/persistent.hpp>
+#include <pjsua2/siptypes.hpp>
 
 /**
@@ -46,5 +47,5 @@
  * Account registration config. This will be specified in AccountConfig.
  */
-struct AccountRegConfig
+struct AccountRegConfig : public PersistentObject
 {
     /**
@@ -138,4 +139,20 @@
      */
     unsigned		proxyUse;
+
+public:
+    /**
+     * Read this object from a container node.
+     *
+     * @param node		Container to read values from.
+     */
+    virtual void readObject(const ContainerNode &node) throw(Error);
+
+    /**
+     * Write this object to a container node.
+     *
+     * @param node		Container to write values to.
+     */
+    virtual void writeObject(ContainerNode &node) const throw(Error);
+
 };
 
@@ -147,5 +164,5 @@
  * AccountConfig.
  */
-struct AccountSipConfig
+struct AccountSipConfig : public PersistentObject
 {
     /**
@@ -221,4 +238,19 @@
      */
     TransportId		transportId;
+
+public:
+    /**
+     * Read this object from a container node.
+     *
+     * @param node		Container to read values from.
+     */
+    virtual void readObject(const ContainerNode &node) throw(Error);
+
+    /**
+     * Write this object to a container node.
+     *
+     * @param node		Container to write values to.
+     */
+    virtual void writeObject(ContainerNode &node) const throw(Error);
 };
 
@@ -226,5 +258,5 @@
  * Account's call settings. This will be specified in AccountConfig.
  */
-struct AccountCallConfig
+struct AccountCallConfig : public PersistentObject
 {
     /**
@@ -265,4 +297,18 @@
     unsigned		timerSessExpiresSec;
 
+public:
+    /**
+     * Read this object from a container node.
+     *
+     * @param node		Container to read values from.
+     */
+    virtual void readObject(const ContainerNode &node) throw(Error);
+
+    /**
+     * Write this object to a container node.
+     *
+     * @param node		Container to write values to.
+     */
+    virtual void writeObject(ContainerNode &node) const throw(Error);
 };
 
@@ -270,5 +316,5 @@
  * Account presence config. This will be specified in AccountConfig.
  */
-struct AccountPresConfig
+struct AccountPresConfig : public PersistentObject
 {
     /**
@@ -317,4 +363,19 @@
      */
     string		pidfTupleId;
+
+public:
+    /**
+     * Read this object from a container node.
+     *
+     * @param node		Container to read values from.
+     */
+    virtual void readObject(const ContainerNode &node) throw(Error);
+
+    /**
+     * Write this object to a container node.
+     *
+     * @param node		Container to write values to.
+     */
+    virtual void writeObject(ContainerNode &node) const throw(Error);
 };
 
@@ -323,5 +384,5 @@
  * in AccountConfig.
  */
-struct AccountMwiConfig
+struct AccountMwiConfig : public PersistentObject
 {
     /**
@@ -342,4 +403,19 @@
      */
     unsigned		expirationSec;
+
+public:
+    /**
+     * Read this object from a container node.
+     *
+     * @param node		Container to read values from.
+     */
+    virtual void readObject(const ContainerNode &node) throw(Error);
+
+    /**
+     * Write this object to a container node.
+     *
+     * @param node		Container to write values to.
+     */
+    virtual void writeObject(ContainerNode &node) const throw(Error);
 };
 
@@ -348,5 +424,5 @@
  * specified in AccountConfig.
  */
-struct AccountNatConfig
+struct AccountNatConfig : public PersistentObject
 {
     /**
@@ -561,4 +637,19 @@
      */
     string		udpKaData;
+
+public:
+    /**
+     * Read this object from a container node.
+     *
+     * @param node		Container to read values from.
+     */
+    virtual void readObject(const ContainerNode &node) throw(Error);
+
+    /**
+     * Write this object to a container node.
+     *
+     * @param node		Container to write values to.
+     */
+    virtual void writeObject(ContainerNode &node) const throw(Error);
 };
 
@@ -567,5 +658,5 @@
  * specified in AccountConfig.
  */
-struct AccountMediaConfig
+struct AccountMediaConfig : public PersistentObject
 {
     /**
@@ -618,4 +709,19 @@
      */
     pjsua_ipv6_use	ipv6Use;
+
+public:
+    /**
+     * Read this object from a container node.
+     *
+     * @param node		Container to read values from.
+     */
+    virtual void readObject(const ContainerNode &node) throw(Error);
+
+    /**
+     * Write this object to a container node.
+     *
+     * @param node		Container to write values to.
+     */
+    virtual void writeObject(ContainerNode &node) const throw(Error);
 };
 
@@ -623,5 +729,5 @@
  * Account video config. This will be specified in AccountConfig.
  */
-struct AccountVideoConfig
+struct AccountVideoConfig : public PersistentObject
 {
     /**
@@ -694,4 +800,19 @@
      */
     unsigned			rateControlBandwidth;
+
+public:
+    /**
+     * Read this object from a container node.
+     *
+     * @param node		Container to read values from.
+     */
+    virtual void readObject(const ContainerNode &node) throw(Error);
+
+    /**
+     * Write this object to a container node.
+     *
+     * @param node		Container to write values to.
+     */
+    virtual void writeObject(ContainerNode &node) const throw(Error);
 };
 
@@ -699,5 +820,5 @@
  * Account configuration.
  */
-struct AccountConfig
+struct AccountConfig : public PersistentObject
 {
     /**
@@ -777,4 +898,17 @@
     void fromPj(const pjsua_acc_config &prm, const pjsua_media_config *mcfg);
 
+    /**
+     * Read this object from a container node.
+     *
+     * @param node		Container to read values from.
+     */
+    virtual void readObject(const ContainerNode &node) throw(Error);
+
+    /**
+     * Write this object to a container node.
+     *
+     * @param node		Container to write values to.
+     */
+    virtual void writeObject(ContainerNode &node) const throw(Error);
 };
 
Index: pjproject/branches/projects/pjsua2/pjsip/include/pjsua2/config.hpp
===================================================================
--- pjproject/branches/projects/pjsua2/pjsip/include/pjsua2/config.hpp	(revision 4643)
+++ pjproject/branches/projects/pjsua2/pjsip/include/pjsua2/config.hpp	(revision 4644)
@@ -1,5 +1,5 @@
 /* $Id$ */
 /*
- * Copyright (C) 2008-2012 Teluu Inc. (http://www.teluu.com)
+ * Copyright (C) 2013 Teluu Inc. (http://www.teluu.com)
  *
  * This program is free software; you can redistribute it and/or modify
Index: pjproject/branches/projects/pjsua2/pjsip/include/pjsua2/endpoint.hpp
===================================================================
--- pjproject/branches/projects/pjsua2/pjsip/include/pjsua2/endpoint.hpp	(revision 4643)
+++ pjproject/branches/projects/pjsua2/pjsip/include/pjsua2/endpoint.hpp	(revision 4644)
@@ -1,5 +1,5 @@
 /* $Id$ */
 /* 
- * Copyright (C) 2008-2012 Teluu Inc. (http://www.teluu.com)
+ * Copyright (C) 2013 Teluu Inc. (http://www.teluu.com)
  *
  * This program is free software; you can redistribute it and/or modify
@@ -24,5 +24,6 @@
  * @brief PJSUA2 Base Agent Operation
  */
-#include <pjsua2/types.hpp>
+#include <pjsua2/persistent.hpp>
+#include <pjsua2/siptypes.hpp>
 
 /** PJSUA2 API is inside pj namespace */
@@ -162,5 +163,5 @@
 //////////////////////////////////////////////////////////////////////////////
 
-struct UaConfig
+struct UaConfig : public PersistentObject
 {
     /**
@@ -265,4 +266,19 @@
      */
     pjsua_config toPj() const;
+
+    /**
+     * Read this object from a container.
+     *
+     * @param node		Container to write values from.
+     */
+    virtual void readObject(const ContainerNode &node) throw(Error);
+
+    /**
+     * Write this object to a container.
+     *
+     * @param node		Container to write values to.
+     */
+    virtual void writeObject(ContainerNode &node) const throw(Error);
+
 };
 
@@ -307,5 +323,5 @@
  * Lib::init().
  */
-struct LogConfig
+struct LogConfig : public PersistentObject
 {
     /** Log incoming and outgoing SIP message? Yes!  */
@@ -350,4 +366,18 @@
     /** Generate pjsua_logging_config. */
     pjsua_logging_config toPj() const;
+
+    /**
+     * Read this object from a container.
+     *
+     * @param node		Container to write values from.
+     */
+    virtual void readObject(const ContainerNode &node) throw(Error);
+
+    /**
+     * Write this object to a container.
+     *
+     * @param node		Container to write values to.
+     */
+    virtual void writeObject(ContainerNode &node) const throw(Error);
 };
 
@@ -357,5 +387,5 @@
  * when calling Lib::init().
  */
-struct MediaConfig
+struct MediaConfig : public PersistentObject
 {
 public:
@@ -555,4 +585,18 @@
     /** Export */
     pjsua_media_config toPj() const;
+
+    /**
+     * Read this object from a container.
+     *
+     * @param node		Container to write values from.
+     */
+    virtual void readObject(const ContainerNode &node) throw(Error);
+
+    /**
+     * Write this object to a container.
+     *
+     * @param node		Container to write values to.
+     */
+    virtual void writeObject(ContainerNode &node) const throw(Error);
 };
 
@@ -561,5 +605,5 @@
  * Endpoint configuration
  */
-struct EpConfig
+struct EpConfig : public PersistentObject
 {
     /** UA config */
@@ -571,4 +615,19 @@
     /** Media config */
     MediaConfig		medConfig;
+
+    /**
+     * Read this object from a container.
+     *
+     * @param node		Container to write values from.
+     */
+    virtual void readObject(const ContainerNode &node) throw(Error);
+
+    /**
+     * Write this object to a container.
+     *
+     * @param node		Container to write values to.
+     */
+    virtual void writeObject(ContainerNode &node) const throw(Error);
+
 };
 
Index: pjproject/branches/projects/pjsua2/pjsip/include/pjsua2/json.hpp
===================================================================
--- pjproject/branches/projects/pjsua2/pjsip/include/pjsua2/json.hpp	(revision 4644)
+++ pjproject/branches/projects/pjsua2/pjsip/include/pjsua2/json.hpp	(revision 4644)
@@ -0,0 +1,114 @@
+/* $Id$ */
+/*
+ * Copyright (C) 2013 Teluu Inc. (http://www.teluu.com)
+ *
+ * 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 __PJSUA2_JSON_HPP__
+#define __PJSUA2_JSON_HPP__
+
+/**
+ * @file pjsua2/persistent.hpp
+ * @brief PJSUA2 Persistent Services
+ */
+#include <pjsua2/persistent.hpp>
+#include <pjlib-util/json.h>
+#include <pj/pool.h>
+#include <string>
+
+/**
+ * @defgroup PJSUA2_JSON JSON Persistent Support
+ * @ingroup PJSUA2_PERSISTENT
+ * @{
+ * Provides object serialization and deserialization to/from JSON document.
+ */
+
+/** PJSUA2 API is inside pj namespace */
+namespace pj
+{
+using std::string;
+
+
+class JsonDocument : public PersistentDocument
+{
+public:
+    /** Default constructor */
+    JsonDocument();
+
+    /** Destructor */
+    ~JsonDocument();
+
+    /**
+     * Load this document from a file.
+     *
+     * @param filename		The file name.
+     */
+    virtual void   loadFile(const string &filename) throw(Error);
+
+    /**
+     * Load this document from string.
+     *
+     * @param input		The string.
+     */
+    virtual void   loadString(const string &input) throw(Error);
+
+    /**
+     * Write this document to a file.
+     *
+     * @param filename		The file name.
+     */
+    virtual void   saveFile(const string &filename) throw(Error);
+
+    /**
+     * Write this document to string.
+     */
+    virtual string saveString() throw(Error);
+
+    /**
+     * Get the root container node for this document
+     */
+    virtual ContainerNode & getRootContainer() const;
+
+    /**
+     * An internal function to create JSON element.
+     */
+    pj_json_elem*    allocElement() const;
+
+    /**
+     * An internal function to get the pool.
+     */
+    pj_pool_t*	     getPool();
+
+private:
+    pj_caching_pool	  cp;
+    mutable ContainerNode rootNode;
+    mutable pj_json_elem *root;
+    mutable pj_pool_t	 *pool;
+
+    void initRoot() const;
+};
+
+
+
+
+} // namespace pj
+
+/**
+ * @}  PJSUA2
+ */
+
+
+
+#endif	/* __PJSUA2_JSON_HPP__ */
Index: pjproject/branches/projects/pjsua2/pjsip/include/pjsua2/persistent.hpp
===================================================================
--- pjproject/branches/projects/pjsua2/pjsip/include/pjsua2/persistent.hpp	(revision 4644)
+++ pjproject/branches/projects/pjsua2/pjsip/include/pjsua2/persistent.hpp	(revision 4644)
@@ -0,0 +1,679 @@
+/* $Id$ */
+/*
+ * Copyright (C) 2013 Teluu Inc. (http://www.teluu.com)
+ *
+ * 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 __PJSUA2_PERSISTENT_HPP__
+#define __PJSUA2_PERSISTENT_HPP__
+
+/**
+ * @file pjsua2/persistent.hpp
+ * @brief PJSUA2 Persistent Services
+ */
+#include <pjsua2/types.hpp>
+
+#include <string>
+#include <vector>
+
+/**
+ * @defgroup PJSUA2_PERSISTENT Persistent API
+ * @ingroup PJSUA2_Ref
+ * @{
+ * The persistent API provides functionality to read/write data from/to
+ * a document (string or file). The data can be simple data types such
+ * as boolean, number, string, and string arrays, or a user defined object.
+ * Currently the implementation supports reading and writing from/to JSON
+ * document, but the framework allows application to extend the API to
+ * support other document formats.
+ */
+
+/** PJSUA2 API is inside pj namespace */
+namespace pj
+{
+using std::string;
+using std::vector;
+
+/* Forward declaration for ContainerNode */
+class ContainerNode;
+
+/**
+ * This is the abstract base class of objects that can be serialized to/from
+ * persistent document.
+ */
+class PersistentObject
+{
+public:
+    /**
+     * Read this object from a container node.
+     *
+     * @param node		Container to read values from.
+     */
+    virtual void readObject(const ContainerNode &node) throw(Error) = 0;
+
+    /**
+     * Write this object to a container node.
+     *
+     * @param node		Container to write values to.
+     */
+    virtual void writeObject(ContainerNode &node) const throw(Error) = 0;
+};
+
+
+/**
+ * This a the abstract base class for a persistent document. A document
+ * is created either by loading from a string or a file, or by constructing
+ * it manually when writing data to it. The document then can be saved
+ * to either string or to a file. A document contains one root ContainerNode
+ * where all data are stored under.
+ *
+ * Document is read and written serially, hence the order of reading must be
+ * the same as the order of writing. The PersistentDocument class provides
+ * API to read and write to the root node, but for more flexible operations
+ * application can use the ContainerNode methods instead. Indeed the read
+ * and write API in PersistentDocument is just a shorthand which calls the
+ * relevant methods in the ContainerNode. As a tip, normally application only
+ * uses the readObject() and writeObject() methods declared here to read/write
+ * top level objects, and use the macros that are explained in ContainerNode
+ * documentation to read/write more detailed data.
+ */
+class PersistentDocument
+{
+public:
+    /**
+     * Virtual destructor
+     */
+    virtual ~PersistentDocument()
+    {}
+
+    /**
+     * Load this document from a file.
+     *
+     * @param filename	The file name.
+     */
+    virtual void   	loadFile(const string &filename) throw(Error) = 0;
+
+    /**
+     * Load this document from string.
+     *
+     * @param input	The string.
+     */
+    virtual void   	loadString(const string &input) throw(Error) = 0;
+
+    /**
+     * Write this document to a file.
+     *
+     * @param filename	The file name.
+     */
+    virtual void   	saveFile(const string &filename) throw(Error) = 0;
+
+    /**
+     * Write this document to string.
+     *
+     * @return		The string document.
+     */
+    virtual string 	saveString() throw(Error) = 0;
+
+    /**
+     * Get the root container node for this document
+     *
+     * @return		The root node.
+     */
+    virtual ContainerNode & getRootContainer() const = 0;
+
+
+    /*
+     * Shorthand functions for reading and writing from/to the root container
+     */
+
+
+    /**
+     * Determine if there is unread element. If yes, then app can use one of
+     * the readXxx() functions to read it.
+     *
+     * @return		True if there is.
+     */
+    bool		hasUnread() const;
+
+    /**
+     * Get the name of the next unread element. It will throw Error if there
+     * is no more element to read.
+     *
+     * @return		The name of the next element .
+     */
+    string		unreadName() const throw(Error);
+
+    /**
+     * Read an integer value from the document and return the value.
+     * This will throw Error if the current element is not a number.
+     * The read position will be advanced to the next element.
+     *
+     * @param name	If specified, then the function will check if the
+     * 			name of the next element matches the specified
+     * 			name and throw Error if it doesn't match.
+     *
+     * @return		The value.
+     */
+    int			readInt(const string &name="") const throw(Error);
+
+    /**
+     * Read a float value from the document and return the value.
+     * This will throw Error if the current element is not a number.
+     * The read position will be advanced to the next element.
+     *
+     * @param name	If specified, then the function will check if the
+     * 			name of the next element matches the specified
+     * 			name and throw Error if it doesn't match.
+     *
+     * @return		The value.
+     */
+    float		readNumber(const string &name="") const throw(Error);
+
+    /**
+     * Read a boolean value from the container and return the value.
+     * This will throw Error if the current element is not a boolean.
+     * The read position will be advanced to the next element.
+     *
+     * @param name	If specified, then the function will check if the
+     * 			name of the next element matches the specified
+     * 			name and throw Error if it doesn't match.
+     *
+     * @return		The value.
+     */
+    bool		readBool(const string &name="") const throw(Error);
+
+    /**
+     * Read a string value from the container and return the value.
+     * This will throw Error if the current element is not a string.
+     * The read position will be advanced to the next element.
+     *
+     * @param name	If specified, then the function will check if the
+     * 			name of the next element matches the specified
+     * 			name and throw Error if it doesn't match.
+     *
+     * @return		The value.
+     */
+    string		readString(const string &name="") const throw(Error);
+
+    /**
+     * Read a string array from the container. This will throw Error
+     * if the current element is not a string array. The read position
+     * will be advanced to the next element.
+     *
+     * @param name	If specified, then the function will check if the
+     * 			name of the next element matches the specified
+     * 			name and throw Error if it doesn't match.
+     *
+     * @return		The value.
+     */
+    StringVector	readStringVector(const string &name="") const
+					 throw(Error);
+
+    /**
+     * Read the specified object from the container. This is equal to
+     * calling PersistentObject.readObject(ContainerNode);
+     *
+     * @param obj	The object to read.
+     */
+    void		readObject(PersistentObject &obj) const throw(Error);
+
+    /**
+     * Read a container from the container. This will throw Error if the
+     * current element is not an object. The read position will be advanced
+     * to the next element.
+     *
+     * @param name	If specified, then the function will check if the
+     * 			name of the next element matches the specified
+     * 			name and throw Error if it doesn't match.
+     *
+     * @return		Container object.
+     */
+    ContainerNode	readContainer(const string &name="") const
+				      throw(Error);
+
+    /**
+     * Read array container from the container. This will throw Error if the
+     * current element is not an array. The read position will be advanced
+     * to the next element.
+     *
+     * @param name	If specified, then the function will check if the
+     * 			name of the next element matches the specified
+     * 			name and throw Error if it doesn't match.
+     *
+     * @return		Container object.
+     */
+    ContainerNode	readArray(const string &name="") const
+				  throw(Error);
+
+    /**
+     * Write a number value to the container.
+     *
+     * @param name	The name for the value in the container.
+     * @param value	The value to be written.
+     */
+    void		writeNumber(const string &name,
+        		            float num) throw(Error);
+
+    /**
+     * Write a number value to the container.
+     *
+     * @param name	The name for the value in the container.
+     * @param value	The value to be written.
+     */
+    void		writeInt(const string &name,
+        		         int num) throw(Error);
+
+    /**
+     * Write a boolean value to the container.
+     *
+     * @param name	The name for the value in the container.
+     * @param value	The value to be written.
+     */
+    void		writeBool(const string &name,
+        		          bool value) throw(Error);
+
+    /**
+     * Write a string value to the container.
+     *
+     * @param name	The name for the value in the container.
+     * @param value	The value to be written.
+     */
+    void		writeString(const string &name,
+        		            const string &value) throw(Error);
+
+    /**
+     * Write string vector to the container.
+     *
+     * @param name	The name for the value in the container.
+     * @param array	The vector to be written.
+     */
+    void		writeStringVector(const string &name,
+        		                  const StringVector &value)
+					  throw(Error);
+
+    /**
+     * Write an object to the container. This is equal to calling
+     * PersistentObject.writeObject(ContainerNode);
+     *
+     * @param obj	The object to be written
+     */
+    void		writeObject(const PersistentObject &obj) throw(Error);
+
+    /**
+     * Create and write an empty Object node that can be used as parent
+     * for subsequent write operations.
+     *
+     * @param name	The name for the new container in the container.
+     *
+     * @return		A sub-container.
+     */
+    ContainerNode 	writeNewContainer(const string &name)
+					  throw(Error);
+
+    /**
+     * Create and write an empty array node that can be used as parent
+     * for subsequent write operations.
+     *
+     * @param name	The name for the array.
+     *
+     * @return		A sub-container.
+     */
+    ContainerNode 	writeNewArray(const string &name)
+				      throw(Error);
+};
+
+/**
+ * Pointer to actual ContainerNode implementation. See ContainerNode
+ * implementation notes for more info.
+ */
+struct container_node_op
+{
+    bool		(*hasUnread)(const ContainerNode*);
+    string		(*unreadName)(const ContainerNode*)
+				      throw(Error);
+    float		(*readNumber)(const ContainerNode*,
+				      const string&)
+				      throw(Error);
+    bool		(*readBool)(const ContainerNode*,
+				    const string&)
+				    throw(Error);
+    string		(*readString)(const ContainerNode*,
+				      const string&)
+				      throw(Error);
+    StringVector	(*readStringVector)(const ContainerNode*,
+					    const string&)
+					    throw(Error);
+    ContainerNode	(*readContainer)(const ContainerNode*,
+					 const string &)
+					 throw(Error);
+    ContainerNode	(*readArray)(const ContainerNode*,
+				     const string &)
+				     throw(Error);
+    void		(*writeNumber)(ContainerNode*,
+				       const string &name,
+        		               float num)
+        		               throw(Error);
+    void		(*writeBool)(ContainerNode*,
+				     const string &name,
+        			     bool value)
+        			     throw(Error);
+    void		(*writeString)(ContainerNode*,
+				       const string &name,
+        			       const string &value)
+        			       throw(Error);
+    void		(*writeStringVector)(ContainerNode*,
+					     const string &name,
+        				     const StringVector &value)
+					     throw(Error);
+    ContainerNode 	(*writeNewContainer)(ContainerNode*,
+					     const string &name)
+					     throw(Error);
+    ContainerNode 	(*writeNewArray)(ContainerNode*,
+				         const string &name)
+					 throw(Error);
+
+};
+
+/**
+ * Internal data for ContainerNode. See ContainerNode implementation notes
+ * for more info.
+ */
+struct container_node_internal_data
+{
+    void	*doc;
+    void	*data1;
+    void	*data2;
+};
+
+/**
+ * A container node is a placeholder for storing other data elements, which
+ * could be boolean, number, string, array of strings, or another container.
+ * Each data in the container is basically a name/value pair, with a type
+ * internally associated with it so that written data can be read in the
+ * correct type. Data is read and written serially, hence the order of
+ * reading must be the same as the order of writing.
+ *
+ * Application can read data from it by using the various read methods, and
+ * write data to it using the various write methods. Alternatively, it
+ * may be more convenient to use the provided macros below to read and write
+ * the data, because these macros set the name automatically:
+ *	- NODE_READ_BOOL(node,item)
+ *	- NODE_READ_UNSIGNED(node,item)
+ *	- NODE_READ_INT(node,item)
+ *	- NODE_READ_FLOAT(node,item)
+ *	- NODE_READ_NUM_T(node,type,item)
+ *	- NODE_READ_STRING(node,item)
+ *	- NODE_READ_STRINGV(node,item)
+ *	- NODE_READ_OBJ(node,item)
+ *	- NODE_WRITE_BOOL(node,item)
+ *	- NODE_WRITE_UNSIGNED(node,item)
+ *	- NODE_WRITE_INT(node,item)
+ *	- NODE_WRITE_FLOAT(node,item)
+ *	- NODE_WRITE_NUM_T(node,type,item)
+ *	- NODE_WRITE_STRING(node,item)
+ *	- NODE_WRITE_STRINGV(node,item)
+ *	- NODE_WRITE_OBJ(node,item)
+ *
+ * Implementation notes:
+ *
+ * The ContainerNode class is subclass-able, but not in the usual C++ way.
+ * With the usual C++ inheritance, some methods will be made pure virtual
+ * and must be implemented by the actual class. However, doing so will
+ * require dynamic instantiation of the ContainerNode class, which means
+ * we will need to pass around the class as pointer, for example as the
+ * return value of readContainer() and writeNewContainer() methods. Then
+ * we will need to establish who needs or how to delete these objects, or
+ * use shared pointer mechanism, each of which is considered too inconvenient
+ * or complicated for the purpose.
+ *
+ * So hence we use C style "inheritance", where the methods are declared in
+ * container_node_op and the data in container_node_internal_data structures.
+ * An implementation of ContainerNode class will need to set up these members
+ * with values that makes sense to itself. The methods in container_node_op
+ * contains the pointer to the actual implementation of the operation, which
+ * would be specific according to the format of the document. The methods in
+ * this ContainerNode class are just thin wrappers which call the
+ * implementation in the container_node_op structure.
+ *
+ */
+class ContainerNode
+{
+public:
+    /**
+     * Determine if there is unread element. If yes, then app can use one of
+     * the readXxx() functions to read it.
+     */
+    bool		hasUnread() const;
+
+    /**
+     * Get the name of the next unread element.
+     */
+    string		unreadName() const throw(Error);
+
+    /**
+     * Read an integer value from the document and return the value.
+     * This will throw Error if the current element is not a number.
+     * The read position will be advanced to the next element.
+     *
+     * @param name	If specified, then the function will check if the
+     * 			name of the next element matches the specified
+     * 			name and throw Error if it doesn't match.
+     *
+     * @return		The value.
+     */
+    int			readInt(const string &name="") const throw(Error);
+
+    /**
+     * Read a number value from the document and return the value.
+     * This will throw Error if the current element is not a number.
+     * The read position will be advanced to the next element.
+     *
+     * @param name	If specified, then the function will check if the
+     * 			name of the next element matches the specified
+     * 			name and throw Error if it doesn't match.
+     *
+     * @return		The value.
+     */
+    float		readNumber(const string &name="") const throw(Error);
+
+    /**
+     * Read a boolean value from the container and return the value.
+     * This will throw Error if the current element is not a boolean.
+     * The read position will be advanced to the next element.
+     *
+     * @param name	If specified, then the function will check if the
+     * 			name of the next element matches the specified
+     * 			name and throw Error if it doesn't match.
+     *
+     * @return		The value.
+     */
+    bool		readBool(const string &name="") const throw(Error);
+
+    /**
+     * Read a string value from the container and return the value.
+     * This will throw Error if the current element is not a string.
+     * The read position will be advanced to the next element.
+     *
+     * @param name	If specified, then the function will check if the
+     * 			name of the next element matches the specified
+     * 			name and throw Error if it doesn't match.
+     *
+     * @return		The value.
+     */
+    string		readString(const string &name="") const throw(Error);
+
+    /**
+     * Read a string array from the container. This will throw Error
+     * if the current element is not a string array. The read position
+     * will be advanced to the next element.
+     *
+     * @param name	If specified, then the function will check if the
+     * 			name of the next element matches the specified
+     * 			name and throw Error if it doesn't match.
+     *
+     * @return		The value.
+     */
+    StringVector	readStringVector(const string &name="") const
+					 throw(Error);
+
+    /**
+     * Read the specified object from the container. This is equal to
+     * calling PersistentObject.readObject(ContainerNode);
+     *
+     * @param obj	The object to read.
+     */
+    void		readObject(PersistentObject &obj) const throw(Error);
+
+    /**
+     * Read a container from the container. This will throw Error if the
+     * current element is not a container. The read position will be advanced
+     * to the next element.
+     *
+     * @param name	If specified, then the function will check if the
+     * 			name of the next element matches the specified
+     * 			name and throw Error if it doesn't match.
+     *
+     * @return		Container object.
+     */
+    ContainerNode	readContainer(const string &name="") const
+				      throw(Error);
+
+    /**
+     * Read array container from the container. This will throw Error if the
+     * current element is not an array. The read position will be advanced
+     * to the next element.
+     *
+     * @param name	If specified, then the function will check if the
+     * 			name of the next element matches the specified
+     * 			name and throw Error if it doesn't match.
+     *
+     * @return		Container object.
+     */
+    ContainerNode	readArray(const string &name="") const
+				  throw(Error);
+
+    /**
+     * Write a number value to the container.
+     *
+     * @param name	The name for the value in the container.
+     * @param value	The value to be written.
+     */
+    void		writeNumber(const string &name,
+        		            float num) throw(Error);
+
+    /**
+     * Write a number value to the container.
+     *
+     * @param name	The name for the value in the container.
+     * @param value	The value to be written.
+     */
+    void		writeInt(const string &name,
+        		         int num) throw(Error);
+
+    /**
+     * Write a boolean value to the container.
+     *
+     * @param name	The name for the value in the container.
+     * @param value	The value to be written.
+     */
+    void		writeBool(const string &name,
+        		          bool value) throw(Error);
+
+    /**
+     * Write a string value to the container.
+     *
+     * @param name	The name for the value in the container.
+     * @param value	The value to be written.
+     */
+    void		writeString(const string &name,
+        		            const string &value) throw(Error);
+
+    /**
+     * Write string vector to the container.
+     *
+     * @param name	The name for the value in the container.
+     * @param array	The vector to be written.
+     */
+    void		writeStringVector(const string &name,
+        		                  const StringVector &value)
+					  throw(Error);
+
+    /**
+     * Write an object to the container. This is equal to calling
+     * PersistentObject.writeObject(ContainerNode);
+     *
+     * @param obj	The object to be written
+     */
+    void		writeObject(const PersistentObject &obj) throw(Error);
+
+    /**
+     * Create and write an empty Object node that can be used as parent
+     * for subsequent write operations.
+     *
+     * @param name	The name for the new container in the container.
+     *
+     * @return		A sub-container.
+     */
+    ContainerNode 	writeNewContainer(const string &name)
+					  throw(Error);
+
+    /**
+     * Create and write an empty array node that can be used as parent
+     * for subsequent write operations.
+     *
+     * @param name	The name for the array.
+     *
+     * @return		A sub-container.
+     */
+    ContainerNode 	writeNewArray(const string &name)
+				      throw(Error);
+
+public:
+    /* internal data */
+    container_node_op *op;
+    container_node_internal_data data;
+};
+
+/*
+ * Convenient macros.
+ */
+#define NODE_READ_BOOL(node,item)	item = node.readBool(#item)
+#define NODE_READ_UNSIGNED(node,item)	item = (unsigned)node.readNumber(#item)
+#define NODE_READ_INT(node,item)	item = (int) node.readNumber(#item)
+#define NODE_READ_FLOAT(node,item)	item = node.readNumber(#item)
+#define NODE_READ_NUM_T(node,T,item)	item = (T)(int)node.readNumber(#item)
+#define NODE_READ_STRING(node,item)	item = node.readString(#item)
+#define NODE_READ_STRINGV(node,item)	item = node.readStringVector(#item)
+#define NODE_READ_OBJ(node,item)	node.readObject(item)
+
+#define NODE_WRITE_BOOL(node,item)	node.writeBool(#item, item)
+#define NODE_WRITE_UNSIGNED(node,item)	node.writeNumber(#item, item)
+#define NODE_WRITE_INT(node,item)	node.writeNumber(#item, item)
+#define NODE_WRITE_NUM_T(node,T,item)	node.writeNumber(#item, (int)item)
+#define NODE_WRITE_FLOAT(node,item)	node.writeNumber(#item, item)
+#define NODE_WRITE_STRING(node,item)	node.writeString(#item, item)
+#define NODE_WRITE_STRINGV(node,item)	node.writeStringVector(#item, item)
+#define NODE_WRITE_OBJ(node,item)	node.writeObject(item)
+
+
+} // namespace pj
+
+/**
+ * @}  PJSUA2
+ */
+
+
+
+#endif	/* __PJSUA2_PERSISTENT_HPP__ */
Index: pjproject/branches/projects/pjsua2/pjsip/include/pjsua2/siptypes.hpp
===================================================================
--- pjproject/branches/projects/pjsua2/pjsip/include/pjsua2/siptypes.hpp	(revision 4644)
+++ pjproject/branches/projects/pjsua2/pjsip/include/pjsua2/siptypes.hpp	(revision 4644)
@@ -0,0 +1,587 @@
+/* $Id$ */
+/*
+ * Copyright (C) 2032 Teluu Inc. (http://www.teluu.com)
+ *
+ * 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 __PJSUA2_SIPTYPES_HPP__
+#define __PJSUA2_SIPTYPES_HPP__
+
+/**
+ * @file pjsua2/types.hpp
+ * @brief PJSUA2 Base Types
+ */
+#include <pjsua2/types.hpp>
+#include <pjsua2/persistent.hpp>
+
+#include <string>
+#include <vector>
+
+/**
+ * @defgroup PJSUA2_TYPES Data structure
+ * @ingroup PJSUA2_Ref
+ * @{
+ */
+
+/** PJSUA2 API is inside pj namespace */
+namespace pj
+{
+
+/**
+ * Credential information. Credential contains information to authenticate
+ * against a service.
+ */
+struct AuthCredInfo : public PersistentObject
+{
+    /**
+     * The authentication scheme (e.g. "digest").
+     */
+    string	scheme;
+
+    /**
+     * Realm on which this credential is to be used. Use "*" to make
+     * a credential that can be used to authenticate against any challenges.
+     */
+    string	realm;
+
+    /**
+     * Authentication user name.
+     */
+    string	username;
+
+    /**
+     * Type of data that is contained in the "data" field. Use 0 if the data
+     * contains plain text password.
+     */
+    int		dataType;
+
+    /**
+     * The data, which can be a plain text password or a hashed digest.
+     */
+    string	data;
+
+    /*
+     * Digest AKA credential information. Note that when AKA credential
+     * is being used, the \a data field of this #pjsip_cred_info is
+     * not used, but it still must be initialized to an empty string.
+     * Please see \ref PJSIP_AUTH_AKA_API for more information.
+     */
+
+    /** Permanent subscriber key. */
+    string	akaK;
+
+    /** Operator variant key. */
+    string	akaOp;
+
+    /** Authentication Management Field	*/
+    string	akaAmf;
+
+public:
+    /** Default constructor */
+    AuthCredInfo();
+
+    /** Construct a credential with the specified parameters */
+    AuthCredInfo(const string &scheme,
+                 const string &realm,
+                 const string &user_name,
+                 const int data_type,
+                 const string data);
+
+    /**
+     * Read this object from a container node.
+     *
+     * @param node		Container to read values from.
+     */
+    virtual void readObject(const ContainerNode &node) throw(Error);
+
+    /**
+     * Write this object to a container node.
+     *
+     * @param node		Container to write values to.
+     */
+    virtual void writeObject(ContainerNode &node) const throw(Error);
+};
+
+
+//////////////////////////////////////////////////////////////////////////////
+
+/**
+ * TLS transport settings, to be specified in TransportConfig.
+ */
+struct TlsConfig : public PersistentObject
+{
+    /**
+     * Certificate of Authority (CA) list file.
+     */
+    string		CaListFile;
+
+    /**
+     * Public endpoint certificate file, which will be used as client-
+     * side  certificate for outgoing TLS connection, and server-side
+     * certificate for incoming TLS connection.
+     */
+    string		certFile;
+
+    /**
+     * Optional private key of the endpoint certificate to be used.
+     */
+    string		privKeyFile;
+
+    /**
+     * Password to open private key.
+     */
+    string		password;
+
+    /**
+     * TLS protocol method from #pjsip_ssl_method.
+     *
+     * Default is PJSIP_SSL_UNSPECIFIED_METHOD (0), which in turn will
+     * use PJSIP_SSL_DEFAULT_METHOD, which default value is
+     * PJSIP_TLSV1_METHOD.
+     */
+    pjsip_ssl_method	method;
+
+    /**
+     * Ciphers and order preference. The Endpoint::utilSslGetAvailableCiphers()
+     * can be used to check the available ciphers supported by backend.
+     * If the array is empty, then default cipher list of the backend
+     * will be used.
+     */
+    IntVector		ciphers;
+
+    /**
+     * Specifies TLS transport behavior on the server TLS certificate
+     * verification result:
+     * - If \a verifyServer is disabled, TLS transport will just notify
+     *   the application via #pjsip_tp_state_callback with state
+     *   PJSIP_TP_STATE_CONNECTED regardless TLS verification result.
+     * - If \a verifyServer is enabled, 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 false.
+     */
+    bool		verifyServer;
+
+    /**
+     * Specifies TLS transport behavior on the client TLS certificate
+     * verification result:
+     * - If \a verifyClient is disabled, TLS transport will just notify
+     *   the application via #pjsip_tp_state_callback with state
+     *   PJSIP_TP_STATE_CONNECTED regardless TLS verification result.
+     * - If \a verifyClient is enabled, 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.
+     */
+    bool		verifyClient;
+
+    /**
+     * When acting as server (incoming TLS connections), reject incoming
+     * 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.
+     */
+    bool		requireClientCert;
+
+    /**
+     * TLS negotiation timeout to be applied for both outgoing and incoming
+     * connection, in milliseconds. If zero, the SSL negotiation doesn't
+     * have a timeout.
+     *
+     * Default: zero
+     */
+    unsigned		msecTimeout;
+
+    /**
+     * 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 qosParam fields since this is more portable.
+     *
+     * Default value is PJ_QOS_TYPE_BEST_EFFORT.
+     */
+    pj_qos_type 	qosType;
+
+    /**
+     * Set the low level QoS parameters to the transport. This is a lower
+     * level operation than setting the \a qosType field and may not be
+     * supported on all platforms.
+     *
+     * By default all settings in this structure are disabled.
+     */
+    pj_qos_params 	qosParams;
+
+    /**
+     * Specify if the transport should ignore any errors when setting the QoS
+     * traffic type/parameters.
+     *
+     * Default: PJ_TRUE
+     */
+    bool		qosIgnoreError;
+
+public:
+    /** Default constructor initialises with default values */
+    TlsConfig();
+
+    /** Convert to pjsip */
+    pjsip_tls_setting toPj() const;
+
+    /** Convert from pjsip */
+    void fromPj(const pjsip_tls_setting &prm);
+
+    /**
+     * Read this object from a container node.
+     *
+     * @param node		Container to read values from.
+     */
+    virtual void readObject(const ContainerNode &node) throw(Error);
+
+    /**
+     * Write this object to a container node.
+     *
+     * @param node		Container to write values to.
+     */
+    virtual void writeObject(ContainerNode &node) const throw(Error);
+};
+
+
+/**
+ * Parameters to create a transport instance.
+ */
+struct TransportConfig : public PersistentObject
+{
+    /**
+     * UDP port number to bind locally. This setting MUST be specified
+     * even when default port is desired. If the value is zero, the
+     * transport will be bound to any available port, and application
+     * can query the port by querying the transport info.
+     */
+    unsigned		port;
+
+    /**
+     * Specify the port range for socket binding, relative to the start
+     * port number specified in \a port. Note that this setting is only
+     * applicable when the start port number is non zero.
+     *
+     * Default value is zero.
+     */
+    unsigned		portRange;
+
+    /**
+     * Optional address to advertise as the address of this transport.
+     * Application can specify any address or hostname for this field,
+     * for example it can point to one of the interface address in the
+     * system, or it can point to the public address of a NAT router
+     * where port mappings have been configured for the application.
+     *
+     * Note: this option can be used for both UDP and TCP as well!
+     */
+    string		publicAddress;
+
+    /**
+     * Optional address where the socket should be bound to. This option
+     * SHOULD only be used to selectively bind the socket to particular
+     * interface (instead of 0.0.0.0), and SHOULD NOT be used to set the
+     * published address of a transport (the public_addr field should be
+     * used for that purpose).
+     *
+     * Note that unlike public_addr field, the address (or hostname) here
+     * MUST correspond to the actual interface address in the host, since
+     * this address will be specified as bind() argument.
+     */
+    string		boundAddress;
+
+    /**
+     * This specifies TLS settings for TLS transport. It is only be used
+     * when this transport config is being used to create a SIP TLS
+     * transport.
+     */
+    TlsConfig		tlsConfig;
+
+    /**
+     * 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 qosParam fields since this is more portable.
+     *
+     * Default is QoS not set.
+     */
+    pj_qos_type		qosType;
+
+    /**
+     * Set the low level QoS parameters to the transport. This is a lower
+     * level operation than setting the \a qosType field and may not be
+     * supported on all platforms.
+     *
+     * Default is QoS not set.
+     */
+    pj_qos_params	qosParams;
+
+public:
+    /** Default constructor initialises with default values */
+    TransportConfig();
+
+    /** Convert from pjsip */
+    void fromPj(const pjsua_transport_config &prm);
+
+    /** Convert to pjsip */
+    pjsua_transport_config toPj() const;
+
+    /**
+     * Read this object from a container node.
+     *
+     * @param node		Container to read values from.
+     */
+    virtual void readObject(const ContainerNode &node) throw(Error);
+
+    /**
+     * Write this object to a container node.
+     *
+     * @param node		Container to write values to.
+     */
+    virtual void writeObject(ContainerNode &node) const throw(Error);
+};
+
+/**
+ * This structure describes transport information returned by
+ * Endpoint::transportGetInfo() function.
+ */
+struct TransportInfo
+{
+    /** PJSUA transport identification. */
+    TransportId	    	    id;
+
+    /** Transport type. */
+    pjsip_transport_type_e  type;
+
+    /** Transport type name. */
+    string		    typeName;
+
+    /** Transport string info/description. */
+    string		    info;
+
+    /** Transport flags (see #pjsip_transport_flags_e). */
+    unsigned		    flags;
+
+    /** Local/bound address. */
+    SocketAddress	    localAddress;
+
+    /** Published address (or transport address name). */
+    SocketAddress	    localName;
+
+    /** Current number of objects currently referencing this transport. */
+    unsigned		    usageCount;
+
+    /** Construct from pjsip */
+    TransportInfo(const pjsua_transport_info &info);
+
+};
+
+//////////////////////////////////////////////////////////////////////////////
+
+/**
+ * This structure describes an incoming SIP message. It corresponds to the
+ * pjsip_rx_data structure in PJSIP library.
+ */
+struct SipRxData
+{
+    /**
+     * A short info string describing the request, which normally contains
+     * the request method and its CSeq.
+     */
+    string		info;
+
+    /**
+     * The whole message data as a string, containing both the header section
+     * and message body section.
+     */
+    string		wholeMsg;
+
+    /**
+     * Source IP address of the message.
+     */
+    string		srcIp;
+
+    /**
+     * Source port number of the message.
+     */
+    unsigned		srcPort;
+
+    /**
+     * Construct from PJSIP's pjsip_rx_data
+     */
+    void fromPj(pjsip_rx_data &rdata);
+};
+
+
+//////////////////////////////////////////////////////////////////////////////
+
+/**
+ * SIP media type containing type and subtype. For example, for
+ * "application/sdp", the type is "application" and the subtype is "sdp".
+ */
+struct SipMediaType
+{
+    /** Media type. */
+    string		type;
+
+    /** Media subtype. */
+    string		subType;
+};
+
+/**
+ * Simple SIP header.
+ */
+struct SipHeader
+{
+    /**
+     * Header name.
+     */
+    string		hName;
+
+    /**
+     * Header value.
+     */
+    string		hValue;
+
+    /**
+     * Initiaize from PJSIP header.
+     */
+    void fromPj(const pjsip_hdr *) throw(Error);
+
+    /**
+     * Convert to PJSIP header.
+     */
+    pjsip_generic_string_hdr &toPj() const;
+
+private:
+    /** Interal buffer for conversion to PJSIP header */
+    mutable pjsip_generic_string_hdr	pjHdr;
+};
+
+
+/** Array of strings */
+typedef std::vector<SipHeader> SipHeaderVector;
+
+/**
+ * This describes each multipart part.
+ */
+struct SipMultipartPart
+{
+    /**
+     * Optional headers to be put in this multipart part.
+     */
+    SipHeaderVector	headers;
+
+    /**
+     * The MIME type of the body part of this multipart part.
+     */
+    SipMediaType	contentType;
+
+    /**
+     * The body part of tthis multipart part.
+     */
+    string		body;
+};
+
+/** Array of multipart parts */
+typedef std::vector<SipMultipartPart> SipMultipartPartVector;
+
+/**
+ * Additional options when sending outgoing SIP message. This corresponds to
+ * pjsua_msg_data structure in PJSIP library.
+ */
+struct SipTxOption
+{
+    /**
+     * Optional remote target URI (i.e. Target header). If NULL, the target
+     * will be set to the remote URI (To header). At the moment this field
+     * is only used when sending initial INVITE and MESSAGE requests.
+     */
+    string		targetUri;
+
+    /**
+     * Additional message headers to be included in the outgoing message.
+     */
+    SipHeaderVector	headers;
+
+    /**
+     * MIME type of the message body, if application specifies the messageBody
+     * in this structure.
+     */
+    string		contentType;
+
+    /**
+     * Optional message body to be added to the message, only when the
+     * message doesn't have a body.
+     */
+    string		msgBody;
+
+    /**
+     * Content type of the multipart body. If application wants to send
+     * multipart message bodies, it puts the parts in multipartParts and set
+     * the content type in multipartContentType. If the message already
+     * contains a body, the body will be added to the multipart bodies.
+     */
+    SipMediaType	multipartContentType;
+
+    /**
+     * Array of multipart parts. If application wants to send multipart
+     * message bodies, it puts the parts in \a parts and set the content
+     * type in \a multipart_ctype. If the message already contains a body,
+     * the body will be added to the multipart bodies.
+     */
+    SipMultipartPartVector	multipartParts;
+
+};
+
+/* Utilities */
+#ifndef SWIG
+void readIntVector( ContainerNode &node,
+                    const string &array_name,
+                    IntVector &v) throw(Error);
+void writeIntVector(ContainerNode &node,
+                    const string &array_name,
+                    const IntVector &v) throw(Error);
+void readQosParams( ContainerNode &node,
+                    pj_qos_params &qos) throw(Error);
+void writeQosParams( ContainerNode &node,
+                     const pj_qos_params &qos) throw(Error);
+void readSipHeaders( const ContainerNode &node,
+                     const string &array_name,
+                     SipHeaderVector &headers) throw(Error);
+void writeSipHeaders(ContainerNode &node,
+                     const string &array_name,
+                     const SipHeaderVector &headers) throw(Error);
+#endif // SWIG
+
+} // namespace pj
+
+/**
+ * @}  PJSUA2
+ */
+
+
+
+#endif	/* __PJSUA2_SIPTYPES_HPP__ */
Index: pjproject/branches/projects/pjsua2/pjsip/include/pjsua2/types.hpp
===================================================================
--- pjproject/branches/projects/pjsua2/pjsip/include/pjsua2/types.hpp	(revision 4643)
+++ pjproject/branches/projects/pjsua2/pjsip/include/pjsua2/types.hpp	(revision 4644)
@@ -1,5 +1,5 @@
 /* $Id$ */
 /* 
- * Copyright (C) 2008-2012 Teluu Inc. (http://www.teluu.com)
+ * Copyright (C) 2013 Teluu Inc. (http://www.teluu.com)
  *
  * This program is free software; you can redistribute it and/or modify
@@ -21,6 +21,6 @@
 
 /**
- * @file pjsua2/ua.hpp
- * @brief PJSUA2 Base Agent Operation
+ * @file pjsua2/types.hpp
+ * @brief PJSUA2 Base Types
  */
 #include <pjsua2/config.hpp>
@@ -207,481 +207,4 @@
 };
 
-//////////////////////////////////////////////////////////////////////////////
-
-/**
- * Credential information. Credential contains information to authenticate
- * against a service.
- */
-struct AuthCredInfo
-{
-    /**
-     * The authentication scheme (e.g. "digest").
-     */
-    string	scheme;
-
-    /**
-     * Realm on which this credential is to be used. Use "*" to make
-     * a credential that can be used to authenticate against any challenges.
-     */
-    string	realm;
-
-    /**
-     * Authentication user name.
-     */
-    string	username;
-
-    /**
-     * Type of data that is contained in the "data" field. Use 0 if the data
-     * contains plain text password.
-     */
-    int		dataType;
-
-    /**
-     * The data, which can be a plain text password or a hashed digest.
-     */
-    string	data;
-
-    /*
-     * Digest AKA credential information. Note that when AKA credential
-     * is being used, the \a data field of this #pjsip_cred_info is
-     * not used, but it still must be initialized to an empty string.
-     * Please see \ref PJSIP_AUTH_AKA_API for more information.
-     */
-
-    /** Permanent subscriber key. */
-    string	akaK;
-
-    /** Operator variant key. */
-    string	akaOp;
-
-    /** Authentication Management Field	*/
-    string	akaAmf;
-
-    /** Default constructor */
-    AuthCredInfo();
-
-    /** Construct a credential with the specified parameters */
-    AuthCredInfo(const string &scheme,
-                 const string &realm,
-                 const string &user_name,
-                 const int data_type,
-                 const string data);
-
-};
-
-
-//////////////////////////////////////////////////////////////////////////////
-
-/**
- * TLS transport settings, to be specified in TransportConfig.
- */
-struct TlsConfig
-{
-    /**
-     * Certificate of Authority (CA) list file.
-     */
-    string		CaListFile;
-
-    /**
-     * Public endpoint certificate file, which will be used as client-
-     * side  certificate for outgoing TLS connection, and server-side
-     * certificate for incoming TLS connection.
-     */
-    string		certFile;
-
-    /**
-     * Optional private key of the endpoint certificate to be used.
-     */
-    string		privKeyFile;
-
-    /**
-     * Password to open private key.
-     */
-    string		password;
-
-    /**
-     * TLS protocol method from #pjsip_ssl_method.
-     *
-     * Default is PJSIP_SSL_UNSPECIFIED_METHOD (0), which in turn will
-     * use PJSIP_SSL_DEFAULT_METHOD, which default value is
-     * PJSIP_TLSV1_METHOD.
-     */
-    pjsip_ssl_method	method;
-
-    /**
-     * Ciphers and order preference. The Endpoint::utilSslGetAvailableCiphers()
-     * can be used to check the available ciphers supported by backend.
-     * If the array is empty, then default cipher list of the backend
-     * will be used.
-     */
-    IntVector		ciphers;
-
-    /**
-     * Specifies TLS transport behavior on the server TLS certificate
-     * verification result:
-     * - If \a verifyServer is disabled, TLS transport will just notify
-     *   the application via #pjsip_tp_state_callback with state
-     *   PJSIP_TP_STATE_CONNECTED regardless TLS verification result.
-     * - If \a verifyServer is enabled, 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 false.
-     */
-    bool		verifyServer;
-
-    /**
-     * Specifies TLS transport behavior on the client TLS certificate
-     * verification result:
-     * - If \a verifyClient is disabled, TLS transport will just notify
-     *   the application via #pjsip_tp_state_callback with state
-     *   PJSIP_TP_STATE_CONNECTED regardless TLS verification result.
-     * - If \a verifyClient is enabled, 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.
-     */
-    bool		verifyClient;
-
-    /**
-     * When acting as server (incoming TLS connections), reject incoming
-     * 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.
-     */
-    bool		requireClientCert;
-
-    /**
-     * TLS negotiation timeout to be applied for both outgoing and incoming
-     * connection, in milliseconds. If zero, the SSL negotiation doesn't
-     * have a timeout.
-     *
-     * Default: zero
-     */
-    unsigned		msecTimeout;
-
-    /**
-     * 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 qosParam fields since this is more portable.
-     *
-     * Default value is PJ_QOS_TYPE_BEST_EFFORT.
-     */
-    pj_qos_type 	qosType;
-
-    /**
-     * Set the low level QoS parameters to the transport. This is a lower
-     * level operation than setting the \a qosType field and may not be
-     * supported on all platforms.
-     *
-     * By default all settings in this structure are disabled.
-     */
-    pj_qos_params 	qosParams;
-
-    /**
-     * Specify if the transport should ignore any errors when setting the QoS
-     * traffic type/parameters.
-     *
-     * Default: PJ_TRUE
-     */
-    bool		qosIgnoreError;
-
-public:
-    /** Default constructor initialises with default values */
-    TlsConfig();
-
-    /** Convert to pjsip */
-    pjsip_tls_setting toPj() const;
-
-    /** Convert from pjsip */
-    void fromPj(const pjsip_tls_setting &prm);
-};
-
-
-/**
- * Parameters to create a transport instance.
- */
-struct TransportConfig
-{
-    /**
-     * UDP port number to bind locally. This setting MUST be specified
-     * even when default port is desired. If the value is zero, the
-     * transport will be bound to any available port, and application
-     * can query the port by querying the transport info.
-     */
-    unsigned		port;
-
-    /**
-     * Specify the port range for socket binding, relative to the start
-     * port number specified in \a port. Note that this setting is only
-     * applicable when the start port number is non zero.
-     *
-     * Default value is zero.
-     */
-    unsigned		portRange;
-
-    /**
-     * Optional address to advertise as the address of this transport.
-     * Application can specify any address or hostname for this field,
-     * for example it can point to one of the interface address in the
-     * system, or it can point to the public address of a NAT router
-     * where port mappings have been configured for the application.
-     *
-     * Note: this option can be used for both UDP and TCP as well!
-     */
-    string		publicAddress;
-
-    /**
-     * Optional address where the socket should be bound to. This option
-     * SHOULD only be used to selectively bind the socket to particular
-     * interface (instead of 0.0.0.0), and SHOULD NOT be used to set the
-     * published address of a transport (the public_addr field should be
-     * used for that purpose).
-     *
-     * Note that unlike public_addr field, the address (or hostname) here
-     * MUST correspond to the actual interface address in the host, since
-     * this address will be specified as bind() argument.
-     */
-    string		boundAddress;
-
-    /**
-     * This specifies TLS settings for TLS transport. It is only be used
-     * when this transport config is being used to create a SIP TLS
-     * transport.
-     */
-    TlsConfig		tlsConfig;
-
-    /**
-     * 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 qosParam fields since this is more portable.
-     *
-     * Default is QoS not set.
-     */
-    pj_qos_type		qosType;
-
-    /**
-     * Set the low level QoS parameters to the transport. This is a lower
-     * level operation than setting the \a qosType field and may not be
-     * supported on all platforms.
-     *
-     * Default is QoS not set.
-     */
-    pj_qos_params	qosParams;
-
-public:
-    /** Default constructor initialises with default values */
-    TransportConfig();
-
-    /** Convert from pjsip */
-    void fromPj(const pjsua_transport_config &prm);
-
-    /** Convert to pjsip */
-    pjsua_transport_config toPj() const;
-};
-
-/**
- * This structure describes transport information returned by
- * Endpoint::transportGetInfo() function.
- */
-struct TransportInfo
-{
-    /** PJSUA transport identification. */
-    TransportId	    	    id;
-
-    /** Transport type. */
-    pjsip_transport_type_e  type;
-
-    /** Transport type name. */
-    string		    typeName;
-
-    /** Transport string info/description. */
-    string		    info;
-
-    /** Transport flags (see #pjsip_transport_flags_e). */
-    unsigned		    flags;
-
-    /** Local/bound address. */
-    SocketAddress	    localAddress;
-
-    /** Published address (or transport address name). */
-    SocketAddress	    localName;
-
-    /** Current number of objects currently referencing this transport. */
-    unsigned		    usageCount;
-
-    /** Construct from pjsip */
-    TransportInfo(const pjsua_transport_info &info);
-
-};
-
-//////////////////////////////////////////////////////////////////////////////
-
-/**
- * This structure describes an incoming SIP message. It corresponds to the
- * pjsip_rx_data structure in PJSIP library.
- */
-struct SipRxData
-{
-    /**
-     * A short info string describing the request, which normally contains
-     * the request method and its CSeq.
-     */
-    string		info;
-
-    /**
-     * The whole message data as a string, containing both the header section
-     * and message body section.
-     */
-    string		wholeMsg;
-
-    /**
-     * Source IP address of the message.
-     */
-    string		srcIp;
-
-    /**
-     * Source port number of the message.
-     */
-    unsigned		srcPort;
-
-    /**
-     * Construct from PJSIP's pjsip_rx_data
-     */
-    void fromPj(pjsip_rx_data &rdata);
-};
-
-
-//////////////////////////////////////////////////////////////////////////////
-
-/**
- * SIP media type containing type and subtype. For example, for
- * "application/sdp", the type is "application" and the subtype is "sdp".
- */
-struct SipMediaType
-{
-    /** Media type. */
-    string		type;
-
-    /** Media subtype. */
-    string		subType;
-};
-
-/**
- * Simple SIP header.
- */
-struct SipHeader
-{
-    /**
-     * Header name.
-     */
-    string		hName;
-
-    /**
-     * Header value.
-     */
-    string		hValue;
-
-    /**
-     * Initiaize from PJSIP header.
-     */
-    void fromPj(const pjsip_hdr *) throw(Error);
-
-    /**
-     * Convert to PJSIP header.
-     */
-    pjsip_generic_string_hdr &toPj() const;
-
-private:
-    /** Interal buffer for conversion to PJSIP header */
-    mutable pjsip_generic_string_hdr	pjHdr;
-};
-
-
-/** Array of strings */
-typedef std::vector<SipHeader> SipHeaderVector;
-
-/**
- * This describes each multipart part.
- */
-struct SipMultipartPart
-{
-    /**
-     * Optional headers to be put in this multipart part.
-     */
-    SipHeaderVector	headers;
-
-    /**
-     * The MIME type of the body part of this multipart part.
-     */
-    SipMediaType	contentType;
-
-    /**
-     * The body part of tthis multipart part.
-     */
-    string		body;
-};
-
-/** Array of multipart parts */
-typedef std::vector<SipMultipartPart> SipMultipartPartVector;
-
-/**
- * Additional options when sending outgoing SIP message. This corresponds to
- * pjsua_msg_data structure in PJSIP library.
- */
-struct SipTxOption
-{
-    /**
-     * Optional remote target URI (i.e. Target header). If NULL, the target
-     * will be set to the remote URI (To header). At the moment this field
-     * is only used when sending initial INVITE and MESSAGE requests.
-     */
-    string		targetUri;
-
-    /**
-     * Additional message headers to be included in the outgoing message.
-     */
-    SipHeaderVector	headers;
-
-    /**
-     * MIME type of the message body, if application specifies the messageBody
-     * in this structure.
-     */
-    string		contentType;
-
-    /**
-     * Optional message body to be added to the message, only when the
-     * message doesn't have a body.
-     */
-    string		msgBody;
-
-    /**
-     * Content type of the multipart body. If application wants to send
-     * multipart message bodies, it puts the parts in multipartParts and set
-     * the content type in multipartContentType. If the message already
-     * contains a body, the body will be added to the multipart bodies.
-     */
-    SipMediaType	multipartContentType;
-
-    /**
-     * Array of multipart parts. If application wants to send multipart
-     * message bodies, it puts the parts in \a parts and set the content
-     * type in \a multipart_ctype. If the message already contains a body,
-     * the body will be added to the multipart bodies.
-     */
-    SipMultipartPartVector	multipartParts;
-
-};
-
 
 } // namespace pj
Index: pjproject/branches/projects/pjsua2/pjsip/src/pjsua2/account.cpp
===================================================================
--- pjproject/branches/projects/pjsua2/pjsip/src/pjsua2/account.cpp	(revision 4643)
+++ pjproject/branches/projects/pjsua2/pjsip/src/pjsua2/account.cpp	(revision 4644)
@@ -1,5 +1,5 @@
 /* $Id$ */
 /*
- * Copyright (C) 2012 Teluu Inc. (http://www.teluu.com)
+ * Copyright (C) 2013 Teluu Inc. (http://www.teluu.com)
  *
  * This program is free software; you can redistribute it and/or modify
@@ -27,4 +27,264 @@
 #define THIS_FILE		"account.cpp"
 
+///////////////////////////////////////////////////////////////////////////////
+
+void AccountRegConfig::readObject(const ContainerNode &node) throw(Error)
+{
+    ContainerNode this_node = node.readContainer("AccountRegConfig");
+
+    NODE_READ_STRING	(this_node, registrarUri);
+    NODE_READ_BOOL	(this_node, registerOnAdd);
+    NODE_READ_UNSIGNED	(this_node, timeoutSec);
+    NODE_READ_UNSIGNED	(this_node, retryIntervalSec);
+    NODE_READ_UNSIGNED	(this_node, firstRetryIntervalSec);
+    NODE_READ_UNSIGNED	(this_node, delayBeforeRefreshSec);
+    NODE_READ_BOOL	(this_node, dropCallsOnFail);
+    NODE_READ_UNSIGNED	(this_node, unregWaitSec);
+    NODE_READ_UNSIGNED	(this_node, proxyUse);
+
+    readSipHeaders(this_node, "headers", headers);
+}
+
+void AccountRegConfig::writeObject(ContainerNode &node) const throw(Error)
+{
+    ContainerNode this_node = node.writeNewContainer("AccountRegConfig");
+
+    NODE_WRITE_STRING	(this_node, registrarUri);
+    NODE_WRITE_BOOL	(this_node, registerOnAdd);
+    NODE_WRITE_UNSIGNED	(this_node, timeoutSec);
+    NODE_WRITE_UNSIGNED	(this_node, retryIntervalSec);
+    NODE_WRITE_UNSIGNED	(this_node, firstRetryIntervalSec);
+    NODE_WRITE_UNSIGNED	(this_node, delayBeforeRefreshSec);
+    NODE_WRITE_BOOL	(this_node, dropCallsOnFail);
+    NODE_WRITE_UNSIGNED	(this_node, unregWaitSec);
+    NODE_WRITE_UNSIGNED	(this_node, proxyUse);
+
+    writeSipHeaders(this_node, "headers", headers);
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+void AccountSipConfig::readObject(const ContainerNode &node) throw(Error)
+{
+    ContainerNode this_node = node.readContainer("AccountSipConfig");
+
+    NODE_READ_STRINGV	(this_node, proxies);
+    NODE_READ_STRING	(this_node, contactForced);
+    NODE_READ_STRING	(this_node, contactParams);
+    NODE_READ_STRING	(this_node, contactUriParams);
+    NODE_READ_BOOL	(this_node, authInitialEmpty);
+    NODE_READ_STRING	(this_node, authInitialAlgorithm);
+    NODE_READ_INT	(this_node, transportId);
+
+    ContainerNode creds_node = this_node.readArray("authCreds");
+    authCreds.resize(0);
+    while (creds_node.hasUnread()) {
+	AuthCredInfo cred;
+	cred.readObject(creds_node);
+	authCreds.push_back(cred);
+    }
+}
+
+void AccountSipConfig::writeObject(ContainerNode &node) const throw(Error)
+{
+    ContainerNode this_node = node.writeNewContainer("AccountSipConfig");
+
+    NODE_WRITE_STRINGV	(this_node, proxies);
+    NODE_WRITE_STRING	(this_node, contactForced);
+    NODE_WRITE_STRING	(this_node, contactParams);
+    NODE_WRITE_STRING	(this_node, contactUriParams);
+    NODE_WRITE_BOOL	(this_node, authInitialEmpty);
+    NODE_WRITE_STRING	(this_node, authInitialAlgorithm);
+    NODE_WRITE_INT	(this_node, transportId);
+
+    ContainerNode creds_node = this_node.writeNewArray("authCreds");
+    for (unsigned i=0; i<authCreds.size(); ++i) {
+	authCreds[i].writeObject(creds_node);
+    }
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+void AccountCallConfig::readObject(const ContainerNode &node) throw(Error)
+{
+    ContainerNode this_node = node.readContainer("AccountCallConfig");
+
+    NODE_READ_NUM_T   ( this_node, pjsua_call_hold_type, holdType);
+    NODE_READ_NUM_T   ( this_node, pjsua_100rel_use, prackUse);
+    NODE_READ_NUM_T   ( this_node, pjsua_sip_timer_use, timerUse);
+    NODE_READ_UNSIGNED( this_node, timerMinSESec);
+    NODE_READ_UNSIGNED( this_node, timerSessExpiresSec);
+}
+
+void AccountCallConfig::writeObject(ContainerNode &node) const throw(Error)
+{
+    ContainerNode this_node = node.writeNewContainer("AccountCallConfig");
+
+    NODE_WRITE_NUM_T   ( this_node, pjsua_call_hold_type, holdType);
+    NODE_WRITE_NUM_T   ( this_node, pjsua_100rel_use, prackUse);
+    NODE_WRITE_NUM_T   ( this_node, pjsua_sip_timer_use, timerUse);
+    NODE_WRITE_UNSIGNED( this_node, timerMinSESec);
+    NODE_WRITE_UNSIGNED( this_node, timerSessExpiresSec);
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+void AccountPresConfig::readObject(const ContainerNode &node) throw(Error)
+{
+    ContainerNode this_node = node.readContainer("AccountPresConfig");
+
+    NODE_READ_BOOL    ( this_node, publishEnabled);
+    NODE_READ_BOOL    ( this_node, publishQueue);
+    NODE_READ_UNSIGNED( this_node, publishShutdownWaitMsec);
+    NODE_READ_STRING  ( this_node, pidfTupleId);
+
+    readSipHeaders(this_node, "headers", headers);
+}
+
+void AccountPresConfig::writeObject(ContainerNode &node) const throw(Error)
+{
+    ContainerNode this_node = node.writeNewContainer("AccountPresConfig");
+
+    NODE_WRITE_BOOL    ( this_node, publishEnabled);
+    NODE_WRITE_BOOL    ( this_node, publishQueue);
+    NODE_WRITE_UNSIGNED( this_node, publishShutdownWaitMsec);
+    NODE_WRITE_STRING  ( this_node, pidfTupleId);
+
+    writeSipHeaders(this_node, "headers", headers);
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+void AccountMwiConfig::readObject(const ContainerNode &node) throw(Error)
+{
+    ContainerNode this_node = node.readContainer("AccountMwiConfig");
+
+    NODE_READ_BOOL    ( this_node, enabled);
+    NODE_READ_UNSIGNED( this_node, expirationSec);
+}
+
+void AccountMwiConfig::writeObject(ContainerNode &node) const throw(Error)
+{
+    ContainerNode this_node = node.writeNewContainer("AccountMwiConfig");
+
+    NODE_WRITE_BOOL    ( this_node, enabled);
+    NODE_WRITE_UNSIGNED( this_node, expirationSec);
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+void AccountNatConfig::readObject(const ContainerNode &node) throw(Error)
+{
+    ContainerNode this_node = node.readContainer("AccountNatConfig");
+
+    NODE_READ_NUM_T   ( this_node, pjsua_stun_use, sipStunUse);
+    NODE_READ_NUM_T   ( this_node, pjsua_stun_use, mediaStunUse);
+    NODE_READ_BOOL    ( this_node, iceEnabled);
+    NODE_READ_INT     ( this_node, iceMaxHostCands);
+    NODE_READ_BOOL    ( this_node, iceAggressiveNomination);
+    NODE_READ_UNSIGNED( this_node, iceNominatedCheckDelayMsec);
+    NODE_READ_INT     ( this_node, iceWaitNominationTimeoutMsec);
+    NODE_READ_BOOL    ( this_node, iceNoRtcp);
+    NODE_READ_BOOL    ( this_node, iceAlwaysUpdate);
+    NODE_READ_BOOL    ( this_node, turnEnabled);
+    NODE_READ_STRING  ( this_node, turnServer);
+    NODE_READ_NUM_T   ( this_node, pj_turn_tp_type, turnConnType);
+    NODE_READ_STRING  ( this_node, turnUserName);
+    NODE_READ_INT     ( this_node, turnPasswordType);
+    NODE_READ_STRING  ( this_node, turnPassword);
+    NODE_READ_INT     ( this_node, contactRewriteUse);
+    NODE_READ_INT     ( this_node, contactRewriteMethod);
+    NODE_READ_INT     ( this_node, viaRewriteUse);
+    NODE_READ_INT     ( this_node, sdpNatRewriteUse);
+    NODE_READ_INT     ( this_node, sipOutboundUse);
+    NODE_READ_STRING  ( this_node, sipOutboundInstanceId);
+    NODE_READ_STRING  ( this_node, sipOutboundRegId);
+    NODE_READ_UNSIGNED( this_node, udpKaIntervalSec);
+    NODE_READ_STRING  ( this_node, udpKaData);
+}
+
+void AccountNatConfig::writeObject(ContainerNode &node) const throw(Error)
+{
+    ContainerNode this_node = node.writeNewContainer("AccountNatConfig");
+
+    NODE_WRITE_NUM_T   ( this_node, pjsua_stun_use, sipStunUse);
+    NODE_WRITE_NUM_T   ( this_node, pjsua_stun_use, mediaStunUse);
+    NODE_WRITE_BOOL    ( this_node, iceEnabled);
+    NODE_WRITE_INT     ( this_node, iceMaxHostCands);
+    NODE_WRITE_BOOL    ( this_node, iceAggressiveNomination);
+    NODE_WRITE_UNSIGNED( this_node, iceNominatedCheckDelayMsec);
+    NODE_WRITE_INT     ( this_node, iceWaitNominationTimeoutMsec);
+    NODE_WRITE_BOOL    ( this_node, iceNoRtcp);
+    NODE_WRITE_BOOL    ( this_node, iceAlwaysUpdate);
+    NODE_WRITE_BOOL    ( this_node, turnEnabled);
+    NODE_WRITE_STRING  ( this_node, turnServer);
+    NODE_WRITE_NUM_T   ( this_node, pj_turn_tp_type, turnConnType);
+    NODE_WRITE_STRING  ( this_node, turnUserName);
+    NODE_WRITE_INT     ( this_node, turnPasswordType);
+    NODE_WRITE_STRING  ( this_node, turnPassword);
+    NODE_WRITE_INT     ( this_node, contactRewriteUse);
+    NODE_WRITE_INT     ( this_node, contactRewriteMethod);
+    NODE_WRITE_INT     ( this_node, viaRewriteUse);
+    NODE_WRITE_INT     ( this_node, sdpNatRewriteUse);
+    NODE_WRITE_INT     ( this_node, sipOutboundUse);
+    NODE_WRITE_STRING  ( this_node, sipOutboundInstanceId);
+    NODE_WRITE_STRING  ( this_node, sipOutboundRegId);
+    NODE_WRITE_UNSIGNED( this_node, udpKaIntervalSec);
+    NODE_WRITE_STRING  ( this_node, udpKaData);
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+void AccountMediaConfig::readObject(const ContainerNode &node) throw(Error)
+{
+    ContainerNode this_node = node.readContainer("AccountMediaConfig");
+
+    NODE_READ_BOOL    ( this_node, lockCodecEnabled);
+    NODE_READ_BOOL    ( this_node, streamKaEnabled);
+    NODE_READ_NUM_T   ( this_node, pjmedia_srtp_use, srtpUse);
+    NODE_READ_INT     ( this_node, srtpSecureSignaling);
+    NODE_READ_NUM_T   ( this_node, pjsua_ipv6_use, ipv6Use);
+    NODE_READ_OBJ     ( this_node, transportConfig);
+}
+
+void AccountMediaConfig::writeObject(ContainerNode &node) const throw(Error)
+{
+    ContainerNode this_node = node.writeNewContainer("AccountMediaConfig");
+
+    NODE_WRITE_BOOL    ( this_node, lockCodecEnabled);
+    NODE_WRITE_BOOL    ( this_node, streamKaEnabled);
+    NODE_WRITE_NUM_T   ( this_node, pjmedia_srtp_use, srtpUse);
+    NODE_WRITE_INT     ( this_node, srtpSecureSignaling);
+    NODE_WRITE_NUM_T   ( this_node, pjsua_ipv6_use, ipv6Use);
+    NODE_WRITE_OBJ     ( this_node, transportConfig);
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+void AccountVideoConfig::readObject(const ContainerNode &node) throw(Error)
+{
+    ContainerNode this_node = node.readContainer("AccountVideoConfig");
+
+    NODE_READ_BOOL    ( this_node, autoShowIncoming);
+    NODE_READ_BOOL    ( this_node, autoTransmitOutgoing);
+    NODE_READ_UNSIGNED( this_node, windowFlags);
+    NODE_READ_NUM_T   ( this_node, pjmedia_vid_dev_index, defaultCaptureDevice);
+    NODE_READ_NUM_T   ( this_node, pjmedia_vid_dev_index, defaultRenderDevice);
+    NODE_READ_NUM_T   ( this_node, pjmedia_vid_stream_rc_method, rateControlMethod);
+    NODE_READ_UNSIGNED( this_node, rateControlBandwidth);
+}
+
+void AccountVideoConfig::writeObject(ContainerNode &node) const throw(Error)
+{
+    ContainerNode this_node = node.writeNewContainer("AccountVideoConfig");
+
+    NODE_WRITE_BOOL    ( this_node, autoShowIncoming);
+    NODE_WRITE_BOOL    ( this_node, autoTransmitOutgoing);
+    NODE_WRITE_UNSIGNED( this_node, windowFlags);
+    NODE_WRITE_NUM_T   ( this_node, pjmedia_vid_dev_index, defaultCaptureDevice);
+    NODE_WRITE_NUM_T   ( this_node, pjmedia_vid_dev_index, defaultRenderDevice);
+    NODE_WRITE_NUM_T   ( this_node, pjmedia_vid_stream_rc_method, rateControlMethod);
+    NODE_WRITE_UNSIGNED( this_node, rateControlBandwidth);
+}
 
 ///////////////////////////////////////////////////////////////////////////////
@@ -331,4 +591,37 @@
 }
 
+void AccountConfig::readObject(const ContainerNode &node) throw(Error)
+{
+    ContainerNode this_node = node.readContainer("AccountConfig");
+
+    NODE_READ_INT     ( this_node, priority);
+    NODE_READ_STRING  ( this_node, idUri);
+    NODE_READ_OBJ     ( this_node, regConfig);
+    NODE_READ_OBJ     ( this_node, sipConfig);
+    NODE_READ_OBJ     ( this_node, callConfig);
+    NODE_READ_OBJ     ( this_node, presConfig);
+    NODE_READ_OBJ     ( this_node, mwiConfig);
+    NODE_READ_OBJ     ( this_node, natConfig);
+    NODE_READ_OBJ     ( this_node, mediaConfig);
+    NODE_READ_OBJ     ( this_node, videoConfig);
+}
+
+void AccountConfig::writeObject(ContainerNode &node) const throw(Error)
+{
+    ContainerNode this_node = node.writeNewContainer("AccountConfig");
+
+    NODE_WRITE_INT     ( this_node, priority);
+    NODE_WRITE_STRING  ( this_node, idUri);
+    NODE_WRITE_OBJ     ( this_node, regConfig);
+    NODE_WRITE_OBJ     ( this_node, sipConfig);
+    NODE_WRITE_OBJ     ( this_node, callConfig);
+    NODE_WRITE_OBJ     ( this_node, presConfig);
+    NODE_WRITE_OBJ     ( this_node, mwiConfig);
+    NODE_WRITE_OBJ     ( this_node, natConfig);
+    NODE_WRITE_OBJ     ( this_node, mediaConfig);
+    NODE_WRITE_OBJ     ( this_node, videoConfig);
+}
+
+
 ///////////////////////////////////////////////////////////////////////////////
 
Index: pjproject/branches/projects/pjsua2/pjsip/src/pjsua2/endpoint.cpp
===================================================================
--- pjproject/branches/projects/pjsua2/pjsip/src/pjsua2/endpoint.cpp	(revision 4643)
+++ pjproject/branches/projects/pjsua2/pjsip/src/pjsua2/endpoint.cpp	(revision 4644)
@@ -1,5 +1,5 @@
 /* $Id$ */
 /* 
- * Copyright (C) 2012 Teluu Inc. (http://www.teluu.com)
+ * Copyright (C) 2013 Teluu Inc. (http://www.teluu.com)
  *
  * This program is free software; you can redistribute it and/or modify
@@ -99,4 +99,32 @@
 }
 
+void UaConfig::readObject(const ContainerNode &node) throw(Error)
+{
+    ContainerNode this_node = node.readContainer("UaConfig");
+
+    NODE_READ_UNSIGNED( this_node, maxCalls);
+    NODE_READ_UNSIGNED( this_node, threadCnt);
+    NODE_READ_STRINGV ( this_node, nameserver);
+    NODE_READ_STRING  ( this_node, userAgent);
+    NODE_READ_STRINGV ( this_node, stunServer);
+    NODE_READ_BOOL    ( this_node, stunIgnoreFailure);
+    NODE_READ_INT     ( this_node, natTypeInSdp);
+    NODE_READ_BOOL    ( this_node, mwiUnsolicitedEnabled);
+}
+
+void UaConfig::writeObject(ContainerNode &node) const throw(Error)
+{
+    ContainerNode this_node = node.writeNewContainer("UaConfig");
+
+    NODE_WRITE_UNSIGNED( this_node, maxCalls);
+    NODE_WRITE_UNSIGNED( this_node, threadCnt);
+    NODE_WRITE_STRINGV ( this_node, nameserver);
+    NODE_WRITE_STRING  ( this_node, userAgent);
+    NODE_WRITE_STRINGV ( this_node, stunServer);
+    NODE_WRITE_BOOL    ( this_node, stunIgnoreFailure);
+    NODE_WRITE_INT     ( this_node, natTypeInSdp);
+    NODE_WRITE_BOOL    ( this_node, mwiUnsolicitedEnabled);
+}
+
 ///////////////////////////////////////////////////////////////////////////////
 
@@ -134,4 +162,28 @@
 
     return lc;
+}
+
+void LogConfig::readObject(const ContainerNode &node) throw(Error)
+{
+    ContainerNode this_node = node.readContainer("LogConfig");
+
+    NODE_READ_UNSIGNED( this_node, msgLogging);
+    NODE_READ_UNSIGNED( this_node, level);
+    NODE_READ_UNSIGNED( this_node, consoleLevel);
+    NODE_READ_UNSIGNED( this_node, decor);
+    NODE_READ_STRING  ( this_node, filename);
+    NODE_READ_UNSIGNED( this_node, fileFlags);
+}
+
+void LogConfig::writeObject(ContainerNode &node) const throw(Error)
+{
+    ContainerNode this_node = node.writeNewContainer("LogConfig");
+
+    NODE_WRITE_UNSIGNED( this_node, msgLogging);
+    NODE_WRITE_UNSIGNED( this_node, level);
+    NODE_WRITE_UNSIGNED( this_node, consoleLevel);
+    NODE_WRITE_UNSIGNED( this_node, decor);
+    NODE_WRITE_STRING  ( this_node, filename);
+    NODE_WRITE_UNSIGNED( this_node, fileFlags);
 }
 
@@ -206,4 +258,79 @@
 }
 
+void MediaConfig::readObject(const ContainerNode &node) throw(Error)
+{
+    ContainerNode this_node = node.readContainer("MediaConfig");
+
+    NODE_READ_UNSIGNED( this_node, clockRate);
+    NODE_READ_UNSIGNED( this_node, sndClockRate);
+    NODE_READ_UNSIGNED( this_node, channelCount);
+    NODE_READ_UNSIGNED( this_node, audioFramePtime);
+    NODE_READ_UNSIGNED( this_node, maxMediaPorts);
+    NODE_READ_BOOL    ( this_node, hasIoqueue);
+    NODE_READ_UNSIGNED( this_node, threadCnt);
+    NODE_READ_UNSIGNED( this_node, quality);
+    NODE_READ_UNSIGNED( this_node, ptime);
+    NODE_READ_BOOL    ( this_node, noVad);
+    NODE_READ_UNSIGNED( this_node, ilbcMode);
+    NODE_READ_UNSIGNED( this_node, txDropPct);
+    NODE_READ_UNSIGNED( this_node, rxDropPct);
+    NODE_READ_UNSIGNED( this_node, ecOptions);
+    NODE_READ_UNSIGNED( this_node, ecTailLen);
+    NODE_READ_UNSIGNED( this_node, sndRecLatency);
+    NODE_READ_UNSIGNED( this_node, sndPlayLatency);
+    NODE_READ_INT     ( this_node, jbInit);
+    NODE_READ_INT     ( this_node, jbMinPre);
+    NODE_READ_INT     ( this_node, jbMaxPre);
+    NODE_READ_INT     ( this_node, jbMax);
+    NODE_READ_INT     ( this_node, sndAutoCloseTime);
+    NODE_READ_BOOL    ( this_node, vidPreviewEnableNative);
+}
+
+void MediaConfig::writeObject(ContainerNode &node) const throw(Error)
+{
+    ContainerNode this_node = node.writeNewContainer("MediaConfig");
+
+    NODE_WRITE_UNSIGNED( this_node, clockRate);
+    NODE_WRITE_UNSIGNED( this_node, sndClockRate);
+    NODE_WRITE_UNSIGNED( this_node, channelCount);
+    NODE_WRITE_UNSIGNED( this_node, audioFramePtime);
+    NODE_WRITE_UNSIGNED( this_node, maxMediaPorts);
+    NODE_WRITE_BOOL    ( this_node, hasIoqueue);
+    NODE_WRITE_UNSIGNED( this_node, threadCnt);
+    NODE_WRITE_UNSIGNED( this_node, quality);
+    NODE_WRITE_UNSIGNED( this_node, ptime);
+    NODE_WRITE_BOOL    ( this_node, noVad);
+    NODE_WRITE_UNSIGNED( this_node, ilbcMode);
+    NODE_WRITE_UNSIGNED( this_node, txDropPct);
+    NODE_WRITE_UNSIGNED( this_node, rxDropPct);
+    NODE_WRITE_UNSIGNED( this_node, ecOptions);
+    NODE_WRITE_UNSIGNED( this_node, ecTailLen);
+    NODE_WRITE_UNSIGNED( this_node, sndRecLatency);
+    NODE_WRITE_UNSIGNED( this_node, sndPlayLatency);
+    NODE_WRITE_INT     ( this_node, jbInit);
+    NODE_WRITE_INT     ( this_node, jbMinPre);
+    NODE_WRITE_INT     ( this_node, jbMaxPre);
+    NODE_WRITE_INT     ( this_node, jbMax);
+    NODE_WRITE_INT     ( this_node, sndAutoCloseTime);
+    NODE_WRITE_BOOL    ( this_node, vidPreviewEnableNative);
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+void EpConfig::readObject(const ContainerNode &node) throw(Error)
+{
+    ContainerNode this_node = node.readContainer("EpConfig");
+    NODE_READ_OBJ( this_node, uaConfig);
+    NODE_READ_OBJ( this_node, logConfig);
+    NODE_READ_OBJ( this_node, medConfig);
+}
+
+void EpConfig::writeObject(ContainerNode &node) const throw(Error)
+{
+    ContainerNode this_node = node.writeNewContainer("EpConfig");
+    NODE_WRITE_OBJ( this_node, uaConfig);
+    NODE_WRITE_OBJ( this_node, logConfig);
+    NODE_WRITE_OBJ( this_node, medConfig);
+}
 
 ///////////////////////////////////////////////////////////////////////////////
@@ -783,5 +910,6 @@
 
     tcfg = cfg.toPj();
-    PJSUA2_CHECK_EXPR( pjsua_transport_create(type, &tcfg, &tid) );
+    PJSUA2_CHECK_EXPR( pjsua_transport_create(type,
+                                              &tcfg, &tid) );
 
     return tid;
Index: pjproject/branches/projects/pjsua2/pjsip/src/pjsua2/json.cpp
===================================================================
--- pjproject/branches/projects/pjsua2/pjsip/src/pjsua2/json.cpp	(revision 4644)
+++ pjproject/branches/projects/pjsua2/pjsip/src/pjsua2/json.cpp	(revision 4644)
@@ -0,0 +1,544 @@
+/* $Id$ */
+/*
+ * Copyright (C) 2013 Teluu Inc. (http://www.teluu.com)
+ *
+ * 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 <pjsua2/json.hpp>
+#include <pjlib-util/errno.h>
+#include <pj/file_io.h>
+#include "util.hpp"
+
+#define THIS_FILE	"json.cpp"
+
+using namespace pj;
+using namespace std;
+
+/* Json node operations */
+static bool		jsonNode_hasUnread(const ContainerNode*);
+static string		jsonNode_unreadName(const ContainerNode*n)
+				            throw(Error);
+static float		jsonNode_readNumber(const ContainerNode*,
+            		                    const string&)
+					      throw(Error);
+static bool		jsonNode_readBool(const ContainerNode*,
+           		                  const string&)
+					  throw(Error);
+static string		jsonNode_readString(const ContainerNode*,
+             		                    const string&)
+					    throw(Error);
+static StringVector	jsonNode_readStringVector(const ContainerNode*,
+                   	                          const string&)
+						  throw(Error);
+static ContainerNode	jsonNode_readContainer(const ContainerNode*,
+                    	                       const string &)
+					       throw(Error);
+static ContainerNode	jsonNode_readArray(const ContainerNode*,
+                    	                   const string &)
+					   throw(Error);
+static void		jsonNode_writeNumber(ContainerNode*,
+           		                     const string &name,
+           		                     float num)
+           		                     throw(Error);
+static void		jsonNode_writeBool(ContainerNode*,
+           		                   const string &name,
+           		                   bool value)
+					   throw(Error);
+static void		jsonNode_writeString(ContainerNode*,
+           		                     const string &name,
+           		                     const string &value)
+					     throw(Error);
+static void		jsonNode_writeStringVector(ContainerNode*,
+           		                           const string &name,
+           		                           const StringVector &value)
+					           throw(Error);
+static ContainerNode 	jsonNode_writeNewContainer(ContainerNode*,
+                     	                           const string &name)
+					           throw(Error);
+static ContainerNode 	jsonNode_writeNewArray(ContainerNode*,
+                     	                       const string &name)
+					       throw(Error);
+
+static container_node_op json_op =
+{
+    &jsonNode_hasUnread,
+    &jsonNode_unreadName,
+    &jsonNode_readNumber,
+    &jsonNode_readBool,
+    &jsonNode_readString,
+    &jsonNode_readStringVector,
+    &jsonNode_readContainer,
+    &jsonNode_readArray,
+    &jsonNode_writeNumber,
+    &jsonNode_writeBool,
+    &jsonNode_writeString,
+    &jsonNode_writeStringVector,
+    &jsonNode_writeNewContainer,
+    &jsonNode_writeNewArray
+};
+
+///////////////////////////////////////////////////////////////////////////////
+JsonDocument::JsonDocument()
+: root(NULL)
+{
+    pj_caching_pool_init(&cp, NULL, 0);
+    pool = pj_pool_create(&cp.factory, "jsondoc", 512, 512, NULL);
+    if (!pool)
+	PJSUA2_RAISE_ERROR(PJ_ENOMEM);
+}
+
+JsonDocument::~JsonDocument()
+{
+    if (pool)
+	pj_pool_release(pool);
+    pj_caching_pool_destroy(&cp);
+}
+
+void JsonDocument::initRoot() const
+{
+    rootNode.op = &json_op;
+    rootNode.data.doc = (void*)this;
+    rootNode.data.data1 = (void*)root;
+    rootNode.data.data2 = root->value.children.next;
+}
+
+void JsonDocument::loadFile(const string &filename) throw(Error)
+{
+    if (root)
+	PJSUA2_RAISE_ERROR3(PJ_EINVALIDOP, "JsonDocument.loadString()",
+	                    "Document already initialized");
+
+    if (!pj_file_exists(filename.c_str()))
+	PJSUA2_RAISE_ERROR(PJ_ENOTFOUND);
+
+    pj_ssize_t size = pj_file_size(filename.c_str());
+    pj_status_t status;
+
+    char *buffer = (char*)pj_pool_alloc(pool, size+1);
+    pj_oshandle_t fd = 0;
+    unsigned parse_size;
+    char err_msg[120];
+    pj_json_err_info err_info;
+
+    err_msg[0] = '\0';
+
+    status = pj_file_open(pool, filename.c_str(), PJ_O_RDONLY, &fd);
+    if (status != PJ_SUCCESS)
+	goto on_error;
+
+    status = pj_file_read(fd, buffer, &size);
+    if (status != PJ_SUCCESS)
+	goto on_error;
+
+    pj_file_close(fd);
+    fd = NULL;
+
+    if (size <= 0) {
+	status = PJ_EEOF;
+	goto on_error;
+    }
+
+    parse_size = (unsigned)size;
+    root = pj_json_parse(pool, buffer, &parse_size, &err_info);
+    if (root == NULL) {
+	pj_ansi_snprintf(err_msg, sizeof(err_msg),
+	                 "JSON parsing failed: syntax error in file '%s' at "
+	                 "line %d column %d",
+	                 filename.c_str(), err_info.line, err_info.col);
+	PJ_LOG(1,(THIS_FILE, err_msg));
+	status = PJLIB_UTIL_EINJSON;
+	goto on_error;
+    }
+
+    initRoot();
+    return;
+
+on_error:
+    if (fd)
+	pj_file_close(fd);
+    if (err_msg[0])
+	PJSUA2_RAISE_ERROR3(status, "loadFile()", err_msg);
+    else
+	PJSUA2_RAISE_ERROR(status);
+}
+
+void JsonDocument::loadString(const string &input) throw(Error)
+{
+    if (root)
+	PJSUA2_RAISE_ERROR3(PJ_EINVALIDOP, "JsonDocument.loadString()",
+	                    "Document already initialized");
+
+    unsigned size = input.size();
+    char *buffer = (char*)pj_pool_alloc(pool, size+1);
+    unsigned parse_size = (unsigned)size;
+    pj_json_err_info err_info;
+
+    pj_memcpy(buffer, input.c_str(), size);
+
+    root = pj_json_parse(pool, buffer, &parse_size, &err_info);
+    if (root == NULL) {
+	char err_msg[80];
+
+	pj_ansi_snprintf(err_msg, sizeof(err_msg),
+	                 "JSON parsing failed at line %d column %d",
+	                 err_info.line, err_info.col);
+	PJ_LOG(1,(THIS_FILE, err_msg));
+	PJSUA2_RAISE_ERROR3(PJLIB_UTIL_EINJSON, "loadString()", err_msg);
+    }
+    initRoot();
+}
+
+struct save_file_data
+{
+    pj_oshandle_t fd;
+};
+
+static pj_status_t json_file_writer(const char *s,
+				    unsigned size,
+				    void *user_data)
+{
+    save_file_data *sd = (save_file_data*)user_data;
+    pj_ssize_t ssize = (pj_ssize_t)size;
+    return pj_file_write(sd->fd, s, &ssize);
+}
+
+void JsonDocument::saveFile(const string &filename) throw(Error)
+{
+    struct save_file_data sd;
+    pj_status_t status;
+
+    /* Make sure root container has been created */
+    getRootContainer();
+
+    status = pj_file_open(pool, filename.c_str(), PJ_O_WRONLY, &sd.fd);
+    if (status != PJ_SUCCESS)
+	PJSUA2_RAISE_ERROR(status);
+
+    status = pj_json_writef(root, &json_file_writer, &sd.fd);
+    pj_file_close(sd.fd);
+
+    if (status != PJ_SUCCESS)
+	PJSUA2_RAISE_ERROR(status);
+}
+
+struct save_string_data
+{
+    string	output;
+};
+
+static pj_status_t json_string_writer(const char *s,
+                                      unsigned size,
+                                      void *user_data)
+{
+    save_string_data *sd = (save_string_data*)user_data;
+    sd->output.append(s, size);
+    return PJ_SUCCESS;
+}
+
+string JsonDocument::saveString() throw(Error)
+{
+    struct save_string_data sd;
+    pj_status_t status;
+
+    /* Make sure root container has been created */
+    getRootContainer();
+
+    status = pj_json_writef(root, &json_string_writer, &sd);
+    if (status != PJ_SUCCESS)
+	PJSUA2_RAISE_ERROR(status);
+
+    return sd.output;
+}
+
+ContainerNode & JsonDocument::getRootContainer() const
+{
+    if (!root) {
+	root = allocElement();
+	pj_json_elem_obj(root, NULL);
+	initRoot();
+    }
+
+    return rootNode;
+}
+
+pj_json_elem* JsonDocument::allocElement() const
+{
+    return (pj_json_elem*)pj_pool_alloc(pool, sizeof(pj_json_elem));
+}
+
+pj_pool_t *JsonDocument::getPool()
+{
+    return pool;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+struct json_node_data
+{
+    JsonDocument	*doc;
+    pj_json_elem	*jnode;
+    pj_json_elem	*childPtr;
+};
+
+static bool jsonNode_hasUnread(const ContainerNode *node)
+{
+    json_node_data *jdat = (json_node_data*)&node->data;
+    return jdat->childPtr != (pj_json_elem*)&jdat->jnode->value.children;
+}
+
+static void json_verify(struct json_node_data *jdat,
+                        const char *op,
+                        const string &name,
+                        pj_json_val_type type)
+{
+    if (jdat->childPtr == (pj_json_elem*)&jdat->jnode->value.children)
+	PJSUA2_RAISE_ERROR3(PJ_EEOF, op, "No unread element");
+
+    /* If name is specified, then check if the names match, except
+     * when the node name itself is empty and the parent node is
+     * an array, then ignore the checking (JSON doesn't allow array
+     * elements to have name).
+     */
+    if (name.size() && name.compare(0, name.size(),
+                                    jdat->childPtr->name.ptr,
+                                    jdat->childPtr->name.slen) &&
+        jdat->childPtr->name.slen &&
+        jdat->jnode->type != PJ_JSON_VAL_ARRAY)
+    {
+	char err_msg[80];
+	pj_ansi_snprintf(err_msg, sizeof(err_msg),
+	                 "Name mismatch: expecting '%s' got '%.*s'",
+	                 name.c_str(), (int)jdat->childPtr->name.slen,
+	                 jdat->childPtr->name.ptr);
+	PJSUA2_RAISE_ERROR3(PJLIB_UTIL_EINJSON, op, err_msg);
+    }
+
+    if (type != PJ_JSON_VAL_NULL && jdat->childPtr->type != type) {
+	char err_msg[80];
+	pj_ansi_snprintf(err_msg, sizeof(err_msg),
+	                 "Type mismatch: expecting %d got %d",
+	                 type, jdat->childPtr->type);
+	PJSUA2_RAISE_ERROR3(PJLIB_UTIL_EINJSON, op, err_msg);
+    }
+}
+
+static string jsonNode_unreadName(const ContainerNode *node)
+				  throw(Error)
+{
+    json_node_data *jdat = (json_node_data*)&node->data;
+    json_verify(jdat, "unreadName()", "", PJ_JSON_VAL_NULL);
+    return pj2Str(jdat->childPtr->name);
+}
+
+static float jsonNode_readNumber(const ContainerNode *node,
+            		         const string &name)
+				 throw(Error)
+{
+    json_node_data *jdat = (json_node_data*)&node->data;
+    json_verify(jdat, "readNumber()", name, PJ_JSON_VAL_NUMBER);
+    jdat->childPtr = jdat->childPtr->next;
+    return jdat->childPtr->prev->value.num;
+}
+
+static bool jsonNode_readBool(const ContainerNode *node,
+			      const string &name)
+			      throw(Error)
+{
+    json_node_data *jdat = (json_node_data*)&node->data;
+    json_verify(jdat, "readBool()", name, PJ_JSON_VAL_BOOL);
+    jdat->childPtr = jdat->childPtr->next;
+    return jdat->childPtr->prev->value.is_true;
+}
+
+static string jsonNode_readString(const ContainerNode *node,
+				  const string &name)
+				  throw(Error)
+{
+    json_node_data *jdat = (json_node_data*)&node->data;
+    json_verify(jdat, "readString()", name, PJ_JSON_VAL_STRING);
+    jdat->childPtr = jdat->childPtr->next;
+    return pj2Str(jdat->childPtr->prev->value.str);
+}
+
+static StringVector jsonNode_readStringVector(const ContainerNode *node,
+                   	                      const string &name)
+					      throw(Error)
+{
+    json_node_data *jdat = (json_node_data*)&node->data;
+    json_verify(jdat, "readStringVector()", name, PJ_JSON_VAL_ARRAY);
+
+    StringVector result;
+    pj_json_elem *child = jdat->childPtr->value.children.next;
+    while (child != (pj_json_elem*)&jdat->childPtr->value.children) {
+	if (child->type != PJ_JSON_VAL_STRING) {
+	    char err_msg[80];
+	    pj_ansi_snprintf(err_msg, sizeof(err_msg),
+			     "Elements not string but type %d",
+			     child->type);
+	    PJSUA2_RAISE_ERROR3(PJLIB_UTIL_EINJSON, "readStringVector()",
+	                        err_msg);
+	}
+	result.push_back(pj2Str(child->value.str));
+	child = child->next;
+    }
+
+    jdat->childPtr = jdat->childPtr->next;
+    return result;
+}
+
+static ContainerNode jsonNode_readContainer(const ContainerNode *node,
+                    	                    const string &name)
+					    throw(Error)
+{
+    json_node_data *jdat = (json_node_data*)&node->data;
+    json_verify(jdat, "readContainer()", name, PJ_JSON_VAL_OBJ);
+
+    ContainerNode json_node;
+
+    json_node.op = &json_op;
+    json_node.data.doc = (void*)jdat->doc;
+    json_node.data.data1 = (void*)jdat->childPtr;
+    json_node.data.data2 = (void*)jdat->childPtr->value.children.next;
+
+    jdat->childPtr = jdat->childPtr->next;
+    return json_node;
+}
+
+static ContainerNode jsonNode_readArray(const ContainerNode *node,
+                    	                const string &name)
+					throw(Error)
+{
+    json_node_data *jdat = (json_node_data*)&node->data;
+    json_verify(jdat, "readArray()", name, PJ_JSON_VAL_ARRAY);
+
+    ContainerNode json_node;
+
+    json_node.op = &json_op;
+    json_node.data.doc = (void*)jdat->doc;
+    json_node.data.data1 = (void*)jdat->childPtr;
+    json_node.data.data2 = (void*)jdat->childPtr->value.children.next;
+
+    jdat->childPtr = jdat->childPtr->next;
+    return json_node;
+}
+
+static pj_str_t alloc_name(JsonDocument *doc, const string &name)
+{
+    pj_str_t new_name;
+    pj_strdup2(doc->getPool(), &new_name, name.c_str());
+    return new_name;
+}
+
+static void jsonNode_writeNumber(ContainerNode *node,
+           		         const string &name,
+           		         float num)
+           		         throw(Error)
+{
+    json_node_data *jdat = (json_node_data*)&node->data;
+    pj_json_elem *el = jdat->doc->allocElement();
+    pj_str_t nm = alloc_name(jdat->doc, name);
+    pj_json_elem_number(el, &nm, num);
+    pj_json_elem_add(jdat->jnode, el);
+}
+
+static void jsonNode_writeBool(ContainerNode *node,
+           		       const string &name,
+           		       bool value)
+			       throw(Error)
+{
+    json_node_data *jdat = (json_node_data*)&node->data;
+    pj_json_elem *el = jdat->doc->allocElement();
+    pj_str_t nm = alloc_name(jdat->doc, name);
+    pj_json_elem_bool(el, &nm, value);
+    pj_json_elem_add(jdat->jnode, el);
+}
+
+static void jsonNode_writeString(ContainerNode *node,
+           		         const string &name,
+           		         const string &value)
+				 throw(Error)
+{
+    json_node_data *jdat = (json_node_data*)&node->data;
+    pj_json_elem *el = jdat->doc->allocElement();
+    pj_str_t nm = alloc_name(jdat->doc, name);
+    pj_str_t new_val;
+    pj_strdup2(jdat->doc->getPool(), &new_val, value.c_str());
+    pj_json_elem_string(el, &nm, &new_val);
+
+    pj_json_elem_add(jdat->jnode, el);
+}
+
+static void jsonNode_writeStringVector(ContainerNode *node,
+           		               const string &name,
+           		               const StringVector &value)
+				       throw(Error)
+{
+    json_node_data *jdat = (json_node_data*)&node->data;
+    pj_json_elem *el = jdat->doc->allocElement();
+    pj_str_t nm = alloc_name(jdat->doc, name);
+
+    pj_json_elem_array(el, &nm);
+    for (unsigned i=0; i<value.size(); ++i) {
+	pj_str_t new_val;
+
+	pj_strdup2(jdat->doc->getPool(), &new_val, value[i].c_str());
+	pj_json_elem *child = jdat->doc->allocElement();
+	pj_json_elem_string(child, NULL, &new_val);
+	pj_json_elem_add(el, child);
+    }
+
+    pj_json_elem_add(jdat->jnode, el);
+}
+
+static ContainerNode jsonNode_writeNewContainer(ContainerNode *node,
+                     	                        const string &name)
+					        throw(Error)
+{
+    json_node_data *jdat = (json_node_data*)&node->data;
+    pj_json_elem *el = jdat->doc->allocElement();
+    pj_str_t nm = alloc_name(jdat->doc, name);
+
+    pj_json_elem_obj(el, &nm);
+    pj_json_elem_add(jdat->jnode, el);
+
+    ContainerNode json_node;
+
+    json_node.op = &json_op;
+    json_node.data.doc = (void*)jdat->doc;
+    json_node.data.data1 = (void*)el;
+    json_node.data.data2 = (void*)el->value.children.next;
+
+    return json_node;
+}
+
+static ContainerNode jsonNode_writeNewArray(ContainerNode *node,
+                     	                    const string &name)
+					    throw(Error)
+{
+    json_node_data *jdat = (json_node_data*)&node->data;
+    pj_json_elem *el = jdat->doc->allocElement();
+    pj_str_t nm = alloc_name(jdat->doc, name);
+
+    pj_json_elem_array(el, &nm);
+    pj_json_elem_add(jdat->jnode, el);
+
+    ContainerNode json_node;
+
+    json_node.op = &json_op;
+    json_node.data.doc = (void*)jdat->doc;
+    json_node.data.data1 = (void*)el;
+    json_node.data.data2 = (void*)el->value.children.next;
+
+    return json_node;
+}
Index: pjproject/branches/projects/pjsua2/pjsip/src/pjsua2/persistent.cpp
===================================================================
--- pjproject/branches/projects/pjsua2/pjsip/src/pjsua2/persistent.cpp	(revision 4644)
+++ pjproject/branches/projects/pjsua2/pjsip/src/pjsua2/persistent.cpp	(revision 4644)
@@ -0,0 +1,227 @@
+/* $Id$ */
+/*
+ * Copyright (C) 2013 Teluu Inc. (http://www.teluu.com)
+ *
+ * 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 <pjsua2/persistent.hpp>
+
+using namespace pj;
+using namespace std;
+
+
+bool PersistentDocument::hasUnread() const
+{
+    return getRootContainer().hasUnread();
+}
+
+string PersistentDocument::unreadName() const throw(Error)
+{
+    return getRootContainer().unreadName();
+}
+
+int PersistentDocument::readInt(const string &name) const throw(Error)
+{
+    return (int)getRootContainer().readNumber(name);
+}
+
+float PersistentDocument::readNumber(const string &name) const throw(Error)
+{
+    return getRootContainer().readNumber(name);
+}
+
+bool PersistentDocument::readBool(const string &name) const throw(Error)
+{
+    return getRootContainer().readBool(name);
+}
+
+string PersistentDocument::readString(const string &name) const throw(Error)
+{
+    return getRootContainer().readString(name);
+}
+
+StringVector PersistentDocument::readStringVector(const string &name) const
+						  throw(Error)
+{
+    return getRootContainer().readStringVector(name);
+}
+
+void PersistentDocument::readObject(PersistentObject &obj) const throw(Error)
+{
+    getRootContainer().readObject(obj);
+}
+
+ContainerNode PersistentDocument::readContainer(const string &name) const
+					        throw(Error)
+{
+    return getRootContainer().readContainer(name);
+}
+
+ContainerNode PersistentDocument::readArray(const string &name) const
+					    throw(Error)
+{
+    return getRootContainer().readArray(name);
+}
+
+void PersistentDocument::writeNumber(const string &name,
+				     float num) throw(Error)
+{
+    getRootContainer().writeNumber(name, num);
+}
+
+void PersistentDocument::writeInt(const string &name,
+				  int num) throw(Error)
+{
+    getRootContainer().writeNumber(name, num);
+}
+
+void PersistentDocument::writeBool(const string &name,
+				   bool value) throw(Error)
+{
+    getRootContainer().writeBool(name, value);
+}
+
+void PersistentDocument::writeString(const string &name,
+                                     const string &value) throw(Error)
+{
+    getRootContainer().writeString(name, value);
+}
+
+void PersistentDocument::writeStringVector(const string &name,
+                                           const StringVector &value)
+					   throw(Error)
+{
+    getRootContainer().writeStringVector(name, value);
+}
+
+void PersistentDocument::writeObject(const PersistentObject &obj) throw(Error)
+{
+    getRootContainer().writeObject(obj);
+}
+
+ContainerNode PersistentDocument::writeNewContainer(const string &name)
+						    throw(Error)
+{
+    return getRootContainer().writeNewContainer(name);
+}
+
+ContainerNode PersistentDocument::writeNewArray(const string &name)
+						    throw(Error)
+{
+    return getRootContainer().writeNewArray(name);
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+bool ContainerNode::hasUnread() const
+{
+    return op->hasUnread(this);
+}
+
+string ContainerNode::unreadName() const throw(Error)
+{
+    return op->unreadName(this);
+}
+
+int ContainerNode::readInt(const string &name) const throw(Error)
+{
+    return (int)op->readNumber(this, name);
+}
+
+float ContainerNode::readNumber(const string &name) const throw(Error)
+{
+    return op->readNumber(this, name);
+}
+
+bool ContainerNode::readBool(const string &name) const throw(Error)
+{
+    return op->readBool(this, name);
+}
+
+string ContainerNode::readString(const string &name) const throw(Error)
+{
+    return op->readString(this, name);
+}
+
+StringVector ContainerNode::readStringVector(const string &name) const
+					     throw(Error)
+{
+    return op->readStringVector(this, name);
+}
+
+void ContainerNode::readObject(PersistentObject &obj) const throw(Error)
+{
+    obj.readObject(*this);
+}
+
+ContainerNode ContainerNode::readContainer(const string &name) const
+					   throw(Error)
+{
+    return op->readContainer(this, name);
+}
+
+ContainerNode ContainerNode::readArray(const string &name) const
+					   throw(Error)
+{
+    return op->readArray(this, name);
+}
+
+void ContainerNode::writeNumber(const string &name,
+				float num) throw(Error)
+{
+    return op->writeNumber(this, name, num);
+}
+
+void ContainerNode::writeInt(const string &name,
+			     int num) throw(Error)
+{
+    return op->writeNumber(this, name, num);
+}
+
+void ContainerNode::writeBool(const string &name,
+			      bool value) throw(Error)
+{
+    return op->writeBool(this, name, value);
+}
+
+void ContainerNode::writeString(const string &name,
+				const string &value) throw(Error)
+{
+    return op->writeString(this, name, value);
+}
+
+void ContainerNode::writeStringVector(const string &name,
+				      const StringVector &value)
+				      throw(Error)
+{
+    return op->writeStringVector(this, name, value);
+}
+
+void ContainerNode::writeObject(const PersistentObject &obj) throw(Error)
+{
+    obj.writeObject(*this);
+}
+
+ContainerNode ContainerNode::writeNewContainer(const string &name)
+					       throw(Error)
+{
+    return op->writeNewContainer(this, name);
+}
+
+ContainerNode ContainerNode::writeNewArray(const string &name)
+					   throw(Error)
+{
+    return op->writeNewArray(this, name);
+}
Index: pjproject/branches/projects/pjsua2/pjsip/src/pjsua2/types.cpp
===================================================================
--- pjproject/branches/projects/pjsua2/pjsip/src/pjsua2/types.cpp	(revision 4643)
+++ pjproject/branches/projects/pjsua2/pjsip/src/pjsua2/types.cpp	(revision 4644)
@@ -1,5 +1,5 @@
 /* $Id$ */
 /*
- * Copyright (C) 2012 Teluu Inc. (http://www.teluu.com)
+ * Copyright (C) 2013 Teluu Inc. (http://www.teluu.com)
  *
  * This program is free software; you can redistribute it and/or modify
@@ -86,175 +86,2 @@
 }
 
-///////////////////////////////////////////////////////////////////////////////
-
-AuthCredInfo::AuthCredInfo()
-: dataType(0)
-{
-}
-
-AuthCredInfo::AuthCredInfo(const string &param_scheme,
-			   const string &param_realm,
-			   const string &param_user_name,
-			   const int param_data_type,
-			   const string param_data)
-: scheme(param_scheme), realm(param_realm), username(param_user_name),
-  dataType(param_data_type), data(param_data)
-{
-}
-
-
-///////////////////////////////////////////////////////////////////////////////
-
-TlsConfig::TlsConfig()
-{
-    pjsip_tls_setting ts;
-    pjsip_tls_setting_default(&ts);
-    this->fromPj(ts);
-}
-
-pjsip_tls_setting TlsConfig::toPj() const
-{
-    pjsip_tls_setting ts;
-
-    ts.ca_list_file	= str2Pj(this->CaListFile);
-    ts.cert_file	= str2Pj(this->certFile);
-    ts.privkey_file	= str2Pj(this->privKeyFile);
-    ts.password		= str2Pj(this->password);
-    ts.method		= this->method;
-    ts.ciphers_num	= this->ciphers.size();
-    // The following will only work if sizeof(enum)==sizeof(int)
-    pj_assert(sizeof(ts.ciphers[0]) == sizeof(int));
-    ts.ciphers		= (pj_ssl_cipher*)&this->ciphers[0];
-    ts.verify_server	= this->verifyServer;
-    ts.verify_client	= this->verifyClient;
-    ts.require_client_cert = this->requireClientCert;
-    ts.timeout.sec 	= this->msecTimeout / 1000;
-    ts.timeout.msec	= this->msecTimeout % 1000;
-    ts.qos_type		= this->qosType;
-    ts.qos_params	= this->qosParams;
-    ts.qos_ignore_error	= this->qosIgnoreError;
-
-    return ts;
-}
-
-void TlsConfig::fromPj(const pjsip_tls_setting &prm)
-{
-    this->CaListFile 	= pj2Str(prm.ca_list_file);
-    this->certFile 	= pj2Str(prm.cert_file);
-    this->privKeyFile 	= pj2Str(prm.privkey_file);
-    this->password 	= pj2Str(prm.password);
-    this->method 	= (pjsip_ssl_method)prm.method;
-    // The following will only work if sizeof(enum)==sizeof(int)
-    pj_assert(sizeof(prm.ciphers[0]) == sizeof(int));
-    this->ciphers 	= IntVector(prm.ciphers, prm.ciphers+prm.ciphers_num);
-    this->verifyServer 	= prm.verify_server;
-    this->verifyClient 	= prm.verify_client;
-    this->requireClientCert = prm.require_client_cert;
-    this->msecTimeout 	= PJ_TIME_VAL_MSEC(prm.timeout);
-    this->qosType 	= prm.qos_type;
-    this->qosParams 	= prm.qos_params;
-    this->qosIgnoreError = prm.qos_ignore_error;
-}
-
-///////////////////////////////////////////////////////////////////////////////
-
-TransportConfig::TransportConfig()
-{
-    pjsua_transport_config tc;
-    pjsua_transport_config_default(&tc);
-    this->fromPj(tc);
-}
-
-void TransportConfig::fromPj(const pjsua_transport_config &prm)
-{
-    this->port 		= prm.port;
-    this->portRange	= prm.port_range;
-    this->publicAddress = pj2Str(prm.public_addr);
-    this->boundAddress	= pj2Str(prm.bound_addr);
-    this->tlsConfig.fromPj(prm.tls_setting);
-    this->qosType	= prm.qos_type;
-    this->qosParams	= prm.qos_params;
-}
-
-pjsua_transport_config TransportConfig::toPj() const
-{
-    pjsua_transport_config tc;
-
-    tc.port		= this->port;
-    tc.port_range	= this->portRange;
-    tc.public_addr	= str2Pj(this->publicAddress);
-    tc.bound_addr	= str2Pj(this->boundAddress);
-    tc.tls_setting	= this->tlsConfig.toPj();
-    tc.qos_type		= this->qosType;
-    tc.qos_params	= this->qosParams;
-
-    return tc;
-}
-
-///////////////////////////////////////////////////////////////////////////////
-
-TransportInfo::TransportInfo(const pjsua_transport_info &info)
-{
-    this->id = info.id;
-    this->type = info.type;
-    this->typeName = pj2Str(info.type_name);
-    this->info = pj2Str(info.info);
-    this->flags = info.flag;
-
-    char straddr[PJ_INET6_ADDRSTRLEN+10];
-    pj_sockaddr_print(&info.local_addr, straddr, sizeof(straddr), 3);
-    this->localAddress = straddr;
-
-    pj_ansi_snprintf(straddr, sizeof(straddr), "%.*s:%d",
-                     (int)info.local_name.host.slen,
-                     info.local_name.host.ptr,
-                     info.local_name.port);
-    this->localName = straddr;
-    this->usageCount = info.usage_count;
-}
-
-///////////////////////////////////////////////////////////////////////////////
-
-void SipRxData::fromPj(pjsip_rx_data &rdata)
-{
-    info	= pjsip_rx_data_get_info(&rdata);
-    wholeMsg	= string(rdata.msg_info.msg_buf, rdata.msg_info.len);
-    srcIp	= rdata.pkt_info.src_name;
-    srcPort	= rdata.pkt_info.src_port;
-}
-
-///////////////////////////////////////////////////////////////////////////////
-
-void SipHeader::fromPj(const pjsip_hdr *hdr) throw(Error)
-{
-    char buf[256];
-
-    int len = pjsip_hdr_print_on((void*)hdr, buf, sizeof(buf)-1);
-    if (len <= 0)
-	PJSUA2_RAISE_ERROR(PJ_ETOOSMALL);
-    buf[len] = '\0';
-
-    char *pos = strchr(buf, ':');
-    if (!pos)
-	PJSUA2_RAISE_ERROR(PJSIP_EINVALIDHDR);
-
-    // Trim white space after header name
-    char *end_name = pos;
-    while (end_name>buf && pj_isspace(*(end_name-1))) --end_name;
-
-    // Trim whitespaces after colon
-    char *start_val = pos+1;
-    while (*start_val && pj_isspace(*start_val)) ++start_val;
-
-    hName = string(buf, end_name);
-    hValue = string(start_val);
-}
-
-pjsip_generic_string_hdr &SipHeader::toPj() const
-{
-    pj_str_t hname  = str2Pj(hName);
-    pj_str_t hvalue = str2Pj(hValue);
-
-    pjsip_generic_string_hdr_init2(&pjHdr, &hname, &hvalue);
-    return pjHdr;
-}
Index: pjproject/branches/projects/pjsua2/pjsip/src/pjsua2/util.hpp
===================================================================
--- pjproject/branches/projects/pjsua2/pjsip/src/pjsua2/util.hpp	(revision 4643)
+++ pjproject/branches/projects/pjsua2/pjsip/src/pjsua2/util.hpp	(revision 4644)
@@ -1,5 +1,5 @@
 /* $Id$ */
 /*
- * Copyright (C) 2012 Teluu Inc. (http://www.teluu.com)
+ * Copyright (C) 2013 Teluu Inc. (http://www.teluu.com)
  *
  * This program is free software; you can redistribute it and/or modify
