Setting svn:eol-style attribute

git-svn-id: https://svn.pjsip.org/repos/pjproject/trunk@167 74dad513-b988-da41-8d7b-12977e46ad98
diff --git a/pjsip/build/pjsua.dsp b/pjsip/build/pjsua.dsp
index 73e9df1..b27d2c2 100644
--- a/pjsip/build/pjsua.dsp
+++ b/pjsip/build/pjsua.dsp
@@ -98,20 +98,14 @@
 # End Source File

 # Begin Source File

 

-SOURCE=..\src\pjsua\main_old.c

-# PROP Exclude_From_Build 1

-# End Source File

-# Begin Source File

-

-SOURCE=..\src\pjsua\misc.c

-# PROP Exclude_From_Build 1

-# End Source File

-# Begin Source File

-

 SOURCE=..\src\pjsua\pjsua_core.c

 # End Source File

 # Begin Source File

 

+SOURCE=..\src\pjsua\pjsua_inv.c

+# End Source File

+# Begin Source File

+

 SOURCE=..\src\pjsua\pjsua_reg.c

 # End Source File

 # End Group

diff --git a/pjsip/include/pjsip-ua/sip_regc.h b/pjsip/include/pjsip-ua/sip_regc.h
index 99a08a4..1295991 100644
--- a/pjsip/include/pjsip-ua/sip_regc.h
+++ b/pjsip/include/pjsip-ua/sip_regc.h
@@ -141,7 +141,7 @@
 /**
  * Set authentication credentials to use by this registration.
  *
- * @param dlg	    The registration structure.
+ * @param regc	    The registration structure.
  * @param count	    Number of credentials in the array.
  * @param cred	    Array of credentials.
  *
@@ -152,6 +152,17 @@
 						 const pjsip_cred_info cred[] );
 
 /**
+ * Set route set to be used for outgoing requests.
+ *
+ * @param regc	    The client registration structure.
+ * @param route_set List containing Route headers.
+ *
+ * @return	    PJ_SUCCESS on success.
+ */
+PJ_DECL(pj_status_t) pjsip_regc_set_route_set(pjsip_regc *regc,
+					      const pjsip_route_hdr*route_set);
+
+/**
  * Create REGISTER request for the specified client registration structure.
  *
  * After successfull registration, application can inspect the contacts in
diff --git a/pjsip/src/pjsip-ua/sip_reg.c b/pjsip/src/pjsip-ua/sip_reg.c
index f3a0354..c94aff2 100644
--- a/pjsip/src/pjsip-ua/sip_reg.c
+++ b/pjsip/src/pjsip-ua/sip_reg.c
@@ -41,33 +41,34 @@
  */
 struct pjsip_regc
 {
-    pj_pool_t	        *pool;
-    pjsip_endpoint	*endpt;
-    pj_bool_t		 _delete_flag;
-    int			 pending_tsx;
+    pj_pool_t			*pool;
+    pjsip_endpoint		*endpt;
+    pj_bool_t			 _delete_flag;
+    int				 pending_tsx;
 
-    void		*token;
-    pjsip_regc_cb	*cb;
+    void			*token;
+    pjsip_regc_cb		*cb;
 
-    pj_str_t		 str_srv_url;
-    pjsip_uri		*srv_url;
-    pjsip_cid_hdr	*cid_hdr;
-    pjsip_cseq_hdr	*cseq_hdr;
-    pjsip_from_hdr	*from_hdr;
-    pjsip_to_hdr	*to_hdr;
-    char		*contact_buf;
+    pj_str_t			 str_srv_url;
+    pjsip_uri			*srv_url;
+    pjsip_cid_hdr		*cid_hdr;
+    pjsip_cseq_hdr		*cseq_hdr;
+    pjsip_from_hdr		*from_hdr;
+    pjsip_to_hdr		*to_hdr;
+    char			*contact_buf;
     pjsip_generic_string_hdr	*contact_hdr;
-    pjsip_expires_hdr	*expires_hdr;
-    pjsip_contact_hdr	*unreg_contact_hdr;
-    pjsip_expires_hdr	*unreg_expires_hdr;
-    pj_uint32_t		 expires;
+    pjsip_expires_hdr		*expires_hdr;
+    pjsip_contact_hdr		*unreg_contact_hdr;
+    pjsip_expires_hdr		*unreg_expires_hdr;
+    pj_uint32_t			 expires;
+    pjsip_route_hdr		 route_set;
 
     /* Authorization sessions. */
-    pjsip_auth_clt_sess	 auth_sess;
+    pjsip_auth_clt_sess		 auth_sess;
 
     /* Auto refresh registration. */
-    pj_bool_t		 auto_reg;
-    pj_timer_entry	 timer;
+    pj_bool_t			 auto_reg;
+    pj_timer_entry		 timer;
 };
 
 
@@ -99,6 +100,8 @@
     if (status != PJ_SUCCESS)
 	return status;
 
+    pj_list_init(&regc->route_set);
+
     /* Done */
     *p_regc = regc;
     return PJ_SUCCESS;
@@ -248,6 +251,24 @@
     return pjsip_auth_clt_set_credentials(&regc->auth_sess, count, cred);
 }
 
