Index: pjproject/branches/projects/uwp/pjsip/src/pjsua-lib/pjsua_acc.c
===================================================================
--- pjproject/branches/projects/uwp/pjsip/src/pjsua-lib/pjsua_acc.c	(revision 5208)
+++ pjproject/branches/projects/uwp/pjsip/src/pjsua-lib/pjsua_acc.c	(revision 5513)
@@ -88,4 +88,6 @@
     pj_strdup_with_null(pool, &dst->reg_uri, &src->reg_uri);
     pj_strdup_with_null(pool, &dst->force_contact, &src->force_contact);
+    pj_strdup_with_null(pool, &dst->reg_contact_params,
+			&src->reg_contact_params);
     pj_strdup_with_null(pool, &dst->contact_params, &src->contact_params);
     pj_strdup_with_null(pool, &dst->contact_uri_params,
@@ -381,4 +383,7 @@
     pj_array_insert(pjsua_var.acc_ids, sizeof(pjsua_var.acc_ids[0]),
 		    pjsua_var.acc_cnt, i, &acc_id);
+
+    if (acc_cfg->transport_id != PJSUA_INVALID_ID)
+	acc->tp_type = pjsua_var.tpdata[acc_cfg->transport_id].type;
 
     return PJ_SUCCESS;
@@ -513,4 +518,6 @@
     char transport_param[32];
     char uri[PJSIP_MAX_URL_SIZE];
+    pjsua_acc_id acc_id;
+    pj_status_t status;
 
     /* ID must be valid */
@@ -555,5 +562,12 @@
     cfg.id = pj_str(uri);
     
-    return pjsua_acc_add(&cfg, is_default, p_acc_id);
+    status = pjsua_acc_add(&cfg, is_default, &acc_id);
+    if (status == PJ_SUCCESS) {
+	pjsua_var.acc[acc_id].tp_type = t->type;
+	if (p_acc_id)
+	    *p_acc_id = acc_id;
+    }
+
+    return status;
 }
 
@@ -981,4 +995,11 @@
 	update_reg = PJ_TRUE;
 	unreg_first = PJ_TRUE;
+    }
+
+    /* Register contact params */
+    if (pj_strcmp(&acc->cfg.reg_contact_params, &cfg->reg_contact_params)) {
+	pj_strdup_with_null(acc->pool, &acc->cfg.reg_contact_params,
+			    &cfg->reg_contact_params);
+	update_reg = PJ_TRUE;
     }
 
@@ -1466,33 +1487,47 @@
 
 done:
-    if (!need_outbound) {
-	/* Outbound is not needed/wanted for the account. acc->reg_contact
-	 * is set to the same as acc->contact.
-	 */
-	acc->reg_contact = acc->contact;
-	acc->rfc5626_status = OUTBOUND_NA;
-    } else {
-	/* Need to use outbound, append the contact with +sip.instance and
-	 * reg-id parameters.
-	 */
+    {
 	pj_ssize_t len;
 	pj_str_t reg_contact;
 
 	acc->rfc5626_status = OUTBOUND_WANTED;
-	len = acc->contact.slen + acc->rfc5626_instprm.slen +
-	      acc->rfc5626_regprm.slen;
-	reg_contact.ptr = (char*) pj_pool_alloc(acc->pool, len);
-
-	pj_strcpy(&reg_contact, &acc->contact);
-	pj_strcat(&reg_contact, &acc->rfc5626_regprm);
-	pj_strcat(&reg_contact, &acc->rfc5626_instprm);
-
-	acc->reg_contact = reg_contact;
-
-	PJ_LOG(4,(THIS_FILE,
-		  "Contact for acc %d updated for SIP outbound: %.*s",
-		  acc->index,
-		  (int)acc->reg_contact.slen,
-		  acc->reg_contact.ptr));
+	len = acc->contact.slen + acc->cfg.reg_contact_params.slen +
+	      (need_outbound?
+	       (acc->rfc5626_instprm.slen + acc->rfc5626_regprm.slen): 0);
+	if (len > acc->contact.slen) {
+	    reg_contact.ptr = (char*) pj_pool_alloc(acc->pool, len);
+
+	    pj_strcpy(&reg_contact, &acc->contact);
+	
+    	    if (need_outbound) {
+    	    	acc->rfc5626_status = OUTBOUND_WANTED;
+
+	    	/* Need to use outbound, append the contact with
+	    	 * +sip.instance and reg-id parameters.
+	     	 */
+	    	pj_strcat(&reg_contact, &acc->rfc5626_regprm);
+	    	pj_strcat(&reg_contact, &acc->rfc5626_instprm);
+	    } else {
+	    	acc->rfc5626_status = OUTBOUND_NA;
+	    }
+
+	    pj_strcat(&reg_contact, &acc->cfg.reg_contact_params);
+	    
+	    acc->reg_contact = reg_contact;
+
+	    PJ_LOG(4,(THIS_FILE,
+		      "Contact for acc %d updated: %.*s",
+		      acc->index,
+		      (int)acc->reg_contact.slen,
+		      acc->reg_contact.ptr));
+
+	} else {
+	     /* Outbound is not needed/wanted for the account and there's
+	      * no custom registration Contact params. acc->reg_contact
+	      * is set to the same as acc->contact.
+	      */
+	     acc->reg_contact = acc->contact;
+	     acc->rfc5626_status = OUTBOUND_NA;
+	}
     }
 }
