Index: pjproject/trunk/pjsip-apps/src/pjsua/pjsua_app.c
===================================================================
--- pjproject/trunk/pjsip-apps/src/pjsua/pjsua_app.c	(revision 2567)
+++ pjproject/trunk/pjsip-apps/src/pjsua/pjsua_app.c	(revision 2568)
@@ -59,4 +59,5 @@
     pjsua_media_config	    media_cfg;
     pj_bool_t		    no_refersub;
+    pj_bool_t		    ipv6;
     pj_bool_t		    no_tcp;
     pj_bool_t		    no_udp;
@@ -139,4 +140,5 @@
 static pj_status_t transport_adapter_sample(void);
 #endif
+static pj_status_t create_ipv6_media_transports(void);
 pj_status_t app_destroy(void);
 
@@ -196,4 +198,7 @@
     puts  ("");
     puts  ("Transport Options:");
+#if defined(PJ_HAS_IPV6) && PJ_HAS_IPV6
+    puts  ("  --ipv6              Use IPv6 instead for SIP and media.");
+#endif
     puts  ("  --local-port=port   Set TCP/UDP port. This implicitly enables both ");
     puts  ("                      TCP and UDP transports on the specified port, unless");
@@ -201,4 +206,5 @@
     puts  ("  --ip-addr=IP        Use the specifed address as SIP and RTP addresses.");
     puts  ("                      (Hint: the IP may be the public IP of the NAT/router)");
+    puts  ("  --bound-addr=IP     Bind transports to this IP interface");
     puts  ("  --no-tcp            Disable TCP transport.");
     puts  ("  --no-udp            Disable UDP transport.");
@@ -465,5 +471,5 @@
 	   OPT_LOCAL_PORT, OPT_IP_ADDR, OPT_PROXY, OPT_OUTBOUND_PROXY, 
 	   OPT_REGISTRAR, OPT_REG_TIMEOUT, OPT_PUBLISH, OPT_ID, OPT_CONTACT,
-	   OPT_CONTACT_PARAMS,
+	   OPT_BOUND_ADDR, OPT_CONTACT_PARAMS,
 	   OPT_100REL, OPT_USE_IMS, OPT_REALM, OPT_USERNAME, OPT_PASSWORD,
 	   OPT_NAMESERVER, OPT_STUN_DOMAIN, OPT_STUN_SRV,
@@ -486,5 +492,5 @@
 	   OPT_CAPTURE_DEV, OPT_PLAYBACK_DEV,
 	   OPT_CAPTURE_LAT, OPT_PLAYBACK_LAT, OPT_NO_TONES, OPT_JB_MAX_SIZE,
-	   OPT_STDOUT_REFRESH, OPT_STDOUT_REFRESH_TEXT,
+	   OPT_STDOUT_REFRESH, OPT_STDOUT_REFRESH_TEXT, OPT_IPV6,
 #ifdef _IONBF
 	   OPT_STDOUT_NO_BUF,
@@ -509,4 +515,5 @@
 	{ "local-port", 1, 0, OPT_LOCAL_PORT},
 	{ "ip-addr",	1, 0, OPT_IP_ADDR},
+	{ "bound-addr", 1, 0, OPT_BOUND_ADDR},
 	{ "no-tcp",     0, 0, OPT_NO_TCP},
 	{ "no-udp",     0, 0, OPT_NO_UDP},
@@ -596,4 +603,7 @@
 	{ "no-tones",    0, 0, OPT_NO_TONES},
 	{ "jb-max-size", 1, 0, OPT_JB_MAX_SIZE},
+#if defined(PJ_HAS_IPV6) && PJ_HAS_IPV6
+	{ "ipv6",	 0, 0, OPT_IPV6},
+#endif
 	{ NULL, 0, 0, 0}
     };
@@ -736,4 +746,9 @@
 	    break;
 
+	case OPT_BOUND_ADDR: /* bound-addr */
+	    cfg->udp_cfg.bound_addr = pj_str(pj_optarg);
+	    cfg->rtp_cfg.bound_addr = pj_str(pj_optarg);
+	    break;
+
 	case OPT_NO_UDP: /* no-udp */
 	    if (cfg->no_tcp) {
@@ -1257,4 +1272,10 @@
 	    cfg->media_cfg.jb_max = atoi(pj_optarg);
 	    break;
+
+#if defined(PJ_HAS_IPV6) && PJ_HAS_IPV6
+	case OPT_IPV6:
+	    cfg->ipv6 = PJ_TRUE;
+	    break;
+#endif
 
 	default:
@@ -1505,4 +1526,8 @@
     }
 
