summaryrefslogtreecommitdiff
path: root/pjsip
diff options
context:
space:
mode:
authorBenny Prijono <bennylp@teluu.com>2007-06-23 07:26:54 +0000
committerBenny Prijono <bennylp@teluu.com>2007-06-23 07:26:54 +0000
commitdd49a84c46ef7ea0cb755bfa8e78e6395f544c4e (patch)
treeabece2181d854eb6f19ad6a1b7bee7fb0849c7a7 /pjsip
parentde1e9a2df94e4a20bbf41f5edd241bfbdacd9b7f (diff)
More ticket #341: renamed pjsip_transport_send_raw() to pjsip_tpmgr_send_raw(), and added pjsip_endpt_send_raw() and pjsip_endpt_send_raw_to_uri()
git-svn-id: http://svn.pjsip.org/repos/pjproject/trunk@1388 74dad513-b988-da41-8d7b-12977e46ad98
Diffstat (limited to 'pjsip')
-rw-r--r--pjsip/include/pjsip/sip_transport.h34
-rw-r--r--pjsip/include/pjsip/sip_util.h88
-rw-r--r--pjsip/src/pjsip/sip_transport.c83
-rw-r--r--pjsip/src/pjsip/sip_util.c150
4 files changed, 317 insertions, 38 deletions
diff --git a/pjsip/include/pjsip/sip_transport.h b/pjsip/include/pjsip/sip_transport.h
index 24b671f0..9f1ff044 100644
--- a/pjsip/include/pjsip/sip_transport.h
+++ b/pjsip/include/pjsip/sip_transport.h
@@ -1058,10 +1058,20 @@ PJ_DECL(pj_status_t) pjsip_transport_send( pjsip_transport *tr,
/**
- * This is a low-level function to send raw data using the specified transport
- * to the specified destination.
+ * This is a low-level function to send raw data to a destination.
*
- * @param tr The SIP transport to be used.
+ * 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.
* @param addr Destination address.
@@ -1079,14 +1089,16 @@ PJ_DECL(pj_status_t) pjsip_transport_send( pjsip_transport *tr,
* indicates immediate failure, and in this case the
* 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);
/**
* @}
diff --git a/pjsip/include/pjsip/sip_util.h b/pjsip/include/pjsip/sip_util.h
index 18c1ce7b..75112ccf 100644
--- a/pjsip/include/pjsip/sip_util.h
+++ b/pjsip/include/pjsip/sip_util.h
@@ -20,6 +20,7 @@
#define __PJSIP_SIP_MISC_H__
#include <pjsip/sip_msg.h>
+#include <pjsip/sip_transport.h>
#include <pjsip/sip_resolve.h>
PJ_BEGIN_DECL
@@ -219,7 +220,6 @@ PJ_DECL(pj_status_t) pjsip_get_request_dest(const pjsip_tx_data *tdata,
PJ_DECL(pj_status_t) pjsip_process_route_set(pjsip_tx_data *tdata,
pjsip_host_info *dest_info );
-
/**
* This structure holds the state of outgoing stateless request.
*/
@@ -258,8 +258,10 @@ typedef struct pjsip_send_state
pj_bool_t *cont);
} 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
* destination and transport to use based on the information in the message,
@@ -281,7 +283,81 @@ PJ_DECL(pj_status_t)
pjsip_endpt_send_request_stateless( pjsip_endpoint *endpt,
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);
/**
* This structure describes destination information to send response.
@@ -357,7 +433,7 @@ PJ_DECL(pj_status_t) pjsip_endpt_send_response( pjsip_endpoint *endpt,
pjsip_response_addr *res_addr,
pjsip_tx_data *tdata,
void *token,
- pjsip_endpt_callback cb);
+ pjsip_send_callback cb);
/**
* This is a convenient function which wraps #pjsip_get_response_addr() and
@@ -380,7 +456,7 @@ PJ_DECL(pj_status_t) pjsip_endpt_send_response2(pjsip_endpoint *endpt,
pjsip_rx_data *rdata,
pjsip_tx_data *tdata,
void *token,
- pjsip_endpt_callback cb);
+ pjsip_send_callback cb);
/**
* This composite function sends response message statelessly to an incoming
diff --git a/pjsip/src/pjsip/sip_transport.c b/pjsip/src/pjsip/sip_transport.c
index 331bc5f7..2305b53f 100644
--- a/pjsip/src/pjsip/sip_transport.c
+++ b/pjsip/src/pjsip/sip_transport.c
@@ -603,31 +603,77 @@ PJ_DEF(pj_status_t) pjsip_transport_send( pjsip_transport *tr,
}
+/* 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)
+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_tx_data *tdata;
+ 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 */
- tdata->buf.start = (char*) pj_pool_alloc(tdata->pool, data_len);
- tdata->buf.end = tdata->buf.start + data_len;
+ 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;
+ }
- /* 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;
/* Save callback data. */
@@ -637,13 +683,14 @@ PJ_DEF(pj_status_t) pjsip_transport_send_raw(pjsip_transport *tr,
/* Mark as pending. */
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);
}
return status;
diff --git a/pjsip/src/pjsip/sip_util.c b/pjsip/src/pjsip/sip_util.c
index 4aad8c2a..6b74d0c5 100644
--- a/pjsip/src/pjsip/sip_util.c
+++ b/pjsip/src/pjsip/sip_util.c
@@ -996,7 +996,7 @@ PJ_DEF(pj_status_t)
pjsip_endpt_send_request_stateless(pjsip_endpoint *endpt,
pjsip_tx_data *tdata,
void *token,
- pjsip_endpt_callback cb)
+ pjsip_send_callback cb)
{
pjsip_host_info dest_info;
pjsip_send_state *stateless_data;
@@ -1024,6 +1024,150 @@ pjsip_endpt_send_request_stateless(pjsip_endpoint *endpt,
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;
+}
+
+
/*
* Determine which address (and transport) to use to send response message
* based on the received request. This function follows the specification
@@ -1215,7 +1359,7 @@ PJ_DEF(pj_status_t) pjsip_endpt_send_response( pjsip_endpoint *endpt,
pjsip_response_addr *res_addr,
pjsip_tx_data *tdata,
void *token,
- pjsip_endpt_callback cb)
+ pjsip_send_callback cb)
{
/* Determine which transports and addresses to send the response,
* based on Section 18.2.2 of RFC 3261.
@@ -1264,7 +1408,7 @@ PJ_DEF(pj_status_t) pjsip_endpt_send_response2( pjsip_endpoint *endpt,
pjsip_rx_data *rdata,
pjsip_tx_data *tdata,
void *token,
- pjsip_endpt_callback cb)
+ pjsip_send_callback cb)
{
pjsip_response_addr res_addr;
pj_status_t status;