+PJ_DEF(pj_status_t) pjsip_regc_set_route_set( pjsip_regc *regc,
+					      const pjsip_route_hdr *route_set)
+{
+    const pjsip_route_hdr *chdr;
+
+    PJ_ASSERT_RETURN(regc && route_set, PJ_EINVAL);
+
+    pj_list_init(&regc->route_set);
+
+    chdr = route_set->next;
+    while (chdr != route_set) {
+	pj_list_push_back(&regc->route_set, pjsip_hdr_clone(regc->pool, chdr));
+	chdr = chdr->next;
+    }
+
+    return PJ_SUCCESS;
+}
+
 static pj_status_t create_request(pjsip_regc *regc, 
 				  pjsip_tx_data **p_tdata)
 {
@@ -273,6 +294,24 @@
     /* Add cached authorization headers. */
     pjsip_auth_clt_init_req( &regc->auth_sess, tdata );
 
+    /* Add Route headers from route set, ideally after Via header */
+    if (!pj_list_empty(&regc->route_set)) {
+	pjsip_hdr *route_pos;
+	const pjsip_route_hdr *route;
+
+	route_pos = pjsip_msg_find_hdr(tdata->msg, PJSIP_H_VIA, NULL);
+	if (!route_pos)
+	    route_pos = &tdata->msg->hdr;
+
+	route = regc->route_set.next;
+	while (route != &regc->route_set) {
+	    pjsip_hdr *new_hdr = pjsip_hdr_shallow_clone(tdata->pool, route);
+	    pj_list_insert_after(route_pos, new_hdr);
+	    route_pos = new_hdr;
+	    route = route->next;
+	}
+    }
+
     /* Done. */
     *p_tdata = tdata;
     return PJ_SUCCESS;
diff --git a/pjsip/src/pjsua/main.c b/pjsip/src/pjsua/main.c
index f802799..287f562 100644
--- a/pjsip/src/pjsua/main.c
+++ b/pjsip/src/pjsua/main.c
@@ -61,7 +61,7 @@
 {
     puts("");
     puts("Console keys:");
-    puts("  m    Make a call");
+    puts("  m    Make a call/another call");
     puts("  a    Answer incoming call");
     puts("  h    Hangup current call");
     puts("  q    Quit");
@@ -352,10 +352,10 @@
     puts("  --use-stun1=host[:port]");
     puts("  --use-stun2=host[:port]  Use STUN and set host name and port of STUN servers");
     puts("");
-    puts("SIMPLE options (may be specified more than once):");
-    puts("  --add-buddy url     Add the specified URL to the buddy list.");
-    puts("  --offer-x-ms-msg    Offer \"x-ms-message\" in outgoing INVITE");
-    puts("  --no-presence	Do not subscribe presence of buddies");
+    //puts("SIMPLE options (may be specified more than once):");
+    //puts("  --add-buddy url     Add the specified URL to the buddy list.");
+    //puts("  --offer-x-ms-msg    Offer \"x-ms-message\" in outgoing INVITE");
+    //puts("  --no-presence	Do not subscribe presence of buddies");
     puts("");
     fflush(stdout);
 }
diff --git a/pjsip/src/pjsua/misc.c b/pjsip/src/pjsua/misc.c
deleted file mode 100644
index 5c063fc..0000000
--- a/pjsip/src/pjsua/misc.c
+++ /dev/null
@@ -1,485 +0,0 @@
-/* $Id$ */
-/* 
- * Copyright (C) 2003-2006 Benny Prijono <benny@prijono.org>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA 
- */
-
-/*
- * THIS FILE IS INCLUDED BY main.c.
- * IT WON'T COMPILE BY ITSELF.
- */
-
-#include "getopt.h"
-#include <stdio.h>
- 
-
-/*
- * Display program usage
- */
-static void usage()
-{
-    puts("Usage:");
-    puts("  pjsua [options] [sip-url]");
-    puts("");
-    puts("  [sip-url]   Default URL to invite.");
-    puts("");
-    puts("General options:");
-    puts("  --config-file=file  Read the config/arguments from file.");
-    puts("  --log-file=fname    Log to filename (default stderr)");
-    puts("  --log-level=N       Set log max level to N (0(none) to 6(trace))");
-    puts("  --app-log-level=N   Set log max level for stdout display to N");
-    puts("  --help              Display this help screen");
-    puts("  --version           Display version info");
-    puts("");
-    puts("Media options:");
-    puts("  --null-audio        Use NULL audio device");
-    puts("");
-    puts("User Agent options:");
-    puts("  --auto-answer=sec   Auto-answer all incoming calls after sec seconds.");
-    puts("  --auto-hangup=sec   Auto-hangup all calls after sec seconds.");
-    puts("");
-    puts("SIP options:");
-    puts("  --local-port=port   Set TCP/UDP port");
-    puts("  --id=url            Set the URL of local ID (used in From header)");
-    puts("  --contact=url       Override the Contact information");
-    puts("  --proxy=url         Set the URL of proxy server");
-    puts("  --outbound=url      Set the URL of outbound proxy server");
-    puts("  --registrar=url     Set the URL of registrar server");
-    puts("  --reg-timeout=secs  Set registration interval to secs (default 3600)");
-    puts("");
-    puts("Authentication options:");
-    puts("  --realm=string      Set realm");
-    puts("  --username=string   Set authentication username");
-    puts("  --password=string   Set authentication password");
-    puts("");
-    puts("STUN options (all must be specified):");
-    puts("  --use-stun1=host[:port]");
-    puts("  --use-stun2=host[:port]  Use STUN and set host name and port of STUN servers");
-    puts("");
-    puts("SIMPLE options (may be specified more than once):");
-    puts("  --add-buddy url     Add the specified URL to the buddy list.");
-    puts("  --offer-x-ms-msg    Offer \"x-ms-message\" in outgoing INVITE");
-    puts("  --no-presence	Do not subscribe presence of buddies");
-    puts("");
-    fflush(stdout);
-}
-
-/* Display keystroke help. */
-static void keystroke_help()
-{
-    int i;
-
-    printf("Advertise status as: %s\n", (global.hide_status ? "Offline" : "Online"));
-    puts("");
-    puts("Buddy list:");
-    puts("-------------------------------------------------------------------------------");
-    for (i=0; i<global.buddy_cnt; ++i) {
-	printf(" %d\t%s  <%s>\n", i+1, global.buddy[i].ptr,
-		(global.buddy_status[i]?"Online":"Offline"));
-    }
-    //printf("-------------------------------------\n");
-    puts("");
-    //puts("Commands:");
-    puts("+=============================================================================+");
-    puts("|       Call Commands:         |      IM & Presence:      |   Misc:           |");
-    puts("|                              |                          |                   |");
-    puts("|  m  Make new call            |  i  Send IM              |  o  Send OPTIONS  |");
-    puts("|  a  Answer call              | su  Subscribe presence   |  d  Dump status   |");
-    puts("|  h  Hangup call              | us  Unsubscribe presence |  d1 Dump detailed |");
-    puts("|  ]  Select next dialog       |  t  Toggle Online status |                   |");
-    puts("|  [  Select previous dialog   |                          |                   |");
-    puts("+-----------------------------------------------------------------------------+");
-    puts("|  q  QUIT                                                                    |");
-    puts("+=============================================================================+");
-    puts("");
-
-
-    fflush(stdout);
-}
-
-/*
- * Verify that valid SIP url is given.
- */
-static pj_status_t verify_sip_url(char *url)
-{
-    pjsip_uri *p;
-    pj_pool_t *pool;
-    int len = (url ? strlen(url) : 0);
-
-    if (!len) return -1;
-
-    pool = pj_pool_create(global.pf, "check%p", 1024, 0, NULL);
-    if (!pool) return -1;
-
-    p = pjsip_parse_uri(pool, url, len, 0);
-    if (!p || pj_stricmp2(pjsip_uri_get_scheme(p), "sip") != 0)
-	p = NULL;
-
-    pj_pool_release(pool);
-    return p ? 0 : -1;
-}
-
-/*
- * Read command arguments from config file.
- */
-static int read_config_file(pj_pool_t *pool, const char *filename, 
-			    int *app_argc, char ***app_argv)
-{
-    int i;
-    FILE *fhnd;
-    char line[200];
-    int argc = 0;
-    char **argv;
-    enum { MAX_ARGS = 64 };
-
-    /* Allocate MAX_ARGS+1 (argv needs to be terminated with NULL argument) */
-    argv = pj_pool_calloc(pool, MAX_ARGS+1, sizeof(char*));
-    argv[argc++] = *app_argv[0];
-
-    /* Open config file. */
-    fhnd = fopen(filename, "rt");
-    if (!fhnd) {
-	printf("Unable to open config file %s\n", filename);
-	return -1;
-    }
-
-    /* Scan tokens in the file. */
-    while (argc < MAX_ARGS && !feof(fhnd)) {
-	char *token, *p = line;
-
-	if (fgets(line, sizeof(line), fhnd) == NULL) break;
-
-	for (token = strtok(p, " \t\r\n"); argc < MAX_ARGS; 
-	     token = strtok(NULL, " \t\r\n"))
-	{
-	    int token_len;
-	    
-	    if (!token) break;
-	    if (*token == '#') break;
-
-	    token_len = strlen(token);
-	    if (!token_len)
-		continue;
-	    argv[argc] = pj_pool_alloc(pool, token_len+1);
-	    pj_memcpy(argv[argc], token, token_len+1);
-	    ++argc;
-	}
-    }
-
-    /* Copy arguments from command line */
-    for (i=1; i<*app_argc && argc < MAX_ARGS; ++i)
-	argv[argc++] = (*app_argv)[i];
-
-    if (argc == MAX_ARGS && (i!=*app_argc || !feof(fhnd))) {
-	printf("Too many arguments specified in cmd line/config file\n");
-	fclose(fhnd);
-	return -1;
-    }
-
-    fclose(fhnd);
-
-    /* Assign the new command line back to the original command line. */
-    *app_argc = argc;
-    *app_argv = argv;
-    return 0;
-
-}
-
-/*
- * Parse program arguments
- */
-static int parse_args(pj_pool_t *pool, int argc, char *argv[])
-{
-    int c;
-    int option_index;
-    enum { OPT_CONFIG_FILE, OPT_LOG_FILE, OPT_LOG_LEVEL, OPT_APP_LOG_LEVEL, 
-	   OPT_HELP, OPT_VERSION, OPT_NULL_AUDIO,
-	   OPT_LOCAL_PORT, OPT_PROXY, OPT_OUTBOUND_PROXY, OPT_REGISTRAR,
-	   OPT_REG_TIMEOUT, OPT_ID, OPT_CONTACT, 
-	   OPT_REALM, OPT_USERNAME, OPT_PASSWORD,
-	   OPT_USE_STUN1, OPT_USE_STUN2, 
-	   OPT_ADD_BUDDY, OPT_OFFER_X_MS_MSG, OPT_NO_PRESENCE,
-	   OPT_AUTO_ANSWER, OPT_AUTO_HANGUP};
-    struct option long_options[] = {
-	{ "config-file",1, 0, OPT_CONFIG_FILE},
-	{ "log-file",	1, 0, OPT_LOG_FILE},
-	{ "log-level",	1, 0, OPT_LOG_LEVEL},
-	{ "app-log-level",1,0,OPT_APP_LOG_LEVEL},
-	{ "help",	0, 0, OPT_HELP},
-	{ "version",	0, 0, OPT_VERSION},
-	{ "null-audio", 0, 0, OPT_NULL_AUDIO},
-	{ "local-port", 1, 0, OPT_LOCAL_PORT},
-	{ "proxy",	1, 0, OPT_PROXY},
-	{ "outbound",	1, 0, OPT_OUTBOUND_PROXY},
-	{ "registrar",	1, 0, OPT_REGISTRAR},
-	{ "reg-timeout",1, 0, OPT_REG_TIMEOUT},
-	{ "id",		1, 0, OPT_ID},
-	{ "contact",	1, 0, OPT_CONTACT},
-	{ "realm",	1, 0, OPT_REALM},
-	{ "username",	1, 0, OPT_USERNAME},
-	{ "password",	1, 0, OPT_PASSWORD},
-	{ "use-stun1",  1, 0, OPT_USE_STUN1},
-	{ "use-stun2",  1, 0, OPT_USE_STUN2},
-	{ "add-buddy",  1, 0, OPT_ADD_BUDDY},
-	{ "offer-x-ms-msg",0,0,OPT_OFFER_X_MS_MSG},
-	{ "no-presence", 0, 0, OPT_NO_PRESENCE},
-	{ "auto-answer",1, 0, OPT_AUTO_ANSWER},
-	{ "auto-hangup",1, 0, OPT_AUTO_HANGUP},
-	{ NULL, 0, 0, 0}
-    };
-    char *config_file = NULL;
-
-    /* Run getopt once to see if user specifies config file to read. */
-    while ((c=getopt_long(argc, argv, "", long_options, &option_index)) != -1) {
-	switch (c) {
-	case 0:
-	    config_file = optarg;
-	    break;
-	}
-	if (config_file)
-	    break;
-    }
-
-    if (config_file) {
-	if (read_config_file(pool, config_file, &argc, &argv) != 0)
-	    return -1;
-    }
-
-    /* Reinitialize and re-run getopt again, possibly with new arguments
-     * read from config file.
-     */
-    optind = 0;
-    while ((c=getopt_long(argc, argv, "", long_options, &option_index)) != -1) {
-	char *err, *p;
-
-	switch (c) {
-	case OPT_LOG_FILE:
-	    global.log_filename = optarg;
-	    break;
-	case OPT_LOG_LEVEL:
-	    c = strtoul(optarg, &err, 10);
-	    if (*err) {
-		printf("Error: expecting integer value 0-6 for --log-level\n");
-		return -1;
-	    }
-	    pj_log_set_level( c );
-	    break;
-	case OPT_APP_LOG_LEVEL:
-	    global.app_log_level = strtoul(optarg, &err, 10);
-	    if (*err) {
-		printf("Error: expecting integer value 0-6 for --app-log-level\n");
-		return -1;
-	    }
-	    break;
-	case OPT_HELP:
-	    usage();
-	    return -1;
-	case OPT_VERSION:   /* version */
-	    pj_dump_config();
-	    return -1;
-	case OPT_NULL_AUDIO:
-	    global.null_audio = 1;
-	    break;
-	case OPT_LOCAL_PORT:   /* local-port */
-	    global.sip_port = strtoul(optarg, &err, 10);
-	    if (*err) {
-		printf("Error: expecting integer value for --local-port\n");
-		return -1;
-	    }
-	    break;
-	case OPT_PROXY:   /* proxy */
-	    if (verify_sip_url(optarg) != 0) {
-		printf("Error: invalid SIP URL '%s' in proxy argument\n", optarg);
-		return -1;
-	    }
-	    global.proxy = pj_str(optarg);
-	    break;
-	case OPT_OUTBOUND_PROXY:   /* outbound proxy */
-	    if (verify_sip_url(optarg) != 0) {
-		printf("Error: invalid SIP URL '%s' in outbound proxy argument\n", optarg);
-		return -1;
-	    }
-	    global.outbound_proxy = pj_str(optarg);
-	    break;
-	case OPT_REGISTRAR:   /* registrar */
-	    if (verify_sip_url(optarg) != 0) {
-		printf("Error: invalid SIP URL '%s' in registrar argument\n", optarg);
-		return -1;
-	    }
-	    global.registrar_uri = pj_str(optarg);
-	    break;
-	case OPT_REG_TIMEOUT:   /* reg-timeout */
-	    global.reg_timeout = strtoul(optarg, &err, 10);
-	    if (*err) {
-		printf("Error: expecting integer value for --reg-timeout\n");
-		return -1;
-	    }
-	    break;
-	case OPT_ID:   /* id */
-	    if (verify_sip_url(optarg) != 0) {
-		printf("Error: invalid SIP URL '%s' in local id argument\n", optarg);
-		return -1;
-	    }
-	    global.local_uri = pj_str(optarg);
-	    break;
-	case OPT_CONTACT:   /* contact */
-	    if (verify_sip_url(optarg) != 0) {
-		printf("Error: invalid SIP URL '%s' in contact argument\n", optarg);
-		return -1;
-	    }
-	    global.contact = pj_str(optarg);
-	    break;
-	case OPT_USERNAME:   /* Default authentication user */
-	    if (!global.cred_count) global.cred_count = 1;
-	    global.cred_info[0].username = pj_str(optarg);
-	    break;
-	case OPT_REALM:	    /* Default authentication realm. */
-	    if (!global.cred_count) global.cred_count = 1;
-	    global.cred_info[0].realm = pj_str(optarg);
-	    break;
-	case OPT_PASSWORD:   /* authentication password */
-	    if (!global.cred_count) global.cred_count = 1;
-	    global.cred_info[0].data_type = 0;
-	    global.cred_info[0].data = pj_str(optarg);
-	    break;
-	case OPT_USE_STUN1:   /* STUN server 1 */
-	    p = pj_native_strchr(optarg, ':');
-	    if (p) {
-		*p = '\0';
-		global.stun_srv1 = pj_str(optarg);
-		global.stun_port1 = strtoul(p+1, &err, 10);
-		if (*err || global.stun_port1==0) {
-		    printf("Error: expecting port number with option --use-stun1\n");
-		    return -1;
-		}
-	    } else {
-		global.stun_port1 = 3478;
-		global.stun_srv1 = pj_str(optarg);
-	    }
-	    break;
-	case OPT_USE_STUN2:   /* STUN server 2 */
-	    p = pj_native_strchr(optarg, ':');
-	    if (p) {
-		*p = '\0';
-		global.stun_srv2 = pj_str(optarg);
-		global.stun_port2 = strtoul(p+1, &err, 10);
-		if (*err || global.stun_port2==0) {
-		    printf("Error: expecting port number with option --use-stun2\n");
-		    return -1;
-		}
-	    } else {
-		global.stun_port2 = 3478;
-		global.stun_srv2 = pj_str(optarg);
-	    }
-	    break;
-	case OPT_ADD_BUDDY: /* Add to buddy list. */
-	    if (verify_sip_url(optarg) != 0) {
-		printf("Error: invalid URL '%s' in --add-buddy option\n", optarg);
-		return -1;
-	    }
-	    if (global.buddy_cnt == MAX_BUDDIES) {
-		printf("Error: too many buddies in buddy list.\n");
-		return -1;
-	    }
-	    global.buddy[global.buddy_cnt++] = pj_str(optarg);
-	    break;
-	case OPT_OFFER_X_MS_MSG:
-	    global.offer_x_ms_msg = 1;
-	    break;
-	case OPT_NO_PRESENCE:
-	    global.no_presence = 1;
-	    break;
-	case OPT_AUTO_ANSWER:
-	    global.auto_answer = strtoul(optarg, &err, 10);
-	    if (*err) {
-		printf("Error: expecting integer value for --auto-answer option\n");
-		return -1;
-	    }
-	    break;
-	case OPT_AUTO_HANGUP:
-	    global.auto_hangup = strtoul(optarg, &err, 10);
-	    if (*err) {
-		printf("Error: expecting integer value for --auto-hangup option\n");
-		return -1;
-	    }
-	    break;
-	}
-    }
-
-    if (optind != argc) {
-	printf("Error: unknown options %s\n", argv[optind]);
-	return -1;
-    }
-
-    if (global.reg_timeout == 0)
-	global.reg_timeout = 3600;
-
-    return 0;
-}
-
-/* Print dialog. */
-static void print_dialog(pjsip_dlg *dlg)
-{
-    if (!dlg) {
-	puts("none");
-	return;
-    }
-
-    printf("%s: call-id=%.*s", dlg->obj_name, 
-			       (int)dlg->call_id->id.slen, 
-			       dlg->call_id->id.ptr);
-
-    printf(" (%s, %s)\n", pjsip_role_name(dlg->role),
-			  pjsip_dlg_state_str(dlg->state));
-}
-
-/* Dump media statistic */
-void dump_media_statistic(pjsip_dlg *dlg)
-{
-    struct dialog_data *dlg_data = dlg->user_data;
-    pj_media_stream_stat stat[2];
-    const char *statname[2] = { "TX", "RX" };
-    int i;
-
-    pj_media_session_get_stat (dlg_data->msession, 0, &stat[0], &stat[1]);
-
-    printf("Media statistic:\n");
-    for (i=0; i<2; ++i) {
-	printf("  %s statistics:\n", statname[i]);
-	printf("    Pkt      TX=%d RX=%d\n", stat[i].pkt_tx, stat[i].pkt_rx);
-	printf("    Octets   TX=%d RX=%d\n", stat[i].oct_tx, stat[i].oct_rx);
-	printf("    Jitter   %d ms\n", stat[i].jitter);
-	printf("    Pkt lost %d\n", stat[i].pkt_lost);
-    }
-    printf("\n");
-}
-
-/* Print all dialogs. */
-static void print_all_dialogs()
-{
-    pjsip_dlg *dlg = (pjsip_dlg *)global.user_agent->dlg_list.next;
-
-    puts("List all dialogs:");
-
-    while (dlg != (pjsip_dlg *) &global.user_agent->dlg_list) {
-	printf("%c", (dlg==global.cur_dlg ? '*' : ' '));
-	print_dialog(dlg);
-	dlg = dlg->next;
-    }
-
-    puts("");
-}
-
diff --git a/pjsip/src/pjsua/pjsua.h b/pjsip/src/pjsua/pjsua.h
index 37740c3..810c57b 100644
--- a/pjsip/src/pjsua/pjsua.h
+++ b/pjsip/src/pjsua/pjsua.h
@@ -128,7 +128,7 @@
 
 
 /*****************************************************************************
- * PJSUA API.
+ * PJSUA API (defined in pjsua_core.c).
  */
 
 /**
@@ -171,6 +171,10 @@
 pj_status_t pjsua_destroy(void);
 
 
+/*****************************************************************************
+ * PJSUA Invite session API (defined in pjsua_inv.c).
+ */
+
 /**
  * Make outgoing call.
  */
@@ -178,8 +182,35 @@
 			 pjsip_inv_session **p_inv);
 
 
