Index: /pjproject/trunk/pjsip/include/pjsip/sip_transport.h
===================================================================
--- /pjproject/trunk/pjsip/include/pjsip/sip_transport.h	(revision 880)
+++ /pjproject/trunk/pjsip/include/pjsip/sip_transport.h	(revision 881)
@@ -918,5 +918,6 @@
  * @param tpmgr	    The transport manager.
  * @param pool	    Pool to allocate memory for the IP address.
- * @param h	    Destination address to contact.
+ * @param type	    Destination address to contact.
+ * @param sel	    Optional pointer to prefered transport, if any.
  * @param ip_addr   Pointer to receive the IP address.
  * @param port	    Pointer to receive the port number.
@@ -927,4 +928,5 @@
 						  pj_pool_t *pool,
 						  pjsip_transport_type_e type,
+						  const pjsip_tpselector *sel,
 						  pj_str_t *ip_addr,
 						  int *port);
Index: /pjproject/trunk/pjsip/include/pjsua-lib/pjsua.h
===================================================================
--- /pjproject/trunk/pjsip/include/pjsua-lib/pjsua.h	(revision 880)
+++ /pjproject/trunk/pjsip/include/pjsua-lib/pjsua.h	(revision 881)
@@ -1342,4 +1342,17 @@
     pjsip_cred_info cred_info[PJSUA_ACC_MAX_PROXIES];
 
+    /**
+     * Optionally bind this account to specific transport. This normally is
+     * not a good idea, as account should be able to send requests using
+     * any available transports according to the destination. But some
+     * application may want to have explicit control over the transport to
+     * use, so in that case it can set this field.
+     *
+     * Default: -1 (PJSUA_INVALID_ID)
+     *
+     * @see pjsua_acc_set_transport()
+     */
+    pjsua_transport_id  transport_id;
+
 } pjsua_acc_config;
 
@@ -1355,4 +1368,5 @@
 
     cfg->reg_timeout = PJSUA_REG_INTERVAL;
+    cfg->transport_id = PJSUA_INVALID_ID;
 }
 
@@ -1655,4 +1669,24 @@
 						   pjsip_rx_data *rdata );
 							   
+
+/**
+ * Lock/bind this account to a specific transport/listener. Normally
+ * application shouldn't need to do this, as transports will be selected
+ * automatically by the stack according to the destination.
+ *
+ * When account is locked/bound to a specific transport, all outgoing
+ * requests from this account will use the specified transport (this
+ * includes SIP registration, dialog (call and event subscription), and
+ * out-of-dialog requests such as MESSAGE).
+ *
+ * Note that transport_id may be specified in pjsua_acc_config too.
+ *
+ * @param acc_id	The account ID.
+ * @param tp_id		The transport ID.
+ *
+ * @return		PJ_SUCCESS on success.
+ */
+PJ_DECL(pj_status_t) pjsua_acc_set_transport(pjsua_acc_id acc_id,
+					     pjsua_transport_id tp_id);
 
 
Index: /pjproject/trunk/pjsip/include/pjsua-lib/pjsua_internal.h
===================================================================
--- /pjproject/trunk/pjsip/include/pjsua-lib/pjsua_internal.h	(revision 880)
+++ /pjproject/trunk/pjsip/include/pjsua-lib/pjsua_internal.h	(revision 881)
@@ -107,5 +107,5 @@
  *Transport.
  */
-typedef struct transport_data
+typedef struct pjsua_transport_data
 {
     int			     index;
@@ -119,5 +119,5 @@
     } data;
 
-} transport_data;
+} pjsua_transport_data;
 
 
@@ -180,5 +180,5 @@
     pjsip_endpoint	*endpt;	    /**< Global endpoint.		*/
     pjsip_module	 mod;	    /**< pjsua's PJSIP module.		*/
-    transport_data	 tpdata[8]; /**< Array of transports.		*/
+    pjsua_transport_data tpdata[8]; /**< Array of transports.		*/
 
     /* Threading: */
