Index: pjproject/trunk/pjsip-apps/build/py_pjsua.dsp
===================================================================
--- pjproject/trunk/pjsip-apps/build/py_pjsua.dsp	(revision 850)
+++ pjproject/trunk/pjsip-apps/build/py_pjsua.dsp	(revision 851)
@@ -99,4 +99,9 @@
 # Begin Source File
 
+SOURCE=..\src\py_pjsua\pjsua_app.py
+# PROP Exclude_From_Build 1
+# End Source File
+# Begin Source File
+
 SOURCE=..\src\py_pjsua\py_pjsua.c
 # End Source File
Index: pjproject/trunk/pjsip-apps/src/py_pjsua/pjsua.py
===================================================================
--- pjproject/trunk/pjsip-apps/src/py_pjsua/pjsua.py	(revision 850)
+++ pjproject/trunk/pjsip-apps/src/py_pjsua/pjsua.py	(revision 851)
@@ -8,7 +8,7 @@
 # Create configuration objects
 #
-ua_cfg = py_pjsua.Config()
-log_cfg = py_pjsua.Logging_Config()
-media_cfg = py_pjsua.Media_Config()
+ua_cfg = py_pjsua.config_default()
+log_cfg = py_pjsua.logging_config_default()
+media_cfg = py_pjsua.media_config_default()
 
 #
@@ -18,11 +18,4 @@
     print str,
 
-
-#
-# Initialize configs with default values.
-#
-py_pjsua.config_default(ua_cfg)
-py_pjsua.logging_config_default(log_cfg)
-py_pjsua.media_config_default(media_cfg)
 
 #
@@ -47,6 +40,6 @@
 
 
-message = py_pjsua.Msg_Data()
-py_pjsua.msg_data_init(message)
+message = py_pjsua.msg_data_init()
+
 print "identitas object message data :" + `message`
 
@@ -76,22 +69,21 @@
 
 # lib transport
-stunc = py_pjsua.STUN_Config();
-py_pjsua.stun_config_default(stunc);
+stunc = py_pjsua.stun_config_default();
 
-tc = py_pjsua.Transport_Config();
-py_pjsua.transport_config_default(tc);
+
+tc = py_pjsua.transport_config_default();
+
 
 py_pjsua.normalize_stun_config(stunc);
 
-id = py_pjsua.Transport_ID();
-status = py_pjsua.transport_create(1, tc, id);
+
+status, id = py_pjsua.transport_create(1, tc);
 print "py transport create status " + `status`
 
-t_id = id.transport_id;
 ti = py_pjsua.Transport_Info();
-status = py_pjsua.transport_get_info(t_id,ti)
+ti = py_pjsua.transport_get_info(id)
 print "py transport get info status " + `status`
 
-status = py_pjsua.transport_set_enable(t_id,1)
+status = py_pjsua.transport_set_enable(id,1)
 print "py transport set enable status " + `status`
 if status != 0 :
@@ -99,5 +91,5 @@
 
 
-status = py_pjsua.transport_close(t_id,1)
+status = py_pjsua.transport_close(id,1)
 print "py transport close status " + `status`
 if status != 0 :
@@ -108,8 +100,6 @@
 # lib account 
 
-accfg = py_pjsua.Acc_Config()
-py_pjsua.acc_config_default(accfg)
-accid = py_pjsua.Acc_ID()
-status = py_pjsua.acc_add(accfg, 1, accid)
+accfg = py_pjsua.acc_config_default()
+status, accid = py_pjsua.acc_add(accfg, 1)
 print "py acc add status " + `status`
 if status != 0 :
@@ -118,9 +108,33 @@
 print "acc count " + `count`
 
-accid.acc_id = py_pjsua.acc_get_default()
+accid = py_pjsua.acc_get_default()
 
-print "acc id default " + `accid.acc_id`
+print "acc id default " + `accid`
 
 # end of lib account
+
+#lib buddy
+
+bcfg = py_pjsua.Buddy_Config()
+status, id = py_pjsua.buddy_add(bcfg)
+print "py buddy add status " + `status` + " id " + `id`
+bool = py_pjsua.buddy_is_valid(id)
+print "py buddy is valid " + `bool`
+count = py_pjsua.get_buddy_count()
+print "buddy count " + `count`
+binfo = py_pjsua.buddy_get_info(id)
+ids = py_pjsua.enum_buddies(3)
+status = py_pjsua.buddy_del(id)
+print "py buddy del status " + `status`
+status = py_pjsua.buddy_subscribe_pres(id, 1)
+print "py buddy subscribe pres status " + `status`
+py_pjsua.pres_dump(1)
+status = py_pjsua.im_send(accid, "fahris@divusi.com", "", "hallo", message, 0)
+print "py im send status " + `status`
+status = py_pjsua.im_typing(accid, "fahris@divusi.com", 1, message)
+print "py im typing status " + `status`
+#print "binfo " + `binfo`
+
+#end of lib buddy
 
 py_pjsua.perror("saya","hallo",70006)
Index: pjproject/trunk/pjsip-apps/src/py_pjsua/pjsua_app.py
===================================================================
--- pjproject/trunk/pjsip-apps/src/py_pjsua/pjsua_app.py	(revision 851)
+++ pjproject/trunk/pjsip-apps/src/py_pjsua/pjsua_app.py	(revision 851)
@@ -0,0 +1,169 @@
+import py_pjsua
+import sys
+import thread
+
+#
+# Configurations
+#
+APP = "pjsua_app.py"
+C_QUIT = 0
+C_LOG_LEVEL = 3
+
+C_SIP_PORT = 5060
+C_STUN_SRV = ""
+C_STUN_PORT = 3478
+
+C_ACC_REGISTRAR = ""
+#C_ACC_REGISTRAR = "sip:iptel.org"
+C_ACC_ID = "sip:bulukucing1@iptel.org"
+C_ACC_REALM = "iptel.org"
+C_ACC_USERNAME = "bulukucing1"
+C_ACC_PASSWORD = "netura"
+
+# Display PJ error and exit
+def err_exit(title, rc):
+    py_pjsua.perror(APP, title, rc)
+    exit(1)
+
+# Logging callback
+def log_cb(level, str, len):
+    if level >= C_LOG_LEVEL:
+        print str,
+
+# Initialize pjsua
+def app_init():
+    # Create pjsua before anything else
+    status = py_pjsua.create()
+    if status != 0:
+        err_exit("pjsua create() error", status)
+
+    # Create and initialize logging config
+    log_cfg = py_pjsua.logging_config_default()
+    log_cfg.level = C_LOG_LEVEL
+    log_cfg.cb = log_cb
+
+    # Create and initialize pjsua config
+    ua_cfg = py_pjsua.config_default()
+    ua_cfg.thread_cnt = 0
+    ua_cfg.user_agent = "PJSUA/Python 0.1"
+
+    # Create and initialize media config
+    med_cfg = py_pjsua.media_config_default()
+    med_cfg.ec_tail_len = 0
+
+    #
+    # Initialize pjsua!!
+    #
+    status = py_pjsua.init(ua_cfg, log_cfg, med_cfg)
+    if status != 0:
+        err_exit("pjsua init() error", status)
+
+    # Configure STUN config
+    stun_cfg = py_pjsua.stun_config_default()
+    stun_cfg.stun_srv1 = C_STUN_SRV
+    stun_cfg.stun_srv2 = C_STUN_SRV
+    stun_cfg.stun_port1 = C_STUN_PORT
+    stun_cfg.stun_port2 = C_STUN_PORT
+
+    # Configure UDP transport config
+    transport_cfg = py_pjsua.transport_config_default()
+    transport_cfg.port = C_SIP_PORT
+    transport_cfg.stun_config = stun_cfg
+    if C_STUN_SRV != "":
+        transport_cfg.use_stun = 1
+
+    # Create UDP transport
+    # Note: transport_id is supposed to be integer
+    status, transport_id = py_pjsua.transport_create(1, transport_cfg)
+    if status != 0:
+        py_pjsua.destroy()
+        err_exit("Error creating UDP transport", status)
+
+
+    # Configure account configuration
+    acc_cfg = py_pjsua.acc_config_default()
+    acc_cfg.id = C_ACC_ID
+    acc_cfg.reg_uri = C_ACC_REGISTRAR
+    acc_cfg.cred_count = 1
+    acc_cfg.cred_info[0].realm = C_ACC_REALM
+    acc_cfg.cred_info[0].scheme = "digest"
+    acc_cfg.cred_info[0].username = C_ACC_USERNAME
+    acc_cfg.cred_info[0].data_type = 0
+    acc_cfg.cred_info[0].data = C_ACC_PASSWORD
+
+    # Add new SIP account
+    # Note: acc_id is supposed to be integer
+    status, acc_id = py_pjsua.acc_add(acc_cfg, 1)
+    if status != 0:
+        py_pjsua.destroy()
+        err_exit("Error adding SIP account", status)
+
+
+# Worker thread function
+def worker_thread_main(arg):
+    thread_desc = 0;
+    status = py_pjsua.thread_register("worker thread", thread_desc)
+    if status != 0:
+        py_pjsua.perror(APP, "Error registering thread", status)
+    else:
+        while C_QUIT == 0:
+            py_pjsua.handle_events(50)
+
+# Start pjsua
+def app_start():
+    # Done with initialization, start pjsua!!
+    #
+    status = py_pjsua.start()
+    if status != 0:
+        py_pjsua.destroy()
+        err_exit("Error starting pjsua!", status)
+
+    # Start worker thread
+    thr = thread.start_new(worker_thread_main, (0,))
+    
+    print "PJSUA Started!!"
+
+
+# Print application menu
+def print_menu():
+    print "Menu:"
+    print "  q   Quit application"
+    print "  s   Add buddy"
+    print "Choice: ",
+
+    
+# Menu
+def app_menu():
+    quit = 0
+    while quit == 0:
+        print_menu()
+        choice = sys.stdin.readline()
+        if choice[0] == "q":
+            quit = 1
+        elif choice[0] == "s":
+            bc = py_pjsua.Buddy_Config()
+            print "Buddy URI: ",
+            bc.uri = sys.stdin.readline()
+            if bc.uri == "":
+                continue
+            
+            bc.subscribe = 1
+            status = py_pjsua.buddy_add(bc)
+            if status != 0:
+                py_pjsua.perror(APP, "Error adding buddy", status)
+
+
+#
+# main
+#
+app_init()
+app_start()
+app_menu()
+
+#
+# Done, quitting..
+#
+print "PJSUA shutting down.."
+C_QUIT = 1
+py_pjsua.destroy()
+
Index: pjproject/trunk/pjsip-apps/src/py_pjsua/py_pjsua.c
===================================================================
--- pjproject/trunk/pjsip-apps/src/py_pjsua/py_pjsua.c	(revision 850)
+++ pjproject/trunk/pjsip-apps/src/py_pjsua/py_pjsua.c	(revision 851)
@@ -237,4 +237,5 @@
 /*
  * Notify application on call being transfered.
+ * !modified @061206
  */
 static void cb_on_call_transfer_request(pjsua_call_id call_id,
@@ -242,7 +243,9 @@
 				        pjsip_status_code *code)
 {
+    PyObject * ret;
+    int cd;
     if (PyCallable_Check(obj_callback->on_call_transfer_request))
     {
-        PyObject_CallFunctionObjArgs(
+        ret = PyObject_CallFunctionObjArgs(
             obj_callback->on_call_transfer_request,
 	    Py_BuildValue("i",call_id),
@@ -251,4 +254,11 @@
 	    NULL
         );
+	if (ret != NULL) {
+	    if (ret != Py_None) {
+		if (PyArg_Parse(ret,"i",&cd)) {
+		    *code = cd;
+		}
+	    }
+	}
     }
 }
@@ -260,4 +270,5 @@
  * call transfer request, for example to decide whether to 
  * terminate existing call.
+ * !modified @061206
  */
 static void cb_on_call_transfer_status( pjsua_call_id call_id,
@@ -267,7 +278,9 @@
 					pj_bool_t *p_cont)
 {
+    PyObject * ret;
+    int cnt;
     if (PyCallable_Check(obj_callback->on_call_transfer_status))
     {
-        PyObject_CallFunctionObjArgs(
+        ret = PyObject_CallFunctionObjArgs(
             obj_callback->on_call_transfer_status,
 	    Py_BuildValue("i",call_id),
@@ -278,4 +291,11 @@
 	    NULL
         );
+	if (ret != NULL) {
+	    if (ret != Py_None) {
+		if (PyArg_Parse(ret,"i",&cnt)) {
+		    *p_cont = cnt;
+		}
+	    }
+	}
     }
 }
@@ -285,4 +305,5 @@
  * Notify application about incoming INVITE with Replaces header.
  * Application may reject the request by setting non-2xx code.
+ * !modified @061206
  */
 static void cb_on_call_replace_request( pjsua_call_id call_id,
@@ -291,12 +312,15 @@
 					pj_str_t *st_text)
 {
+    PyObject * ret;
+    PyObject * txt;
+    int cd;
     if (PyCallable_Check(obj_callback->on_call_replace_request))
     {
-	pjsip_rx_data_Object * obj = (pjsip_rx_data_Object *)
+        pjsip_rx_data_Object * obj = (pjsip_rx_data_Object *)
 				      PyType_GenericNew(&pjsip_rx_data_Type,
 							NULL, NULL);
-	obj->rdata = rdata;
-
-        PyObject_CallFunctionObjArgs(
+        obj->rdata = rdata;
+
+        ret = PyObject_CallFunctionObjArgs(
             obj_callback->on_call_replace_request,
 	    Py_BuildValue("i",call_id),
@@ -306,4 +330,13 @@
 	    NULL
         );
+	if (ret != NULL) {
+	    if (ret != Py_None) {
+		if (PyArg_ParseTuple(ret,"iO",&cd, &txt)) {
+		    *st_code = cd;
+		    st_text->ptr = PyString_AsString(txt);
+		    st_text->slen = strlen(PyString_AsString(txt));
+		}
+	    }
+	}
     }
 }
@@ -1111,4 +1144,5 @@
  * msg_data_Object
  * typewrapper for MessageData class
+ * !modified @ 061206
  */
 typedef struct
@@ -1116,5 +1150,6 @@
     PyObject_HEAD
     /* Type-specific fields go here. */
-    pjsip_hdr hdr_list;
+    /*pjsip_hdr hdr_list;*/
+    PyObject * hdr_list;
     PyObject * content_type;
     PyObject * msg_body;
@@ -1125,7 +1160,9 @@
  * msg_data_dealloc
  * deletes a msg_data
+ * !modified @ 061206
  */
 static void msg_data_dealloc(msg_data_Object* self)
 {
+    Py_XDECREF(self->hdr_list);
     Py_XDECREF(self->content_type);
     Py_XDECREF(self->msg_body);
@@ -1137,4 +1174,5 @@
  * msg_data_new
  * constructor for msg_data object
+ * !modified @ 061206
  */
 static PyObject * msg_data_new(PyTypeObject *type, PyObject *args,
@@ -1146,4 +1184,11 @@
     if (self != NULL)
     {
+        Py_INCREF(Py_None);
+        self->hdr_list = Py_None;
+        if (self->hdr_list == NULL)
+    	{
+            Py_DECREF(self);
+            return NULL;
+        }
         self->content_type = PyString_FromString("");
         if (self->content_type == NULL)
@@ -1166,9 +1211,14 @@
 /*
  * msg_data_members
+ * !modified @ 061206
  */
 static PyMemberDef msg_data_members[] =
 {
     {
-    	"content_type", T_OBJECT_EX, offsetof(msg_data_Object, content_type),
+        "hdr_list", T_OBJECT_EX, offsetof(msg_data_Object, hdr_list),
+	0, "Additional message headers as linked list."
+    }, 
+    {
+	"content_type", T_OBJECT_EX, offsetof(msg_data_Object, content_type),
     	0, "MIME type of optional message body."
     },
@@ -1228,4 +1278,74 @@
 };
 
+/* 
+ * translate_hdr
+ * internal function 
+ * translate from hdr_list to pjsip_generic_string_hdr
+ */
+void translate_hdr(pj_pool_t *pool, pjsip_hdr *hdr, PyObject *py_hdr_list)
+{
+    int i;
+
+    if (PyList_Check(py_hdr_list)) {
+        pj_list_init(hdr);
+
+        for (i = 0; i < PyList_Size(py_hdr_list); i++) { 
+            pj_str_t hname, hvalue;
+	    pjsip_generic_string_hdr * new_hdr;
+            PyObject * tuple = PyList_GetItem(py_hdr_list, i);
+
+            if (PyTuple_Check(tuple)) {
+                hname.ptr = PyString_AsString(PyTuple_GetItem(tuple,0));
+                hname.slen = strlen(PyString_AsString(PyTuple_GetItem(tuple,0)));
+                hvalue.ptr = PyString_AsString(PyTuple_GetItem(tuple,1));
+                hvalue.slen = strlen(PyString_AsString(PyTuple_GetItem(tuple,1)));
+            } else {
+		hname.ptr = "";
+		hname.slen = 0;
+		hvalue.ptr = "";
+		hvalue.slen = 0;
+            }  
+            new_hdr = pjsip_generic_string_hdr_create(pool, &hname, &hvalue);
+            pj_list_push_back((pj_list_type *)hdr, (pj_list_type *)new_hdr);
+	}     
+    }
+}
+
+/* 
+ * translate_hdr_rev
+ * internal function
+ * translate from pjsip_generic_string_hdr to hdr_list
+ */
+
+void translate_hdr_rev(pjsip_generic_string_hdr *hdr, PyObject *py_hdr_list)
+{
+    int i;
+    int len;
+    pjsip_generic_string_hdr * p_hdr;
+
+    len = pj_list_size(hdr);
+    
+    if (len > 0) {
+	p_hdr = hdr;
+        Py_XDECREF(py_hdr_list);
+        py_hdr_list = PyList_New(len);
+
+	for (i = 0; i < len && p_hdr != NULL; i++) {
+	    PyObject * tuple;
+	    PyObject * str;
+
+	    tuple = PyTuple_New(2);
+	    
+	    str = PyString_FromStringAndSize(p_hdr->name.ptr, p_hdr->name.slen);
+	    PyTuple_SetItem(tuple, 0, str);
+	    str = PyString_FromStringAndSize(hdr->hvalue.ptr, p_hdr->hvalue.slen);
+	    PyTuple_SetItem(tuple, 1, str);
+	    PyList_SetItem(py_hdr_list, i, tuple);
+	    p_hdr = p_hdr->next;
+	}
+    }
+    
+    
+}
 
 /*
@@ -1444,5 +1564,5 @@
             return NULL;
         }
-         self->scheme = PyString_FromString("");
+        self->scheme = PyString_FromString("");
         if (self->scheme == NULL)
     	{
@@ -1450,5 +1570,5 @@
             return NULL;
         }
-		 self->username = PyString_FromString("");
+        self->username = PyString_FromString("");
         if (self->username == NULL)
     	{
@@ -1456,5 +1576,5 @@
             return NULL;
         }
-		 self->data = PyString_FromString("");
+        self->data = PyString_FromString("");
         if (self->data == NULL)
     	{
@@ -1473,27 +1593,27 @@
 static PyMemberDef pjsip_cred_info_members[] =
 {
-	{
-    	"realm", T_OBJECT_EX,
-    	offsetof(pjsip_cred_info_Object, realm), 0,
-    	"Realm"
-    },
-	{
-    	"scheme", T_OBJECT_EX,
-    	offsetof(pjsip_cred_info_Object, scheme), 0,
-    	"Scheme"
-    },
-	{
-    	"username", T_OBJECT_EX,
-    	offsetof(pjsip_cred_info_Object, username), 0,
-    	"User name"
-    },
-	{
-    	"data", T_OBJECT_EX,
-    	offsetof(pjsip_cred_info_Object, data), 0,
-    	"The data, which can be a plaintext password or a hashed digest. "
-    },
-    {
-    	"data_type", T_INT, offsetof(pjsip_cred_info_Object, data_type), 0,
-    	"Type of data"
+    {
+        "realm", T_OBJECT_EX,
+        offsetof(pjsip_cred_info_Object, realm), 0,
+        "Realm"
+    },
+    {
+        "scheme", T_OBJECT_EX,
+        offsetof(pjsip_cred_info_Object, scheme), 0,
+        "Scheme"
+    },
+    {
+        "username", T_OBJECT_EX,
+        offsetof(pjsip_cred_info_Object, username), 0,
+        "User name"
+    },
+    {
+        "data", T_OBJECT_EX,
+        offsetof(pjsip_cred_info_Object, data), 0,
+        "The data, which can be a plaintext password or a hashed digest. "
+    },
+    {
+        "data_type", T_INT, offsetof(pjsip_cred_info_Object, data_type), 0,
+        "Type of data"
     },
     
@@ -1548,42 +1668,65 @@
 };
 
+/*
+ * py_pjsua_thread_register
+ * !added @ 061206
+ */
+static PyObject *py_pjsua_thread_register(PyObject *pSelf, PyObject 
+*pArgs)
+{
+	
+    pj_status_t status;	
+    const char *name;
+    PyObject *py_desc;
+    pj_thread_t *thread;
+    void *thread_desc;
+    int size;
+    int i;
+    int *td;
+
+    if (!PyArg_ParseTuple(pArgs, "sO", &name, &py_desc))
+    {
+         return NULL;
+    }
+#if 0
+    size = PyList_Size(py_desc);
+    td = (int *)malloc(size * sizeof(int));
+    for (i = 0; i < size; i++) {
+	if (!PyArg_Parse(PyList_GetItem(py_desc,i),"i", td[i])) {
+	    return NULL;
+	}
+    }
+    thread_desc = td;
+#else
+    thread_desc = malloc(sizeof(pj_thread_desc));
+#endif
+    status = pj_thread_register(name, thread_desc, &thread);
+    return Py_BuildValue("i",status);
+}
 
 /*
  * py_pjsua_logging_config_default
+ * !modified @ 051206
  */
 static PyObject *py_pjsua_logging_config_default(PyObject *pSelf,
                                                     PyObject *pArgs)
 {
-    logging_config_Object *obj;
+    logging_config_Object *obj;	
     pjsua_logging_config cfg;
 
-    if (!PyArg_ParseTuple(pArgs, "O", &obj))
-    {
-        return NULL;
-    }
-    /*pj_bzero(cfg, sizeof(*cfg));
-
-    cfg->msg_logging = obj->msg_logging;
-    cfg->level = obj->level;
-    cfg->console_level = obj->console_level;
-    cfg->decor = obj->decor;*/
+    if (!PyArg_ParseTuple(pArgs, ""))
+    {
+        return NULL;
+    }
+    
     pjsua_logging_config_default(&cfg);
+	obj = (logging_config_Object *) logging_config_new
+		(&logging_config_Type,NULL,NULL);
     obj->msg_logging = cfg.msg_logging;
     obj->level = cfg.level;
     obj->console_level = cfg.console_level;
     obj->decor = cfg.decor;
-    /*printf("msg logging : %d\n",obj->msg_logging);
-    printf("level : %d\n",obj->level);
-    printf("console level : %d\n",obj->console_level);
-    printf("decor : %d\n",obj->decor);
-    printf("str sebelum ");
-    printf(PyString_AsString(obj->log_filename));
-
-    Py_XDECREF(obj->log_filename);
-    obj->log_filename = PyString_FromString("oke");
-    printf("\nstr sesudah ");
-    printf(PyString_AsString(obj->log_filename));*/
-    Py_INCREF(Py_None);
-    return Py_None;
+    
+    return (PyObject *)obj;
 }
 
@@ -1591,4 +1734,5 @@
 /*
  * py_pjsua_config_default
+ * !modified @ 051206
  */
 static PyObject *py_pjsua_config_default(PyObject *pSelf, PyObject *pArgs)
@@ -1597,13 +1741,13 @@
     pjsua_config cfg;
 
-    if (!PyArg_ParseTuple(pArgs, "O", &obj))
+    if (!PyArg_ParseTuple(pArgs, ""))
     {
         return NULL;
     }
     pjsua_config_default(&cfg);
+	obj = (config_Object *) config_new(&config_Type, NULL, NULL);
     obj->max_calls = cfg.max_calls;
     obj->thread_cnt = cfg.thread_cnt;
-    Py_INCREF(Py_None);
-    return Py_None;
+    return (PyObject *)obj;
 }
 
@@ -1611,4 +1755,5 @@
 /*
  * py_pjsua_media_config_default
+ * !modified @ 051206
  */
 static PyObject * py_pjsua_media_config_default(PyObject *pSelf,
@@ -1617,9 +1762,10 @@
     media_config_Object *obj;
     pjsua_media_config cfg;
-    if (!PyArg_ParseTuple(pArgs, "O", &obj))
+    if (!PyArg_ParseTuple(pArgs, ""))
     {
         return NULL;
     }
     pjsua_media_config_default(&cfg);
+    obj = (media_config_Object *)PyType_GenericNew(&media_config_Type, NULL, NULL);
     obj->clock_rate = cfg.clock_rate;
     obj->ec_options = cfg.ec_options;
@@ -1634,6 +1780,5 @@
     obj->thread_cnt = cfg.thread_cnt;
     obj->tx_drop_pct = cfg.tx_drop_pct;
-    Py_INCREF(Py_None);
-    return Py_None;
+    return (PyObject *)obj;
 }
 
@@ -1641,4 +1786,5 @@
 /*
  * py_pjsua_msg_data_init
+ * !modified @ 051206
  */
 static PyObject *py_pjsua_msg_data_init(PyObject *pSelf, PyObject *pArgs)
@@ -1646,9 +1792,11 @@
     msg_data_Object *obj;
     pjsua_msg_data msg;
-    if (!PyArg_ParseTuple(pArgs, "O", &obj))
+    
+    if (!PyArg_ParseTuple(pArgs, ""))
     {
         return NULL;
     }
     pjsua_msg_data_init(&msg);
+    obj = (msg_data_Object *)msg_data_new(&msg_data_Type, NULL, NULL);
     Py_XDECREF(obj->content_type);
     obj->content_type = PyString_FromStringAndSize(
@@ -1659,135 +1807,8 @@
         msg.msg_body.ptr, msg.msg_body.slen
     );
-    obj->hdr_list = msg.hdr_list;
-    Py_INCREF(Py_None);
-    return Py_None;
-}
-
-
-/*
- * py_pjsua_logging_config_dup
- */
-static PyObject *py_pjsua_logging_config_dup(PyObject *pSelf, PyObject *pArgs)
-{
-    pj_pool_Object *pool;
-    logging_config_Object *src;
-    logging_config_Object *dest;
-    pj_str_t strdest;
-    pj_str_t strsrc;
-    int len;
-
-    if (!PyArg_ParseTuple(pArgs, "OOO", &pool, &dest, &src))
-    {
-        return NULL;
-    }
-    pj_memcpy(dest, src, sizeof(*src));
-    len = strlen(PyString_AsString(src->log_filename));
-    strsrc.ptr = PyString_AsString(src->log_filename);
-    strsrc.slen = len;
-    pj_strdup_with_null(pool->pool, &strdest, &strsrc);
-    Py_XDECREF(dest->log_filename);
-    dest->log_filename = PyString_FromStringAndSize(strdest.ptr, strdest.slen);
-    Py_INCREF(Py_None);
-    return Py_None;
-}
-
-
-/*
- * py_pjsua_config_dup
- */
-static PyObject *py_pjsua_config_dup(PyObject *pSelf, PyObject *pArgs)
-{
-    pj_pool_Object *pool;
-    config_Object *src;
-    config_Object *dest;
-    pj_str_t strdest;
-    pj_str_t strsrc;
-    int len;
-    unsigned i;
-
-    if (!PyArg_ParseTuple(pArgs, "OOO", &pool, &dest, &src))
-    {
-        return NULL;
-    }
-    pj_memcpy(dest, src, sizeof(*src));
-
-    for (i=0; i<src->outbound_proxy_cnt; ++i)
-    {
-        pj_strdup_with_null(
-            pool->pool, &dest->outbound_proxy[i], &src->outbound_proxy[i]
-        );
-    }
-
-    for (i=0; i<src->cred_count; ++i)
-    {
-        pjsip_cred_dup(pool->pool, &dest->cred_info[i], &src->cred_info[i]);
-    }
-    len = strlen(PyString_AsString(src->user_agent));
-    strsrc.ptr = PyString_AsString(src->user_agent);
-    strsrc.slen = len;
-    pj_strdup_with_null(pool->pool, &strdest, &strsrc);
-    Py_XDECREF(dest->user_agent);
-    dest->user_agent = PyString_FromStringAndSize(strdest.ptr, strdest.slen);
-    Py_INCREF(Py_None);
-    return Py_None;
-}
-
-
-/*
- * py_pjsip_cred_dup
- */
-static PyObject *py_pjsip_cred_dup(PyObject *pSelf, PyObject *pArgs)
-{
-    pj_pool_Object *pool;
-    pjsip_cred_info_Object *src;
-    pjsip_cred_info_Object *dest;
-	pjsip_cred_info s;
-	pjsip_cred_info d;
-    if (!PyArg_ParseTuple(pArgs, "OOO", &pool, &dest, &src))
-    {
-        return NULL;
-    }
-	s.data.ptr = PyString_AsString(src->data);
-	s.data.slen = strlen(PyString_AsString(src->data));
-	s.realm.ptr = PyString_AsString(src->realm);
-	s.realm.slen = strlen(PyString_AsString(src->realm));
-	s.scheme.ptr = PyString_AsString(src->scheme);
-	s.scheme.slen = strlen(PyString_AsString(src->scheme));
-	s.username.ptr = PyString_AsString(src->username);
-	s.username.slen = strlen(PyString_AsString(src->username));
-	s.data_type = src->data_type;
-	d.data.ptr = PyString_AsString(dest->data);
-	d.data.slen = strlen(PyString_AsString(dest->data));
-	d.realm.ptr = PyString_AsString(dest->realm);
-	d.realm.slen = strlen(PyString_AsString(dest->realm));
-	d.scheme.ptr = PyString_AsString(dest->scheme);
-	d.scheme.slen = strlen(PyString_AsString(dest->scheme));
-	d.username.ptr = PyString_AsString(dest->username);
-	d.username.slen = strlen(PyString_AsString(dest->username));
-	d.data_type = dest->data_type;
-    pjsip_cred_dup(pool->pool, &d, &s);
-	Py_XDECREF(src->data);
-	src->data = PyString_FromStringAndSize(s.data.ptr, s.data.slen);
-	Py_XDECREF(src->realm);
-	src->realm = PyString_FromStringAndSize(s.realm.ptr, s.realm.slen);
-	Py_XDECREF(src->scheme);
-	src->scheme = PyString_FromStringAndSize(s.scheme.ptr, s.scheme.slen);
-	Py_XDECREF(src->username);
-	src->username = 
-		PyString_FromStringAndSize(s.username.ptr, s.username.slen);
-    Py_INCREF(Py_None);
-	src->data_type = s.data_type;
-	Py_XDECREF(dest->data);
-	dest->data = PyString_FromStringAndSize(d.data.ptr, d.data.slen);
-	Py_XDECREF(dest->realm);
-	dest->realm = PyString_FromStringAndSize(d.realm.ptr, d.realm.slen);
-	Py_XDECREF(dest->scheme);
-	dest->scheme = PyString_FromStringAndSize(d.scheme.ptr, d.scheme.slen);
-	Py_XDECREF(dest->username);
-	dest->username = 
-		PyString_FromStringAndSize(d.username.ptr, d.username.slen);
-    Py_INCREF(Py_None);
-	src->data_type = s.data_type;
-    return Py_None;
+
+    translate_hdr_rev((pjsip_generic_string_hdr *)&msg.hdr_list, obj->hdr_list);
+    
+    return (PyObject *)obj;
 }
 
@@ -1922,4 +1943,5 @@
         return NULL;
     }
+	
     pjsua_perror(sender, title, status);
     Py_INCREF(Py_None);
@@ -1939,5 +1961,5 @@
     }
     status = pjsua_create();
-    printf("status %d\n",status);
+    //printf("status %d\n",status);
     return Py_BuildValue("i",status);
 }
@@ -2037,5 +2059,5 @@
     }
     status = pjsua_start();
