diff options
author | David M. Lee <dlee@digium.com> | 2013-01-07 14:24:28 -0600 |
---|---|---|
committer | David M. Lee <dlee@digium.com> | 2013-01-07 14:24:28 -0600 |
commit | f3ab456a17af1c89a6e3be4d20c5944853df1cb0 (patch) | |
tree | d00e1a332cd038a6d906a1ea0ac91e1a4458e617 /pjsip/src/pjsip/sip_util_statefull.c |
Import pjproject-2.0.1
Diffstat (limited to 'pjsip/src/pjsip/sip_util_statefull.c')
-rw-r--r-- | pjsip/src/pjsip/sip_util_statefull.c | 192 |
1 files changed, 192 insertions, 0 deletions
diff --git a/pjsip/src/pjsip/sip_util_statefull.c b/pjsip/src/pjsip/sip_util_statefull.c new file mode 100644 index 0000000..3212cab --- /dev/null +++ b/pjsip/src/pjsip/sip_util_statefull.c @@ -0,0 +1,192 @@ +/* $Id: sip_util_statefull.c 4169 2012-06-18 09:19:58Z nanang $ */ +/* + * Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com) + * Copyright (C) 2003-2008 Benny Prijono <benny@prijono.org> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +#include <pjsip/sip_util.h> +#include <pjsip/sip_module.h> +#include <pjsip/sip_endpoint.h> +#include <pjsip/sip_transaction.h> +#include <pjsip/sip_event.h> +#include <pjsip/sip_errno.h> +#include <pj/assert.h> +#include <pj/log.h> +#include <pj/pool.h> +#include <pj/string.h> + +struct tsx_data +{ + void *token; + void (*cb)(void*, pjsip_event*); +}; + +static void mod_util_on_tsx_state(pjsip_transaction*, pjsip_event*); + +/* This module will be registered in pjsip_endpt.c */ + +pjsip_module mod_stateful_util = +{ + NULL, NULL, /* prev, next. */ + { "mod-stateful-util", 17 }, /* Name. */ + -1, /* Id */ + PJSIP_MOD_PRIORITY_APPLICATION, /* Priority */ + NULL, /* load() */ + NULL, /* start() */ + NULL, /* stop() */ + NULL, /* unload() */ + NULL, /* on_rx_request() */ + NULL, /* on_rx_response() */ + NULL, /* on_tx_request. */ + NULL, /* on_tx_response() */ + &mod_util_on_tsx_state, /* on_tsx_state() */ +}; + +static void mod_util_on_tsx_state(pjsip_transaction *tsx, pjsip_event *event) +{ + struct tsx_data *tsx_data; + + /* Check if the module has been unregistered (see ticket #1535) and also + * verify the event type. + */ + if (mod_stateful_util.id < 0 || event->type != PJSIP_EVENT_TSX_STATE) + return; + + tsx_data = (struct tsx_data*) tsx->mod_data[mod_stateful_util.id]; + if (tsx_data == NULL) + return; + + if (tsx->status_code < 200) + return; + + /* Call the callback, if any, and prevent the callback to be called again + * by clearing the transaction's module_data. + */ + tsx->mod_data[mod_stateful_util.id] = NULL; + + if (tsx_data->cb) { + (*tsx_data->cb)(tsx_data->token, event); + } +} + + +PJ_DEF(pj_status_t) pjsip_endpt_send_request( pjsip_endpoint *endpt, + pjsip_tx_data *tdata, + pj_int32_t timeout, + void *token, + pjsip_endpt_send_callback cb) +{ + pjsip_transaction *tsx; + struct tsx_data *tsx_data; + pj_status_t status; + + PJ_ASSERT_RETURN(endpt && tdata && (timeout==-1 || timeout>0), PJ_EINVAL); + + /* Check that transaction layer module is registered to endpoint */ + PJ_ASSERT_RETURN(mod_stateful_util.id != -1, PJ_EINVALIDOP); + + PJ_UNUSED_ARG(timeout); + + status = pjsip_tsx_create_uac(&mod_stateful_util, tdata, &tsx); + if (status != PJ_SUCCESS) { + pjsip_tx_data_dec_ref(tdata); + return status; + } + + pjsip_tsx_set_transport(tsx, &tdata->tp_sel); + + tsx_data = PJ_POOL_ALLOC_T(tsx->pool, struct tsx_data); + tsx_data->token = token; + tsx_data->cb = cb; + + tsx->mod_data[mod_stateful_util.id] = tsx_data; + + status = pjsip_tsx_send_msg(tsx, NULL); + if (status != PJ_SUCCESS) + pjsip_tx_data_dec_ref(tdata); + + return status; +} + + +/* + * Send response statefully. + */ +PJ_DEF(pj_status_t) pjsip_endpt_respond( pjsip_endpoint *endpt, + pjsip_module *tsx_user, + pjsip_rx_data *rdata, + int st_code, + const pj_str_t *st_text, + const pjsip_hdr *hdr_list, + const pjsip_msg_body *body, + pjsip_transaction **p_tsx ) +{ + pj_status_t status; + pjsip_tx_data *tdata; + pjsip_transaction *tsx; + + /* Validate arguments. */ + PJ_ASSERT_RETURN(endpt && rdata, PJ_EINVAL); + + if (p_tsx) *p_tsx = NULL; + + /* Create response message */ + status = pjsip_endpt_create_response( endpt, rdata, st_code, st_text, + &tdata); + if (status != PJ_SUCCESS) + return status; + + /* Add the message headers, if any */ + if (hdr_list) { + const pjsip_hdr *hdr = hdr_list->next; + while (hdr != hdr_list) { + pjsip_msg_add_hdr(tdata->msg, (pjsip_hdr*) + pjsip_hdr_clone(tdata->pool, hdr) ); + hdr = hdr->next; + } + } + + /* Add the message body, if any. */ + if (body) { + tdata->msg->body = pjsip_msg_body_clone( tdata->pool, body ); + if (tdata->msg->body == NULL) { + pjsip_tx_data_dec_ref(tdata); + return status; + } + } + + /* Create UAS transaction. */ + status = pjsip_tsx_create_uas(tsx_user, rdata, &tsx); + if (status != PJ_SUCCESS) { + pjsip_tx_data_dec_ref(tdata); + return status; + } + + /* Feed the request to the transaction. */ + pjsip_tsx_recv_msg(tsx, rdata); + + /* Send the message. */ + status = pjsip_tsx_send_msg(tsx, tdata); + if (status != PJ_SUCCESS) { + pjsip_tx_data_dec_ref(tdata); + } else if (p_tsx) { + *p_tsx = tsx; + } + + return status; +} + + |