@@ -380,4 +380,12 @@
 
 
+/*
+ * Internal function to init transport selector from transport id.
+ */
+void pjsua_init_tpselector(pjsua_transport_id tp_id,
+			   pjsip_tpselector *sel);
+
+
+
 PJ_END_DECL
 
Index: /pjproject/trunk/pjsip/src/pjsip/sip_dialog.c
===================================================================
--- /pjproject/trunk/pjsip/src/pjsip/sip_dialog.c	(revision 880)
+++ /pjproject/trunk/pjsip/src/pjsip/sip_dialog.c	(revision 881)
@@ -102,4 +102,8 @@
 	dlg->mutex_ = NULL;
     }
+    if (dlg->tp_sel.type != PJSIP_TPSELECTOR_NONE) {
+	pjsip_tpselector_dec_ref(&dlg->tp_sel);
+	pj_bzero(&dlg->tp_sel, sizeof(pjsip_tpselector));
+    }
     pjsip_endpt_release_pool(dlg->endpt, dlg->pool);
 }
Index: /pjproject/trunk/pjsip/src/pjsip/sip_errno.c
===================================================================
--- /pjproject/trunk/pjsip/src/pjsip/sip_errno.c	(revision 880)
+++ /pjproject/trunk/pjsip/src/pjsip/sip_errno.c	(revision 881)
@@ -68,4 +68,5 @@
     PJ_BUILD_ERR( PJSIP_ERXOVERFLOW,	"Rx buffer overflow"),
     PJ_BUILD_ERR( PJSIP_EBUFDESTROYED,	"Buffer destroyed"),
+    PJ_BUILD_ERR( PJSIP_ETPNOTSUITABLE,	"Unsuitable transport selected"),
 
     /* Transaction errors */
Index: /pjproject/trunk/pjsip/src/pjsip/sip_transport.c
===================================================================
--- /pjproject/trunk/pjsip/src/pjsip/sip_transport.c	(revision 880)
+++ /pjproject/trunk/pjsip/src/pjsip/sip_transport.c	(revision 881)
@@ -941,4 +941,5 @@
 						 pj_pool_t *pool,
 						 pjsip_transport_type_e type,
+						 const pjsip_tpselector *sel,
 						 pj_str_t *ip_addr,
 						 int *port)
@@ -955,5 +956,19 @@
     flag = pjsip_transport_get_flag_from_type(type);
 