-    printf("status %d\n",status);
+    //printf("status %d\n",status);
     return Py_BuildValue("i",status);
 }
@@ -2053,5 +2075,5 @@
     }
     status = pjsua_destroy();
-    printf("status %d\n",status);
+    //printf("status %d\n",status);
     return Py_BuildValue("i",status);
 }
@@ -2070,5 +2092,5 @@
     }
     ret = pjsua_handle_events(msec);
-    printf("return %d\n",ret);
+    //printf("return %d\n",ret);
     return Py_BuildValue("i",ret);
 }
@@ -2087,17 +2109,15 @@
     }
     status = pjsua_verify_sip_url(url);
-    printf("status %d\n",status);
+    //printf("status %d\n",status);
     return Py_BuildValue("i",status);
 }
 
 
-
-
-
-
-/*
- * error messages
- */
-
+/*
+ * function doc
+ */
+
+static char pjsua_thread_register_doc[] =
+    "int py_pjsua.thread_register(string name, int[] desc)";
 static char pjsua_perror_doc[] =
     "void py_pjsua.perror (string sender, string title, int status) "
@@ -2182,38 +2202,19 @@
 
 static char pjsua_logging_config_default_doc[] =
-    "void py_pjsua.logging_config_default  (py_pjsua.Logging_Config cfg)  "
+    "py_pjsua.Logging_Config py_pjsua.logging_config_default  ()  "
     "Use this function to initialize logging config.";
 
 static char pjsua_config_default_doc[] =
-    "void py_pjsua.config_default (py_pjsua.Config cfg). Use this function to "
-    "initialize pjsua config. Parameters: "
-        "cfg: pjsua config to be initialized.";
+    "py_pjsua.Config py_pjsua.config_default (). Use this function to "
+    "initialize pjsua config. ";
 
 static char pjsua_media_config_default_doc[] =
+    "py_pjsua.Media_Config py_pjsua.media_config_default (). "
     "Use this function to initialize media config.";
 
-static char pjsua_logging_config_dup_doc[] =
-    "void py_pjsua.logging_config_dup  (py_pjsua.PJ_Pool pool, "
-        "py_pjsua.Logging_Config dst, py_pjsua.Logging_Config src) "
-    "Use this function to duplicate logging config. Parameters: "
-        "pool: Pool to use;  "
-        "dst: Destination config;  "
-        "src: Source config.";
-
-static char pjsua_config_dup_doc[] =
-    "void py_pjsua.config_dup (py_pjsua.PJ_Pool pool, py_pjsua.Config dst, "
-                                "py_pjsua.Config src) "
-    "Duplicate pjsua_config. ";
-
-static char pjsip_cred_dup_doc[] =
-    "void py_pjsua.pjsip_cred_dup (py_pjsua.PJ_Pool pool, "
-                                "py_pjsua.PJSIP_Cred_Info dst, "
-                                "py_pjsua.PJSIP_Cred_Info src) "
-    "Duplicate credential.";
-
 static char pjsua_msg_data_init_doc[] =
-    "void py_pjsua.msg_data_init (py_pjsua.Msg_Data msg_data) "
-    "Initialize message data Parameters: "
-        "msg_data: Message data to be initialized.";
+    "py_pjsua.Msg_Data void py_pjsua.msg_data_init () "
+    "Initialize message data ";
+        
 
 /* END OF LIB BASE */
@@ -2229,5 +2230,5 @@
     PyObject_HEAD
     /* Type-specific fields go here. */
-	PyObject * stun_srv1;    
+    PyObject * stun_srv1;    
     unsigned stun_port1;
     PyObject * stun_srv2;
@@ -2283,23 +2284,23 @@
 {
     {
-    	"stun_port1", T_INT, offsetof(stun_config_Object, stun_port1), 0,
-    	"The first STUN server IP address or hostname."
-    },
-    {
-    	"stun_port2", T_INT, offsetof(stun_config_Object, stun_port2), 0,
-    	"Port number of the second STUN server. "
-		"If zero, default STUN port will be used."
+        "stun_port1", T_INT, offsetof(stun_config_Object, stun_port1), 0,
+        "The first STUN server IP address or hostname."
+    },
+    {
+        "stun_port2", T_INT, offsetof(stun_config_Object, stun_port2), 0,
+        "Port number of the second STUN server. "
+        "If zero, default STUN port will be used."
     },    
     {
-    	"stun_srv1", T_OBJECT_EX,
-    	offsetof(stun_config_Object, stun_srv1), 0,
-    	"The first STUN server IP address or hostname"
-    },
-    {
-    	"stun_srv2", T_OBJECT_EX,
-    	offsetof(stun_config_Object, stun_srv2), 0,
-    	"Optional second STUN server IP address or hostname, for which the "
-		"result of the mapping request will be compared to. If the value "
-		"is empty, only one STUN server will be used"
+        "stun_srv1", T_OBJECT_EX,
+        offsetof(stun_config_Object, stun_srv1), 0,
+        "The first STUN server IP address or hostname"
+    },
+    {
+        "stun_srv2", T_OBJECT_EX,
+        offsetof(stun_config_Object, stun_srv2), 0,
+        "Optional second STUN server IP address or hostname, for which the "
+        "result of the mapping request will be compared to. If the value "
+        "is empty, only one STUN server will be used"
     },
     {NULL}  /* Sentinel */
@@ -2365,9 +2366,9 @@
     PyObject_HEAD
     /* Type-specific fields go here. */
-	unsigned port;
-	PyObject * public_addr;
-	PyObject * bound_addr;
-	int use_stun;
-	stun_config_Object * stun_config;
+    unsigned port;
+    PyObject * public_addr;
+    PyObject * bound_addr;
+    int use_stun;
+    stun_config_Object * stun_config;
 } transport_config_Object;
 
@@ -2379,6 +2380,6 @@
 static void transport_config_dealloc(transport_config_Object* self)
 {
-	Py_XDECREF(self->public_addr);    
-	Py_XDECREF(self->bound_addr);    
+    Py_XDECREF(self->public_addr);    
+    Py_XDECREF(self->bound_addr);    
     Py_XDECREF(self->stun_config);    
     self->ob_type->tp_free((PyObject*)self);
@@ -2411,5 +2412,5 @@
         }
         self->stun_config = 
-			(stun_config_Object *)stun_config_new(&stun_config_Type,NULL,NULL);
+            (stun_config_Object *)stun_config_new(&stun_config_Type,NULL,NULL);
         if (self->stun_config == NULL)
     	{
@@ -2430,37 +2431,37 @@
 {
     {
-    	"port", T_INT, offsetof(transport_config_Object, port), 0,
-    	"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."
-    },
-    {
-    	"public_addr", T_OBJECT_EX, 
-		offsetof(transport_config_Object, public_addr), 0,
-    	"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."		
+        "port", T_INT, offsetof(transport_config_Object, port), 0,
+        "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."
+    },
+    {
+        "public_addr", T_OBJECT_EX, 
+	offsetof(transport_config_Object, public_addr), 0,
+        "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."		
     },    
-	{
-    	"bound_addr", T_OBJECT_EX, 
-		offsetof(transport_config_Object, bound_addr), 0,
-    	"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)."		
+    {
+        "bound_addr", T_OBJECT_EX, 
+        offsetof(transport_config_Object, bound_addr), 0,
+        "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)."		
     },    
     {
-    	"use_stun", T_INT,
-    	offsetof(transport_config_Object, use_stun), 0,
-    	"Flag to indicate whether STUN should be used."
-    },
-    {
-    	"stun_config", T_OBJECT_EX,
-    	offsetof(transport_config_Object, stun_config), 0,
-    	"STUN configuration, must be specified when STUN is used."
+        "use_stun", T_INT,
+        offsetof(transport_config_Object, use_stun), 0,
+        "Flag to indicate whether STUN should be used."
+    },
+    {
+        "stun_config", T_OBJECT_EX,
+        offsetof(transport_config_Object, stun_config), 0,
+        "STUN configuration, must be specified when STUN is used."
     },
     {NULL}  /* Sentinel */
@@ -2594,7 +2595,7 @@
 #endif
     {
-    	"sa_data", T_OBJECT_EX,
-    	offsetof(sockaddr_Object, sa_data), 0,
-    	"Address data"
+        "sa_data", T_OBJECT_EX,
+        offsetof(sockaddr_Object, sa_data), 0,
+        "Address data"
     },
     {NULL}  /* Sentinel */
@@ -2708,7 +2709,7 @@
     },
     {
-    	"host", T_OBJECT_EX,
-    	offsetof(host_port_Object, host), 0,
-    	"Host part or IP address."
+        "host", T_OBJECT_EX,
+        offsetof(host_port_Object, host), 0,
+        "Host part or IP address."
     },
     {NULL}  /* Sentinel */
@@ -2762,7 +2763,10 @@
 };
 
-/*
- * transport_id_Object
- * C/Python wrapper for transport_id object
+
+
+
+/*
+ * transport_info_Object
+ * Transport info
  */
 typedef struct
@@ -2770,143 +2774,13 @@
     PyObject_HEAD
     /* Type-specific fields go here. */
-    int transport_id;
-} transport_id_Object;
-
-
-/*
- * transport_id_members
- * declares attributes accessible from 
- * both C and Python for transport_id object
- */
-static PyMemberDef transport_id_members[] =
-{
-    {
-        "transport_id", T_INT, offsetof(transport_id_Object, transport_id), 0,
-        "SIP transport identification"
-    },
-    {NULL}  /* Sentinel */
-};
-
-
-/*
- * transport_id_Type
- */
-static PyTypeObject transport_id_Type =
-{
-    PyObject_HEAD_INIT(NULL)
-    0,                              /*ob_size*/
-    "py_pjsua.Transport_ID",        /*tp_name*/
-    sizeof(transport_id_Object),    /*tp_basicsize*/
-    0,                              /*tp_itemsize*/
-    0,                              /*tp_dealloc*/
-    0,                              /*tp_print*/
-    0,                              /*tp_getattr*/
-    0,                              /*tp_setattr*/
-    0,                              /*tp_compare*/
-    0,                              /*tp_repr*/
-    0,                              /*tp_as_number*/
-    0,                              /*tp_as_sequence*/
-    0,                              /*tp_as_mapping*/
-    0,                              /*tp_hash */
-    0,                              /*tp_call*/
-    0,                              /*tp_str*/
-    0,                              /*tp_getattro*/
-    0,                              /*tp_setattro*/
-    0,                              /*tp_as_buffer*/
-    Py_TPFLAGS_DEFAULT,             /*tp_flags*/
-    "Transport ID objects",         /*tp_doc*/
-    0,                              /*tp_traverse*/
-    0,                              /*tp_clear*/
-    0,                              /*tp_richcompare*/
-    0,                              /* tp_weaklistoffset */
-    0,                              /* tp_iter */
-    0,                              /* tp_iternext */
-    0,                              /* tp_methods */
-    transport_id_members,           /* tp_members */
-
-};
-
-/*
- * integer_Object
- * C/Python wrapper for integer object
- */
-typedef struct
-{
-    PyObject_HEAD
-    /* Type-specific fields go here. */
-    int integer;
-} integer_Object;
-
-
-/*
- * integer_members
- * declares attributes accessible from both C and Python for integer object
- */
-static PyMemberDef integer_members[] =
-{
-    {
-        "integer", T_INT, offsetof(integer_Object, integer), 0,
-        "integer value"
-    },
-    {NULL}  /* Sentinel */
-};
-
-
-/*
- * integer_Type
- */
-static PyTypeObject integer_Type =
-{
-    PyObject_HEAD_INIT(NULL)
-    0,                              /*ob_size*/
-    "py_pjsua.Integer",        /*tp_name*/
-    sizeof(integer_Object),    /*tp_basicsize*/
-    0,                              /*tp_itemsize*/
-    0,                              /*tp_dealloc*/
-    0,                              /*tp_print*/
-    0,                              /*tp_getattr*/
-    0,                              /*tp_setattr*/
-    0,                              /*tp_compare*/
-    0,                              /*tp_repr*/
-    0,                              /*tp_as_number*/
-    0,                              /*tp_as_sequence*/
-    0,                              /*tp_as_mapping*/
-    0,                              /*tp_hash */
-    0,                              /*tp_call*/
-    0,                              /*tp_str*/
-    0,                              /*tp_getattro*/
-    0,                              /*tp_setattro*/
-    0,                              /*tp_as_buffer*/
-    Py_TPFLAGS_DEFAULT,             /*tp_flags*/
-    "Integer objects",         /*tp_doc*/
-    0,                              /*tp_traverse*/
-    0,                              /*tp_clear*/
-    0,                              /*tp_richcompare*/
-    0,                              /* tp_weaklistoffset */
-    0,                              /* tp_iter */
-    0,                              /* tp_iternext */
-    0,                              /* tp_methods */
-    integer_members,           /* tp_members */
-
-};
-
-
-/*
- * transport_info_Object
- * Transport info
- */
-typedef struct
-{
-    PyObject_HEAD
-    /* Type-specific fields go here. */
-	int id;
-	int type;
-	PyObject * type_name;
-	PyObject * info;
-	unsigned flag;
-	unsigned addr_len;
-	sockaddr_Object * local_addr;
-	host_port_Object * local_name;
-	unsigned usage_count;
+    int id;
+    int type;
+    PyObject * type_name;
+    PyObject * info;
+    unsigned flag;
+    unsigned addr_len;
+    sockaddr_Object * local_addr;
+    host_port_Object * local_name;
+    unsigned usage_count;
 } transport_info_Object;
 
