Index: pjproject/trunk/pjsip/include/pjsip/sip_transport.h
===================================================================
--- pjproject/trunk/pjsip/include/pjsip/sip_transport.h	(revision 1387)
+++ pjproject/trunk/pjsip/include/pjsip/sip_transport.h	(revision 1388)
@@ -1059,8 +1059,18 @@
 
 /**
- * This is a low-level function to send raw data using the specified transport
- * to the specified destination.
- *
- * @param tr	    The SIP transport to be used.
+ * This is a low-level function to send raw data to a destination.
+ *
+ * See also #pjsip_endpt_send_raw() and #pjsip_endpt_send_raw_to_uri().
+ *
+ * @param mgr	    Transport manager.
+ * @param tp_type   Transport type.
+ * @param sel	    Optional pointer to transport selector instance if
+ *		    application wants to use a specific transport instance
+ *		    rather then letting transport manager finds the suitable
+ *		    transport.
+ * @param tdata	    Optional transmit data buffer to be used. If this value
+ *		    is NULL, this function will create one internally. If
+ *		    tdata is specified, this function will decrement the
+ *		    reference counter upon completion.
  * @param raw_data  The data to be sent.
  * @param data_len  The length of the data.
@@ -1080,12 +1090,14 @@
  *		    callback will not be called.
  */