+/**
+ * Handle incoming invite request.
+ */
+pj_bool_t pjsua_inv_on_incoming(pjsip_rx_data *rdata);
+
+
+/**
+ * Callback to be called by session when invite session's state has changed.
+ */
+void pjsua_inv_on_state_changed(pjsip_inv_session *inv, pjsip_event *e);
+
+
+/**
+ * Callback to be called by session when outgoing dialog has forked.
+ * This function will create a forked dialog.
+ */
+void pjsua_inv_on_new_session(pjsip_inv_session *inv, pjsip_event *e);
+
+
+/**
+ * Callback to be called when SDP offer/answer negotiation has just completed
+ * in the session. This function will start/update media if negotiation
+ * has succeeded.
+ */
+void pjsua_inv_on_media_update(pjsip_inv_session *inv, pj_status_t status);
+
+
 /*****************************************************************************
- * PJSUA Client Registration API.
+ * PJSUA Client Registration API (defined in pjsua_reg.c).
  */
 
 /**
@@ -198,6 +229,7 @@
 
 /*****************************************************************************
  * User Interface API.
+ *
  * The UI API specifies functions that will be called by pjsua upon
  * occurence of various events.
  */
diff --git a/pjsip/src/pjsua/pjsua_core.c b/pjsip/src/pjsua/pjsua_core.c
index f6de89f..cc9ae86 100644
--- a/pjsip/src/pjsua/pjsua_core.c
+++ b/pjsip/src/pjsua/pjsua_core.c
@@ -18,13 +18,23 @@
  */
 #include "pjsua.h"
 