@@ -2919,7 +2793,7 @@
 {
     Py_XDECREF(self->type_name); 
-	Py_XDECREF(self->info);
-	Py_XDECREF(self->local_addr);
-	Py_XDECREF(self->local_name);
+    Py_XDECREF(self->info);
+    Py_XDECREF(self->local_addr);
+    Py_XDECREF(self->local_name);
     self->ob_type->tp_free((PyObject*)self);
 }
@@ -2938,5 +2812,5 @@
     if (self != NULL)
     {
-		self->type_name = PyString_FromString("");
+        self->type_name = PyString_FromString("");
         if (self->type_name == NULL)
     	{
@@ -2944,5 +2818,5 @@
             return NULL;
         }
-		self->info = PyString_FromString("");
+        self->info = PyString_FromString("");
         if (self->info == NULL)
     	{
@@ -2951,5 +2825,5 @@
         }
         self->local_addr = 
-			(sockaddr_Object *)sockaddr_new(&sockaddr_Type,NULL,NULL);
+            (sockaddr_Object *)sockaddr_new(&sockaddr_Type,NULL,NULL);
         if (self->local_addr == NULL)
     	{
@@ -2958,5 +2832,5 @@
         }
         self->local_name = 
-			(host_port_Object *)host_port_new(&host_port_Type,NULL,NULL);
+            (host_port_Object *)host_port_new(&host_port_Type,NULL,NULL);
         if (self->local_name == NULL)
     	{
@@ -2975,43 +2849,43 @@
 static PyMemberDef transport_info_members[] =
 {
-	{
-    	"id", T_INT, offsetof(transport_info_Object, id), 0,
-    	"PJSUA transport identification."
-    },
-	{
-    	"type", T_INT, offsetof(transport_info_Object, id), 0,
-    	"Transport type."
-    },
-	{
-    	"type_name", T_OBJECT_EX,
-    	offsetof(transport_info_Object, type_name), 0,
-    	"Transport type name."
-    },
-	{
-    	"info", T_OBJECT_EX,
-    	offsetof(transport_info_Object, info), 0,
-    	"Transport string info/description."
-    },
-	{
-    	"flag", T_INT, offsetof(transport_info_Object, flag), 0,
-    	"Transport flag (see ##pjsip_transport_flags_e)."
-    },
-	{
-    	"addr_len", T_INT, offsetof(transport_info_Object, addr_len), 0,
-    	"Local address length."
-    },
-	{
-    	"local_addr", T_OBJECT_EX,
-    	offsetof(transport_info_Object, local_addr), 0,
-    	"Local/bound address."
-    },
-	{
-    	"local_name", T_OBJECT_EX,
-    	offsetof(transport_info_Object, local_name), 0,
-    	"Published address (or transport address name)."
-    },
-	{
-    	"usage_count", T_INT, offsetof(transport_info_Object, usage_count), 0,
-    	"Current number of objects currently referencing this transport."
+    {
+        "id", T_INT, offsetof(transport_info_Object, id), 0,
+        "PJSUA transport identification."
+    },
+    {
+        "type", T_INT, offsetof(transport_info_Object, id), 0,
+        "Transport type."
+    },
+    {
+        "type_name", T_OBJECT_EX,
+        offsetof(transport_info_Object, type_name), 0,
+        "Transport type name."
+    },
+    {
+        "info", T_OBJECT_EX,
+        offsetof(transport_info_Object, info), 0,
+        "Transport string info/description."
+    },
+    {
+        "flag", T_INT, offsetof(transport_info_Object, flag), 0,
+        "Transport flag (see ##pjsip_transport_flags_e)."
+    },
+    {
+        "addr_len", T_INT, offsetof(transport_info_Object, addr_len), 0,
+        "Local address length."
+    },
+    {
+        "local_addr", T_OBJECT_EX,
+        offsetof(transport_info_Object, local_addr), 0,
+        "Local/bound address."
+    },
+    {
+        "local_name", T_OBJECT_EX,
+        offsetof(transport_info_Object, local_name), 0,
+        "Published address (or transport address name)."
+    },
+    {
+        "usage_count", T_INT, offsetof(transport_info_Object, usage_count), 0,
+        "Current number of objects currently referencing this transport."
     },    
     {NULL}  /* Sentinel */
@@ -3112,4 +2986,5 @@
 /*
  * py_pjsua_stun_config_default
+ * !modified @ 051206
  */
 static PyObject *py_pjsua_stun_config_default(PyObject *pSelf, PyObject *pArgs)
@@ -3118,17 +2993,91 @@
     pjsua_stun_config cfg;
 
+    if (!PyArg_ParseTuple(pArgs, ""))
+    {
+        return NULL;
+    }
+	
+    pjsua_stun_config_default(&cfg);
+	obj = (stun_config_Object *)stun_config_new(&stun_config_Type, NULL, NULL);
+    obj->stun_port1 = cfg.stun_port1;
+    obj->stun_port2 = cfg.stun_port2;
+    Py_XDECREF(obj->stun_srv1);
+    obj->stun_srv1 = 
+        PyString_FromStringAndSize(cfg.stun_srv1.ptr, cfg.stun_srv1.slen);
+    Py_XDECREF(obj->stun_srv2);
+    obj->stun_srv2 = 
+        PyString_FromStringAndSize(cfg.stun_srv2.ptr, cfg.stun_srv2.slen);
+    return (PyObject *)obj;
+}
+
+/*
+ * py_pjsua_transport_config_default
+ * !modified @ 051206
+ */
+static PyObject *py_pjsua_transport_config_default
+(PyObject *pSelf, PyObject *pArgs)
+{
+    transport_config_Object *obj;
+    pjsua_transport_config cfg;
+
+    if (!PyArg_ParseTuple(pArgs, ""))
+    {
+        return NULL;
+    }
+    pjsua_transport_config_default(&cfg);
+	obj = (transport_config_Object *)transport_config_new
+		(&transport_config_Type,NULL,NULL);
+    obj->public_addr = 
+        PyString_FromStringAndSize(cfg.public_addr.ptr, cfg.public_addr.slen);
+    obj->bound_addr = 
+        PyString_FromStringAndSize(cfg.bound_addr.ptr, cfg.bound_addr.slen);
+    obj->port = cfg.port;
+    obj->use_stun = cfg.use_stun;
+    Py_XDECREF(obj->stun_config);
+    obj->stun_config = 
+        (stun_config_Object *)stun_config_new(&stun_config_Type, NULL, NULL);
+    obj->stun_config->stun_port1 = cfg.stun_config.stun_port1;
+    obj->stun_config->stun_port2 = cfg.stun_config.stun_port2;
+    Py_XDECREF(obj->stun_config->stun_srv1);
+    obj->stun_config->stun_srv1 = 
+        PyString_FromStringAndSize(cfg.stun_config.stun_srv1.ptr, 
+    cfg.stun_config.stun_srv1.slen);
+    Py_XDECREF(obj->stun_config->stun_srv2);
+    obj->stun_config->stun_srv2 = 
+        PyString_FromStringAndSize(cfg.stun_config.stun_srv2.ptr, 
+    cfg.stun_config.stun_srv2.slen);
+    return (PyObject *)obj;
+}
+
+/*
+ * py_pjsua_normalize_stun_config
+ */
+static PyObject *py_pjsua_normalize_stun_config
+(PyObject *pSelf, PyObject *pArgs)
+{
+    stun_config_Object *obj;
+    pjsua_stun_config *cfg;
+
     if (!PyArg_ParseTuple(pArgs, "O", &obj))
     {
         return NULL;
     }
-    pjsua_stun_config_default(&cfg);
-    obj->stun_port1 = cfg.stun_port1;
-	obj->stun_port2 = cfg.stun_port2;
-	Py_XDECREF(obj->stun_srv1);
+    cfg = (pjsua_stun_config *)malloc(sizeof(pjsua_stun_config));
+    cfg->stun_port1 = obj->stun_port1;
+    cfg->stun_port2 = obj->stun_port2;
+    cfg->stun_srv1.ptr = PyString_AsString(obj->stun_srv1);
+    cfg->stun_srv1.slen = strlen(PyString_AsString(obj->stun_srv1));
+    cfg->stun_srv2.ptr = PyString_AsString(obj->stun_srv2);
+    cfg->stun_srv2.slen = strlen(PyString_AsString(obj->stun_srv2));
+    pjsua_normalize_stun_config(cfg);
+    obj->stun_port1 = cfg->stun_port1;
+    obj->stun_port2 = cfg->stun_port2;
+    Py_XDECREF(obj->stun_srv1);
     obj->stun_srv1 = 
-		PyString_FromStringAndSize(cfg.stun_srv1.ptr, cfg.stun_srv1.slen);
-	Py_XDECREF(obj->stun_srv2);
-	obj->stun_srv2 = 
-		PyString_FromStringAndSize(cfg.stun_srv2.ptr, cfg.stun_srv2.slen);
+        PyString_FromStringAndSize(cfg->stun_srv1.ptr, cfg->stun_srv1.slen);
+    Py_XDECREF(obj->stun_srv2);
+    obj->stun_srv2 = 
+        PyString_FromStringAndSize(cfg->stun_srv2.ptr, cfg->stun_srv2.slen);
+    free(cfg);
     Py_INCREF(Py_None);
     return Py_None;
@@ -3136,298 +3085,131 @@
 
 /*
- * py_pjsua_transport_config_default
- */
-static PyObject *py_pjsua_transport_config_default
-(PyObject *pSelf, PyObject *pArgs)
-{
+ * py_pjsua_transport_create
+ * !modified @ 051206
+ */
+static PyObject *py_pjsua_transport_create(PyObject *pSelf, PyObject *pArgs)
+{
+    pj_status_t status;
+    int type;
+    
     transport_config_Object *obj;
     pjsua_transport_config cfg;
-
+    pjsua_transport_id id;
+    if (!PyArg_ParseTuple(pArgs, "iO", &type, &obj))
+    {
+        return NULL;
+    }
+    cfg.public_addr.ptr = PyString_AsString(obj->public_addr);
+    cfg.public_addr.slen = strlen(PyString_AsString(obj->public_addr));
+    cfg.bound_addr.ptr = PyString_AsString(obj->bound_addr);
+    cfg.bound_addr.slen = strlen(PyString_AsString(obj->bound_addr));
+    cfg.port = obj->port;
+    cfg.use_stun = obj->use_stun;
+    cfg.stun_config.stun_port1 = obj->stun_config->stun_port1;
+    cfg.stun_config.stun_port2 = obj->stun_config->stun_port2;
+    cfg.stun_config.stun_srv1.ptr = 
+        PyString_AsString(obj->stun_config->stun_srv1);
+    cfg.stun_config.stun_srv1.slen = 
+        strlen(PyString_AsString(obj->stun_config->stun_srv1));
+    cfg.stun_config.stun_srv2.ptr = 
+        PyString_AsString(obj->stun_config->stun_srv2);
+    cfg.stun_config.stun_srv2.slen = 
+        strlen(PyString_AsString(obj->stun_config->stun_srv2));
+    status = pjsua_transport_create(type, &cfg, &id);
+    
+    
+    return Py_BuildValue("ii",status,id);
+}
+
+/*
+ * py_pjsua_transport_register
+ * !modified @ 051206
+ */
+static PyObject *py_pjsua_transport_register(PyObject *pSelf, PyObject *pArgs)
+{
+    pj_status_t status;	    
+    pjsip_transport_Object *obj;	
+    pjsua_transport_id id;
     if (!PyArg_ParseTuple(pArgs, "O", &obj))
     {
         return NULL;
     }
-    pjsua_transport_config_default(&cfg);
-    obj->public_addr = 
-		PyString_FromStringAndSize(cfg.public_addr.ptr, cfg.public_addr.slen);
-	obj->bound_addr = 
-		PyString_FromStringAndSize(cfg.bound_addr.ptr, cfg.bound_addr.slen);
-	obj->port = cfg.port;
-	obj->use_stun = cfg.use_stun;
-	Py_XDECREF(obj->stun_config);
-	obj->stun_config = 
-		(stun_config_Object *)stun_config_new(&stun_config_Type, NULL, NULL);
-    obj->stun_config->stun_port1 = cfg.stun_config.stun_port1;
-	obj->stun_config->stun_port2 = cfg.stun_config.stun_port2;
-	Py_XDECREF(obj->stun_config->stun_srv1);
-    obj->stun_config->stun_srv1 = 
-		PyString_FromStringAndSize(cfg.stun_config.stun_srv1.ptr, 
-		cfg.stun_config.stun_srv1.slen);
-	Py_XDECREF(obj->stun_config->stun_srv2);
-	obj->stun_config->stun_srv2 = 
-		PyString_FromStringAndSize(cfg.stun_config.stun_srv2.ptr, 
-		cfg.stun_config.stun_srv2.slen);
-    Py_INCREF(Py_None);
-    return Py_None;
-}
-
-/*
- * py_pjsua_normalize_stun_config
- */
-static PyObject *py_pjsua_normalize_stun_config
-(PyObject *pSelf, PyObject *pArgs)
-{
-    stun_config_Object *obj;
-    pjsua_stun_config *cfg;
-
-    if (!PyArg_ParseTuple(pArgs, "O", &obj))
-    {
-        return NULL;
-    }
-	cfg = (pjsua_stun_config *)malloc(sizeof(pjsua_stun_config));
-	cfg->stun_port1 = obj->stun_port1;
-	cfg->stun_port2 = obj->stun_port2;
-	cfg->stun_srv1.ptr = PyString_AsString(obj->stun_srv1);
-	cfg->stun_srv1.slen = strlen(PyString_AsString(obj->stun_srv1));
-	cfg->stun_srv2.ptr = PyString_AsString(obj->stun_srv2);
-	cfg->stun_srv2.slen = strlen(PyString_AsString(obj->stun_srv2));
-    pjsua_normalize_stun_config(cfg);
-    obj->stun_port1 = cfg->stun_port1;
-	obj->stun_port2 = cfg->stun_port2;
-	Py_XDECREF(obj->stun_srv1);
-    obj->stun_srv1 = 
-		PyString_FromStringAndSize(cfg->stun_srv1.ptr, cfg->stun_srv1.slen);
-	Py_XDECREF(obj->stun_srv2);
-	obj->stun_srv2 = 
-		PyString_FromStringAndSize(cfg->stun_srv2.ptr, cfg->stun_srv2.slen);
-	free(cfg);
-    Py_INCREF(Py_None);
-    return Py_None;
-}
-
-/*
- * py_pjsua_transport_config_dup
- */
-static PyObject *py_pjsua_transport_config_dup
-(PyObject *pSelf, PyObject *pArgs)
-{
-    pj_pool_Object *pool;
-    transport_config_Object *src;
-    transport_config_Object *dest;
-	pj_pool_t *p;
-	pjsua_transport_config s;
-	pjsua_transport_config d;	
-
-    if (!PyArg_ParseTuple(pArgs, "OOO", &pool, &dest, &src))
-    {
-        return NULL;
-    }
-    p = pool->pool;
-	s.public_addr.ptr = PyString_AsString(src->public_addr);
-	s.public_addr.slen = strlen(PyString_AsString(src->public_addr));
-	s.bound_addr.ptr = PyString_AsString(src->bound_addr);
-	s.bound_addr.slen = strlen(PyString_AsString(src->bound_addr));
-	s.port = src->port;
-	s.use_stun = src->use_stun;
-	s.stun_config.stun_port1 = src->stun_config->stun_port1;
-	s.stun_config.stun_port2 = src->stun_config->stun_port2;
-	s.stun_config.stun_srv1.ptr = 
-		PyString_AsString(src->stun_config->stun_srv1);
-	s.stun_config.stun_srv1.slen = 
-		strlen(PyString_AsString(src->stun_config->stun_srv1));
-	s.stun_config.stun_srv2.ptr = 
-		PyString_AsString(src->stun_config->stun_srv2);
-	s.stun_config.stun_srv2.slen = 
-		strlen(PyString_AsString(src->stun_config->stun_srv2));
-	d.public_addr.ptr = PyString_AsString(dest->public_addr);
-	d.public_addr.slen = strlen(PyString_AsString(dest->public_addr));
-	d.bound_addr.ptr = PyString_AsString(dest->bound_addr);
-	d.bound_addr.slen = strlen(PyString_AsString(dest->bound_addr));
-	d.port = dest->port;
-	d.use_stun = dest->use_stun;
-	d.stun_config.stun_port1 = dest->stun_config->stun_port1;
-	d.stun_config.stun_port2 = dest->stun_config->stun_port2;
-	d.stun_config.stun_srv1.ptr = 
-		PyString_AsString(dest->stun_config->stun_srv1);
-	d.stun_config.stun_srv1.slen = 
-		strlen(PyString_AsString(dest->stun_config->stun_srv1));
-	d.stun_config.stun_srv2.ptr = 
-		PyString_AsString(dest->stun_config->stun_srv2);
-	d.stun_config.stun_srv2.slen = 
-		strlen(PyString_AsString(dest->stun_config->stun_srv2));
-	pjsua_transport_config_dup(p, &d, &s);
-	src->public_addr = 
-		PyString_FromStringAndSize(s.public_addr.ptr, s.public_addr.slen);
-	src->bound_addr = 
-		PyString_FromStringAndSize(s.bound_addr.ptr, s.bound_addr.slen);
-	src->port = s.port;
-	src->use_stun = s.use_stun;
-	src->stun_config->stun_port1 = s.stun_config.stun_port1;
-	src->stun_config->stun_port2 = s.stun_config.stun_port2;
-	Py_XDECREF(src->stun_config->stun_srv1);
-	src->stun_config->stun_srv1 = 
-		PyString_FromStringAndSize(s.stun_config.stun_srv1.ptr, 
-		s.stun_config.stun_srv1.slen);
-	Py_XDECREF(src->stun_config->stun_srv2);
-	src->stun_config->stun_srv2 = 
-		PyString_FromStringAndSize(s.stun_config.stun_srv2.ptr, 
-		s.stun_config.stun_srv2.slen);	
-	dest->public_addr = 
-		PyString_FromStringAndSize(d.public_addr.ptr, d.public_addr.slen);
-	dest->bound_addr = 
-		PyString_FromStringAndSize(d.bound_addr.ptr, d.bound_addr.slen);
-	dest->port = d.port;
-	dest->use_stun = d.use_stun;
-	dest->stun_config->stun_port1 = d.stun_config.stun_port1;
-	dest->stun_config->stun_port2 = d.stun_config.stun_port2;
-	Py_XDECREF(dest->stun_config->stun_srv1);
-	dest->stun_config->stun_srv1 = 
-		PyString_FromStringAndSize(d.stun_config.stun_srv1.ptr, 
-		d.stun_config.stun_srv1.slen);
-	Py_XDECREF(dest->stun_config->stun_srv2);
-	dest->stun_config->stun_srv2 = 
-		PyString_FromStringAndSize(d.stun_config.stun_srv2.ptr, 
-		d.stun_config.stun_srv2.slen);
-    Py_INCREF(Py_None);
-    return Py_None;
-}
-
-/*
- * py_pjsua_transport_create
- */
-static PyObject *py_pjsua_transport_create(PyObject *pSelf, PyObject *pArgs)
+	
+    
+    status = pjsua_transport_register(obj->tp, &id);
+    
+    return Py_BuildValue("ii",status, id);
+}
+
+/*
+ * py_pjsua_enum_transports
+ */
+static PyObject *py_pjsua_enum_transports(PyObject *pSelf, PyObject *pArgs)
 {
     pj_status_t status;
-	int type;
-	transport_id_Object *p_id;
-	transport_config_Object *obj;
-	pjsua_transport_config cfg;
-	pjsua_transport_id id;
-    if (!PyArg_ParseTuple(pArgs, "iOO", &type, &obj, &p_id))
-    {
-        return NULL;
-    }
-	cfg.public_addr.ptr = PyString_AsString(obj->public_addr);
-	cfg.public_addr.slen = strlen(PyString_AsString(obj->public_addr));
-	cfg.bound_addr.ptr = PyString_AsString(obj->bound_addr);
-	cfg.bound_addr.slen = strlen(PyString_AsString(obj->bound_addr));
-	cfg.port = obj->port;
-	cfg.use_stun = obj->use_stun;
-	cfg.stun_config.stun_port1 = obj->stun_config->stun_port1;
-	cfg.stun_config.stun_port2 = obj->stun_config->stun_port2;
-	cfg.stun_config.stun_srv1.ptr = 
-		PyString_AsString(obj->stun_config->stun_srv1);
-	cfg.stun_config.stun_srv1.slen = 
-		strlen(PyString_AsString(obj->stun_config->stun_srv1));
-	cfg.stun_config.stun_srv2.ptr = 
-		PyString_AsString(obj->stun_config->stun_srv2);
-	cfg.stun_config.stun_srv2.slen = 
-		strlen(PyString_AsString(obj->stun_config->stun_srv2));
-    status = pjsua_transport_create(type, &cfg, &id);
-	p_id->transport_id = id;
-    printf("status %d\n",status);
-    return Py_BuildValue("i",status);
-}
-
-/*
- * py_pjsua_transport_register
- */
-static PyObject *py_pjsua_transport_register(PyObject *pSelf, PyObject *pArgs)
-{
-    pj_status_t status;	
-	transport_id_Object *p_id;
-	pjsip_transport_Object *obj;	
-	pjsua_transport_id id;
-    if (!PyArg_ParseTuple(pArgs, "OO", &obj, &p_id))
-    {
-        return NULL;
-    }
-	
-	id = p_id->transport_id;
-    status = pjsua_transport_register(obj->tp, &id);
-	p_id->transport_id = id;    
-    return Py_BuildValue("i",status);
-}
-
-/*
- * py_pjsua_enum_transports
- */
-static PyObject *py_pjsua_enum_transports(PyObject *pSelf, PyObject *pArgs)
+    PyObject *list;
+    
+    pjsua_transport_id *id;
+    int c, i;
+    if (!PyArg_ParseTuple(pArgs, "i", &c))
+    {
+        return NULL;
+    }	
+    
+    id = (pjsua_transport_id *)malloc(c * sizeof(pjsua_transport_id));
+    status = pjsua_enum_transports(id, &c);
+    
+    list = PyList_New(c);
+    for (i = 0; i < c; i++) 
+    {     
+        int ret = PyList_SetItem(list, i, Py_BuildValue("i", id[i]));
+        if (ret == -1) 
+        {
+            return NULL;
+        }
+    }
+    
+    free(id);
+    return Py_BuildValue("O",list);
+}
+
+/*
+ * py_pjsua_transport_get_info
+ * !modified @ 051206
+ */
+static PyObject *py_pjsua_transport_get_info(PyObject *pSelf, PyObject *pArgs)
 {
     pj_status_t status;
-	PyObject *list;
-	integer_Object *count;
-	pjsua_transport_id *id;
-	int c, i;
-    if (!PyArg_ParseTuple(pArgs, "OO", &list, &count))
+    int id;
+    transport_info_Object *obj;
+    pjsua_transport_info info;
+    
+
+    if (!PyArg_ParseTuple(pArgs, "i", &id))
     {
         return NULL;
     }	
-	c = count->integer;
-	id = (pjsua_transport_id *)malloc(c * sizeof(pjsua_transport_id));
-    status = pjsua_enum_transports(id, &c);
-	Py_XDECREF(list);
-	list = PyList_New(c);
-	for (i = 0; i < c; i++) {
-		int ret = PyList_SetItem(list, i, Py_BuildValue("i", id[i]));
-		if (ret == -1) {
-			return NULL;
-		}
-	}
-	count->integer = c;
-	free(id);
-    return Py_BuildValue("i",status);
-}
-
-/*
- * py_pjsua_transport_get_info
- */
-static PyObject *py_pjsua_transport_get_info(PyObject *pSelf, PyObject *pArgs)
-{
-    pj_status_t status;
-	int id;
-	transport_info_Object *obj;
-	pjsua_transport_info info;
-	char * str;
-	int len;
-	int i;
-
-    if (!PyArg_ParseTuple(pArgs, "iO", &id, &obj))
-    {
-        return NULL;
-    }	
-	info.addr_len = obj->addr_len;
-	info.flag = obj->flag;
-	info.id = obj->id;
-	info.info.ptr = PyString_AsString(obj->info);
-	info.info.slen = strlen(PyString_AsString(obj->info));
-	str = PyString_AsString(obj->local_addr->sa_data);
-	len = strlen(str);
-	if (len > 14) {
-		len = 14;
-	}
-	for (i = 0; i < len; i++) {
-		info.local_addr.sa_data[i] = str[i];
-	}
+    
+    status = pjsua_transport_get_info(id, &info);	
+    if (status == PJ_SUCCESS) {
+        obj = (transport_info_Object *) transport_info_new
+			(&transport_info_Type,NULL,NULL);
+        obj->addr_len = info.addr_len;
+        obj->flag = info.flag;
+        obj->id = info.id;
+        obj->info = PyString_FromStringAndSize(info.info.ptr, info.info.slen);
+        obj->local_addr->sa_data = 
+			PyString_FromStringAndSize(info.local_addr.sa_data, 14);
 #if defined(PJ_SOCKADDR_HAS_LEN) && PJ_SOCKADDR_HAS_LEN!=0
-	info.local_addr.sa_zero_len = obj->local_addr->sa_zero_len;
-	info.local_addr.sa_family = obj->local_addr->sa_family;
+        obj->local_addr->sa_zero_len = info.local_addr.sa_zero_len;
+        obj->local_addr->sa_family = info.local_addr.sa_family;
 #else
-	info.local_addr.sa_family = obj->local_addr->sa_family;
+        obj->local_addr->sa_family = info.local_addr.sa_family;
 #endif
-    status = pjsua_transport_get_info(id, &info);	
-    obj->addr_len = info.addr_len;
-	obj->flag = info.flag;
-	obj->id = info.id;
-	obj->info = PyString_FromStringAndSize(info.info.ptr, info.info.slen);
-	obj->local_addr->sa_data = 
-		PyString_FromStringAndSize(info.local_addr.sa_data, 14);
-#if defined(PJ_SOCKADDR_HAS_LEN) && PJ_SOCKADDR_HAS_LEN!=0
-	obj->local_addr->sa_zero_len = info.local_addr.sa_zero_len;
-	obj->local_addr->sa_family = info.local_addr.sa_family;
-#else
-	obj->local_addr->sa_family = info.local_addr.sa_family;
-#endif
-    return Py_BuildValue("i",status);
+        return Py_BuildValue("O", obj);
+    } else {
+        Py_INCREF(Py_None);
+        return Py_None;
+    }
 }
 
@@ -3439,6 +3221,6 @@
 {
     pj_status_t status;
-	int id;
-	int enabled;
+    int id;
+    int enabled;
     if (!PyArg_ParseTuple(pArgs, "ii", &id, &enabled))
     {
@@ -3456,6 +3238,6 @@
 {
     pj_status_t status;
-	int id;
-	int force;
+    int id;
+    int force;
     if (!PyArg_ParseTuple(pArgs, "ii", &id, &force))
     {
@@ -3468,48 +3250,43 @@
 
 static char pjsua_stun_config_default_doc[] =
-    "void py_pjsua.stun_config_default (py_pjsua.STUN_Config cfg) "
+    "py_pjsua.STUN_Config py_pjsua.stun_config_default () "
     "Call this function to initialize STUN config with default values.";
 static char pjsua_transport_config_default_doc[] =
-	"void py_pjsua.transport_config_default (py_pjsua.Transport_Config cfg) "
-	"Call this function to initialize UDP config with default values.";
+    "py_pjsua.Transport_Config py_pjsua.transport_config_default () "
+    "Call this function to initialize UDP config with default values.";
 static char pjsua_normalize_stun_config_doc[] =
-	"void py_pjsua.normalize_stun_config (py_pjsua.STUN_Config cfg) "
-	"Normalize STUN config. ";
-static char pjsua_transport_config_dup_doc[] =
-	"void py_pjsua.transport_config_dup (py_pjsua.Pool pool, "
-	"py_pjsua.Transport_Config dest, py_pjsua.Transport_Config dest) "
-	"Duplicate transport config. ";
+    "void py_pjsua.normalize_stun_config (py_pjsua.STUN_Config cfg) "
+    "Normalize STUN config. ";
 static char pjsua_transport_create_doc[] =
-	"void py_pjsua.transport_create (int type, "
-	"py_pjsua.Transport_Config cfg, py_pjsua.Transport_ID p_id) "
-	"Create SIP transport.";
+    "int, int py_pjsua.transport_create (int type, "
+    "py_pjsua.Transport_Config cfg) "
+    "Create SIP transport.";
 static char pjsua_transport_register_doc[] =
-	"void py_pjsua.transport_register "
-	"(py_pjsua.PJSIP_Transport tp, py_pjsua.Transport_ID p_id) "
-	"Register transport that has been created by application.";
+    "int, int py_pjsua.transport_register "
+    "(py_pjsua.PJSIP_Transport tp) "
+    "Register transport that has been created by application.";
 static char pjsua_enum_transports_doc[] =
-	"void py_pjsua.enum_transports "
-	"(py_pjsua.Transport_ID id[], py_pjsua.Integer count) "
-	"Enumerate all transports currently created in the system.";
+    "int[] py_pjsua.enum_transports (int count) "
+    "Enumerate all transports currently created in the system.";
 static char pjsua_transport_get_info_doc[] =
-	"void py_pjsua.transport_get_info "
-	"(py_pjsua.Transport_ID id, py_pjsua.Transport_Info info) "
-	"Get information about transports.";
+    "void py_pjsua.transport_get_info "
+    "(py_pjsua.Transport_ID id, py_pjsua.Transport_Info info) "
+    "Get information about transports.";
 static char pjsua_transport_set_enable_doc[] =
-	"void py_pjsua.transport_set_enable "
-	"(py_pjsua.Transport_ID id, int enabled) "
-	"Disable a transport or re-enable it. "
-	"By default transport is always enabled after it is created. "
-	"Disabling a transport does not necessarily close the socket, "
-	"it will only discard incoming messages and prevent the transport "
-	"from being used to send outgoing messages.";
+    "void py_pjsua.transport_set_enable "
+    "(py_pjsua.Transport_ID id, int enabled) "
+    "Disable a transport or re-enable it. "
+    "By default transport is always enabled after it is created. "
+    "Disabling a transport does not necessarily close the socket, "
+    "it will only discard incoming messages and prevent the transport "
+    "from being used to send outgoing messages.";
 static char pjsua_transport_close_doc[] =
-	"void py_pjsua.transport_close (py_pjsua.Transport_ID id, int force) "
-	"Close the transport. If transport is forcefully closed, "
-	"it will be immediately closed, and any pending transactions "
-	"that are using the transport may not terminate properly. "
-	"Otherwise, the system will wait until all transactions are closed "
-	"while preventing new users from using the transport, and will close "
-	"the transport when it is safe to do so.";
+    "void py_pjsua.transport_close (py_pjsua.Transport_ID id, int force) "
+    "Close the transport. If transport is forcefully closed, "
+    "it will be immediately closed, and any pending transactions "
+    "that are using the transport may not terminate properly. "
+    "Otherwise, the system will wait until all transactions are closed "
+    "while preventing new users from using the transport, and will close "
+    "the transport when it is safe to do so.";
 
 /* END OF LIB TRANSPORT */
@@ -3525,14 +3302,16 @@
     PyObject_HEAD
     /* Type-specific fields go here. */
-	int priority;	
-	PyObject * id;
-	PyObject * reg_uri;
-	int publish_enabled;
-	PyObject * force_contact;
-	unsigned proxy_cnt;
-	pj_str_t proxy[8];
-	unsigned reg_timeout;
-	unsigned cred_count;
-	pjsip_cred_info cred_info[8];
+    int priority;	
+    PyObject * id;
+    PyObject * reg_uri;
+    int publish_enabled;
+    PyObject * force_contact;
+    unsigned proxy_cnt;
+    /*pj_str_t proxy[8];*/
+    PyListObject * proxy;
+    unsigned reg_timeout;
+    unsigned cred_count;
+    /*pjsip_cred_info cred_info[8];*/
+    PyListObject * cred_info;
 } acc_config_Object;
 
@@ -3545,6 +3324,8 @@
 {
     Py_XDECREF(self->id); 
-	Py_XDECREF(self->reg_uri);
-	Py_XDECREF(self->force_contact);	
+    Py_XDECREF(self->reg_uri);
+    Py_XDECREF(self->force_contact);	
+    Py_XDECREF(self->proxy);
+    Py_XDECREF(self->cred_info);
     self->ob_type->tp_free((PyObject*)self);
 }
@@ -3563,5 +3344,5 @@
     if (self != NULL)
     {
-		self->id = PyString_FromString("");
+        self->id = PyString_FromString("");
         if (self->id == NULL)
     	{
@@ -3569,5 +3350,5 @@
             return NULL;
         }
-		self->reg_uri = PyString_FromString("");
+        self->reg_uri = PyString_FromString("");
         if (self->reg_uri == NULL)
     	{
@@ -3581,4 +3362,16 @@
             return NULL;
         }
+	self->proxy = (PyListObject *)PyList_New(8);
+	if (self->proxy == NULL)
+	{
+	    Py_DECREF(self);
+	    return NULL;
+	}
+	self->cred_info = (PyListObject *)PyList_New(8);
+	if (self->cred_info == NULL)
+	{
+	    Py_DECREF(self);
+	    return NULL;
+	}
     }
 
@@ -3586,126 +3379,4 @@
 }
 
-static PyObject * acc_config_get_proxy
-(acc_config_Object *self, PyObject * args)
-{
-	int idx;
-	pj_str_t elmt;
-	if (!PyArg_ParseTuple(args,"i",&idx)) 
-	{
-		return NULL;
-	}
-	if ((idx >= 0) && (idx < 8)) 
-	{
-		elmt = self->proxy[idx];
-	} 
-	else
-	{
-		return NULL;
-	}
-	return PyString_FromStringAndSize(elmt.ptr, elmt.slen);
-}
-
-static PyObject * acc_config_set_proxy
-(acc_config_Object *self, PyObject * args)
-{
-	int idx;
-	PyObject * str;	
-	if (!PyArg_ParseTuple(args,"iO",&idx, &str)) 
-	{
-		return NULL;
-	}
-	if ((idx >= 0) && (idx < 8)) 
-	{
-		self->proxy[idx].ptr = PyString_AsString(str);
-		self->proxy[idx].slen = strlen(PyString_AsString(str));
-	} 
-	else
-	{
-		return NULL;
-	}
-	Py_INCREF(Py_None);
-	return Py_None;
-}
-static PyObject * acc_config_get_cred_info
-(acc_config_Object *self, PyObject * args)
-{
-	int idx;
-	pjsip_cred_info elmt;
-	pjsip_cred_info_Object *obj;
-	if (!PyArg_ParseTuple(args,"i",&idx)) 
-	{
-		return NULL;
-	}
-	if ((idx >= 0) && (idx < 8)) 
-	{
-		elmt = self->cred_info[idx];
-	} 
-	else
-	{
-		return NULL;
-	}
-	obj = (pjsip_cred_info_Object *)
-		PyType_GenericNew(&pjsip_cred_info_Type, NULL, NULL);
-	obj->data = PyString_FromStringAndSize(elmt.data.ptr, elmt.data.slen);
-	obj->realm = PyString_FromStringAndSize(elmt.realm.ptr, elmt.realm.slen);
-	obj->scheme = 
-		PyString_FromStringAndSize(elmt.scheme.ptr, elmt.scheme.slen);
-	obj->username = 
-		PyString_FromStringAndSize(elmt.username.ptr, elmt.username.slen);
-	obj->data_type = elmt.data_type;
-	return (PyObject *)obj;
-}
-
-static PyObject * acc_config_set_cred_info
-(acc_config_Object *self, PyObject * args)
-{
-	int idx;
-	pjsip_cred_info_Object * obj;	
-	if (!PyArg_ParseTuple(args,"iO",&idx, &obj)) 
-	{
-		return NULL;
-	}
-	if ((idx >= 0) && (idx < 8)) 
-	{
-		self->cred_info[idx].data.ptr = PyString_AsString(obj->data);
-		self->cred_info[idx].data.slen = strlen(PyString_AsString(obj->data));
-		self->cred_info[idx].realm.ptr = PyString_AsString(obj->realm);
-		self->cred_info[idx].realm.slen = strlen(PyString_AsString(obj->realm));
-		self->cred_info[idx].scheme.ptr = PyString_AsString(obj->scheme);
-		self->cred_info[idx].scheme.slen = 
-			strlen(PyString_AsString(obj->scheme));
-		self->cred_info[idx].username.ptr = PyString_AsString(obj->username);
-		self->cred_info[idx].username.slen = 
-			strlen(PyString_AsString(obj->username));
-		self->cred_info[idx].data_type = obj->data_type;
-	} 
-	else
-	{
-		return NULL;
-	}
-	Py_INCREF(Py_None);
-	return Py_None;
-}
-
-static PyMethodDef acc_config_methods[] = {
-    {
-		"get_proxy", (PyCFunction)acc_config_get_proxy, METH_VARARGS,
-		"Return proxy at specified index"
-    },
-	{
-		"set_proxy", (PyCFunction)acc_config_set_proxy, METH_VARARGS,
-		"Set proxy at specified index"
-    },
-	{
-		"get_cred_info", (PyCFunction)acc_config_get_cred_info, METH_VARARGS,
-		"Return cred_info at specified index"
-    },
-	{
-		"set_cred_info", (PyCFunction)acc_config_set_cred_info, METH_VARARGS,
-		"Set cred_info at specified index"
-    },
-    {NULL}  /* Sentinel */
-};
-
 
 
@@ -3715,52 +3386,70 @@
 static PyMemberDef acc_config_members[] =
 {
-	{
-    	"priority", T_INT, offsetof(acc_config_Object, priority), 0,
-    	"Account priority, which is used to control the order of matching "
-		"incoming/outgoing requests. The higher the number means the higher "
-		"the priority is, and the account will be matched first. "
-    },
-	{
-    	"id", T_OBJECT_EX,
-    	offsetof(acc_config_Object, id), 0,
-    	"The full SIP URL for the account. "
-		"The value can take name address or URL format, "
-		"and will look something like 'sip:account@serviceprovider'. "
-		"This field is mandatory."
-    },
-	{
-    	"reg_uri", T_OBJECT_EX,
-    	offsetof(acc_config_Object, reg_uri), 0,
-    	"This is the URL to be put in the request URI for the registration, "
-		"and will look something like 'sip:serviceprovider'. "
-		"This field should be specified if registration is desired. "
-		"If the value is empty, no account registration will be performed. "
-    },
-	{
-    	"publish_enabled", T_INT, 
-			offsetof(acc_config_Object, publish_enabled), 0,
-    	"Publish presence? "
-    },
-	{
-    	"force_contact", T_OBJECT_EX,
-    	offsetof(acc_config_Object, force_contact), 0,
-    	"Optional URI to be put as Contact for this account. "
-		"It is recommended that this field is left empty, "
-		"so that the value will be calculated automatically "
-		"based on the transport address. "
-    },
-	{
-    	"proxy_cnt", T_INT, offsetof(acc_config_Object, proxy_cnt), 0,
-    	"Number of proxies in the proxy array below. "
-    },
-	{
-    	"reg_timeout", T_INT, offsetof(acc_config_Object, reg_timeout), 0,
-    	"Optional interval for registration, in seconds. "
-		"If the value is zero, default interval will be used "
-		"(PJSUA_REG_INTERVAL, 55 seconds). "
-    },
-	{
-    	"cred_count", T_INT, offsetof(acc_config_Object, cred_count), 0,
-    	"Number of credentials in the credential array. "
+    {
+        "priority", T_INT, offsetof(acc_config_Object, priority), 0,
+        "Account priority, which is used to control the order of matching "
+        "incoming/outgoing requests. The higher the number means the higher "
+        "the priority is, and the account will be matched first. "
+    },
+    {
+        "id", T_OBJECT_EX,
+        offsetof(acc_config_Object, id), 0,
+        "The full SIP URL for the account. "
+        "The value can take name address or URL format, "
+        "and will look something like 'sip:account@serviceprovider'. "
+        "This field is mandatory."
+    },
+    {
+        "reg_uri", T_OBJECT_EX,
+        offsetof(acc_config_Object, reg_uri), 0,
+        "This is the URL to be put in the request URI for the registration, "
+        "and will look something like 'sip:serviceprovider'. "
+        "This field should be specified if registration is desired. "
+        "If the value is empty, no account registration will be performed. "
+    },
+    {
+        "publish_enabled", T_INT, 
+        offsetof(acc_config_Object, publish_enabled), 0,
+        "Publish presence? "
+    },
+    {
+        "force_contact", T_OBJECT_EX,
+        offsetof(acc_config_Object, force_contact), 0,
+        "Optional URI to be put as Contact for this account. "
+        "It is recommended that this field is left empty, "
+        "so that the value will be calculated automatically "
+        "based on the transport address. "
+    },
+    {
+        "proxy_cnt", T_INT, offsetof(acc_config_Object, proxy_cnt), 0,
+        "Number of proxies in the proxy array below. "
+    },
+    {
+        "proxy", T_OBJECT_EX,
+        offsetof(acc_config_Object, proxy), 0,
+        "Optional URI of the proxies to be visited for all outgoing requests "
+	"that are using this account (REGISTER, INVITE, etc). Application need "
+	"to specify these proxies if the service provider requires "
+	"that requests destined towards its network should go through certain "
+	"proxies first (for example, border controllers)."
+    },
+    {
+        "reg_timeout", T_INT, offsetof(acc_config_Object, reg_timeout), 0,
+        "Optional interval for registration, in seconds. "
+        "If the value is zero, default interval will be used "
+        "(PJSUA_REG_INTERVAL, 55 seconds). "
+    },
+    {
+        "cred_count", T_INT, offsetof(acc_config_Object, cred_count), 0,
+        "Number of credentials in the credential array. "
+    },
+    {
+        "cred_info", T_OBJECT_EX,
+        offsetof(acc_config_Object, cred_info), 0,
+        "Array of credentials. If registration is desired, normally there "
+	"should be at least one credential specified, to successfully "
+	"authenticate against the service provider. More credentials can "
+	"be specified, for example when the requests are expected to be "
+	"challenged by the proxies in the route set."
     },
     {NULL}  /* Sentinel */
@@ -3803,5 +3492,5 @@
     0,                              /* tp_iter */
     0,                              /* tp_iternext */
-    acc_config_methods,                              /* tp_methods */
+    0/*acc_config_methods*/,                              /* tp_methods */
     acc_config_members,         /* tp_members */
     0,                              /* tp_getset */
@@ -3825,13 +3514,13 @@
     PyObject_HEAD
     /* Type-specific fields go here. */
-	int id;	
-	int is_default;
-	PyObject * acc_uri;
-	int has_registration;
-	int expires;
-	int status;
-	PyObject * status_text;
-	int online_status;	
-	char buf_[PJ_ERR_MSG_SIZE];
+    int id;	
+    int is_default;
+    PyObject * acc_uri;
+    int has_registration;
+    int expires;
+    int status;
+    PyObject * status_text;
+    int online_status;	
+    char buf_[PJ_ERR_MSG_SIZE];
 } acc_info_Object;
 
@@ -3844,5 +3533,5 @@
 {
     Py_XDECREF(self->acc_uri); 
-	Py_XDECREF(self->status_text);	
+    Py_XDECREF(self->status_text);	
     self->ob_type->tp_free((PyObject*)self);
 }
@@ -3861,5 +3550,5 @@
     if (self != NULL)
     {
-		self->acc_uri = PyString_FromString("");
+        self->acc_uri = PyString_FromString("");
         if (self->acc_uri == NULL)
     	{
@@ -3882,19 +3571,19 @@
 (acc_info_Object *self, PyObject * args)
 {
-	int idx;
-	char elmt;
-	if (!PyArg_ParseTuple(args,"i",&idx)) 
-	{
-		return NULL;
-	}
-	if ((idx >= 0) && (idx < PJ_ERR_MSG_SIZE)) 
-	{
-		elmt = self->buf_[idx];
-	} 
-	else
-	{
-		return NULL;
-	}
-	return PyString_FromStringAndSize(&elmt, 1);
+    int idx;
+    char elmt;
+    if (!PyArg_ParseTuple(args,"i",&idx)) 
+    {
+        return NULL;
+    }
+    if ((idx >= 0) && (idx < PJ_ERR_MSG_SIZE)) 
+    {
+        elmt = self->buf_[idx];
+    } 
+    else
+    {
+        return NULL;
+    }
+    return PyString_FromStringAndSize(&elmt, 1);
 }
 
@@ -3902,39 +3591,39 @@
 (acc_info_Object *self, PyObject * args)
 {
-	int idx;
-	PyObject * str;	
-	char * s;
-	if (!PyArg_ParseTuple(args,"iO",&idx, &str)) 
-	{
-		return NULL;
-	}
-	if ((idx >= 0) && (idx < PJ_ERR_MSG_SIZE)) 
-	{
-		s = PyString_AsString(str);
-		if (s[0]) 
-		{
-			self->buf_[idx] = s[0];
-		} 
-		else 
-		{
-			return NULL;
-		}
-	} 
-	else
-	{
-		return NULL;
-	}
-	Py_INCREF(Py_None);
-	return Py_None;
+    int idx;
+    PyObject * str;	
+    char * s;
+    if (!PyArg_ParseTuple(args,"iO",&idx, &str)) 
+    {
+        return NULL;
+    }
+    if ((idx >= 0) && (idx < PJ_ERR_MSG_SIZE)) 
+    {
+        s = PyString_AsString(str);
+        if (s[0]) 
+        {
+        self->buf_[idx] = s[0];
+        }	 
+	else 
+        {
+            return NULL;
+        }
+    } 
+    else
+    {
+        return NULL;
+    }
+    Py_INCREF(Py_None);
+    return Py_None;
 }
 
 static PyMethodDef acc_info_methods[] = {
     {
-		"get_buf", (PyCFunction)acc_info_get_buf, METH_VARARGS,
-		"Return buf char at specified index"
-    },
-	{
-		"set_buf", (PyCFunction)acc_info_set_buf, METH_VARARGS,
-		"Set buf at specified index"
+        "get_buf", (PyCFunction)acc_info_get_buf, METH_VARARGS,
+        "Return buf char at specified index"
+    },
+    {
+        "set_buf", (PyCFunction)acc_info_set_buf, METH_VARARGS,
+        "Set buf at specified index"
     },
 	
@@ -3949,41 +3638,41 @@
 static PyMemberDef acc_info_members[] =
 {
-	{
-    	"id", T_INT, offsetof(acc_info_Object, id), 0,
-    	"The account ID."
-    },
-	{
-    	"is_default", T_INT, offsetof(acc_info_Object, is_default), 0,
-    	"Flag to indicate whether this is the default account. "
-    },
-	{
-    	"acc_uri", T_OBJECT_EX,
-    	offsetof(acc_info_Object, acc_uri), 0,
-    	"Account URI"
-    },
-	{
-    	"has_registration", T_INT, offsetof(acc_info_Object, has_registration),
-		0,
-    	"Flag to tell whether this account has registration setting "
-		"(reg_uri is not empty)."
-    },
-	{
-    	"expires", T_INT, offsetof(acc_info_Object, expires), 0,
-    	"An up to date expiration interval for account registration session."
-    },
-	{
-    	"status", T_INT, offsetof(acc_info_Object, status), 0,
-    	"Last registration status code. If status code is zero, "
-		"the account is currently not registered. Any other value indicates "
-		"the SIP status code of the registration. "
-    },
-	{
-    	"status_text", T_OBJECT_EX,
-    	offsetof(acc_info_Object, status_text), 0,
-    	"String describing the registration status."
-    },
-	{
-    	"online_status", T_INT, offsetof(acc_info_Object, online_status), 0,
-    	"Presence online status for this account. "
+    {
+        "id", T_INT, offsetof(acc_info_Object, id), 0,
+        "The account ID."
+    },
+    {
+        "is_default", T_INT, offsetof(acc_info_Object, is_default), 0,
+        "Flag to indicate whether this is the default account. "
+    },
+    {
+        "acc_uri", T_OBJECT_EX,
+        offsetof(acc_info_Object, acc_uri), 0,
+        "Account URI"
+    },
+    {
+        "has_registration", T_INT, offsetof(acc_info_Object, has_registration),
+        0,
+        "Flag to tell whether this account has registration setting "
+        "(reg_uri is not empty)."
+    },
+    {
+        "expires", T_INT, offsetof(acc_info_Object, expires), 0,
+        "An up to date expiration interval for account registration session."
+    },
+    {
+        "status", T_INT, offsetof(acc_info_Object, status), 0,
+        "Last registration status code. If status code is zero, "
+        "the account is currently not registered. Any other value indicates "
+        "the SIP status code of the registration. "
+    },
+    {
+        "status_text", T_OBJECT_EX,
+        offsetof(acc_info_Object, status_text), 0,
+        "String describing the registration status."
+    },
+    {
+        "online_status", T_INT, offsetof(acc_info_Object, online_status), 0,
+        "Presence online status for this account. "
     },
     {NULL}  /* Sentinel */
@@ -4040,7 +3729,633 @@
 };
 
-/*
- * acc_id_Object
- * C/Python wrapper for acc_id object
+
+
+/*
+ * py_pjsua_acc_config_default
+ * !modified @ 051206
+ */
+static PyObject *py_pjsua_acc_config_default
+(PyObject *pSelf, PyObject *pArgs)
+{
+    acc_config_Object *obj;
+    pjsua_acc_config cfg;
+    int i;
+
+    if (!PyArg_ParseTuple(pArgs, ""))
+    {
+        return NULL;
+    }
+    pjsua_acc_config_default(&cfg);
+    obj = (acc_config_Object *)acc_config_new(&acc_config_Type, NULL, NULL);
+    obj->cred_count = cfg.cred_count;
+    for (i = 0; i < 8; i++) 
+    {
+        /*obj->cred_info[i] = cfg.cred_info[i];*/
+	int ret;
+	pjsip_cred_info_Object * ci = 
+	    (pjsip_cred_info_Object *)pjsip_cred_info_new
+	    (&pjsip_cred_info_Type,NULL,NULL);
+	ci->data = PyString_FromStringAndSize(cfg.cred_info[i].data.ptr, 
+	    cfg.cred_info[i].data.slen);
+	ci->realm = PyString_FromStringAndSize(cfg.cred_info[i].realm.ptr, 
+	    cfg.cred_info[i].realm.slen);
+	ci->scheme = PyString_FromStringAndSize(cfg.cred_info[i].scheme.ptr, 
+	    cfg.cred_info[i].scheme.slen);
+	ci->username = PyString_FromStringAndSize(cfg.cred_info[i].username.ptr, 
+	    cfg.cred_info[i].username.slen);
+	ci->data_type = cfg.cred_info[i].data_type;
+	ret = PyList_SetItem((PyObject *)obj->cred_info,i,(PyObject *)ci);
+	if (ret == -1) {
+	    return NULL;
+	}
+    }
+    
+    Py_XDECREF(obj->force_contact);
+    obj->force_contact = 
+        PyString_FromStringAndSize(cfg.force_contact.ptr, 
+        cfg.force_contact.slen);
+    obj->priority = cfg.priority;
+    Py_XDECREF(obj->id);
+    obj->id = 
+        PyString_FromStringAndSize(cfg.id.ptr, cfg.id.slen);
+    Py_XDECREF(obj->reg_uri);
+    obj->reg_uri = 
+        PyString_FromStringAndSize(cfg.reg_uri.ptr, cfg.reg_uri.slen);
+    obj->proxy_cnt = cfg.proxy_cnt;
+    for (i = 0; i < 8; i++) 
+    {
+	PyObject * str;
+	int ret;
+        /*obj->proxy[i] = cfg.proxy[i];*/
+	str = PyString_FromStringAndSize(cfg.proxy[i].ptr, cfg.proxy[i].slen);
+	ret = PyList_SetItem((PyObject *)obj->proxy,i,str);
+	if (ret == -1) {
+	    return NULL;
+	}
+    }
+    obj->publish_enabled = cfg.publish_enabled;
+    obj->reg_timeout = cfg.reg_timeout;
+	
+    return (PyObject *)obj;
+}
+
+/*
+ * py_pjsua_acc_get_count
+ */
+static PyObject *py_pjsua_acc_get_count
+(PyObject *pSelf, PyObject *pArgs)
+{
+    int count;
+    if (!PyArg_ParseTuple(pArgs, ""))
+    {
+        return NULL;
+    }
+    count = pjsua_acc_get_count();
+    return Py_BuildValue("i",count);
+}
+
+/*
+ * py_pjsua_acc_is_valid
+ */
+static PyObject *py_pjsua_acc_is_valid
+(PyObject *pSelf, PyObject *pArgs)
+{    
+    int id;
+    int is_valid;
+
+    if (!PyArg_ParseTuple(pArgs, "i", &id))
+    {
+        return NULL;
+    }
+    is_valid = pjsua_acc_is_valid(id);
+	
+    return Py_BuildValue("i", is_valid);
+}
+
+/*
+ * py_pjsua_acc_set_default
+ */
+static PyObject *py_pjsua_acc_set_default
+(PyObject *pSelf, PyObject *pArgs)
+{    
+    int id;
+    int status;
+
+    if (!PyArg_ParseTuple(pArgs, "i", &id))
+    {
+        return NULL;
+    }
+    status = pjsua_acc_set_default(id);
+	
+    return Py_BuildValue("i", status);
+}
+
+/*
+ * py_pjsua_acc_get_default
+ */
+static PyObject *py_pjsua_acc_get_default
+(PyObject *pSelf, PyObject *pArgs)
+{    
+    int id;
+	
+    if (!PyArg_ParseTuple(pArgs, ""))
+    {
+        return NULL;
+    }
+    id = pjsua_acc_get_default();
+	
+    return Py_BuildValue("i", id);
+}
+
+/*
+ * py_pjsua_acc_add
+ * !modified @ 051206
+ */
+static PyObject *py_pjsua_acc_add
+(PyObject *pSelf, PyObject *pArgs)
+{    
+    int is_default;
+    acc_config_Object * ac;
+    pjsua_acc_config cfg;
+    
+    int p_acc_id;
+    int status;
+    int i;
+
+    if (!PyArg_ParseTuple(pArgs, "Oi", &ac, &is_default))
+    {
+        return NULL;
+    }
+    cfg.cred_count = ac->cred_count;
+    for (i = 0; i < 8; i++) 
+    {
+        /*cfg.cred_info[i] = ac->cred_info[i];*/
+	pjsip_cred_info_Object * ci = (pjsip_cred_info_Object *)PyList_GetItem((PyObject *)ac->cred_info,i);
+	cfg.cred_info[i].data.ptr = PyString_AsString(ci->data);
+	cfg.cred_info[i].data.slen = strlen(PyString_AsString(ci->data));
+	cfg.cred_info[i].realm.ptr = PyString_AsString(ci->realm);
+	cfg.cred_info[i].realm.slen = strlen(PyString_AsString(ci->realm));
+	cfg.cred_info[i].scheme.ptr = PyString_AsString(ci->scheme);
+	cfg.cred_info[i].scheme.slen = strlen(PyString_AsString(ci->scheme));
+	cfg.cred_info[i].username.ptr = PyString_AsString(ci->username);
+	cfg.cred_info[i].username.slen = strlen(PyString_AsString(ci->username));
+	cfg.cred_info[i].data_type = ci->data_type;
+    }
+    cfg.force_contact.ptr = PyString_AsString(ac->force_contact);
+    cfg.force_contact.slen = strlen(PyString_AsString(ac->force_contact));
+    cfg.id.ptr = PyString_AsString(ac->id);
+    cfg.id.slen = strlen(PyString_AsString(ac->id));
+    cfg.priority = ac->priority;
+    for (i = 0; i < 8; i++) {
+        /*cfg.proxy[i] = ac->proxy[i];*/
+	cfg.proxy[i].ptr = PyString_AsString(PyList_GetItem((PyObject *)ac->proxy,i));
+    }
+    cfg.proxy_cnt = ac->proxy_cnt;
+    cfg.publish_enabled = ac->publish_enabled;
+    cfg.reg_timeout = ac->reg_timeout;
+    cfg.reg_uri.ptr = PyString_AsString(ac->reg_uri);
+    cfg.reg_uri.slen = strlen(PyString_AsString(ac->reg_uri));
+    
+    status = pjsua_acc_add(&cfg, is_default, &p_acc_id);
+    
+    return Py_BuildValue("ii", status, p_acc_id);
+}
+
+/*
+ * py_pjsua_acc_add_local
+ * !modified @ 051206
+ */
+static PyObject *py_pjsua_acc_add_local
+(PyObject *pSelf, PyObject *pArgs)
+{    
+    int is_default;
+    int tid;
+    
+    int p_acc_id;
+    int status;
+	
+
+    if (!PyArg_ParseTuple(pArgs, "iiO", &tid, &is_default))
+    {
+        return NULL;
+    }
+	
+    
+    status = pjsua_acc_add_local(tid, is_default, &p_acc_id);
+    
+    return Py_BuildValue("ii", status, p_acc_id);
+}
+
+/*
+ * py_pjsua_acc_del
+ */
+static PyObject *py_pjsua_acc_del
+(PyObject *pSelf, PyObject *pArgs)
+{    
+    int acc_id;
+    int status;
+
+    if (!PyArg_ParseTuple(pArgs, "i", &acc_id))
+    {
+        return NULL;
+    }
+	
+	
+    status = pjsua_acc_del(acc_id);	
+    return Py_BuildValue("i", status);
+}
+
+/*
+ * py_pjsua_acc_modify
+ */
+static PyObject *py_pjsua_acc_modify
+(PyObject *pSelf, PyObject *pArgs)
+{    	
+    acc_config_Object * ac;
+    pjsua_acc_config cfg;	
+    int acc_id;
+    int status;
+    int i;
+
+    if (!PyArg_ParseTuple(pArgs, "iO", &acc_id, &ac))
+    {
+        return NULL;
+    }
+    cfg.cred_count = ac->cred_count;
+    for (i = 0; i < 8; i++) 
+    {
+        /*cfg.cred_info[i] = ac->cred_info[i];*/
+	pjsip_cred_info_Object * ci = (pjsip_cred_info_Object *)PyList_GetItem((PyObject *)ac->cred_info,i);
+	cfg.cred_info[i].data.ptr = PyString_AsString(ci->data);
+	cfg.cred_info[i].data.slen = strlen(PyString_AsString(ci->data));
+	cfg.cred_info[i].realm.ptr = PyString_AsString(ci->realm);
+	cfg.cred_info[i].realm.slen = strlen(PyString_AsString(ci->realm));
+	cfg.cred_info[i].scheme.ptr = PyString_AsString(ci->scheme);
+	cfg.cred_info[i].scheme.slen = strlen(PyString_AsString(ci->scheme));
+	cfg.cred_info[i].username.ptr = PyString_AsString(ci->username);
+	cfg.cred_info[i].username.slen = strlen(PyString_AsString(ci->username));
+    }
+    cfg.force_contact.ptr = PyString_AsString(ac->force_contact);
+    cfg.force_contact.slen = strlen(PyString_AsString(ac->force_contact));
+    cfg.id.ptr = PyString_AsString(ac->id);
+    cfg.id.slen = strlen(PyString_AsString(ac->id));
+    cfg.priority = ac->priority;
+    for (i = 0; i < 8; i++) {
+        /*cfg.proxy[i] = ac->proxy[i];*/
+	cfg.proxy[i].ptr = PyString_AsString(PyList_GetItem((PyObject *)ac->proxy,i));
+    }
+    cfg.proxy_cnt = ac->proxy_cnt;
+    cfg.publish_enabled = ac->publish_enabled;
+    cfg.reg_timeout = ac->reg_timeout;
+    cfg.reg_uri.ptr = PyString_AsString(ac->reg_uri);
+    cfg.reg_uri.slen = strlen(PyString_AsString(ac->reg_uri));	
+    status = pjsua_acc_modify(acc_id, &cfg);	
+    return Py_BuildValue("i", status);
+}
+
+/*
+ * py_pjsua_acc_set_online_status
+ */
+static PyObject *py_pjsua_acc_set_online_status
+(PyObject *pSelf, PyObject *pArgs)
+{    
+    int is_online;	
+    int acc_id;
+    int status;	
+
+    if (!PyArg_ParseTuple(pArgs, "ii", &acc_id, &is_online))
+    {
+        return NULL;
+    }
+	
+    status = pjsua_acc_set_online_status(acc_id, is_online);
+	
+    return Py_BuildValue("i", status);
+}
+
+/*
+ * py_pjsua_acc_set_registration
+ */
+static PyObject *py_pjsua_acc_set_registration
+(PyObject *pSelf, PyObject *pArgs)
+{    
+    int renew;	
+    int acc_id;
+    int status;	
+
+    if (!PyArg_ParseTuple(pArgs, "ii", &acc_id, &renew))
+    {
+        return NULL;
+    }
+	
+    status = pjsua_acc_set_registration(acc_id, renew);
+	
+    return Py_BuildValue("i", status);
+}
+
+/*
+ * py_pjsua_acc_get_info
+ * !modified @ 051206
+ */
+static PyObject *py_pjsua_acc_get_info
+(PyObject *pSelf, PyObject *pArgs)
+{    	
+    int acc_id;
+    acc_info_Object * obj;
+    pjsua_acc_info info;
+    int status;	
+    int i;
+
+    if (!PyArg_ParseTuple(pArgs, "i", &acc_id))
+    {
+        return NULL;
+    }
+	
+    
+    status = pjsua_acc_get_info(acc_id, &info);
+    if (status == PJ_SUCCESS) {
+	obj = (acc_info_Object *)acc_info_new(&acc_info_Type,NULL, NULL);
+        obj->acc_uri =
+            PyString_FromStringAndSize(info.acc_uri.ptr, 
+            info.acc_uri.slen);
+        for (i = 0; i < PJ_ERR_MSG_SIZE; i++) {
+            obj->buf_[i] = info.buf_[i];
+	}
+        obj->expires = info.expires;
+        obj->has_registration = info.has_registration;
+        obj->id = info.id;
+        obj->is_default = info.is_default;
+        obj->online_status = info.online_status;
+        obj->status = info.status;
+        obj->status_text =
+	    PyString_FromStringAndSize(info.status_text.ptr, 
+	    info.status_text.slen);
+        return Py_BuildValue("O", obj);
+    } else {
+	Py_INCREF(Py_None);
+	return Py_None;
+    }
+}
+
+/*
+ * py_pjsua_enum_accs
+ * !modified @ 051206
+ */
+static PyObject *py_pjsua_enum_accs(PyObject *pSelf, PyObject *pArgs)
+{
+    pj_status_t status;
+    PyObject *list;
+    
+    pjsua_acc_id *id;
+    int c, i;
+    if (!PyArg_ParseTuple(pArgs, "i", &c))
+    {
+        return NULL;
+    }	
+    
+    id = (pjsua_acc_id *)malloc(c * sizeof(pjsua_acc_id));
+    status = pjsua_enum_accs(id, &c);
+    
+    list = PyList_New(c);
+    for (i = 0; i < c; i++) {
+        int ret = PyList_SetItem(list, i, Py_BuildValue("i", id[i]));
+        if (ret == -1) {
+            return NULL;
+	}
+    }
+    
+    free(id);
+    return Py_BuildValue("O",list);
+}
+
+/*
+ * py_pjsua_acc_enum_info
+ * !modified @ 051206
+ */
+static PyObject *py_pjsua_acc_enum_info(PyObject *pSelf, PyObject *pArgs)
+{
+    pj_status_t status;
+    PyObject *list;
+    
+    pjsua_acc_info *info;
+    int c, i;
+    if (!PyArg_ParseTuple(pArgs, "i", &c))
+    {
+        return NULL;
+    }	
+    
+    info = (pjsua_acc_info *)malloc(c * sizeof(pjsua_acc_info));
+    status = pjsua_acc_enum_info(info, &c);
+    
+    list = PyList_New(c);
+    for (i = 0; i < c; i++) {
+        int ret;
+	int j;
+	acc_info_Object *obj;
+	obj = (acc_info_Object *)acc_info_new(&acc_info_Type,NULL,NULL);
+	obj->acc_uri = PyString_FromStringAndSize
+	    (info[i].acc_uri.ptr, info[i].acc_uri.slen);
+	for(j = 0; j < PJ_ERR_MSG_SIZE; j++) {
+	    obj->buf_[j] = info[i].buf_[j];
+	}
+	obj->expires = info[i].expires;
+	obj->has_registration = info[i].has_registration;
+	obj->id = info[i].id;
+	obj->is_default = info[i].is_default;
+	obj->online_status = info[i].online_status;
+	obj->status = info[i].status;
+	obj->status_text = PyString_FromStringAndSize(info[i].status_text.ptr,
+	    info[i].status_text.slen);
+	ret = PyList_SetItem(list, i, (PyObject *)obj);
+        if (ret == -1) {
+	    return NULL;
+        }
+    }
+    
+    free(info);
+    return Py_BuildValue("O",list);
+}
+
+/*
+ * py_pjsua_acc_find_for_outgoing
+ */
+static PyObject *py_pjsua_acc_find_for_outgoing
+(PyObject *pSelf, PyObject *pArgs)
+{    
+	
+    int acc_id;	
+    PyObject * url;
+    pj_str_t str;
+
+    if (!PyArg_ParseTuple(pArgs, "O", &url))
+    {
+        return NULL;
+    }
+    str.ptr = PyString_AsString(url);
+    str.slen = strlen(PyString_AsString(url));
+	
+    acc_id = pjsua_acc_find_for_outgoing(&str);
+	
+    return Py_BuildValue("i", acc_id);
+}
+
+/*
+ * py_pjsua_acc_find_for_incoming
+ */
+static PyObject *py_pjsua_acc_find_for_incoming
+(PyObject *pSelf, PyObject *pArgs)
+{    	
+    int acc_id;	
+    pjsip_rx_data_Object * obj;
+    pjsip_rx_data * rdata;
+
+    if (!PyArg_ParseTuple(pArgs, "O", &obj))
+    {
+        return NULL;
+    }
+	
+    rdata = obj->rdata;
+    acc_id = pjsua_acc_find_for_incoming(rdata);
+	
+    return Py_BuildValue("i", acc_id);
+}
+
+/*
+ * py_pjsua_acc_create_uac_contact
+ * !modified @ 061206
+ */
+static PyObject *py_pjsua_acc_create_uac_contact
+(PyObject *pSelf, PyObject *pArgs)
+{    	
+    int status;
+    int acc_id;	
+    pj_pool_Object * p;
+    pj_pool_t * pool;
+    PyObject * strc;
+    pj_str_t contact;
+    PyObject * stru;
+    pj_str_t uri;
+
+    if (!PyArg_ParseTuple(pArgs, "OiO", &p, &acc_id, &stru))
+    {
+        return NULL;
+    }
+	
+    pool = p->pool;    
+    uri.ptr = PyString_AsString(stru);
+    uri.slen = strlen(PyString_AsString(stru));
+    status = pjsua_acc_create_uac_contact(pool, &contact, acc_id, &uri);
+    strc = PyString_FromStringAndSize(contact.ptr, contact.slen);
+	
+    return Py_BuildValue("O", strc);
+}
+
+/*
+ * py_pjsua_acc_create_uas_contact
+ * !modified @ 061206
+ */
+static PyObject *py_pjsua_acc_create_uas_contact
+(PyObject *pSelf, PyObject *pArgs)
+{    	
+    int status;
+    int acc_id;	
+    pj_pool_Object * p;
+    pj_pool_t * pool;
+    PyObject * strc;
+    pj_str_t contact;
+    pjsip_rx_data_Object * objr;
+    pjsip_rx_data * rdata;
+
+    if (!PyArg_ParseTuple(pArgs, "OiO", &p, &acc_id, &objr))
+    {
+        return NULL;
+    }
+	
+    pool = p->pool;
+    
+    rdata = objr->rdata;
+    status = pjsua_acc_create_uas_contact(pool, &contact, acc_id, rdata);
+    strc = PyString_FromStringAndSize(contact.ptr, contact.slen);
+	
+    return Py_BuildValue("O", strc);
+}
+
+static char pjsua_acc_config_default_doc[] =
+    "py_pjsua.Acc_Config py_pjsua.acc_config_default () "
+    "Call this function to initialize account config with default values.";
+static char pjsua_acc_get_count_doc[] =
+    "int py_pjsua.acc_get_count () "
+    "Get number of current accounts.";
+static char pjsua_acc_is_valid_doc[] =
+    "int py_pjsua.acc_is_valid (int acc_id)  "
+    "Check if the specified account ID is valid.";
+static char pjsua_acc_set_default_doc[] =
+    "int py_pjsua.acc_set_default (int acc_id) "
+    "Set default account to be used when incoming "
+    "and outgoing requests doesn't match any accounts.";
+static char pjsua_acc_get_default_doc[] =
+    "int py_pjsua.acc_get_default () "
+    "Get default account.";
+static char pjsua_acc_add_doc[] =
+    "int, int py_pjsua.acc_add (py_pjsua.Acc_Config cfg, "
+    "int is_default) "
+    "Add a new account to pjsua. PJSUA must have been initialized "
+    "(with pjsua_init()) before calling this function.";
+static char pjsua_acc_add_local_doc[] =
+    "int,int py_pjsua.acc_add_local (int tid, "
+    "int is_default) "
+    "Add a local account. A local account is used to identify "
+    "local endpoint instead of a specific user, and for this reason, "
+    "a transport ID is needed to obtain the local address information.";
+static char pjsua_acc_del_doc[] =
+    "int py_pjsua.acc_del (int acc_id) "
+    "Delete account.";
+static char pjsua_acc_modify_doc[] =
+    "int py_pjsua.acc_modify (int acc_id, py_pjsua.Acc_Config cfg) "
+    "Modify account information.";
+static char pjsua_acc_set_online_status_doc[] =
+    "int py_pjsua.acc_set_online_status (int acc_id, int is_online) "
+    "Modify account's presence status to be advertised "
+    "to remote/presence subscribers.";
+static char pjsua_acc_set_registration_doc[] =
+    "int py_pjsua.acc_set_registration (int acc_id, int renew) "
+    "Update registration or perform unregistration.";
+static char pjsua_acc_get_info_doc[] =
+    "py_pjsua.Acc_Info py_pjsua.acc_get_info (int acc_id) "
+    "Get account information.";
+static char pjsua_enum_accs_doc[] =
+    "int[] py_pjsua.enum_accs (int count) "
+    "Enum accounts all account ids.";
+static char pjsua_acc_enum_info_doc[] =
+    "py_pjsua.Acc_Info[] py_pjsua.acc_enum_info (int count) "
+    "Enum accounts info.";
+static char pjsua_acc_find_for_outgoing_doc[] =
+    "int py_pjsua.acc_find_for_outgoing (string url) "
+    "This is an internal function to find the most appropriate account "
+    "to used to reach to the specified URL.";
+static char pjsua_acc_find_for_incoming_doc[] =
+    "int py_pjsua.acc_find_for_incoming (pjsip_rx_data_Object rdata) "
+    "This is an internal function to find the most appropriate account "
+    "to be used to handle incoming calls.";
+static char pjsua_acc_create_uac_contact_doc[] =
+    "string py_pjsua.acc_create_uac_contact (pj_pool_Object pool, "
+    "int acc_id, string uri) "
+    "Create a suitable URI to be put as Contact based on the specified "
+    "target URI for the specified account.";
+static char pjsua_acc_create_uas_contact_doc[] =
+    "string py_pjsua.acc_create_uas_contact (pj_pool_Object pool, "
+    "int acc_id, pjsip_rx_data_Object rdata) "
+    "Create a suitable URI to be put as Contact based on the information "
+    "in the incoming request.";
+
+/* END OF LIB ACCOUNT */
+
+/* LIB BUDDY */
+
+
+
+/*
+ * buddy_config_Object
+ * Buddy Config
  */
 typedef struct
@@ -4048,34 +4363,78 @@
     PyObject_HEAD
     /* Type-specific fields go here. */
-    int acc_id;
-} acc_id_Object;
-
-
-/*
- * acc_id_members
- * declares attributes accessible from 
- * both C and Python for acc_id object
- */
-static PyMemberDef acc_id_members[] =
-{
-    {
-        "acc_id", T_INT, offsetof(acc_id_Object, acc_id), 0,
-        "Account identification"
-    },
+    
+    PyObject * uri;
+    int subscribe;
+} buddy_config_Object;
+
+
+/*
+ * buddy_config_dealloc
+ * deletes a buddy_config from memory
+ */
+static void buddy_config_dealloc(buddy_config_Object* self)
+{
+    Py_XDECREF(self->uri);     
+    self->ob_type->tp_free((PyObject*)self);
+}
+
+
+/*
+ * buddy_config_new
+ * constructor for buddy_config object
+ */
+static PyObject * buddy_config_new(PyTypeObject *type, PyObject *args,
+                                    PyObject *kwds)
+{
+    buddy_config_Object *self;
+
+    self = (buddy_config_Object *)type->tp_alloc(type, 0);
+    if (self != NULL)
+    {
+        self->uri = PyString_FromString("");
+        if (self->uri == NULL)
+    	{
+            Py_DECREF(self);
+            return NULL;
+        }        
+    }
+    return (PyObject *)self;
+}
+
+/*
+ * buddy_config_members
+ */
+static PyMemberDef buddy_config_members[] =
+{
+    
+    {
+        "uri", T_OBJECT_EX,
+        offsetof(buddy_config_Object, uri), 0,
+        "TBuddy URL or name address."        
+    },
+    
+    {
+        "subscribe", T_INT, 
+        offsetof(buddy_config_Object, subscribe), 0,
+        "Specify whether presence subscription should start immediately. "
+    },
+    
     {NULL}  /* Sentinel */
 };
 
 
-/*
- * acc_id_Type
- */
-static PyTypeObject acc_id_Type =
+
+
+/*
+ * buddy_config_Type
+ */
+static PyTypeObject buddy_config_Type =
 {
     PyObject_HEAD_INIT(NULL)
     0,                              /*ob_size*/
-    "py_pjsua.Acc_ID",        /*tp_name*/
-    sizeof(acc_id_Object),    /*tp_basicsize*/
+    "py_pjsua.Buddy_Config",      /*tp_name*/
+    sizeof(buddy_config_Object),  /*tp_basicsize*/
     0,                              /*tp_itemsize*/
-    0,                              /*tp_dealloc*/
+    (destructor)buddy_config_dealloc,/*tp_dealloc*/
     0,                              /*tp_print*/
     0,                              /*tp_getattr*/
@@ -4093,55 +4452,383 @@
     0,                              /*tp_as_buffer*/
     Py_TPFLAGS_DEFAULT,             /*tp_flags*/
-    "Acc ID objects",         /*tp_doc*/
-    0,                              /*tp_traverse*/
-    0,                              /*tp_clear*/
-    0,                              /*tp_richcompare*/
+    "Buddy Config objects",       /* tp_doc */
+    0,                              /* tp_traverse */
+    0,                              /* tp_clear */
+    0,                              /* tp_richcompare */
     0,                              /* tp_weaklistoffset */
     0,                              /* tp_iter */
     0,                              /* tp_iternext */
     0,                              /* tp_methods */
-    acc_id_members,           /* tp_members */
+    buddy_config_members,         /* tp_members */
+    0,                              /* tp_getset */
+    0,                              /* tp_base */
+    0,                              /* tp_dict */
+    0,                              /* tp_descr_get */
+    0,                              /* tp_descr_set */
+    0,                              /* tp_dictoffset */
+    0,                              /* tp_init */
+    0,                              /* tp_alloc */
+    buddy_config_new,             /* tp_new */
 
 };
 
 /*
- * py_pjsua_acc_config_default
- */
-static PyObject *py_pjsua_acc_config_default
+ * buddy_info_Object
+ * Buddy Info
+ * !modified @ 071206
+ */
+typedef struct
+{
+    PyObject_HEAD
+    /* Type-specific fields go here. */ 
+    int id;
+    PyObject * uri;
+    PyObject * contact;
+    int status;
+    PyObject * status_text;
+    int monitor_pres;
+    char buf_[256];
+} buddy_info_Object;
+
+
+/*
+ * buddy_info_dealloc
+ * deletes a buddy_info from memory
+ * !modified @ 071206
+ */
+static void buddy_info_dealloc(buddy_info_Object* self)
+{
+    Py_XDECREF(self->uri);
+    Py_XDECREF(self->contact);
+    Py_XDECREF(self->status_text);
+    
+    self->ob_type->tp_free((PyObject*)self);
+}
+
+
+/*
+ * buddy_info_new
+ * constructor for buddy_info object
+ * !modified @ 071206
+ */
+static PyObject * buddy_info_new(PyTypeObject *type, PyObject *args,
+                                    PyObject *kwds)
+{
+    buddy_info_Object *self;
+
+    self = (buddy_info_Object *)type->tp_alloc(type, 0);
+    if (self != NULL)
+    {
+        self->uri = PyString_FromString("");
+        if (self->uri == NULL)
+    	{
+            Py_DECREF(self);
+            return NULL;
+        }        
+	self->contact = PyString_FromString("");
+        if (self->contact == NULL)
+    	{
+            Py_DECREF(self);
+            return NULL;
+        }
+	self->status_text = PyString_FromString("");
+        if (self->status_text == NULL)
+    	{
+            Py_DECREF(self);
+            return NULL;
+        }
+	
+    }
+    return (PyObject *)self;
+}
+
+/*
+ * buddy_info_members
+ * !modified @ 071206
+ */
+static PyMemberDef buddy_info_members[] =
+{
+    {
+        "id", T_INT, 
+        offsetof(buddy_info_Object, id), 0,
+        "The buddy ID."
+    },
+    {
+        "uri", T_OBJECT_EX,
+        offsetof(buddy_info_Object, uri), 0,
+        "The full URI of the buddy, as specified in the configuration. "        
+    },
+    {
+        "contact", T_OBJECT_EX,
+        offsetof(buddy_info_Object, contact), 0,
+        "Buddy's Contact, only available when presence subscription "
+        "has been established to the buddy."        
+    },
+    {
+        "status", T_INT, 
+        offsetof(buddy_info_Object, status), 0,
+        "Buddy's online status. "
+    },
+    {
+        "status_text", T_OBJECT_EX,
+        offsetof(buddy_info_Object, status_text), 0,
+        "Text to describe buddy's online status."        
+    },
+    {
+        "monitor_pres", T_INT, 
+        offsetof(buddy_info_Object, monitor_pres), 0,
+        "Flag to indicate that we should monitor the presence information "
+        "for this buddy (normally yes, unless explicitly disabled). "
+    },
+    
+    
+    {NULL}  /* Sentinel */
+};
+
+
+
+
+/*
+ * buddy_info_Type
+ */
+static PyTypeObject buddy_info_Type =
+{
+    PyObject_HEAD_INIT(NULL)
+    0,                              /*ob_size*/
+    "py_pjsua.Buddy_Info",      /*tp_name*/
+    sizeof(buddy_info_Object),  /*tp_basicsize*/
+    0,                              /*tp_itemsize*/
+    (destructor)buddy_info_dealloc,/*tp_dealloc*/
+    0,                              /*tp_print*/
+    0,                              /*tp_getattr*/
+    0,                              /*tp_setattr*/
+    0,                              /*tp_compare*/
+    0,                              /*tp_repr*/
+    0,                              /*tp_as_number*/
+    0,                              /*tp_as_sequence*/
+    0,                              /*tp_as_mapping*/
+    0,                              /*tp_hash */
+    0,                              /*tp_call*/
+    0,                              /*tp_str*/
+    0,                              /*tp_getattro*/
+    0,                              /*tp_setattro*/
+    0,                              /*tp_as_buffer*/
+    Py_TPFLAGS_DEFAULT,             /*tp_flags*/
+    "Buddy Info objects",       /* tp_doc */
+    0,                              /* tp_traverse */
+    0,                              /* tp_clear */
+    0,                              /* tp_richcompare */
+    0,                              /* tp_weaklistoffset */
+    0,                              /* tp_iter */
+    0,                              /* tp_iternext */
+    0,                              /* tp_methods */
+    buddy_info_members,         /* tp_members */
+    0,                              /* tp_getset */
+    0,                              /* tp_base */
+    0,                              /* tp_dict */
+    0,                              /* tp_descr_get */
+    0,                              /* tp_descr_set */
+    0,                              /* tp_dictoffset */
+    0,                              /* tp_init */
+    0,                              /* tp_alloc */
+    buddy_info_new,             /* tp_new */
+
+};
+
+/*
+ * py_pjsua_get_buddy_count
+ */
+static PyObject *py_pjsua_get_buddy_count
 (PyObject *pSelf, PyObject *pArgs)
-{
-    acc_config_Object *obj;
-    pjsua_acc_config cfg;
-	int i;
-
-    if (!PyArg_ParseTuple(pArgs, "O", &obj))
-    {
-        return NULL;
-    }
-    pjsua_acc_config_default(&cfg);
-	obj->cred_count = cfg.cred_count;
-	for (i = 0; i < 8; i++) 
-	{
-		obj->cred_info[i] = cfg.cred_info[i];
+{    
+    int ret;
+
+    if (!PyArg_ParseTuple(pArgs, ""))
+    {
+        return NULL;
+    }
+    ret = pjsua_get_buddy_count();
+	
+    return Py_BuildValue("i", ret);
+}
+
+/*
+ * py_pjsua_buddy_is_valid
+ */
+static PyObject *py_pjsua_buddy_is_valid
+(PyObject *pSelf, PyObject *pArgs)
+{    
+    int id;
+    int is_valid;
+
+    if (!PyArg_ParseTuple(pArgs, "i", &id))
+    {
+        return NULL;
+    }
+    is_valid = pjsua_buddy_is_valid(id);
+	
+    return Py_BuildValue("i", is_valid);
+}
+
+/*
+ * py_pjsua_enum_buddies
+ * !modified @ 061206
+ */
+static PyObject *py_pjsua_enum_buddies(PyObject *pSelf, PyObject *pArgs)
+{
+    pj_status_t status;
+    PyObject *list;
+    
+    pjsua_buddy_id *id;
+    int c, i;
+    if (!PyArg_ParseTuple(pArgs, "i", &c))
+    {
+        return NULL;
+    }	
+    
+    id = (pjsua_buddy_id *)malloc(c * sizeof(pjsua_buddy_id));
+    status = pjsua_enum_buddies(id, &c);
+    
+    list = PyList_New(c);
+    for (i = 0; i < c; i++) {
+        int ret = PyList_SetItem(list, i, Py_BuildValue("i", id[i]));
+        if (ret == -1) {
+            return NULL;
 	}
-	Py_XDECREF(obj->force_contact);
-	obj->force_contact = 
-		PyString_FromStringAndSize(cfg.force_contact.ptr, 
-		cfg.force_contact.slen);
-	obj->priority = cfg.priority;
-	Py_XDECREF(obj->id);
-	obj->id = 
-		PyString_FromStringAndSize(cfg.id.ptr, cfg.id.slen);
-	Py_XDECREF(obj->reg_uri);
-	obj->reg_uri = 
-		PyString_FromStringAndSize(cfg.reg_uri.ptr, cfg.reg_uri.slen);
-	obj->proxy_cnt = cfg.proxy_cnt;
-	for (i = 0; i < 8; i++) 
-	{
-		obj->proxy[i] = cfg.proxy[i];
+    }
+    
+    free(id);
+    return Py_BuildValue("O",list);
+}
+
+/*
+ * py_pjsua_buddy_get_info
+ * !modified @ 071206
+ */
+static PyObject *py_pjsua_buddy_get_info
+(PyObject *pSelf, PyObject *pArgs)
+{    	
+    int buddy_id;
+    buddy_info_Object * obj;
+    pjsua_buddy_info info;
+    int status;	
+    int i;
+
+    if (!PyArg_ParseTuple(pArgs, "i", &buddy_id))
+    {
+        return NULL;
+    }
+	
+    
+    status = pjsua_buddy_get_info(buddy_id, &info);
+    if (status == PJ_SUCCESS) {
+	obj = (buddy_info_Object *)buddy_info_new(&buddy_info_Type,NULL,NULL);
+        obj->id = info.id;
+        Py_XDECREF(obj->uri);
+        obj->uri =
+            PyString_FromStringAndSize(info.uri.ptr, 
+            info.uri.slen);
+        Py_XDECREF(obj->contact);
+        obj->contact =
+            PyString_FromStringAndSize(info.contact.ptr, 
+            info.contact.slen);
+        obj->status = info.status;
+        Py_XDECREF(obj->status_text);
+        obj->status_text =
+            PyString_FromStringAndSize(info.status_text.ptr, 
+            info.status_text.slen);
+        obj->monitor_pres = info.monitor_pres;
+        for (i = 0; i < 256; i++) {
+	    
+            obj->buf_[i] = info.buf_[i];
 	}
-	obj->publish_enabled = cfg.publish_enabled;
-	obj->reg_timeout = cfg.reg_timeout;
 	
+        return Py_BuildValue("O", obj);
+    } else {
+	Py_INCREF(Py_None);
+	return Py_None;
+    }
+}
+
+/*
+ * py_pjsua_buddy_add
+ * !modified @ 061206
+ */
+static PyObject *py_pjsua_buddy_add
+(PyObject *pSelf, PyObject *pArgs)
+{        
+    buddy_config_Object * bc;
+    pjsua_buddy_config cfg;
+    
+    int p_buddy_id;
+    int status;
+
+    if (!PyArg_ParseTuple(pArgs, "O", &bc))
+    {
+        return NULL;
+    }
+    cfg.subscribe = bc->subscribe;
+    cfg.uri.ptr = PyString_AsString(bc->uri);
+    cfg.uri.slen = strlen(PyString_AsString(bc->uri));    
+    
+    status = pjsua_buddy_add(&cfg, &p_buddy_id);
+    
+    return Py_BuildValue("ii", status, p_buddy_id);
+}
+
+/*
+ * py_pjsua_buddy_del
+ */
+static PyObject *py_pjsua_buddy_del
+(PyObject *pSelf, PyObject *pArgs)
+{    
+    int buddy_id;
+    int status;
+
+    if (!PyArg_ParseTuple(pArgs, "i", &buddy_id))
+    {
+        return NULL;
+    }
+	
+	
+    status = pjsua_buddy_del(buddy_id);	
+    return Py_BuildValue("i", status);
+}
+
+/*
+ * py_pjsua_buddy_subscribe_pres
+ */
+static PyObject *py_pjsua_buddy_subscribe_pres
+(PyObject *pSelf, PyObject *pArgs)
+{    
+    int buddy_id;
+    int status;
+    int subscribe;
+
+    if (!PyArg_ParseTuple(pArgs, "ii", &buddy_id, &subscribe))
+    {
+        return NULL;
+    }
+	
+	
+    status = pjsua_buddy_subscribe_pres(buddy_id, subscribe);	
+    return Py_BuildValue("i", status);
+}
+
+/*
+ * py_pjsua_pres_dump
+ */
+static PyObject *py_pjsua_pres_dump
+(PyObject *pSelf, PyObject *pArgs)
+{    
+    int verbose;
+
+    if (!PyArg_ParseTuple(pArgs, "i", &verbose))
+    {
+        return NULL;
+    }
+	
+	
+    pjsua_pres_dump(verbose);	
     Py_INCREF(Py_None);
     return Py_None;
@@ -4149,536 +4836,114 @@
 
 /*
- * py_pjsua_acc_get_count
- */
-static PyObject *py_pjsua_acc_get_count
-(PyObject *pSelf, PyObject *pArgs)
-{
-	int count;
-    if (!PyArg_ParseTuple(pArgs, ""))
-    {
-        return NULL;
-    }
-    count = pjsua_acc_get_count();
-    return Py_BuildValue("i",count);
-}
-
-/*
- * py_pjsua_acc_is_valid
- */
-static PyObject *py_pjsua_acc_is_valid
+ * py_pjsua_im_send
+ * !modified @ 071206
+ */
+static PyObject *py_pjsua_im_send
 (PyObject *pSelf, PyObject *pArgs)
 {    
-	int id;
-	int is_valid;
-
-    if (!PyArg_ParseTuple(pArgs, "i", &id))
-    {
-        return NULL;
-    }
-    is_valid = pjsua_acc_is_valid(id);
+    int status;
+    int acc_id;
+    pj_str_t to, mime_type, content;
+    PyObject * st;
+    PyObject * smt;
+    PyObject * sc;
+    pjsua_msg_data msg_data;
+    msg_data_Object * omd;
+    int user_data;
+    pj_pool_t *pool;
+
+    if (!PyArg_ParseTuple(pArgs, "iOOOOi", &acc_id, &st, &smt, &sc, &omd, &user_data))
+    {
+        return NULL;
+    }
 	
-    return Py_BuildValue("i", is_valid);
-}
-
-/*
- * py_pjsua_acc_set_default
- */
-static PyObject *py_pjsua_acc_set_default
+    to.ptr = PyString_AsString(st);
+    to.slen = strlen(PyString_AsString(st));
+    mime_type.ptr = PyString_AsString(smt);
+    mime_type.slen = strlen(PyString_AsString(smt));
+    content.ptr = PyString_AsString(sc);
+    content.slen = strlen(PyString_AsString(sc));
+    msg_data.content_type.ptr = PyString_AsString(omd->content_type);
+    msg_data.content_type.slen = strlen(PyString_AsString(omd->content_type));
+    msg_data.msg_body.ptr = PyString_AsString(omd->msg_body);
+    msg_data.msg_body.slen = strlen(PyString_AsString(omd->msg_body));
+    pool = pjsua_pool_create("pjsua", 4000, 4000);
+
+    translate_hdr(pool, &msg_data.hdr_list, omd->hdr_list);
+    status = pjsua_im_send(acc_id, &to, &mime_type, &content, &msg_data, &user_data);	
+    pj_pool_release(pool);
+    return Py_BuildValue("i",status);
+}
+
+/*
+ * py_pjsua_im_typing
+ */
+static PyObject *py_pjsua_im_typing
 (PyObject *pSelf, PyObject *pArgs)
 {    
-	int id;
-	int status;
-
-    if (!PyArg_ParseTuple(pArgs, "i", &id))
-    {
-        return NULL;
-    }
-    status = pjsua_acc_set_default(id);
+    int status;
+    int acc_id;
+    pj_str_t to;
+    PyObject * st;
+    int is_typing;
+    pjsua_msg_data msg_data;
+    msg_data_Object * omd;
+    pj_pool_t * pool;
+
+    if (!PyArg_ParseTuple(pArgs, "iOiO", &acc_id, &st, &is_typing, &omd))
+    {
+        return NULL;
+    }
 	
-    return Py_BuildValue("i", status);
-}
-
-/*
- * py_pjsua_acc_get_default
- */
-static PyObject *py_pjsua_acc_get_default
-(PyObject *pSelf, PyObject *pArgs)
-{    
-	int id;
-	
-    if (!PyArg_ParseTuple(pArgs, ""))
-    {
-        return NULL;
-    }
-    id = pjsua_acc_get_default();
-	
-    return Py_BuildValue("i", id);
-}
-
-/*
- * py_pjsua_acc_add
- */
-static PyObject *py_pjsua_acc_add
-(PyObject *pSelf, PyObject *pArgs)
-{    
-	int is_default;
-	acc_config_Object * ac;
-	pjsua_acc_config cfg;
-	acc_id_Object * id;
-	int p_acc_id;
-	int status;
-	int i;
-
-    if (!PyArg_ParseTuple(pArgs, "OiO", &ac, &is_default, &id))
-    {
-        return NULL;
-    }
-	cfg.cred_count = ac->cred_count;
-	for (i = 0; i < 8; i++) 
-	{
-		cfg.cred_info[i] = ac->cred_info[i];
-	}
-	cfg.force_contact.ptr = PyString_AsString(ac->force_contact);
-	cfg.force_contact.slen = strlen(PyString_AsString(ac->force_contact));
-	cfg.id.ptr = PyString_AsString(ac->id);
-	cfg.id.slen = strlen(PyString_AsString(ac->id));
-	cfg.priority = ac->priority;
-	for (i = 0; i < 8; i++) {
-		cfg.proxy[i] = ac->proxy[i];
-	}
-	cfg.proxy_cnt = ac->proxy_cnt;
-	cfg.publish_enabled = ac->publish_enabled;
-	cfg.reg_timeout = ac->reg_timeout;
-	cfg.reg_uri.ptr = PyString_AsString(ac->reg_uri);
-	cfg.reg_uri.slen = strlen(PyString_AsString(ac->reg_uri));
-	p_acc_id = id->acc_id;
-    status = pjsua_acc_add(&cfg, is_default, &p_acc_id);
-	id->acc_id = p_acc_id;
-    return Py_BuildValue("i", status);
-}
-
-/*
- * py_pjsua_acc_add_local
- */
-static PyObject *py_pjsua_acc_add_local
-(PyObject *pSelf, PyObject *pArgs)
-{    
-	int is_default;
-	int tid;
-	acc_id_Object * id;
-	int p_acc_id;
-	int status;
-	
-
-    if (!PyArg_ParseTuple(pArgs, "iiO", &tid, &is_default, &id))
-    {
-        return NULL;
-    }
-	
-	p_acc_id = id->acc_id;
-    status = pjsua_acc_add_local(tid, is_default, &p_acc_id);
-	id->acc_id = p_acc_id;
-    return Py_BuildValue("i", status);
-}
-
-/*
- * py_pjsua_acc_del
- */
-static PyObject *py_pjsua_acc_del
-(PyObject *pSelf, PyObject *pArgs)
-{    
-	int acc_id;
-	int status;
-	
-    if (!PyArg_ParseTuple(pArgs, "i", &acc_id))
-    {
-        return NULL;
-    }
-	
-	
-    status = pjsua_acc_del(acc_id);	
-    return Py_BuildValue("i", status);
-}
-
-/*
- * py_pjsua_acc_modify
- */
-static PyObject *py_pjsua_acc_modify
-(PyObject *pSelf, PyObject *pArgs)
-{    	
-	acc_config_Object * ac;
-	pjsua_acc_config cfg;	
-	int acc_id;
-	int status;
-	int i;
-
-    if (!PyArg_ParseTuple(pArgs, "iO", &acc_id, &ac))
-    {
-        return NULL;
-    }
-	cfg.cred_count = ac->cred_count;
-	for (i = 0; i < 8; i++) 
-	{
-		cfg.cred_info[i] = ac->cred_info[i];
-	}
-	cfg.force_contact.ptr = PyString_AsString(ac->force_contact);
-	cfg.force_contact.slen = strlen(PyString_AsString(ac->force_contact));
-	cfg.id.ptr = PyString_AsString(ac->id);
-	cfg.id.slen = strlen(PyString_AsString(ac->id));
-	cfg.priority = ac->priority;
-	for (i = 0; i < 8; i++) {
-		cfg.proxy[i] = ac->proxy[i];
-	}
-	cfg.proxy_cnt = ac->proxy_cnt;
-	cfg.publish_enabled = ac->publish_enabled;
-	cfg.reg_timeout = ac->reg_timeout;
-	cfg.reg_uri.ptr = PyString_AsString(ac->reg_uri);
-	cfg.reg_uri.slen = strlen(PyString_AsString(ac->reg_uri));	
-    status = pjsua_acc_modify(acc_id, &cfg);	
-    return Py_BuildValue("i", status);
-}
-
-/*
- * py_pjsua_acc_set_online_status
- */
-static PyObject *py_pjsua_acc_set_online_status
-(PyObject *pSelf, PyObject *pArgs)
-{    
-	int is_online;	
-	int acc_id;
-	int status;	
-
-    if (!PyArg_ParseTuple(pArgs, "ii", &acc_id, &is_online))
-    {
-        return NULL;
-    }
-	
-    status = pjsua_acc_set_online_status(acc_id, is_online);
-	
-    return Py_BuildValue("i", status);
-}
-
-/*
- * py_pjsua_acc_set_registration
- */
-static PyObject *py_pjsua_acc_set_registration
-(PyObject *pSelf, PyObject *pArgs)
-{    
-	int renew;	
-	int acc_id;
-	int status;	
-
-    if (!PyArg_ParseTuple(pArgs, "ii", &acc_id, &renew))
-    {
-        return NULL;
-    }
-	
-    status = pjsua_acc_set_registration(acc_id, renew);
-	
-    return Py_BuildValue("i", status);
-}
-
-/*
- * py_pjsua_acc_set_get_info
- */
-static PyObject *py_pjsua_acc_get_info
-(PyObject *pSelf, PyObject *pArgs)
-{    	
-	int acc_id;
-	acc_info_Object * obj;
-	pjsua_acc_info info;
-	int status;	
-	int i;
-
-    if (!PyArg_ParseTuple(pArgs, "iO", &acc_id, &obj))
-    {
-        return NULL;
-    }
-	
-	info.acc_uri.ptr = PyString_AsString(obj->acc_uri);
-	info.acc_uri.slen = strlen(PyString_AsString(obj->acc_uri));
-	for (i = 0; i < PJ_ERR_MSG_SIZE; i++) {
-		info.buf_[i] = obj->buf_[i];
-	}
-	info.expires = obj->expires;
-	info.has_registration = obj->has_registration;
-	info.id = obj->id;
-	info.is_default = obj->is_default;
-	info.online_status = obj->online_status;
-	info.status = obj->status;
-	info.status_text.ptr = PyString_AsString(obj->status_text);
-	info.status_text.slen = strlen(PyString_AsString(obj->status_text));
-    status = pjsua_acc_get_info(acc_id, &info);
-	obj->acc_uri =
-		PyString_FromStringAndSize(info.acc_uri.ptr, 
-		info.acc_uri.slen);
-	for (i = 0; i < PJ_ERR_MSG_SIZE; i++) {
-		obj->buf_[i] = info.buf_[i];
-	}
-	obj->expires = info.expires;
-	obj->has_registration = info.has_registration;
-	obj->id = info.id;
-	obj->is_default = info.is_default;
-	obj->online_status = info.online_status;
-	obj->status = info.status;
-	obj->status_text =
-		PyString_FromStringAndSize(info.status_text.ptr, 
-		info.status_text.slen);
-    return Py_BuildValue("i", status);
-}
-
-/*
- * py_pjsua_enum_accs
- */
-static PyObject *py_pjsua_enum_accs(PyObject *pSelf, PyObject *pArgs)
-{
-    pj_status_t status;
-	PyObject *list;
-	integer_Object *count;
-	pjsua_acc_id *id;
-	int c, i;
-    if (!PyArg_ParseTuple(pArgs, "OO", &list, &count))
-    {
-        return NULL;
-    }	
-	c = count->integer;
-	id = (pjsua_acc_id *)malloc(c * sizeof(pjsua_acc_id));
-    status = pjsua_enum_accs(id, &c);
-	Py_XDECREF(list);
-	list = PyList_New(c);
-	for (i = 0; i < c; i++) {
-		int ret = PyList_SetItem(list, i, Py_BuildValue("i", id[i]));
-		if (ret == -1) {
-			return NULL;
-		}
-	}
-	count->integer = c;
-	free(id);
+    to.ptr = PyString_AsString(st);
+    to.slen = strlen(PyString_AsString(st));    
+    msg_data.content_type.ptr = PyString_AsString(omd->content_type);
+    msg_data.content_type.slen = strlen(PyString_AsString(omd->content_type));
+    msg_data.msg_body.ptr = PyString_AsString(omd->msg_body);
+    msg_data.msg_body.slen = strlen(PyString_AsString(omd->msg_body));
+    pool = pjsua_pool_create("pjsua", 4000, 4000);
+
+    translate_hdr(pool, &msg_data.hdr_list, omd->hdr_list);
+    status = pjsua_im_typing(acc_id, &to, is_typing, &msg_data);	
+    pj_pool_release(pool);
     return Py_BuildValue("i",status);
 }
 
-/*
- * py_pjsua_acc_enum_info
- */
-static PyObject *py_pjsua_acc_enum_info(PyObject *pSelf, PyObject *pArgs)
-{
-    pj_status_t status;
-	PyObject *list;
-	integer_Object *count;
-	pjsua_acc_info *info;
-	int c, i;
-    if (!PyArg_ParseTuple(pArgs, "OO", &list, &count))
-    {
-        return NULL;
-    }	
-	c = count->integer;
-	info = (pjsua_acc_info *)malloc(c * sizeof(pjsua_acc_info));
-    status = pjsua_acc_enum_info(info, &c);
-	Py_XDECREF(list);
-	list = PyList_New(c);
-	for (i = 0; i < c; i++) {
-		int ret = PyList_SetItem(list, i, Py_BuildValue("i", info[i]));
-		if (ret == -1) {
-			return NULL;
-		}
-	}
-	count->integer = c;
-	free(info);
-    return Py_BuildValue("i",status);
-}
-
-/*
- * py_pjsua_acc_find_for_outgoing
- */
-static PyObject *py_pjsua_acc_find_for_outgoing
-(PyObject *pSelf, PyObject *pArgs)
-{    
-	
-	int acc_id;	
-	PyObject * url;
-	pj_str_t str;
-
-    if (!PyArg_ParseTuple(pArgs, "O", &url))
-    {
-        return NULL;
-    }
-	str.ptr = PyString_AsString(url);
-	str.slen = strlen(PyString_AsString(url));
-	
-    acc_id = pjsua_acc_find_for_outgoing(&str);
-	
-    return Py_BuildValue("i", acc_id);
-}
-
-/*
- * py_pjsua_acc_find_for_incoming
- */
-static PyObject *py_pjsua_acc_find_for_incoming
-(PyObject *pSelf, PyObject *pArgs)
-{    	
-	int acc_id;	
-	pjsip_rx_data_Object * obj;
-	pjsip_rx_data * rdata;
-
-    if (!PyArg_ParseTuple(pArgs, "O", &obj))
-    {
-        return NULL;
-    }
-	
-	rdata = obj->rdata;
-    acc_id = pjsua_acc_find_for_incoming(rdata);
-	
-    return Py_BuildValue("i", acc_id);
-}
-
-/*
- * py_pjsua_acc_create_uac_contact
- */
-static PyObject *py_pjsua_acc_create_uac_contact
-(PyObject *pSelf, PyObject *pArgs)
-{    	
-	int status;
-	int acc_id;	
-	pj_pool_Object * p;
-	pj_pool_t * pool;
-	PyObject * strc;
-	pj_str_t contact;
-	PyObject * stru;
-	pj_str_t uri;
-
-    if (!PyArg_ParseTuple(pArgs, "OOiO", &p, &strc, &acc_id, &stru))
-    {
-        return NULL;
-    }
-	
-	pool = p->pool;
-	contact.ptr = PyString_AsString(strc);
-	contact.slen = strlen(PyString_AsString(strc));
-	uri.ptr = PyString_AsString(stru);
-	uri.slen = strlen(PyString_AsString(stru));
-    status = pjsua_acc_create_uac_contact(pool, &contact, acc_id, &uri);
-	strc = PyString_FromStringAndSize(contact.ptr, contact.slen);
-	
-    return Py_BuildValue("i", status);
-}
-
-/*
- * py_pjsua_acc_create_uas_contact
- */
-static PyObject *py_pjsua_acc_create_uas_contact
-(PyObject *pSelf, PyObject *pArgs)
-{    	
-	int status;
-	int acc_id;	
-	pj_pool_Object * p;
-	pj_pool_t * pool;
-	PyObject * strc;
-	pj_str_t contact;
-	pjsip_rx_data_Object * objr;
-	pjsip_rx_data * rdata;
-
-    if (!PyArg_ParseTuple(pArgs, "OOiO", &p, &strc, &acc_id, &objr))
-    {
-        return NULL;
-    }
-	
-	pool = p->pool;
-	contact.ptr = PyString_AsString(strc);
-	contact.slen = strlen(PyString_AsString(strc));
-	rdata = objr->rdata;
-    status = pjsua_acc_create_uas_contact(pool, &contact, acc_id, rdata);
-	strc = PyString_FromStringAndSize(contact.ptr, contact.slen);
-	
-    return Py_BuildValue("i", status);
-}
-
-static char pjsua_acc_config_default_doc[] =
-    "void py_pjsua.acc_config_default (py_pjsua.Acc_Config cfg) "
-    "Call this function to initialize account config with default values.";
-static char pjsua_acc_get_count_doc[] =
-    "int py_pjsua.acc_get_count () "
-    "Get number of current accounts.";
-static char pjsua_acc_is_valid_doc[] =
-    "int py_pjsua.acc_is_valid (int acc_id)  "
-    "Check if the specified account ID is valid.";
-static char pjsua_acc_set_default_doc[] =
-    "int py_pjsua.acc_set_default (int acc_id) "
-    "Set default account to be used when incoming "
-	"and outgoing requests doesn't match any accounts.";
-static char pjsua_acc_get_default_doc[] =
-    "int py_pjsua.acc_get_default () "
-    "Get default account.";
-static char pjsua_acc_add_doc[] =
-    "int py_pjsua.acc_add (py_pjsua.Acc_Config cfg, "
-	"int is_default, py_pjsua.Acc_ID p_acc_id) "
-    "Add a new account to pjsua. PJSUA must have been initialized "
-	"(with pjsua_init()) before calling this function.";
-static char pjsua_acc_add_local_doc[] =
-    "int py_pjsua.acc_add_local (int tid, "
-	"int is_default, py_pjsua.Acc_ID p_acc_id) "
-    "Add a local account. A local account is used to identify "
-	"local endpoint instead of a specific user, and for this reason, "
-	"a transport ID is needed to obtain the local address information.";
-static char pjsua_acc_del_doc[] =
-    "int py_pjsua.acc_del (int acc_id) "
-    "Delete account.";
-static char pjsua_acc_modify_doc[] =
-    "int py_pjsua.acc_modify (int acc_id, py_pjsua.Acc_Config cfg) "
-    "Modify account information.";
-static char pjsua_acc_set_online_status_doc[] =
-    "int py_pjsua.acc_set_online_status (int acc_id, int is_online) "
-    "Modify account's presence status to be advertised "
-	"to remote/presence subscribers.";
-static char pjsua_acc_set_registration_doc[] =
-    "int py_pjsua.acc_set_registration (int acc_id, int renew) "
-    "Update registration or perform unregistration.";
-static char pjsua_acc_get_info_doc[] =
-    "int py_pjsua.acc_get_info (int acc_id, py_pjsua.Acc_Info info) "
-    "Get account information.";
-static char pjsua_enum_accs_doc[] =
-    "int py_pjsua.enum_accs (py_pjsua.Acc_ID ids[], py_pjsua.Integer count) "
-    "Enum accounts all account ids.";
-static char pjsua_acc_enum_info_doc[] =
-    "int py_pjsua.acc_enum_info (py_pjsua.Acc_Info info[], "
-	"py_pjsua.Integer count) "
-    "Enum accounts info.";
-static char pjsua_acc_find_for_outgoing_doc[] =
-    "int py_pjsua.acc_find_for_outgoing (string url) "
-    "This is an internal function to find the most appropriate account "
-	"to used to reach to the specified URL.";
-static char pjsua_acc_find_for_incoming_doc[] =
-    "int py_pjsua.acc_find_for_incoming (pjsip_rx_data_Object rdata) "
-    "This is an internal function to find the most appropriate account "
-	"to be used to handle incoming calls.";
-static char pjsua_acc_create_uac_contact_doc[] =
-    "int py_pjsua.acc_create_uac_contact (pj_pool_Object pool, "
-	"string contact, int acc_id, string uri) "
-    "Create a suitable URI to be put as Contact based on the specified "
-	"target URI for the specified account.";
-static char pjsua_acc_create_uas_contact_doc[] =
-    "int py_pjsua.acc_create_uas_contact (pj_pool_Object pool, "
-	"string contact, int acc_id, pjsip_rx_data_Object rdata) "
-    "Create a suitable URI to be put as Contact based on the information "
-	"in the incoming request.";
-
-/* END OF LIB ACCOUNT */
-
-/* XXX test */
-static PyObject *py_my_parse_by_reference
-(PyObject *pSelf, PyObject *pArgs)
-{    
-    PyObject *obj;
-
-    if (!PyArg_ParseTuple(pArgs, "O", &obj))
-    {
-        return NULL;
-    }
-
-
-    Py_INCREF(Py_None);
-    return Py_None;
-}
-
-/* XXX end-test */
+static char pjsua_get_buddy_count_doc[] =
+    "int py_pjsua.get_buddy_count () "
+    "Get total number of buddies.";
+static char pjsua_buddy_is_valid_doc[] =
+    "int py_pjsua.buddy_is_valid (int buddy_id) "
+    "Check if buddy ID is valid.";
+static char pjsua_enum_buddies_doc[] =
+    "int[] py_pjsua.enum_buddies (int count) "
+    "Enum buddy IDs.";
+static char pjsua_buddy_get_info_doc[] =
+    "py_pjsua.Buddy_Info py_pjsua.buddy_get_info (int buddy_id) "
+    "Get detailed buddy info.";
+static char pjsua_buddy_add_doc[] =
+    "int,int py_pjsua.buddy_add (py_pjsua.Buddy_Config cfg) "
+    "Add new buddy.";
+static char pjsua_buddy_del_doc[] =
+    "int py_pjsua.buddy_del (int buddy_id) "
+    "Delete buddy.";
+static char pjsua_buddy_subscribe_pres_doc[] =
+    "int py_pjsua.buddy_subscribe_pres (int buddy_id, int subscribe) "
+    "Enable/disable buddy's presence monitoring.";
+static char pjsua_pres_dump_doc[] =
+    "void py_pjsua.pres_dump (int verbose) "
+    "Dump presence subscriptions to log file.";
+static char pjsua_im_send_doc[] =
+    "int py_pjsua.im_send (int acc_id, string to, string mime_type, "
+    "string content, py_pjsua.Msg_Data msg_data, int user_data) "
+    "Send instant messaging outside dialog, using the specified account "
+    "for route set and authentication.";
+static char pjsua_im_typing_doc[] =
+    "int py_pjsua.im_typing (int acc_id, string to, int is_typing, "
+    "py_pjsua.Msg_Data msg_data) "
+    "Send typing indication outside dialog.";
+
+/* END OF LIB BUDDY */
+
 
 
@@ -4689,5 +4954,6 @@
 {
     {
-	"my_parse_by_reference", py_my_parse_by_reference, METH_VARARGS, ""
+        "thread_register", py_pjsua_thread_register, METH_VARARGS, 
+         pjsua_thread_register_doc
     },
     {
@@ -4746,130 +5012,161 @@
     	pjsua_media_config_default_doc
     },
-    {
-    	"logging_config_dup", py_pjsua_logging_config_dup, METH_VARARGS,
-    	pjsua_logging_config_dup_doc
-    },
-    {
-    	"config_dup", py_pjsua_config_dup, METH_VARARGS, pjsua_config_dup_doc
-    },
-    {
-    	"pjsip_cred_dup", py_pjsip_cred_dup, METH_VARARGS, pjsip_cred_dup_doc
-    },
+    
+    
     {
     	"msg_data_init", py_pjsua_msg_data_init, METH_VARARGS,
     	pjsua_msg_data_init_doc
     },
-	{
-    	"stun_config_default", py_pjsua_stun_config_default, METH_VARARGS,
-    	pjsua_stun_config_default_doc
-    },
-	{
-    	"transport_config_default", py_pjsua_transport_config_default, 
-			METH_VARARGS,pjsua_transport_config_default_doc
-    },
-	{
-    	"normalize_stun_config", py_pjsua_normalize_stun_config, METH_VARARGS,
-    	pjsua_normalize_stun_config_doc
-    },
-	{
-    	"transport_config_dup", py_pjsua_transport_config_dup, METH_VARARGS,
-    	pjsua_transport_config_dup_doc
-    },
-	{
-    	"transport_create", py_pjsua_transport_create, METH_VARARGS,
-    	pjsua_transport_create_doc
-    },
-	{
-    	"transport_register", py_pjsua_transport_register, METH_VARARGS,
-    	pjsua_transport_register_doc
-    },
-	{
-    	"transport_enum_transports", py_pjsua_enum_transports, METH_VARARGS,
-    	pjsua_enum_transports_doc
-    },
-	{
-    	"transport_get_info", py_pjsua_transport_get_info, METH_VARARGS,
-    	pjsua_transport_get_info_doc
-    },
-	{
-    	"transport_set_enable", py_pjsua_transport_set_enable, METH_VARARGS,
-    	pjsua_transport_set_enable_doc
-    },
-	{
-    	"transport_close", py_pjsua_transport_close, METH_VARARGS,
-    	pjsua_transport_close_doc
-    },
-	{
-    	"acc_config_default", py_pjsua_acc_config_default, METH_VARARGS,
-    	pjsua_acc_config_default_doc
-    },
-	{
-    	"acc_get_count", py_pjsua_acc_get_count, METH_VARARGS,
-    	pjsua_acc_get_count_doc
-    },
-	{
-    	"acc_is_valid", py_pjsua_acc_is_valid, METH_VARARGS,
-    	pjsua_acc_is_valid_doc
-    },
-	{
-    	"acc_set_default", py_pjsua_acc_set_default, METH_VARARGS,
-    	pjsua_acc_set_default_doc
-    },
-	{
-    	"acc_get_default", py_pjsua_acc_get_default, METH_VARARGS,
-    	pjsua_acc_get_default_doc
-    },
-	{
-    	"acc_add", py_pjsua_acc_add, METH_VARARGS,
-    	pjsua_acc_add_doc
-    },
-	{
-    	"acc_add_local", py_pjsua_acc_add_local, METH_VARARGS,
-    	pjsua_acc_add_local_doc
-    },
-	{
-    	"acc_del", py_pjsua_acc_del, METH_VARARGS,
-    	pjsua_acc_del_doc
-    },
-	{
-    	"acc_modify", py_pjsua_acc_modify, METH_VARARGS,
-    	pjsua_acc_modify_doc
-    },
-	{
-    	"acc_set_online_status", py_pjsua_acc_set_online_status, METH_VARARGS,
-    	pjsua_acc_set_online_status_doc
-    },
-	{
-    	"acc_set_registration", py_pjsua_acc_set_registration, METH_VARARGS,
-    	pjsua_acc_set_registration_doc
-    },
-	{
-    	"acc_get_info", py_pjsua_acc_get_info, METH_VARARGS,
-    	pjsua_acc_get_info_doc
-    },
-	{
-    	"enum_accs", py_pjsua_enum_accs, METH_VARARGS,
-    	pjsua_enum_accs_doc
-    },
-	{
-    	"acc_enum_info", py_pjsua_acc_enum_info, METH_VARARGS,
-    	pjsua_acc_enum_info_doc
-    },
-	{
-    	"acc_find_for_outgoing", py_pjsua_acc_find_for_outgoing, METH_VARARGS,
-    	pjsua_acc_find_for_outgoing_doc
-    },
-	{
-    	"acc_find_for_incoming", py_pjsua_acc_find_for_incoming, METH_VARARGS,
-    	pjsua_acc_find_for_incoming_doc
-    },
-	{
-    	"acc_create_uac_contact", py_pjsua_acc_create_uac_contact, METH_VARARGS,
-    	pjsua_acc_create_uac_contact_doc
-    },
-	{
-    	"acc_create_uas_contact", py_pjsua_acc_create_uas_contact, METH_VARARGS,
-    	pjsua_acc_create_uas_contact_doc
-    },
+    {
+        "stun_config_default", py_pjsua_stun_config_default, METH_VARARGS,
+        pjsua_stun_config_default_doc
+    },
+    {
+        "transport_config_default", py_pjsua_transport_config_default, 
+        METH_VARARGS,pjsua_transport_config_default_doc
+    },
+    {
+        "normalize_stun_config", py_pjsua_normalize_stun_config, METH_VARARGS,
+        pjsua_normalize_stun_config_doc
+    },
+    
+    {
+        "transport_create", py_pjsua_transport_create, METH_VARARGS,
+        pjsua_transport_create_doc
+    },
+    {
+        "transport_register", py_pjsua_transport_register, METH_VARARGS,
+        pjsua_transport_register_doc
+    },
+    {
+        "transport_enum_transports", py_pjsua_enum_transports, METH_VARARGS,
+        pjsua_enum_transports_doc
+    },
+    {
+        "transport_get_info", py_pjsua_transport_get_info, METH_VARARGS,
+        pjsua_transport_get_info_doc
+    },
+    {
+        "transport_set_enable", py_pjsua_transport_set_enable, METH_VARARGS,
+        pjsua_transport_set_enable_doc
+    },
+    {
+       "transport_close", py_pjsua_transport_close, METH_VARARGS,
+        pjsua_transport_close_doc
+    },
+    {
+        "acc_config_default", py_pjsua_acc_config_default, METH_VARARGS,
+        pjsua_acc_config_default_doc
+    },
+    {
+        "acc_get_count", py_pjsua_acc_get_count, METH_VARARGS,
+        pjsua_acc_get_count_doc
+    },
+    {
+        "acc_is_valid", py_pjsua_acc_is_valid, METH_VARARGS,
+        pjsua_acc_is_valid_doc
+    },
+    {
+        "acc_set_default", py_pjsua_acc_set_default, METH_VARARGS,
+        pjsua_acc_set_default_doc
+    },
+    {
+        "acc_get_default", py_pjsua_acc_get_default, METH_VARARGS,
+        pjsua_acc_get_default_doc
+    },
+    {
+        "acc_add", py_pjsua_acc_add, METH_VARARGS,
+        pjsua_acc_add_doc
+    },
+    {
+        "acc_add_local", py_pjsua_acc_add_local, METH_VARARGS,
+        pjsua_acc_add_local_doc
+    },
+    {
+        "acc_del", py_pjsua_acc_del, METH_VARARGS,
+        pjsua_acc_del_doc
+    },
+    {
+        "acc_modify", py_pjsua_acc_modify, METH_VARARGS,
+        pjsua_acc_modify_doc
+    },
+    {
+        "acc_set_online_status", py_pjsua_acc_set_online_status, METH_VARARGS,
+        pjsua_acc_set_online_status_doc
+    },
+    {
+        "acc_set_registration", py_pjsua_acc_set_registration, METH_VARARGS,
+        pjsua_acc_set_registration_doc
+    },
+    {
+        "acc_get_info", py_pjsua_acc_get_info, METH_VARARGS,
+        pjsua_acc_get_info_doc
+    },
+    {
+        "enum_accs", py_pjsua_enum_accs, METH_VARARGS,
+        pjsua_enum_accs_doc
+    },
+    {
+        "acc_enum_info", py_pjsua_acc_enum_info, METH_VARARGS,
+        pjsua_acc_enum_info_doc
+    },
+    {
+        "acc_find_for_outgoing", py_pjsua_acc_find_for_outgoing, METH_VARARGS,
+        pjsua_acc_find_for_outgoing_doc
+    },
+    {
+        "acc_find_for_incoming", py_pjsua_acc_find_for_incoming, METH_VARARGS,
+        pjsua_acc_find_for_incoming_doc
+    },
+    {
+        "acc_create_uac_contact", py_pjsua_acc_create_uac_contact, METH_VARARGS,
+        pjsua_acc_create_uac_contact_doc
+    },
+    {
+        "acc_create_uas_contact", py_pjsua_acc_create_uas_contact, METH_VARARGS,
+        pjsua_acc_create_uas_contact_doc
+    },
+    {
+        "get_buddy_count", py_pjsua_get_buddy_count, METH_VARARGS,
+        pjsua_get_buddy_count_doc
+    },
+    {
+        "buddy_is_valid", py_pjsua_buddy_is_valid, METH_VARARGS,
+        pjsua_buddy_is_valid_doc
+    },
+    {
+        "enum_buddies", py_pjsua_enum_buddies, METH_VARARGS,
+        pjsua_enum_buddies_doc
+    },
+    {
+        "buddy_get_info", py_pjsua_buddy_get_info, METH_VARARGS,
+        pjsua_buddy_get_info_doc
+    },
+    {
+        "buddy_add", py_pjsua_buddy_add, METH_VARARGS,
+        pjsua_buddy_add_doc
+    },
+    {
+        "buddy_del", py_pjsua_buddy_del, METH_VARARGS,
+        pjsua_buddy_del_doc
+    },
+    {
+        "buddy_subscribe_pres", py_pjsua_buddy_subscribe_pres, METH_VARARGS,
+        pjsua_buddy_subscribe_pres_doc
+    },
+    {
+        "pres_dump", py_pjsua_pres_dump, METH_VARARGS,
+        pjsua_pres_dump_doc
+    },
+    {
+        "im_send", py_pjsua_im_send, METH_VARARGS,
+        pjsua_im_send_doc
+    },
+    {
+        "im_typing", py_pjsua_im_typing, METH_VARARGS,
+        pjsua_im_typing_doc
+    },
+    
+    
     {NULL, NULL} /* end of function list */
 };
@@ -4885,4 +5182,5 @@
     PyObject* m = NULL;
 
+    
     if (PyType_Ready(&callback_Type) < 0)
         return;
@@ -4918,39 +5216,44 @@
         return;
 
-	/* LIB TRANSPORT */
-
-	if (PyType_Ready(&stun_config_Type) < 0)
+    /* LIB TRANSPORT */
+
+    if (PyType_Ready(&stun_config_Type) < 0)
         return;
-	if (PyType_Ready(&transport_config_Type) < 0)
+    if (PyType_Ready(&transport_config_Type) < 0)
         return;
-	if (PyType_Ready(&sockaddr_Type) < 0)
+    if (PyType_Ready(&sockaddr_Type) < 0)
         return;
-	if (PyType_Ready(&host_port_Type) < 0)
+    if (PyType_Ready(&host_port_Type) < 0)
         return;
-	transport_id_Type.tp_new = PyType_GenericNew;
-	if (PyType_Ready(&transport_id_Type) < 0)
+    
+    if (PyType_Ready(&transport_info_Type) < 0)
         return;
-	if (PyType_Ready(&transport_info_Type) < 0)
-        return;
-	integer_Type.tp_new = PyType_GenericNew;
-    if (PyType_Ready(&integer_Type) < 0)
-        return;
-	pjsip_transport_Type.tp_new = PyType_GenericNew;
+    
+    pjsip_transport_Type.tp_new = PyType_GenericNew;
     if (PyType_Ready(&pjsip_transport_Type) < 0)
         return;
 
-	/* END OF LIB TRANSPORT */
-
-	/* LIB ACCOUNT */
-
-	acc_id_Type.tp_new = PyType_GenericNew;
-	if (PyType_Ready(&acc_id_Type) < 0)
+    /* END OF LIB TRANSPORT */
+
+    /* LIB ACCOUNT */
+
+    
+    if (PyType_Ready(&acc_config_Type) < 0)
         return;
-	if (PyType_Ready(&acc_config_Type) < 0)
+    if (PyType_Ready(&acc_info_Type) < 0)
         return;
-	if (PyType_Ready(&acc_info_Type) < 0)
+
+    /* END OF LIB ACCOUNT */
+
+    /* LIB BUDDY */
+
+    if (PyType_Ready(&buddy_config_Type) < 0)
         return;
-
-	/* END OF LIB ACCOUNT */
+    if (PyType_Ready(&buddy_info_Type) < 0)
+        return;
+
+    /* END OF LIB BUDDY */
+
+    
 
     m = Py_InitModule3(
@@ -4998,36 +5301,44 @@
     );
 
-	/* LIB TRANSPORT */
-
-	Py_INCREF(&stun_config_Type);
+    /* LIB TRANSPORT */
+
+    Py_INCREF(&stun_config_Type);
     PyModule_AddObject(m, "STUN_Config", (PyObject *)&stun_config_Type);
-	Py_INCREF(&transport_config_Type);
+    Py_INCREF(&transport_config_Type);
     PyModule_AddObject
-		(m, "Transport_Config", (PyObject *)&transport_config_Type);
-	Py_INCREF(&sockaddr_Type);
+        (m, "Transport_Config", (PyObject *)&transport_config_Type);
+    Py_INCREF(&sockaddr_Type);
     PyModule_AddObject(m, "Sockaddr", (PyObject *)&sockaddr_Type);
-	Py_INCREF(&host_port_Type);
+    Py_INCREF(&host_port_Type);
     PyModule_AddObject(m, "Host_Port", (PyObject *)&host_port_Type);
-	Py_INCREF(&transport_id_Type);
-    PyModule_AddObject(m, "Transport_ID", (PyObject *)&transport_id_Type);
-	Py_INCREF(&transport_info_Type);
+    
+    Py_INCREF(&transport_info_Type);
     PyModule_AddObject(m, "Transport_Info", (PyObject *)&transport_info_Type);
-	Py_INCREF(&integer_Type);
-    PyModule_AddObject(m, "Integer", (PyObject *)&integer_Type);
-	Py_INCREF(&pjsip_transport_Type);
+    
+    Py_INCREF(&pjsip_transport_Type);
     PyModule_AddObject(m, "PJSIP_Transport", (PyObject *)&pjsip_transport_Type);
 
-	/* END OF LIB TRANSPORT */
-
-	/* LIB ACCOUNT */
-
-	Py_INCREF(&acc_id_Type);
-    PyModule_AddObject(m, "Acc_ID", (PyObject *)&acc_id_Type);
-	Py_INCREF(&acc_config_Type);
+    /* END OF LIB TRANSPORT */
+
+    /* LIB ACCOUNT */
+
+    
+    Py_INCREF(&acc_config_Type);
     PyModule_AddObject(m, "Acc_Config", (PyObject *)&acc_config_Type);
-	Py_INCREF(&acc_info_Type);
+    Py_INCREF(&acc_info_Type);
     PyModule_AddObject(m, "Acc_Info", (PyObject *)&acc_info_Type);
 
-	/* END OF LIB ACCOUNT */
+    /* END OF LIB ACCOUNT */
+
+    /* LIB BUDDY */
+    
+    Py_INCREF(&buddy_config_Type);
+    PyModule_AddObject(m, "Buddy_Config", (PyObject *)&buddy_config_Type);
+    Py_INCREF(&buddy_info_Type);
+    PyModule_AddObject(m, "Buddy_Info", (PyObject *)&buddy_info_Type);
+
+    /* END OF LIB BUDDY */
+
+    
 
 #ifdef PJSUA_INVALID_ID
@@ -5083,3 +5394,15 @@
 #endif
 
-}
+#ifdef PJSUA_MAX_BUDDIES
+    /*
+     * Default account priority.
+     */
+    PyModule_AddIntConstant(
+        m, "PJSUA_MAX_BUDDIES", PJSUA_MAX_BUDDIES
+    );
+#endif
+
+
+
+
+}
