diff options
author | Benny Prijono <bennylp@teluu.com> | 2007-06-23 07:26:54 +0000 |
---|---|---|
committer | Benny Prijono <bennylp@teluu.com> | 2007-06-23 07:26:54 +0000 |
commit | dd49a84c46ef7ea0cb755bfa8e78e6395f544c4e (patch) | |
tree | abece2181d854eb6f19ad6a1b7bee7fb0849c7a7 /pjsip | |
parent | de1e9a2df94e4a20bbf41f5edd241bfbdacd9b7f (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.h | 34 | ||||
-rw-r--r-- | pjsip/include/pjsip/sip_util.h | 88 | ||||
-rw-r--r-- | pjsip/src/pjsip/sip_transport.c | 83 | ||||
-rw-r--r-- | pjsip/src/pjsip/sip_util.c | 150 |
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; |