-PJ_DECL(pj_status_t) pjsip_transport_send_raw(pjsip_transport *tr,
-					      const void *raw_data,
-					      pj_size_t data_len,
-					      const pj_sockaddr_t *addr,
-					      int addr_len,
-					      void *token,
-					      pjsip_tp_send_callback cb);
-
+PJ_DECL(pj_status_t) pjsip_tpmgr_send_raw(pjsip_tpmgr *mgr,
+					  pjsip_transport_type_e tp_type,
+					  const pjsip_tpselector *sel,
+					  pjsip_tx_data *tdata,
+					  const void *raw_data,
+					  pj_size_t data_len,
+					  const pj_sockaddr_t *addr,
+					  int addr_len,
+					  void *token,
+					  pjsip_tp_send_callback cb);
 
 /**
Index: pjproject/trunk/pjsip/include/pjsip/sip_util.h
===================================================================
--- pjproject/trunk/pjsip/include/pjsip/sip_util.h	(revision 1387)
+++ pjproject/trunk/pjsip/include/pjsip/sip_util.h	(revision 1388)
@@ -21,4 +21,5 @@
 
 #include <pjsip/sip_msg.h>
+#include <pjsip/sip_transport.h>
 #include <pjsip/sip_resolve.h>
 
@@ -220,5 +221,4 @@
 					     pjsip_host_info *dest_info );
 
-
 /**
  * This structure holds the state of outgoing stateless request.
@@ -259,6 +259,8 @@
 } pjsip_send_state;
 
-typedef void (*pjsip_endpt_callback)(pjsip_send_state*, pj_ssize_t sent,
-									 pj_bool_t *cont);
+
+typedef void (*pjsip_send_callback)(pjsip_send_state*, pj_ssize_t sent,
+				    pj_bool_t *cont);
+
 /**
  * Send outgoing request statelessly The function will take care of which 
@@ -282,5 +284,79 @@
 				    pjsip_tx_data *tdata,
 				    void *token,
-				    pjsip_endpt_callback cb);
+				    pjsip_send_callback cb);
+
+/**
+ * This is a low-level function to send raw data to a destination.
+ *
+ * See also #pjsip_endpt_send_raw_to_uri().
+ *
+ * @param endpt	    The SIP endpoint instance.
+ * @param tp_type   Transport type.
+ * @param sel	    Optional pointer to transport selector instance if
+ *		    application wants to use a specific transport instance
+ *		    rather then letting transport manager finds the suitable
+ *		    transport..
+ * @param raw_data  The data to be sent.
+ * @param data_len  The length of the data.
+ * @param addr	    Destination address.
+ * @param addr_len  Length of destination address.
+ * @param token	    Arbitrary token to be returned back to callback.
+ * @param cb	    Optional callback to be called to notify caller about
+ *		    the completion status of the pending send operation.
+ *
+ * @return	    If the message has been sent successfully, this function
+ *		    will return PJ_SUCCESS and the callback will not be 
+ *		    called. If message cannot be sent immediately, this
+ *		    function will return PJ_EPENDING, and application will
+ *		    be notified later about the completion via the callback.
+ *		    Any statuses other than PJ_SUCCESS or PJ_EPENDING
+ *		    indicates immediate failure, and in this case the 
+ *		    callback will not be called.
+ */
+PJ_DECL(pj_status_t) pjsip_endpt_send_raw(pjsip_endpoint *endpt,
+					  pjsip_transport_type_e tp_type,
+					  const pjsip_tpselector *sel,
+					  const void *raw_data,
+					  pj_size_t data_len,
+					  const pj_sockaddr_t *addr,
+					  int addr_len,
+					  void *token,
+					  pjsip_tp_send_callback cb);
+
+/**
+ * Send raw data to the specified destination URI. The actual destination
+ * address will be calculated from the URI, using normal SIP URI to host
+ * resolution.
+ *
+ * See also #pjsip_endpt_send_raw().
+ *
+ * @param endpt	    The SIP endpoint instance.
+ * @param dst_uri   Destination address URI.
+ * @param sel	    Optional pointer to transport selector instance if
+ *		    application wants to use a specific transport instance
+ *		    rather then letting transport manager finds the suitable
+ *		    transport..
+ * @param raw_data  The data to be sent.
+ * @param data_len  The length of the data.
+ * @param token	    Arbitrary token to be returned back to callback.
+ * @param cb	    Optional callback to be called to notify caller about
+ *		    the completion status of the pending send operation.
+ *
+ * @return	    If the message has been sent successfully, this function
+ *		    will return PJ_SUCCESS and the callback will not be 
+ *		    called. If message cannot be sent immediately, this
+ *		    function will return PJ_EPENDING, and application will
+ *		    be notified later about the completion via the callback.
+ *		    Any statuses other than PJ_SUCCESS or PJ_EPENDING
+ *		    indicates immediate failure, and in this case the 
+ *		    callback will not be called.
+ */
+PJ_DECL(pj_status_t) pjsip_endpt_send_raw_to_uri(pjsip_endpoint *endpt,
+						 const pj_str_t *dst_uri,
+						 const pjsip_tpselector *sel,
+						 const void *raw_data,
+						 pj_size_t data_len,
+						 void *token,
+						 pjsip_tp_send_callback cb);
 
 /**
@@ -358,5 +434,5 @@
 					        pjsip_tx_data *tdata,
 						void *token,
-						pjsip_endpt_callback cb);
+						pjsip_send_callback cb);
 
 /**
@@ -381,5 +457,5 @@
 					        pjsip_tx_data *tdata,
 						void *token,
-						pjsip_endpt_callback cb);
+						pjsip_send_callback cb);
 
 /**
Index: pjproject/trunk/pjsip/src/pjsip/sip_transport.c
===================================================================
--- pjproject/trunk/pjsip/src/pjsip/sip_transport.c	(revision 1387)
+++ pjproject/trunk/pjsip/src/pjsip/sip_transport.c	(revision 1388)
@@ -604,29 +604,75 @@
 
 
+/* send_raw() callback */
+static void send_raw_callback(pjsip_transport *transport,
+			      void *token,
+			      pj_ssize_t size)
+{
+    pjsip_tx_data *tdata = (pjsip_tx_data*) token;
+
+    /* Mark pending off so that app can resend/reuse txdata from inside
+     * the callback.
+     */
+    tdata->is_pending = 0;
+
+    /* Call callback, if any. */
+    if (tdata->cb) {
+	(*tdata->cb)(tdata->token, tdata, size);
+    }
+
+    /* Decrement tdata reference count. */
+    pjsip_tx_data_dec_ref(tdata);
+
+    /* Decrement transport reference count */
+    pjsip_transport_dec_ref(transport);
+}
+
+
 /* Send raw data */