+    /* Transport options */
+    if (config->ipv6) {
+	pj_strcat2(&cfg, "--ipv6\n");
+    }
 
     /* UDP Transport. */
@@ -1515,4 +1540,12 @@
 			(int)config->udp_cfg.public_addr.slen,
 			config->udp_cfg.public_addr.ptr);
+	pj_strcat2(&cfg, line);
+    }
+
+    /* Bound IP address, if any. */
+    if (config->udp_cfg.bound_addr.slen) {
+	pj_ansi_sprintf(line, "--bound-addr %.*s\n", 
+			(int)config->udp_cfg.bound_addr.slen,
+			config->udp_cfg.bound_addr.ptr);
 	pj_strcat2(&cfg, line);
     }
@@ -4334,6 +4367,10 @@
     if (!app_config.no_udp) {
 	pjsua_acc_id aid;
-
-	status = pjsua_transport_create(PJSIP_TRANSPORT_UDP,
+	pjsip_transport_type_e type = PJSIP_TRANSPORT_UDP;
+
+	if (app_config.ipv6)
+	    type = PJSIP_TRANSPORT_UDP6;
+
+	status = pjsua_transport_create(type,
 					&app_config.udp_cfg, 
 					&transport_id);
@@ -4431,5 +4468,8 @@
 
 #else
-    status = pjsua_media_transports_create(&app_config.rtp_cfg);
+    if (app_config.ipv6)
+	status = create_ipv6_media_transports();
+    else
+	status = pjsua_media_transports_create(&app_config.rtp_cfg);
 #endif
     if (status != PJ_SUCCESS)
@@ -4655,2 +4695,45 @@
 #endif
 
+static pj_status_t create_ipv6_media_transports(void)
+{
+    pjsua_media_transport tp[PJSUA_MAX_CALLS];
+    pj_status_t status;
+    int port = app_config.rtp_cfg.port;
+    unsigned i;
+
+    for (i=0; i<app_config.cfg.max_calls; ++i) {
+	enum { MAX_RETRY = 10 };
+	unsigned j;
+
+	/* Get rid of uninitialized var compiler warning with MSVC */
+	status = PJ_SUCCESS;
+
+	for (j=0; j<MAX_RETRY; ++j) {
+	    status = pjmedia_transport_udp_create3(pjsua_get_pjmedia_endpt(), 
+						   pj_AF_INET6(),
+						   NULL, 
+						   &app_config.rtp_cfg.bound_addr,
+						   port, 
+						   0, &tp[i].transport);
+
+	    if (port != 0)
+		port += 10;
+	    else
+		break;
+
+	    if (status == PJ_SUCCESS)
+		break;
+	}
+
+	if (status != PJ_SUCCESS) {
+	    pjsua_perror(THIS_FILE, "Error creating IPv6 UDP media transport", 
+			 status);
+	    for (j=0; j<i; ++j) {
+		pjmedia_transport_close(tp[j].transport);
+	    }
+	    return status;
+	}
+    }
+
+    return pjsua_media_transports_attach(tp, i, PJ_TRUE);
+}
Index: pjproject/trunk/pjsip/src/pjsua-lib/pjsua_acc.c
===================================================================
--- pjproject/trunk/pjsip/src/pjsua-lib/pjsua_acc.c	(revision 2567)
+++ pjproject/trunk/pjsip/src/pjsua-lib/pjsua_acc.c	(revision 2568)
@@ -679,14 +679,25 @@
     {
 	char *tmp;
+	const char *beginquote, *endquote;
 	int len;
+
+	/* Enclose IPv6 address in square brackets */
+	if (tp->key.type & PJSIP_TRANSPORT_IPV6) {
+	    beginquote = "[";
+	    endquote = "]";
+	} else {
+	    beginquote = endquote = "";
+	}
 
 	tmp = (char*) pj_pool_alloc(pool, PJSIP_MAX_URL_SIZE);
 	len = pj_ansi_snprintf(tmp, PJSIP_MAX_URL_SIZE,
-			       "<sip:%.*s%s%.*s:%d;transport=%s%.*s>",
+			       "<sip:%.*s%s%s%.*s%s:%d;transport=%s%.*s>",
 			       (int)acc->user_part.slen,
 			       acc->user_part.ptr,
 			       (acc->user_part.slen? "@" : ""),
+			       beginquote,
 			       (int)via_addr->slen,
 			       via_addr->ptr,
+			       endquote,
 			       rport,
 			       tp->type_name,
