[asterisk-commits] file: branch file/gulp_transfer r387926 - /team/file/gulp_transfer/res/
SVN commits to the Asterisk project
asterisk-commits at lists.digium.com
Wed May 8 06:00:33 CDT 2013
Author: file
Date: Wed May 8 06:00:31 2013
New Revision: 387926
URL: http://svnview.digium.com/svn/asterisk?view=rev&rev=387926
Log:
Expose Replaces information to the dialplan for INVITE w/ Replaces when the dialog does not exist locally.
Modified:
team/file/gulp_transfer/res/res_sip_refer.c
Modified: team/file/gulp_transfer/res/res_sip_refer.c
URL: http://svnview.digium.com/svn/asterisk/team/file/gulp_transfer/res/res_sip_refer.c?view=diff&rev=387926&r1=387925&r2=387926
==============================================================================
--- team/file/gulp_transfer/res/res_sip_refer.c (original)
+++ team/file/gulp_transfer/res/res_sip_refer.c Wed May 8 06:00:31 2013
@@ -368,52 +368,6 @@
return 0;
}
-static int refer_incoming_attended_request(struct ast_sip_session *session, pjsip_rx_data *rdata, pjsip_param *replaces_param,
- struct refer_progress *progress)
-{
- const pj_str_t str_replaces = { "Replaces", 8 };
- pj_str_t replaces_content;
- pjsip_replaces_hdr *replaces;
- int parsed_len;
- pjsip_dialog *dlg;
-
- pj_strdup_with_null(rdata->tp_info.pool, &replaces_content, &replaces_param->value);
-
- /* Parsing the parameter as a Replaces header easily grabs the needed information */
- if (!(replaces = pjsip_parse_hdr(rdata->tp_info.pool, &str_replaces, replaces_content.ptr,
- pj_strlen(&replaces_content), &parsed_len))) {
- return 400;
- }
-
- /* See if the dialog is local, or remote */
- if ((dlg = pjsip_ua_find_dialog(&replaces->call_id, &replaces->to_tag, &replaces->from_tag, PJ_TRUE))) {
- RAII_VAR(struct ast_sip_session *, other_session, ast_sip_dialog_get_session(dlg), ao2_cleanup);
- struct refer_attended *attended;
-
- pjsip_dlg_dec_lock(dlg);
-
- if (!other_session) {
- return 603;
- }
-
- /* We defer actually doing the attended transfer to the other session so no deadlock can occur */
- if (!(attended = refer_attended_alloc(session, other_session, progress))) {
- return 500;
- }
-
- /* Push it to the other session, which will have both channels with minimal locking */
- if (ast_sip_push_task(other_session->serializer, refer_attended, attended)) {
- ao2_cleanup(attended);
- return 500;
- }
-
- return 200;
- } else {
- }
-
- return 0;
-}
-
/*! \brief Structure for blind transfer callback details */
struct refer_blind {
/*! \brief Context being used for transfer */
@@ -422,6 +376,10 @@
struct refer_progress *progress;
/*! \brief REFER message */
pjsip_rx_data *rdata;
+ /*! \brief Optional Replaces header */
+ pjsip_replaces_hdr *replaces;
+ /*! \brief Optional Refer-To header */
+ pjsip_sip_uri *refer_to;
};
/*! \brief Blind transfer callback function */
@@ -430,6 +388,8 @@
struct refer_blind *refer = user_data;
const pj_str_t str_referred_by = { "Referred-By", 11 };
pjsip_generic_string_hdr *referred_by = pjsip_msg_find_hdr_by_name(refer->rdata->msg_info.msg, &str_referred_by, NULL);
+
+ pbx_builtin_setvar_helper(chan, "SIPTRANSFER", "yes");
/* If progress monitoring is being done attach a frame hook so we can monitor it */
if (refer->progress) {
@@ -466,6 +426,96 @@
uri[referred_by->hvalue.slen] = '\0';
pbx_builtin_setvar_helper(chan, "SIPREFERREDBYHDR", uri);
}
+
+ if (refer->replaces) {
+ char replaces[512];
+
+ pjsip_hdr_print_on(refer->replaces, replaces, sizeof(replaces));
+ pbx_builtin_setvar_helper(chan, "SIPREPLACESHDR", replaces);
+ }
+
+ if (refer->refer_to) {
+ char refer_to[PJSIP_MAX_URL_SIZE];
+
+ pjsip_uri_print(PJSIP_URI_IN_REQ_URI, refer->refer_to, refer_to, sizeof(refer_to));
+ pbx_builtin_setvar_helper(chan, "SIPREFERTOHDR", refer_to);
+ }
+}
+
+static int refer_incoming_attended_request(struct ast_sip_session *session, pjsip_rx_data *rdata, pjsip_sip_uri *target_uri,
+ pjsip_param *replaces_param, struct refer_progress *progress)
+{
+ const pj_str_t str_replaces = { "Replaces", 8 };
+ pj_str_t replaces_content;
+ pjsip_replaces_hdr *replaces;
+ int parsed_len;
+ pjsip_dialog *dlg;
+
+ pj_strdup_with_null(rdata->tp_info.pool, &replaces_content, &replaces_param->value);
+
+ /* Parsing the parameter as a Replaces header easily grabs the needed information */
+ if (!(replaces = pjsip_parse_hdr(rdata->tp_info.pool, &str_replaces, replaces_content.ptr,
+ pj_strlen(&replaces_content), &parsed_len))) {
+ return 400;
+ }
+
+ /* See if the dialog is local, or remote */
+ if ((dlg = pjsip_ua_find_dialog(&replaces->call_id, &replaces->to_tag, &replaces->from_tag, PJ_TRUE))) {
+ RAII_VAR(struct ast_sip_session *, other_session, ast_sip_dialog_get_session(dlg), ao2_cleanup);
+ struct refer_attended *attended;
+
+ pjsip_dlg_dec_lock(dlg);
+
+ if (!other_session) {
+ return 603;
+ }
+
+ /* We defer actually doing the attended transfer to the other session so no deadlock can occur */
+ if (!(attended = refer_attended_alloc(session, other_session, progress))) {
+ return 500;
+ }
+
+ /* Push it to the other session, which will have both channels with minimal locking */
+ if (ast_sip_push_task(other_session->serializer, refer_attended, attended)) {
+ ao2_cleanup(attended);
+ return 500;
+ }
+
+ return 200;
+ } else {
+ const char *context = (session->channel ? pbx_builtin_getvar_helper(session->channel, "TRANSFER_CONTEXT") : "");
+ struct refer_blind refer;
+
+ if (ast_strlen_zero(context)) {
+ context = session->endpoint->context;
+ }
+
+ if (!ast_exists_extension(NULL, context, "external_replaces", 1, NULL)) {
+ return 404;
+ }
+
+ refer.context = context;
+ refer.progress = progress;
+ refer.rdata = rdata;
+ refer.replaces = replaces;
+ refer.refer_to = target_uri;
+
+ switch (ast_bridge_transfer_blind(session->channel, "external_replaces", context, refer_blind_callback, &refer)) {
+ case AST_BRIDGE_TRANSFER_INVALID:
+ return 503;
+ case AST_BRIDGE_TRANSFER_NOT_PERMITTED:
+ return 403;
+ case AST_BRIDGE_TRANSFER_FAIL:
+ return 500;
+ case AST_BRIDGE_TRANSFER_SUCCESS:
+ session->defer_terminate = 1;
+ return 200;
+ }
+
+ return 503;
+ }
+
+ return 0;
}
static int refer_incoming_blind_request(struct ast_sip_session *session, pjsip_rx_data *rdata, pjsip_sip_uri *target,
@@ -518,6 +568,10 @@
pjsip_param *replaces;
int response;
+ if (pjsip_method_cmp(&rdata->msg_info.msg->line.req.method, pjsip_get_refer_method())) {
+ return 0;
+ }
+
/* A Refer-To header is required */
if (!(refer_to = pjsip_msg_find_hdr_by_name(rdata->msg_info.msg, &str_refer_to, NULL))) {
pjsip_dlg_respond(session->inv_session->dlg, rdata, 400, NULL, NULL, NULL);
@@ -546,7 +600,7 @@
/* Determine if this is an attended or blind transfer */
if ((replaces = pjsip_param_find(&target_uri->header_param, &str_replaces)) ||
(replaces = pjsip_param_find(&target_uri->other_param, &str_replaces))) {
- response = refer_incoming_attended_request(session, rdata, replaces, progress);
+ response = refer_incoming_attended_request(session, rdata, target_uri, replaces, progress);
} else {
response = refer_incoming_blind_request(session, rdata, target_uri, progress);
}
@@ -580,9 +634,23 @@
return 0;
}
+static void refer_outgoing_request(struct ast_sip_session *session, struct pjsip_tx_data *tdata)
+{
+ const char *replaces;
+
+ if (pjsip_method_cmp(&tdata->msg->line.req.method, &pjsip_invite_method) ||
+ !session->channel ||
+ (ast_channel_state(session->channel) != AST_STATE_DOWN) ||
+ !(replaces = pbx_builtin_getvar_helper(session->channel, "SIPREPLACESHDR"))) {
+ return;
+ }
+
+ ast_sip_add_header(tdata, "Replaces", replaces);
+}
+
static struct ast_sip_session_supplement refer_supplement = {
- .method = "REFER",
.incoming_request = refer_incoming_request,
+ .outgoing_request = refer_outgoing_request,
};
static int load_module(void)
More information about the asterisk-commits
mailing list