@@ -1533,5 +1568,5 @@
     pjsip_via_hdr *via;
     pj_sockaddr contact_addr;
-    pj_sockaddr recv_addr;
+    pj_sockaddr recv_addr = {{0}};
     pj_status_t status;
     pj_bool_t matched;
@@ -1646,6 +1681,10 @@
 				   &recv_addr);
     if (status == PJ_SUCCESS) {
-	/* Compare the addresses as sockaddr according to the ticket above */
-	matched = (uri->port == rport &&
+	/* Compare the addresses as sockaddr according to the ticket above,
+	 * but only if they have the same family (ipv4 vs ipv4, or
+	 * ipv6 vs ipv6)
+	 */
+	matched = (contact_addr.addr.sa_family != recv_addr.addr.sa_family) ||
+	          (uri->port == rport &&
 		   pj_sockaddr_cmp(&contact_addr, &recv_addr)==0);
     } else {
@@ -1941,5 +1980,5 @@
     /* Send raw packet */
     status = pjsip_tpmgr_send_raw(pjsip_endpt_get_tpmgr(pjsua_var.endpt),
-				  PJSIP_TRANSPORT_UDP, &tp_sel,
+				  acc->ka_transport->key.type, &tp_sel,
 				  NULL, acc->cfg.ka_data.ptr, 
 				  acc->cfg.ka_data.slen, 
@@ -2008,5 +2047,6 @@
 	if (/*pjsua_var.stun_srv.ipv4.sin_family == 0 ||*/
 	    acc->cfg.ka_interval == 0 ||
-	    param->rdata->tp_info.transport->key.type != PJSIP_TRANSPORT_UDP)
+	    (param->rdata->tp_info.transport->key.type &  
+	     ~PJSIP_TRANSPORT_IPV6)!= PJSIP_TRANSPORT_UDP)
 	{
 	    /* Keep alive is not necessary */
@@ -2288,5 +2328,5 @@
 	reg_info.cbparam = param;
 	reg_info.regc = param->regc;
-	reg_info.renew = (rinfo.interval != 0);
+	reg_info.renew = !param->is_unreg;
 	(*pjsua_var.ua_cfg.cb.on_reg_state2)(acc->index, &reg_info);
     }
@@ -2476,4 +2516,11 @@
 }
 
+pj_bool_t pjsua_sip_acc_is_using_ipv6(pjsua_acc_id acc_id)
+{
+    pjsua_acc *acc = &pjsua_var.acc[acc_id];
+
+    return (acc->tp_type & PJSIP_TRANSPORT_IPV6) == PJSIP_TRANSPORT_IPV6;
+}
+
 pj_bool_t pjsua_sip_acc_is_using_stun(pjsua_acc_id acc_id)
 {
@@ -2481,5 +2528,13 @@
 
     return acc->cfg.sip_stun_use != PJSUA_STUN_USE_DISABLED &&
-	    pjsua_var.ua_cfg.stun_srv_cnt != 0;
+	   pjsua_var.ua_cfg.stun_srv_cnt != 0;
+}
+
+pj_bool_t pjsua_media_acc_is_using_stun(pjsua_acc_id acc_id)
+{
+    pjsua_acc *acc = &pjsua_var.acc[acc_id];
+
+    return acc->cfg.media_stun_use != PJSUA_STUN_USE_DISABLED &&
+	   pjsua_var.ua_cfg.stun_srv_cnt != 0;
 }
 
@@ -2907,13 +2962,8 @@
 
 	if (acc->valid && pj_stricmp(&acc->user_part, &sip_uri->user)==0) {
-
-	    if (acc->cfg.transport_id != PJSUA_INVALID_ID) {
-		pjsip_transport_type_e type;
-		type = pjsip_transport_get_type_from_name(&sip_uri->transport_param);
-		if (type == PJSIP_TRANSPORT_UNSPECIFIED)
-		    type = PJSIP_TRANSPORT_UDP;
-
-		if (pjsua_var.tpdata[acc->cfg.transport_id].type != type)
-		    continue;
+	    if (acc->tp_type != PJSIP_TRANSPORT_UNSPECIFIED &&
+		acc->tp_type != rdata->tp_info.transport->key.type)
+	    {
+		continue;
 	    }
 
@@ -3019,6 +3069,6 @@
     pj_in6_addr dummy6;
 
-    /* First check with inet_aton() */
-    if (pj_inet_aton(host, &dummy) > 0)
+    /* First check if this is an IPv4 address */
+    if (pj_inet_pton(pj_AF_INET(), host, &dummy) == PJ_SUCCESS)
 	return 4;
 
@@ -3088,9 +3138,10 @@
 	return PJSIP_EUNSUPTRANSPORT;
 
-    /* If destination URI specifies IPv6, then set transport type
-     * to use IPv6 as well.
+    /* If destination URI specifies IPv6 or account is configured to use IPv6,
+     * then set transport type to use IPv6 as well.
      */
-    if (pj_strchr(&sip_uri->host, ':'))
-	tp_type = (pjsip_transport_type_e)(((int)tp_type) + PJSIP_TRANSPORT_IPV6);
+    if (pj_strchr(&sip_uri->host, ':') || pjsua_sip_acc_is_using_ipv6(acc_id))
+	tp_type = (pjsip_transport_type_e)(((int)tp_type) |
+	 	  PJSIP_TRANSPORT_IPV6);
 
     flag = pjsip_transport_get_flag_from_type(tp_type);
@@ -3153,8 +3204,24 @@
 	if (status == PJ_SUCCESS) {
 	    unsigned cnt=1;
-	    int af;
-
-	    af = (dinfo.type & PJSIP_TRANSPORT_IPV6)? PJ_AF_INET6 : PJ_AF_INET;
+	    int af = pj_AF_UNSPEC();
+
+	    if (pjsua_sip_acc_is_using_ipv6(acc_id) ||
+		(dinfo.type & PJSIP_TRANSPORT_IPV6))
+	    {
+		af = pj_AF_INET6();
+	    }
 	    status = pj_getaddrinfo(af, &dinfo.addr.host, &cnt, &ai);
+	    if (cnt == 0) {
+		status = PJ_ENOTSUP;
+	    } else if ((dinfo.type & PJSIP_TRANSPORT_IPV6)==0 &&
+			ai.ai_addr.addr.sa_family == pj_AF_INET6())
+	    {
+		/* Destination is a hostname and account is not bound to IPv6,
+		 * but hostname resolution reveals that it has IPv6 address,
+		 * so let's use IPv6 transport type.
+		 */
+		dinfo.type |= PJSIP_TRANSPORT_IPV6;
+		tp_type |= PJSIP_TRANSPORT_IPV6;
+	    }
 	}
 
@@ -3402,9 +3469,15 @@
 	return PJSIP_EUNSUPTRANSPORT;
 
-    /* If destination URI specifies IPv6, then set transport type
-     * to use IPv6 as well.
+    /* If destination URI specifies IPv6 or account is configured to use IPv6
+     * or the transport being used to receive data is an IPv6 transport,
+     * then set transport type to use IPv6 as well.
      */
-    if (pj_strchr(&sip_uri->host, ':'))
-	tp_type = (pjsip_transport_type_e)(((int)tp_type) + PJSIP_TRANSPORT_IPV6);
+    if (pj_strchr(&sip_uri->host, ':') ||
+	pjsua_sip_acc_is_using_ipv6(acc_id) ||
+	(rdata->tp_info.transport->key.type & PJSIP_TRANSPORT_IPV6))
+    {
+	tp_type = (pjsip_transport_type_e)
+		  (((int)tp_type) | PJSIP_TRANSPORT_IPV6);
+    }
 
     flag = pjsip_transport_get_flag_from_type(tp_type);
@@ -3490,4 +3563,5 @@
     
     acc->cfg.transport_id = tp_id;
+    acc->tp_type = pjsua_var.tpdata[tp_id].type;
 
     return PJ_SUCCESS;