-PJ_DEF(pj_status_t) pjsip_transport_send_raw(pjsip_transport *tr,
-					     const void *raw_data,
-					     pj_size_t data_len,
-					     const pj_sockaddr_t *addr,
-					     int addr_len,
-					     void *token,
-					     pjsip_tp_send_callback cb)
-{
-    pjsip_tx_data *tdata;
+PJ_DEF(pj_status_t) pjsip_tpmgr_send_raw(pjsip_tpmgr *mgr,
+					 pjsip_transport_type_e tp_type,
+					 const pjsip_tpselector *sel,
+					 pjsip_tx_data *tdata,
+					 const void *raw_data,
+					 pj_size_t data_len,
+					 const pj_sockaddr_t *addr,
+					 int addr_len,
+					 void *token,
+					 pjsip_tp_send_callback cb)
+{
+    pjsip_transport *tr;
     pj_status_t status;
  
-    status = pjsip_endpt_create_tdata(tr->endpt, &tdata);
+    /* Acquire the transport */
+    status = pjsip_tpmgr_acquire_transport(mgr, tp_type, addr, addr_len,
+					   sel, &tr);
     if (status != PJ_SUCCESS)
 	return status;
 
-    /* Add reference counter. */
-    pjsip_tx_data_add_ref(tdata);
+    /* Create transmit data buffer if one is not specified */
+    if (tdata == NULL) {
+	status = pjsip_endpt_create_tdata(tr->endpt, &tdata);
+	if (status != PJ_SUCCESS) {
+	    pjsip_transport_dec_ref(tr);
+	    return status;
+	}
+
+	/* Add reference counter. */
+	pjsip_tx_data_add_ref(tdata);
+    }
+
+    /* Allocate buffer */
+    if (tdata->buf.start == NULL ||
+	(tdata->buf.end - tdata->buf.start) < (int)data_len)
+    {
+	/* Note: data_len may be zero, so allocate +1 */
+	tdata->buf.start = (char*) pj_pool_alloc(tdata->pool, data_len+1);
+	tdata->buf.end = tdata->buf.start + data_len + 1;
+    }
  
-    /* Allocate buffer */
-    tdata->buf.start = (char*) pj_pool_alloc(tdata->pool, data_len);
-    tdata->buf.end = tdata->buf.start + data_len;
- 
-    /* Copy data */
-    pj_memcpy(tdata->buf.start, raw_data, data_len);
+    /* Copy data, if any! (application may send zero len packet) */
+    if (data_len) {
+	pj_memcpy(tdata->buf.start, raw_data, data_len);
+    }
     tdata->buf.cur = tdata->buf.start + data_len;
  
@@ -638,11 +684,12 @@
     tdata->is_pending = 1;
 
-    /* Send to transoprt */
+    /* Send to transport */
     status = tr->send_msg(tr, tdata, addr, addr_len,
-			  tdata, &transport_send_callback);
+			  tdata, &send_raw_callback);
  
     if (status != PJ_EPENDING) {
 	/* callback will not be called, so destroy tdata now. */
 	pjsip_tx_data_dec_ref(tdata);
+	pjsip_transport_dec_ref(tr);
     }
 
Index: pjproject/trunk/pjsip/src/pjsip/sip_util.c
===================================================================
--- pjproject/trunk/pjsip/src/pjsip/sip_util.c	(revision 1387)
+++ pjproject/trunk/pjsip/src/pjsip/sip_util.c	(revision 1388)
@@ -997,5 +997,5 @@
 				   pjsip_tx_data *tdata,
 				   void *token,
-				   pjsip_endpt_callback cb)
+				   pjsip_send_callback cb)
 {
     pjsip_host_info dest_info;
@@ -1024,4 +1024,148 @@
     return PJ_SUCCESS;
 }