+/*
+ * pjsua_core.c
+ *
+ * Core application functionalities.
+ */
 
-#define THIS_FILE   "pjsua.c"
+#define THIS_FILE   "pjsua_core.c"
 
-struct pjsua pjsua;
 
 /* 
- * Default local URI, if not specified in cmd-line 
+ * Global variable.
+ */
+struct pjsua pjsua;
+
+
+/* 
+ * Default local URI, if none is specified in cmd-line 
  */
 #define PJSUA_LOCAL_URI	    "<sip:user@127.0.0.1>"
 
@@ -92,106 +102,13 @@
  */
 static pj_bool_t mod_pjsua_on_rx_request(pjsip_rx_data *rdata)
 {
-    pjsip_dialog *dlg = pjsip_rdata_get_dlg(rdata);
-    pjsip_transaction *tsx = pjsip_rdata_get_tsx(rdata);
-    pjsip_msg *msg = rdata->msg_info.msg;
 
-    /*
-     * Handle incoming INVITE outside dialog.
-     */
-    if (dlg == NULL && tsx == NULL &&
-	msg->line.req.method.id == PJSIP_INVITE_METHOD)
-    {
-	pj_status_t status;
-	pjsip_tx_data *response = NULL;
-	unsigned options = 0;
+    if (rdata->msg_info.msg->line.req.method.id == PJSIP_INVITE_METHOD) {
 
-	/* Verify that we can handle the request. */
-	status = pjsip_inv_verify_request(rdata, &options, NULL, NULL,
-					  pjsua.endpt, &response);
-	if (status != PJ_SUCCESS) {
+	return pjsua_inv_on_incoming(rdata);
 
-	    /*
-	     * No we can't handle the incoming INVITE request.
-	     */
-
-	    if (response) {
-		pjsip_response_addr res_addr;
-
-		pjsip_get_response_addr(response->pool, rdata, &res_addr);
-		pjsip_endpt_send_response(pjsua.endpt, &res_addr, response, 
-					  NULL, NULL);
-
-	    } else {
-
-		/* Respond with 500 (Internal Server Error) */
-		pjsip_endpt_respond_stateless(pjsua.endpt, rdata, 500, NULL,
-					      NULL, NULL);
-	    }
-
-	} else {
-	    /*
-	     * Yes we can handle the incoming INVITE request.
-	     */
-	    pjsip_inv_session *inv;
-	    struct pjsua_inv_data *inv_data;
-	    pjmedia_sdp_session *answer;
-
-
-	    /* Get media capability from media endpoint: */
-
-	    status = pjmedia_endpt_create_sdp( pjsua.med_endpt, rdata->tp_info.pool,
-					       1, &pjsua.med_skinfo, &answer );
-	    if (status != PJ_SUCCESS) {
-
-		pjsip_endpt_respond_stateless(pjsua.endpt, rdata, 500, NULL,
-					      NULL, NULL);
-		return PJ_TRUE;
-	    }
-
-	    /* Create dialog: */
-
-	    status = pjsip_dlg_create_uas( pjsip_ua_instance(), rdata,
-					   &pjsua.contact_uri, &dlg);
-	    if (status != PJ_SUCCESS)
-		return PJ_TRUE;
-
-
-	    /* Create invite session: */
-
-	    status = pjsip_inv_create_uas( dlg, rdata, answer, 0, &inv);
-	    if (status != PJ_SUCCESS) {
-
-		status = pjsip_dlg_create_response( dlg, rdata, 500, NULL,
-						    &response);
-		if (status == PJ_SUCCESS)
-		    status = pjsip_dlg_send_response(dlg, 
-						     pjsip_rdata_get_tsx(rdata),
-						     response);
-		return PJ_TRUE;
-
-	    }
-
-
-	    /* Create and attach pjsua data to the dialog: */
-
-	    inv_data = pj_pool_zalloc(dlg->pool, sizeof(struct pjsua_inv_data));
-	    dlg->mod_data[pjsua.mod.id] = inv_data;
-
-
-	    /* Answer with 100 (using the dialog, not invite): */
-
-	    status = pjsip_dlg_create_response(dlg, rdata, 100, NULL, &response);
-	    if (status == PJ_SUCCESS)
-		status = pjsip_dlg_send_response(dlg, pjsip_rdata_get_tsx(rdata), response);
-	}
-
-	/* This INVITE request has been handled. */
-	return PJ_TRUE;
     }
 
-    
-
     return PJ_FALSE;
 }
 
@@ -214,98 +131,6 @@
 }
 
 
