From a64cd7c6bbd8bc54dd68cb54447dabd37bfe2437 Mon Sep 17 00:00:00 2001 From: Joshua Colp Date: Thu, 28 Nov 2013 00:38:36 +0000 Subject: res_pjsip_session: Add configurable behavior for redirects. The action taken when a redirect occurs is now configurable on a per-endpoint basis. The redirect can either be treated as a redirect to a local extension, to a URI that is dialed through the Asterisk core, or to a URI that is dialed within PJSIP itself. (closes issue ASTERISK-21710) Reported by: Matt Jordan Review: https://reviewboard.asterisk.org/r/2963/ ........ Merged revisions 403207 from http://svn.asterisk.org/svn/asterisk/branches/12 git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@403208 65c4cc65-6c06-0410-ace0-fbb531ad65f3 --- res/res_pjsip.c | 21 +++++++++++++++++++++ res/res_pjsip/pjsip_configuration.c | 20 ++++++++++++++++++++ res/res_pjsip_session.c | 22 ++++++++++++++++++++-- 3 files changed, 61 insertions(+), 2 deletions(-) (limited to 'res') diff --git a/res/res_pjsip.c b/res/res_pjsip.c index db4f32f2c..37762e6cf 100644 --- a/res/res_pjsip.c +++ b/res/res_pjsip.c @@ -244,6 +244,27 @@ + + How redirects received from an endpoint are handled + + When a redirect is received from an endpoint there are multiple ways it can be handled. + If this option is set to user the user portion of the redirect target + is treated as an extension within the dialplan and dialed using a Local channel. If this option + is set to uri_core the target URI is returned to the dialing application + which dials it using the PJSIP channel driver and endpoint originally used. If this option is + set to uri_pjsip the redirect occurs within chan_pjsip itself and is not exposed + to the core at all. The uri_pjsip option has the benefit of being more efficient + and also supporting multiple potential redirect targets. The con is that since redirection occurs + within chan_pjsip redirecting information is not forwarded and redirection can not be + prevented. + + + + + + + + Mailbox(es) to be associated with diff --git a/res/res_pjsip/pjsip_configuration.c b/res/res_pjsip/pjsip_configuration.c index 4642c5e66..835dbfbf6 100644 --- a/res/res_pjsip/pjsip_configuration.c +++ b/res/res_pjsip/pjsip_configuration.c @@ -455,6 +455,25 @@ static int ident_to_str(const void *obj, const intptr_t *args, char **buf) return 0; } +static int redirect_handler(const struct aco_option *opt, struct ast_variable *var, void *obj) +{ + struct ast_sip_endpoint *endpoint = obj; + + if (!strcasecmp(var->value, "user")) { + endpoint->redirect_method = AST_SIP_REDIRECT_USER; + } else if (!strcasecmp(var->value, "uri_core")) { + endpoint->redirect_method = AST_SIP_REDIRECT_URI_CORE; + } else if (!strcasecmp(var->value, "uri_pjsip")) { + endpoint->redirect_method = AST_SIP_REDIRECT_URI_PJSIP; + } else { + ast_log(LOG_ERROR, "Unrecognized redirect method %s specified for endpoint %s\n", + var->value, ast_sorcery_object_get_id(endpoint)); + return -1; + } + + return 0; +} + static int direct_media_method_handler(const struct aco_option *opt, struct ast_variable *var, void *obj) { struct ast_sip_endpoint *endpoint = obj; @@ -1353,6 +1372,7 @@ int ast_res_pjsip_initialize_configuration(const struct ast_module_info *ast_mod ast_sorcery_object_field_register_custom(sip_sorcery, "endpoint", "dtls_ca_path", "", dtls_handler, dtlscapath_to_str, 0, 0); ast_sorcery_object_field_register_custom(sip_sorcery, "endpoint", "dtls_setup", "", dtls_handler, dtlssetup_to_str, 0, 0); ast_sorcery_object_field_register(sip_sorcery, "endpoint", "srtp_tag_32", "no", OPT_BOOL_T, 1, FLDSET(struct ast_sip_endpoint, media.rtp.srtp_tag_32)); + ast_sorcery_object_field_register_custom(sip_sorcery, "endpoint", "redirect_method", "user", redirect_handler, NULL, 0, 0); if (ast_sip_initialize_sorcery_transport(sip_sorcery)) { ast_log(LOG_ERROR, "Failed to register SIP transport support with sorcery\n"); diff --git a/res/res_pjsip_session.c b/res/res_pjsip_session.c index f44ec4422..065f40d4e 100644 --- a/res/res_pjsip_session.c +++ b/res/res_pjsip_session.c @@ -2065,13 +2065,31 @@ static void session_inv_on_media_update(pjsip_inv_session *inv, pj_status_t stat static pjsip_redirect_op session_inv_on_redirected(pjsip_inv_session *inv, const pjsip_uri *target, const pjsip_event *e) { struct ast_sip_session *session = inv->mod_data[session_module.id]; + const pjsip_sip_uri *uri; - if (PJSIP_URI_SCHEME_IS_SIP(target) || PJSIP_URI_SCHEME_IS_SIPS(target)) { - const pjsip_sip_uri *uri = pjsip_uri_get_uri(target); + if (session->endpoint->redirect_method == AST_SIP_REDIRECT_URI_PJSIP) { + return PJSIP_REDIRECT_ACCEPT; + } + + if (!PJSIP_URI_SCHEME_IS_SIP(target) && !PJSIP_URI_SCHEME_IS_SIPS(target)) { + return PJSIP_REDIRECT_STOP; + } + + uri = pjsip_uri_get_uri(target); + + if (session->endpoint->redirect_method == AST_SIP_REDIRECT_USER) { char exten[AST_MAX_EXTENSION]; ast_copy_pj_str(exten, &uri->user, sizeof(exten)); ast_channel_call_forward_set(session->channel, exten); + } else if (session->endpoint->redirect_method == AST_SIP_REDIRECT_URI_CORE) { + char target_uri[PJSIP_MAX_URL_SIZE]; + /* PJSIP/ + endpoint length + / + max URL size */ + char forward[8 + strlen(ast_sorcery_object_get_id(session->endpoint)) + PJSIP_MAX_URL_SIZE]; + + pjsip_uri_print(PJSIP_URI_IN_REQ_URI, uri, target_uri, sizeof(target_uri)); + sprintf(forward, "PJSIP/%s/%s", ast_sorcery_object_get_id(session->endpoint), target_uri); + ast_channel_call_forward_set(session->channel, forward); } return PJSIP_REDIRECT_STOP; -- cgit v1.2.3