+
+
+/*
+ * Send raw data to a destination.
+ */
+PJ_DEF(pj_status_t) pjsip_endpt_send_raw( pjsip_endpoint *endpt,
+					  pjsip_transport_type_e tp_type,
+					  const pjsip_tpselector *sel,
+					  const void *raw_data,
+					  pj_size_t data_len,
+					  const pj_sockaddr_t *addr,
+					  int addr_len,
+					  void *token,
+					  pjsip_tp_send_callback cb)
+{
+    return pjsip_tpmgr_send_raw(pjsip_endpt_get_tpmgr(endpt), tp_type, sel,
+				NULL, raw_data, data_len, addr, addr_len,
+				token, cb);
+}
+
+
+/* Callback data for sending raw data */
+struct send_raw_data
+{
+    pjsip_endpoint	    *endpt;
+    pjsip_tx_data	    *tdata;
+    pjsip_tpselector	    *sel;
+    void		    *app_token;
+    pjsip_tp_send_callback   app_cb;
+};
+
+
+/* Resolver callback for sending raw data. */
+static void send_raw_resolver_callback( pj_status_t status,
+    					void *token,
+					const pjsip_server_addresses *addr)
+{
+    struct send_raw_data *sraw_data = (struct send_raw_data*) token;
+
+    if (status != PJ_SUCCESS) {
+	if (sraw_data->app_cb) {
+	    (*sraw_data->app_cb)(sraw_data->app_token, sraw_data->tdata,
+				 -status);
+	}
+    } else {
+	pj_size_t data_len;
+
+	pj_assert(addr->count != 0);
+
+	data_len = sraw_data->tdata->buf.cur - sraw_data->tdata->buf.start;
+	status = pjsip_tpmgr_send_raw(pjsip_endpt_get_tpmgr(sraw_data->endpt),
+				      addr->entry[0].type,
+				      sraw_data->sel, sraw_data->tdata,
+				      sraw_data->tdata->buf.start, data_len,
+				      &addr->entry[0].addr, 
+				      addr->entry[0].addr_len, 
+				      sraw_data->app_token,
+				      sraw_data->app_cb);
+	if (status == PJ_SUCCESS) {
+	    (*sraw_data->app_cb)(sraw_data->app_token, sraw_data->tdata,
+				 data_len);
+	} else if (status != PJ_EPENDING) {
+	    (*sraw_data->app_cb)(sraw_data->app_token, sraw_data->tdata,
+				 -status);
+	}
+    }
+
+    if (sraw_data->sel) {
+	pjsip_tpselector_dec_ref(sraw_data->sel);
+    }
+    pjsip_tx_data_dec_ref(sraw_data->tdata);
+}
+
+
+/*
+ * Send raw data to the specified destination URI. 
+ */
+PJ_DEF(pj_status_t) pjsip_endpt_send_raw_to_uri(pjsip_endpoint *endpt,
+						const pj_str_t *p_dst_uri,
+						const pjsip_tpselector *sel,
+						const void *raw_data,
+						pj_size_t data_len,
+						void *token,
+						pjsip_tp_send_callback cb)
+{
+    pjsip_tx_data *tdata;
+    struct send_raw_data *sraw_data;
+    pj_str_t dst_uri;
+    pjsip_uri *uri;
+    pjsip_host_info dest_info;
+    pj_status_t status;
+
+    /* Allocate buffer */
+    status = pjsip_endpt_create_tdata(endpt, &tdata);
+    if (status != PJ_SUCCESS)
+	return status;
+
+    pjsip_tx_data_add_ref(tdata);
+
+    /* Duplicate URI since parser requires URI to be NULL terminated */
+    pj_strdup_with_null(tdata->pool, &dst_uri, p_dst_uri);
+
+    /* Parse URI */
+    uri = pjsip_parse_uri(tdata->pool, dst_uri.ptr, dst_uri.slen, 0);
+    if (uri == NULL) {
+	pjsip_tx_data_dec_ref(tdata);
+	return PJSIP_EINVALIDURI;
+    }
+
+    /* Build destination info. */
+    status = get_dest_info(uri, tdata->pool, &dest_info);
+    if (status != PJ_SUCCESS) {
+	pjsip_tx_data_dec_ref(tdata);
+	return status;
+    }
+
+    /* Copy data (note: data_len may be zero!) */
+    tdata->buf.start = (char*) pj_pool_alloc(tdata->pool, data_len+1);
+    tdata->buf.end = tdata->buf.start + data_len + 1;
+    if (data_len)
+	pj_memcpy(tdata->buf.start, raw_data, data_len);
+    tdata->buf.cur = tdata->buf.start + data_len;
+
+    /* Init send_raw_data */
+    sraw_data = PJ_POOL_ZALLOC_T(tdata->pool, struct send_raw_data);
+    sraw_data->endpt = endpt;
+    sraw_data->tdata = tdata;
+    sraw_data->app_token = token;
+    sraw_data->app_cb = cb;
+
+    if (sel) {
+	sraw_data->sel = PJ_POOL_ALLOC_T(tdata->pool, pjsip_tpselector);
+	pj_memcpy(sraw_data->sel, sel, sizeof(pjsip_tpselector));
+	pjsip_tpselector_add_ref(sraw_data->sel);
+    }
+
+    /* Resolve destination host.
+     * The processing then resumed when the resolving callback is called.
+     */
+    pjsip_endpt_resolve( endpt, tdata->pool, &dest_info, sraw_data,
+			 &send_raw_resolver_callback);
+    return PJ_SUCCESS;
+}
+
 
 /*
@@ -1216,5 +1360,5 @@
 					       pjsip_tx_data *tdata,
 					       void *token,
-					       pjsip_endpt_callback cb)
+					       pjsip_send_callback cb)
 {
     /* Determine which transports and addresses to send the response,
@@ -1265,5 +1409,5 @@
 					        pjsip_tx_data *tdata,
 						void *token,
-						pjsip_endpt_callback cb)
+						pjsip_send_callback cb)
 {
     pjsip_response_addr res_addr;