-/*
- * This callback receives notification from invite session when the
- * session state has changed.
- */
-static void pjsua_inv_on_state_changed(pjsip_inv_session *inv, pjsip_event *e)
-{
-
-    /* Destroy media session when invite session is disconnected. */
-    if (inv->state == PJSIP_INV_STATE_DISCONNECTED) {
-	struct pjsua_inv_data *inv_data;
-
-	inv_data = inv->dlg->mod_data[pjsua.mod.id];
-	if (inv_data && inv_data->session) {
-	    pjmedia_session_destroy(inv_data->session);
-	    inv_data->session = NULL;
-
-	    PJ_LOG(3,(THIS_FILE,"Media session is destroyed"));
-	}
-
-    }
-
-    pjsua_ui_inv_on_state_changed(inv, e);
-}
-
-
-/*
- * This callback is called by invite session framework when UAC session
- * has forked.
- */
-static void pjsua_inv_on_new_session(pjsip_inv_session *inv, pjsip_event *e)
-{
-    PJ_UNUSED_ARG(inv);
-    PJ_UNUSED_ARG(e);
-
-    PJ_TODO(HANDLE_FORKED_DIALOG);
-}
-
-/*
- *
- */
-static void pjsua_inv_on_media_update(pjsip_inv_session *inv, 
-				      pj_status_t status)
-{
-    struct pjsua_inv_data *inv_data;
-    const pjmedia_sdp_session *local_sdp;
-    const pjmedia_sdp_session *remote_sdp;
-
-    if (status != PJ_SUCCESS) {
-
-	pjsua_perror("SDP negotiation has failed", status);
-	return;
-
-    }
-
-    /* Destroy existing media session, if any. */
-
-    inv_data = inv->dlg->mod_data[pjsua.mod.id];
-    if (inv_data && inv_data->session) {
-	pjmedia_session_destroy(inv_data->session);
-	inv_data->session = NULL;
-    }
-
-    /* Get local and remote SDP */
-
-    status = pjmedia_sdp_neg_get_active_local(inv->neg, &local_sdp);
-    if (status != PJ_SUCCESS) {
-	pjsua_perror("Unable to retrieve currently active local SDP", status);
-	return;
-    }
-
-
-    status = pjmedia_sdp_neg_get_active_remote(inv->neg, &remote_sdp);
-    if (status != PJ_SUCCESS) {
-	pjsua_perror("Unable to retrieve currently active remote SDP", status);
-	return;
-    }
-
-
-    /* Create new media session. 
-     * The media session is active immediately.
-     */
-
-    status = pjmedia_session_create( pjsua.med_endpt, 1, &pjsua.med_skinfo,
-				     local_sdp, remote_sdp, &inv_data->session );
-    if (status != PJ_SUCCESS) {
-	pjsua_perror("Unable to create media session", status);
-	return;
-    }
-
-    PJ_LOG(3,(THIS_FILE,"Media has been started successfully"));
-}
-
 /* 
  * Initialize sockets and optionally get the public address via STUN. 
  */