-    if ((flag & PJSIP_TRANSPORT_DATAGRAM) != 0) {
+    if (sel && sel->type == PJSIP_TPSELECTOR_TRANSPORT &&
+	sel->u.transport)
+    {
+	pj_strdup(pool, ip_addr, &sel->u.transport->local_name.host);
+	*port = sel->u.transport->local_name.port;
+	status = PJ_SUCCESS;
+
+    } else if (sel && sel->type == PJSIP_TPSELECTOR_LISTENER &&
+	       sel->u.listener)
+    {
+	pj_strdup(pool, ip_addr, &sel->u.listener->addr_name.host);
+	*port = sel->u.listener->addr_name.port;
+	status = PJ_SUCCESS;
+
+    } else if ((flag & PJSIP_TRANSPORT_DATAGRAM) != 0) {
 	
 	pj_sockaddr_in remote;
Index: /pjproject/trunk/pjsip/src/pjsua-lib/pjsua_acc.c
===================================================================
--- /pjproject/trunk/pjsip/src/pjsua-lib/pjsua_acc.c	(revision 880)
+++ /pjproject/trunk/pjsip/src/pjsua-lib/pjsua_acc.c	(revision 881)
@@ -226,5 +226,4 @@
 	return status;
 
-
     /* Mark account as valid */
     pjsua_var.acc[acc_id].valid = PJ_TRUE;
@@ -259,5 +258,4 @@
 
     /* Must have a transport */
-    PJ_TODO(associate_acc_with_transport);
     PJ_ASSERT_RETURN(pjsua_var.tpdata[0].data.ptr != NULL, PJ_EINVALIDOP);
 
@@ -321,5 +319,5 @@
 {
     pjsua_acc_config cfg;
-    struct transport_data *t = &pjsua_var.tpdata[tid];
+    pjsua_transport_data *t = &pjsua_var.tpdata[tid];
     char uri[PJSIP_MAX_URL_SIZE];
 
@@ -383,5 +381,8 @@
     }
 
-    PJ_TODO(may_need_to_scan_calls);
+    /* Leave the calls intact, as I don't think calls need to
+     * access account once it's created
+     */
+
 
     PJSUA_UNLOCK();
@@ -492,4 +493,5 @@
     pj_status_t status;
 
+    PJ_ASSERT_RETURN(pjsua_acc_is_valid(acc_id), PJ_EINVAL);
     acc = &pjsua_var.acc[acc_id];
 
@@ -539,4 +541,15 @@
     }
 
+    /* If account is locked to specific transport, then set transport to
+     * the client registration.
+     */
+    if (pjsua_var.acc[acc_id].cfg.transport_id != PJSUA_INVALID_ID) {
+	pjsip_tpselector tp_sel;
+
+	pjsua_init_tpselector(pjsua_var.acc[acc_id].cfg.transport_id, &tp_sel);
+	pjsip_regc_set_transport(acc->regc, &tp_sel);
+    }
+
+
     /* Set credentials
      */
@@ -641,4 +654,5 @@
 
     PJ_ASSERT_RETURN(info != NULL, PJ_EINVAL);
+    PJ_ASSERT_RETURN(pjsua_acc_is_valid(acc_id), PJ_EINVAL);
     
     pj_bzero(info, sizeof(pjsua_acc_info));
@@ -855,5 +869,5 @@
 	pjsua_acc *acc = &pjsua_var.acc[acc_id];
 
-	if (pj_stricmp(&acc->user_part, &sip_uri->user)==0 &&
+	if (acc->valid && pj_stricmp(&acc->user_part, &sip_uri->user)==0 &&
 	    pj_stricmp(&acc->srv_domain, &sip_uri->host)==0) 
 	{
@@ -869,5 +883,5 @@
 	pjsua_acc *acc = &pjsua_var.acc[acc_id];
 
-	if (pj_stricmp(&acc->srv_domain, &sip_uri->host)==0) {
+	if (acc->valid && pj_stricmp(&acc->srv_domain, &sip_uri->host)==0) {
 	    /* Match ! */
 	    PJSUA_UNLOCK();
@@ -876,10 +890,21 @@
     }
 
-    /* No matching account, try match user part only. */
+    /* No matching account, try match user part (and transport type) only. */
     for (i=0; i < pjsua_var.acc_cnt; ++i) {
 	unsigned acc_id = pjsua_var.acc_ids[i];
 	pjsua_acc *acc = &pjsua_var.acc[acc_id];
 
-	if (pj_stricmp(&acc->user_part, &sip_uri->user)==0) {
+	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;
+	    }
+
 	    /* Match ! */
 	    PJSUA_UNLOCK();
@@ -904,8 +929,10 @@
     pjsip_transport_type_e tp_type = PJSIP_TRANSPORT_UNSPECIFIED;
     pj_str_t local_addr;
+    pjsip_tpselector tp_sel;
     unsigned flag;
     int secure;
     int local_port;
     
+    PJ_ASSERT_RETURN(pjsua_acc_is_valid(acc_id), PJ_EINVAL);
     acc = &pjsua_var.acc[acc_id];
 
@@ -946,7 +973,11 @@
     secure = (flag & PJSIP_TRANSPORT_SECURE) != 0;
 
+    /* Init transport selector. */
+    pjsua_init_tpselector(pjsua_var.acc[acc_id].cfg.transport_id, &tp_sel);
+
     /* Get local address suitable to send request from */
     status = pjsip_tpmgr_find_local_addr(pjsip_endpt_get_tpmgr(pjsua_var.endpt),
-					 pool, tp_type, &local_addr, &local_port);
+					 pool, tp_type, &tp_sel, 
+					 &local_addr, &local_port);
     if (status != PJ_SUCCESS)
 	return status;
@@ -991,8 +1022,10 @@
     pjsip_transport_type_e tp_type = PJSIP_TRANSPORT_UNSPECIFIED;
     pj_str_t local_addr;
+    pjsip_tpselector tp_sel;
     unsigned flag;
     int secure;
     int local_port;
     
+    PJ_ASSERT_RETURN(pjsua_acc_is_valid(acc_id), PJ_EINVAL);
     acc = &pjsua_var.acc[acc_id];
 
@@ -1039,7 +1072,11 @@
     secure = (flag & PJSIP_TRANSPORT_SECURE) != 0;
 
+    /* Init transport selector. */
+    pjsua_init_tpselector(pjsua_var.acc[acc_id].cfg.transport_id, &tp_sel);
+
     /* Get local address suitable to send request from */
     status = pjsip_tpmgr_find_local_addr(pjsip_endpt_get_tpmgr(pjsua_var.endpt),
-					 pool, tp_type, &local_addr, &local_port);
+					 pool, tp_type, &tp_sel,
+					 &local_addr, &local_port);
     if (status != PJ_SUCCESS)
 	return status;
@@ -1065,3 +1102,18 @@
 
 
-
+PJ_DEF(pj_status_t) pjsua_acc_set_transport( pjsua_acc_id acc_id,
+					     pjsua_transport_id tp_id)
+{
+    pjsua_acc *acc;
+
+    PJ_ASSERT_RETURN(pjsua_acc_is_valid(acc_id), PJ_EINVAL);
+    acc = &pjsua_var.acc[acc_id];
+
+    PJ_ASSERT_RETURN(tp_id >= 0 && tp_id < PJ_ARRAY_SIZE(pjsua_var.tpdata),
+		     PJ_EINVAL);
+    
+    acc->cfg.transport_id = tp_id;
+
+    return PJ_SUCCESS;
+}
+
Index: /pjproject/trunk/pjsip/src/pjsua-lib/pjsua_call.c
===================================================================
--- /pjproject/trunk/pjsip/src/pjsua-lib/pjsua_call.c	(revision 880)
+++ /pjproject/trunk/pjsip/src/pjsua-lib/pjsua_call.c	(revision 881)
@@ -331,4 +331,14 @@
     call->user_data = user_data;
 
+    /* If account is locked to specific transport, then lock dialog
+     * to this transport too.
+     */
+    if (acc->cfg.transport_id != PJSUA_INVALID_ID) {
+	pjsip_tpselector tp_sel;
+
+	pjsua_init_tpselector(acc->cfg.transport_id, &tp_sel);
+	pjsip_dlg_set_transport(dlg, &tp_sel);
+    }
+
     /* Set dialog Route-Set: */
     if (!pj_list_empty(&acc->route_set))
@@ -620,4 +630,13 @@
     inv->mod_data[pjsua_var.mod.id] = call;
 
+    /* If account is locked to specific transport, then lock dialog
+     * to this transport too.
+     */
+    if (pjsua_var.acc[acc_id].cfg.transport_id != PJSUA_INVALID_ID) {
+	pjsip_tpselector tp_sel;
+
+	pjsua_init_tpselector(pjsua_var.acc[acc_id].cfg.transport_id, &tp_sel);
+	pjsip_dlg_set_transport(dlg, &tp_sel);
+    }
 
     /* Must answer with some response to initial INVITE.
Index: /pjproject/trunk/pjsip/src/pjsua-lib/pjsua_core.c
===================================================================
--- /pjproject/trunk/pjsip/src/pjsua-lib/pjsua_core.c	(revision 880)
+++ /pjproject/trunk/pjsip/src/pjsua-lib/pjsua_core.c	(revision 881)
@@ -1190,5 +1190,5 @@
 					      pjsua_transport_info *info)
 {
-    struct transport_data *t = &pjsua_var.tpdata[id];
+    pjsua_transport_data *t = &pjsua_var.tpdata[id];
     pj_status_t status;
 
@@ -1417,4 +1417,32 @@
 
 /*
+ * Internal function to init transport selector from transport id.
+ */
+void pjsua_init_tpselector(pjsua_transport_id tp_id,
+			   pjsip_tpselector *sel)
+{
+    pjsua_transport_data *tpdata;
+    unsigned flag;
+
+    pj_bzero(sel, sizeof(*sel));
+    if (tp_id == PJSUA_INVALID_ID)
+	return;
+
+    pj_assert(tp_id >= 0 && tp_id < PJ_ARRAY_SIZE(pjsua_var.tpdata));
+    tpdata = &pjsua_var.tpdata[tp_id];
+
+    flag = pjsip_transport_get_flag_from_type(tpdata->type);
+
+    if (flag & PJSIP_TRANSPORT_DATAGRAM) {
+	sel->type = PJSIP_TPSELECTOR_TRANSPORT;
+	sel->u.transport = tpdata->data.tp;
+    } else {
+	sel->type = PJSIP_TPSELECTOR_LISTENER;
+	sel->u.listener = tpdata->data.factory;
+    }
+}
+
+
+/*
  * Verify that valid SIP url is given.
  */
Index: /pjproject/trunk/pjsip/src/pjsua-lib/pjsua_im.c
===================================================================
--- /pjproject/trunk/pjsip/src/pjsua-lib/pjsua_im.c	(revision 880)
+++ /pjproject/trunk/pjsip/src/pjsua-lib/pjsua_im.c	(revision 881)
@@ -434,4 +434,14 @@
     }
 
+    /* If account is locked to specific transport, then set transport to
+     * the request.
+     */
+    if (pjsua_var.acc[acc_id].cfg.transport_id != PJSUA_INVALID_ID) {
+	pjsip_tpselector tp_sel;
+
+	pjsua_init_tpselector(pjsua_var.acc[acc_id].cfg.transport_id, &tp_sel);
+	pjsip_tx_data_set_transport(tdata, &tp_sel);
+    }
+
     /* Add accept header. */
     pjsip_msg_add_hdr( tdata->msg, 
@@ -521,4 +531,14 @@
 
 
+    /* If account is locked to specific transport, then set transport to
+     * the request.
+     */
+    if (pjsua_var.acc[acc_id].cfg.transport_id != PJSUA_INVALID_ID) {
+	pjsip_tpselector tp_sel;
+
+	pjsua_init_tpselector(pjsua_var.acc[acc_id].cfg.transport_id, &tp_sel);
+	pjsip_tx_data_set_transport(tdata, &tp_sel);
+    }
+
     /* Add accept header. */
     pjsip_msg_add_hdr( tdata->msg, 
Index: /pjproject/trunk/pjsip/src/pjsua-lib/pjsua_pres.c
===================================================================
--- /pjproject/trunk/pjsip/src/pjsua-lib/pjsua_pres.c	(revision 880)
+++ /pjproject/trunk/pjsip/src/pjsua-lib/pjsua_pres.c	(revision 881)
@@ -502,4 +502,14 @@
     }
 
+    /* If account is locked to specific transport, then lock dialog
+     * to this transport too.
+     */
+    if (acc->cfg.transport_id != PJSUA_INVALID_ID) {
+	pjsip_tpselector tp_sel;
+
+	pjsua_init_tpselector(acc->cfg.transport_id, &tp_sel);
+	pjsip_dlg_set_transport(dlg, &tp_sel);
+    }
+
     /* Attach our data to the subscription: */
     uapres = pj_pool_alloc(dlg->pool, sizeof(pjsua_srv_pres));
@@ -989,4 +999,14 @@
     }
 
+    /* If account is locked to specific transport, then lock dialog
+     * to this transport too.
+     */
+    if (acc->cfg.transport_id != PJSUA_INVALID_ID) {
+	pjsip_tpselector tp_sel;
+
+	pjsua_init_tpselector(acc->cfg.transport_id, &tp_sel);
+	pjsip_dlg_set_transport(dlg, &tp_sel);
+    }
+
     /* Set route-set */
     if (!pj_list_empty(&acc->route_set)) {