@@ -845,10 +670,12 @@
     }
 
     /* Destroy endpoint. */
+
     pjsip_endpt_destroy(pjsua.endpt);
     pjsua.endpt = NULL;
 
     /* Destroy caching pool. */
+
     pj_caching_pool_destroy(&pjsua.cp);
 
 
@@ -857,99 +684,3 @@
     return PJ_SUCCESS;
 }
 
-
-/**
- * Make outgoing call.
- */
-pj_status_t pjsua_invite(const char *cstr_dest_uri,
-			 pjsip_inv_session **p_inv)
-{
-    pj_str_t dest_uri;
-    pjsip_dialog *dlg;
-    pjmedia_sdp_session *offer;
-    pjsip_inv_session *inv;
-    struct pjsua_inv_data *inv_data;
-    pjsip_tx_data *tdata;
-    pj_status_t status;
-
-    /* Convert cstr_dest_uri to dest_uri */
-    
-    dest_uri = pj_str((char*)cstr_dest_uri);
-
-    /* Create outgoing dialog: */
-
-    status = pjsip_dlg_create_uac( pjsip_ua_instance(), &pjsua.local_uri,
-				   &pjsua.contact_uri, &dest_uri, &dest_uri,
-				   &dlg);
-    if (status != PJ_SUCCESS) {
-	pjsua_perror("Dialog creation failed", status);
-	return status;
-    }
-
-    /* Get media capability from media endpoint: */
-
-    status = pjmedia_endpt_create_sdp( pjsua.med_endpt, dlg->pool,
-				       1, &pjsua.med_skinfo, &offer);
-    if (status != PJ_SUCCESS) {
-	pjsua_perror("pjmedia unable to create SDP", status);
-	goto on_error;
-    }
-
-    /* Create the INVITE session: */
-
-    status = pjsip_inv_create_uac( dlg, offer, 0, &inv);
-    if (status != PJ_SUCCESS) {
-	pjsua_perror("Invite session creation failed", status);
-	goto on_error;
-    }
-
-
-    /* Create and associate our data in the session. */
-
-    inv_data = pj_pool_zalloc( dlg->pool, sizeof(struct pjsua_inv_data));
-    dlg->mod_data[pjsua.mod.id] = inv_data;
-
-
-    /* Set dialog Route-Set: */
-
-    if (!pj_list_empty(&pjsua.route_set))
-	pjsip_dlg_set_route_set(dlg, &pjsua.route_set);
-
-
-    /* Set credentials: */
-
-    pjsip_auth_clt_set_credentials( &dlg->auth_sess, pjsua.cred_count, 
-				    pjsua.cred_info);
-
-
-    /* Create initial INVITE: */
-
-    status = pjsip_inv_invite(inv, &tdata);
-    if (status != PJ_SUCCESS) {
-	pjsua_perror("Unable to create initial INVITE request", status);
-	goto on_error;
-    }
-
-
-    /* Send initial INVITE: */
-
-    status = pjsip_inv_send_msg(inv, tdata, NULL);
-    if (status != PJ_SUCCESS) {
-	pjsua_perror("Unable to send initial INVITE request", status);
-	goto on_error;
-    }
-
-
-    /* Done. */
-
-    *p_inv = inv;
-
-    return PJ_SUCCESS;
-
-
-on_error:
-
-    PJ_TODO(DESTROY_DIALOG_ON_FAIL);
-    return status;
-}
-
diff --git a/pjsip/src/pjsua/pjsua_inv.c b/pjsip/src/pjsua/pjsua_inv.c
new file mode 100644
index 0000000..72272c3
--- /dev/null
+++ b/pjsip/src/pjsua/pjsua_inv.c
@@ -0,0 +1,331 @@
+/* $Id$ */
+/* 
+ * Copyright (C) 2003-2006 Benny Prijono <benny@prijono.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA 
+ */
+#include "pjsua.h"
+#include <pj/log.h>
+
+
+/*
+ * pjsua_inv.c
+ *
+ * Invite session specific functionalities.
+ */
+
+#define THIS_FILE   "pjsua_inv.c"
+
+
+/**
+ * Make outgoing call.
+ */
+pj_status_t pjsua_invite(const char *cstr_dest_uri,
+			 pjsip_inv_session **p_inv)
+{
+    pj_str_t dest_uri;
+    pjsip_dialog *dlg;
+    pjmedia_sdp_session *offer;
+    pjsip_inv_session *inv;
+    struct pjsua_inv_data *inv_data;
+    pjsip_tx_data *tdata;
+    pj_status_t status;
+
+    /* Convert cstr_dest_uri to dest_uri */
+    
+    dest_uri = pj_str((char*)cstr_dest_uri);
+
+    /* Create outgoing dialog: */
+
+    status = pjsip_dlg_create_uac( pjsip_ua_instance(), &pjsua.local_uri,
+				   &pjsua.contact_uri, &dest_uri, &dest_uri,
+				   &dlg);
+    if (status != PJ_SUCCESS) {
+	pjsua_perror("Dialog creation failed", status);
+	return status;
+    }
+
+    /* Get media capability from media endpoint: */
+
+    status = pjmedia_endpt_create_sdp( pjsua.med_endpt, dlg->pool,
+				       1, &pjsua.med_skinfo, &offer);
+    if (status != PJ_SUCCESS) {
+	pjsua_perror("pjmedia unable to create SDP", status);
+	goto on_error;
+    }
+
+    /* Create the INVITE session: */
+
+    status = pjsip_inv_create_uac( dlg, offer, 0, &inv);
+    if (status != PJ_SUCCESS) {
+	pjsua_perror("Invite session creation failed", status);
+	goto on_error;
+    }
+
+
+    /* Create and associate our data in the session. */
+
+    inv_data = pj_pool_zalloc( dlg->pool, sizeof(struct pjsua_inv_data));
+    dlg->mod_data[pjsua.mod.id] = inv_data;
+
+
+    /* Set dialog Route-Set: */
+
+    if (!pj_list_empty(&pjsua.route_set))
+	pjsip_dlg_set_route_set(dlg, &pjsua.route_set);
+
+
+    /* Set credentials: */
+
+    pjsip_auth_clt_set_credentials( &dlg->auth_sess, pjsua.cred_count, 
+				    pjsua.cred_info);
+
+
+    /* Create initial INVITE: */
+
+    status = pjsip_inv_invite(inv, &tdata);
+    if (status != PJ_SUCCESS) {
+	pjsua_perror("Unable to create initial INVITE request", status);
+	goto on_error;
+    }
+
+
+    /* Send initial INVITE: */
+
+    status = pjsip_inv_send_msg(inv, tdata, NULL);
+    if (status != PJ_SUCCESS) {
+	pjsua_perror("Unable to send initial INVITE request", status);
+	goto on_error;
+    }
+
+
+    /* Done. */
+
+    *p_inv = inv;
+
+    return PJ_SUCCESS;
+
+
+on_error:
+
+    PJ_TODO(DESTROY_DIALOG_ON_FAIL);
+    return status;
+}
+
+
+/**
+ * Handle incoming INVITE request.
+ */
+pj_bool_t pjsua_inv_on_incoming(pjsip_rx_data *rdata)
+{
+    pjsip_dialog *dlg = pjsip_rdata_get_dlg(rdata);
+    pjsip_transaction *tsx = pjsip_rdata_get_tsx(rdata);
+    pjsip_msg *msg = rdata->msg_info.msg;
+
+    /*
+     * Handle incoming INVITE outside dialog.
+     */
+    if (dlg == NULL && tsx == NULL &&
+	msg->line.req.method.id == PJSIP_INVITE_METHOD)
+    {
+	pj_status_t status;
+	pjsip_tx_data *response = NULL;
+	unsigned options = 0;
+
+	/* Verify that we can handle the request. */
+	status = pjsip_inv_verify_request(rdata, &options, NULL, NULL,
+					  pjsua.endpt, &response);
+	if (status != PJ_SUCCESS) {
+
+	    /*
+	     * No we can't handle the incoming INVITE request.
+	     */
+
+	    if (response) {
+		pjsip_response_addr res_addr;
+
+		pjsip_get_response_addr(response->pool, rdata, &res_addr);
+		pjsip_endpt_send_response(pjsua.endpt, &res_addr, response, 
+					  NULL, NULL);
+
+	    } else {
+
+		/* Respond with 500 (Internal Server Error) */
+		pjsip_endpt_respond_stateless(pjsua.endpt, rdata, 500, NULL,
+					      NULL, NULL);
+	    }
+
+	} else {
+	    /*
+	     * Yes we can handle the incoming INVITE request.
+	     */
+	    pjsip_inv_session *inv;
+	    struct pjsua_inv_data *inv_data;
+	    pjmedia_sdp_session *answer;
+
+
+	    /* Get media capability from media endpoint: */
+
+	    status = pjmedia_endpt_create_sdp( pjsua.med_endpt, rdata->tp_info.pool,
+					       1, &pjsua.med_skinfo, &answer );
+	    if (status != PJ_SUCCESS) {
+
+		pjsip_endpt_respond_stateless(pjsua.endpt, rdata, 500, NULL,
+					      NULL, NULL);
+		return PJ_TRUE;
+	    }
+
+	    /* Create dialog: */
+
+	    status = pjsip_dlg_create_uas( pjsip_ua_instance(), rdata,
+					   &pjsua.contact_uri, &dlg);
+	    if (status != PJ_SUCCESS)
+		return PJ_TRUE;
+
+
+	    /* Create invite session: */
+
+	    status = pjsip_inv_create_uas( dlg, rdata, answer, 0, &inv);
+	    if (status != PJ_SUCCESS) {
+
+		status = pjsip_dlg_create_response( dlg, rdata, 500, NULL,
+						    &response);
+		if (status == PJ_SUCCESS)
+		    status = pjsip_dlg_send_response(dlg, 
+						     pjsip_rdata_get_tsx(rdata),
+						     response);
+		return PJ_TRUE;
+
+	    }
+
+
+	    /* Create and attach pjsua data to the dialog: */
+
+	    inv_data = pj_pool_zalloc(dlg->pool, sizeof(struct pjsua_inv_data));
+	    dlg->mod_data[pjsua.mod.id] = inv_data;
+
+
+	    /* Answer with 100 (using the dialog, not invite): */
+
+	    status = pjsip_dlg_create_response(dlg, rdata, 100, NULL, &response);
+	    if (status == PJ_SUCCESS)
+		status = pjsip_dlg_send_response(dlg, pjsip_rdata_get_tsx(rdata), response);
+	}
+
+	/* This INVITE request has been handled. */
+	return PJ_TRUE;
+    }
+
+    return PJ_FALSE;
+}
+
+
+/*
+ * This callback receives notification from invite session when the
+ * session state has changed.
+ */
+void pjsua_inv_on_state_changed(pjsip_inv_session *inv, pjsip_event *e)
+{
+
+    /* Destroy media session when invite session is disconnected. */
+    if (inv->state == PJSIP_INV_STATE_DISCONNECTED) {
+	struct pjsua_inv_data *inv_data;
+
+	inv_data = inv->dlg->mod_data[pjsua.mod.id];
+	if (inv_data && inv_data->session) {
+	    pjmedia_session_destroy(inv_data->session);
+	    inv_data->session = NULL;
+
+	    PJ_LOG(3,(THIS_FILE,"Media session is destroyed"));
+	}
+
+    }
+
+    pjsua_ui_inv_on_state_changed(inv, e);
+}
+
+
+/*
+ * This callback is called by invite session framework when UAC session
+ * has forked.
+ */
+void pjsua_inv_on_new_session(pjsip_inv_session *inv, pjsip_event *e)
+{
+    PJ_UNUSED_ARG(inv);
+    PJ_UNUSED_ARG(e);
+
+    PJ_TODO(HANDLE_FORKED_DIALOG);
+}
+
+
+/*
+ * Callback to be called when SDP offer/answer negotiation has just completed
+ * in the session. This function will start/update media if negotiation
+ * has succeeded.
+ */
+void pjsua_inv_on_media_update(pjsip_inv_session *inv, pj_status_t status)
+{
+    struct pjsua_inv_data *inv_data;
+    const pjmedia_sdp_session *local_sdp;
+    const pjmedia_sdp_session *remote_sdp;
+
+    if (status != PJ_SUCCESS) {
+
+	pjsua_perror("SDP negotiation has failed", status);
+	return;
+
+    }
+
+    /* Destroy existing media session, if any. */
+
+    inv_data = inv->dlg->mod_data[pjsua.mod.id];
+    if (inv_data && inv_data->session) {
+	pjmedia_session_destroy(inv_data->session);
+	inv_data->session = NULL;
+    }
+
+    /* Get local and remote SDP */
+
+    status = pjmedia_sdp_neg_get_active_local(inv->neg, &local_sdp);
+    if (status != PJ_SUCCESS) {
+	pjsua_perror("Unable to retrieve currently active local SDP", status);
+	return;
+    }
+
+
+    status = pjmedia_sdp_neg_get_active_remote(inv->neg, &remote_sdp);
+    if (status != PJ_SUCCESS) {
+	pjsua_perror("Unable to retrieve currently active remote SDP", status);
+	return;
+    }
+
+
+    /* Create new media session. 
+     * The media session is active immediately.
+     */
+
+    if (!pjsua.null_audio) {
+
+	status = pjmedia_session_create( pjsua.med_endpt, 1, &pjsua.med_skinfo,
+					 local_sdp, remote_sdp, 
+					 &inv_data->session );
+	if (status != PJ_SUCCESS) {
+	    pjsua_perror("Unable to create media session", status);
+	    return;
+	}
+
+	PJ_LOG(3,(THIS_FILE,"Media has been started successfully"));
+    }
+}
diff --git a/pjsip/src/pjsua/pjsua_reg.c b/pjsip/src/pjsua/pjsua_reg.c
index 2afb48d..0a76750 100644
--- a/pjsip/src/pjsua/pjsua_reg.c
+++ b/pjsip/src/pjsua/pjsua_reg.c
@@ -18,8 +18,20 @@
  */
 #include "pjsua.h"
 
+
+/*
+ * pjsua_reg.c
+ *
+ * Client registration handler.
+ */
+
 #define THIS_FILE   "pjsua_reg.c"
 
+
+/*
+ * This callback is called by pjsip_regc when outgoing register
+ * request has completed.
+ */
 static void regc_cb(struct pjsip_regc_cbparam *param)
 {
     /*
@@ -97,6 +109,8 @@
 
 	pjsip_regc_set_credentials( pjsua.regc, pjsua.cred_count, 
 				    pjsua.cred_info );
+
+	pjsip_regc_set_route_set( pjsua.regc, &pjsua.route_set );
     }
 
     return PJ_SUCCESS;