Asterisk - The Open Source Telephony Project GIT-master-0a46be9
Data Structures | Enumerations | Functions | Variables
res_pjsip_diversion.c File Reference
#include "asterisk.h"
#include <pjsip.h>
#include <pjsip_ua.h>
#include "asterisk/res_pjsip.h"
#include "asterisk/res_pjsip_session.h"
#include "asterisk/callerid.h"
#include "asterisk/channel.h"
#include "asterisk/module.h"
#include "asterisk/strings.h"
Include dependency graph for res_pjsip_diversion.c:

Go to the source code of this file.

Data Structures

struct  reasons
 Diversion header reasons. More...
 

Enumerations

enum  pjsip_diversion_send_update { PJSIP_DIVERSION_NOSEND_UPDATE = 0 , PJSIP_DIVERSION_SEND_UPDATE = 1 }
 

Functions

static void __reg_module (void)
 
static void __unreg_module (void)
 
static void add_diversion_header (pjsip_tx_data *tdata, struct ast_party_redirecting *data)
 
static void add_history_info_header (pjsip_tx_data *tdata, struct ast_party_redirecting *data)
 
static int add_supported (pjsip_tx_data *tdata)
 
struct ast_moduleAST_MODULE_SELF_SYM (void)
 
static enum AST_REDIRECTING_REASON cause_to_reason (const unsigned long cause)
 
static void copy_redirecting_id (struct ast_party_id *dst, const struct ast_party_id *src, struct ast_set_party_id *update)
 
static int diversion_incoming_request (struct ast_sip_session *session, pjsip_rx_data *rdata)
 
static void diversion_incoming_response (struct ast_sip_session *session, pjsip_rx_data *rdata, pjsip_diversion_send_update send_update)
 
static void diversion_incoming_response_media (struct ast_sip_session *session, pjsip_rx_data *rdata)
 
static void diversion_incoming_response_redirecting (struct ast_sip_session *session, pjsip_rx_data *rdata)
 
static void diversion_outgoing_request (struct ast_sip_session *session, pjsip_tx_data *tdata)
 
static void diversion_outgoing_response (struct ast_sip_session *session, pjsip_tx_data *tdata)
 
static pjsip_fromto_hdr * get_diversion_header (pjsip_rx_data *rdata)
 
static pjsip_fromto_hdr * get_history_info_header (pjsip_rx_data *rdata, const unsigned int first)
 
static void get_redirecting_add_diversion (struct ast_sip_session *session, pjsip_tx_data *tdata)
 
static int load_module (void)
 
static const unsigned int reason_code_to_cause (const struct ast_party_redirecting_reason *reason)
 
static const char * reason_code_to_str (const struct ast_party_redirecting_reason *reason)
 
static void set_redirecting (struct ast_sip_session *session, pjsip_fromto_hdr *from_info, pjsip_name_addr *to_info, pjsip_diversion_send_update send_update)
 
static void set_redirecting_id (pjsip_name_addr *name_addr, struct ast_party_id *data, struct ast_set_party_id *update)
 
static void set_redirecting_reason (pjsip_fromto_hdr *from_info, pjsip_name_addr *to_info, struct ast_party_redirecting_reason *data)
 
static void set_redirecting_reason_by_cause (pjsip_name_addr *name_addr, struct ast_party_redirecting_reason *data)
 
static void set_redirecting_value (char **dst, const pj_str_t *src)
 
static int sip_is_token (const char *str)
 
static int unload_module (void)
 

Variables

static struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_LOAD_ORDER , .description = "PJSIP Add Diversion Header Support" , .key = "This paragraph is copyright (c) 2006 by Digium, Inc. \In order for your module to load, it must return this \key via a function called \"key\". Any code which \includes this paragraph must be licensed under the GNU \General Public License version 2 or later (at your \option). In addition to Digium's general reservations \of rights, Digium expressly reserves the right to \allow other parties to license this paragraph under \different terms. Any use of Digium, Inc. trademarks or \logos (including \"Asterisk\" or \"Digium\") without \express written permission of Digium, Inc. is prohibited.\n" , .buildopt_sum = AST_BUILDOPT_SUM, .support_level = AST_MODULE_SUPPORT_CORE, .load = load_module, .unload = unload_module, .load_pri = AST_MODPRI_APP_DEPEND, .requires = "res_pjsip,res_pjsip_session", }
 
static const struct ast_module_infoast_module_info = &__mod_info
 
static const pj_str_t diversion_name = { "Diversion", 9 }
 
static struct ast_sip_session_supplement diversion_supplement_media
 
static struct ast_sip_session_supplement diversion_supplement_redirecting
 
static pj_str_t HISTINFO_SUPPORTED_NAME = { "histinfo", 8 }
 
static const pj_str_t history_info_name = { "History-Info", 12 }
 
static const struct reasons reason_table []
 

Enumeration Type Documentation

◆ pjsip_diversion_send_update

Enumerator
PJSIP_DIVERSION_NOSEND_UPDATE 
PJSIP_DIVERSION_SEND_UPDATE 

Definition at line 45 of file res_pjsip_diversion.c.

Function Documentation

◆ __reg_module()

static void __reg_module ( void  )
static

Definition at line 762 of file res_pjsip_diversion.c.

◆ __unreg_module()

static void __unreg_module ( void  )
static

Definition at line 762 of file res_pjsip_diversion.c.

◆ add_diversion_header()

static void add_diversion_header ( pjsip_tx_data *  tdata,
struct ast_party_redirecting data 
)
static

Definition at line 527 of file res_pjsip_diversion.c.

528{
529 static const pj_str_t reason_name = { "reason", 6 };
530
531 pjsip_fromto_hdr *hdr;
532 pjsip_name_addr *name_addr;
533 pjsip_param *param;
534 pjsip_fromto_hdr *old_hdr;
535 const char *reason_str;
536 const char *quote_str;
537 char *reason_buf;
538 pjsip_uri *base;
539
540 struct ast_party_id *id = NULL;
541 if (tdata->msg->type == PJSIP_REQUEST_MSG) {
542 id = &data->from;
543 } else {
544 /* In responses indicate the new destination */
545 id = &data->to;
546 }
547
548 base = PJSIP_MSG_FROM_HDR(tdata->msg)->uri;
549
550 if (!id->number.valid || ast_strlen_zero(id->number.str)) {
551 return;
552 }
553
554 hdr = pjsip_from_hdr_create(tdata->pool);
555 hdr->type = PJSIP_H_OTHER;
556 hdr->sname = hdr->name = diversion_name;
557
558 name_addr = pjsip_uri_clone(tdata->pool, base);
559
560 pj_strdup2(tdata->pool, &name_addr->display, id->name.str);
561 pj_strdup2(tdata->pool, (pj_str_t *)ast_sip_pjsip_uri_get_username(name_addr->uri), id->number.str);
562
563 param = PJ_POOL_ALLOC_T(tdata->pool, pjsip_param);
564 param->name = reason_name;
565
566 reason_str = reason_code_to_str(&data->reason);
567
568 /* Reason is either already quoted or it is a token to not need quotes added. */
569 quote_str = *reason_str == '\"' || sip_is_token(reason_str) ? "" : "\"";
570
571 reason_buf = pj_pool_alloc(tdata->pool, strlen(reason_str) + 3);
572 sprintf(reason_buf, "%s%s%s", quote_str, reason_str, quote_str);/* Safe */
573
574 param->value = pj_str(reason_buf);
575
576 pj_list_insert_before(&hdr->other_param, param);
577
578 hdr->uri = (pjsip_uri *) name_addr;
579 old_hdr = pjsip_msg_find_hdr_by_name(tdata->msg, &diversion_name, NULL);
580 if (old_hdr) {
581 pj_list_erase(old_hdr);
582 }
583 pjsip_msg_add_hdr(tdata->msg, (pjsip_hdr *)hdr);
584}
enum queue_result id
Definition: app_queue.c:1764
const pj_str_t * ast_sip_pjsip_uri_get_username(pjsip_uri *uri)
Get the user portion of the pjsip_uri.
Definition: res_pjsip.c:3477
static const pj_str_t diversion_name
static const char * reason_code_to_str(const struct ast_party_redirecting_reason *reason)
static int sip_is_token(const char *str)
#define NULL
Definition: resample.c:96
static force_inline int attribute_pure ast_strlen_zero(const char *s)
Definition: strings.h:65
Information needed to identify an endpoint in a call.
Definition: channel.h:340
struct ast_party_redirecting_reason reason
Reason for the redirection.
Definition: channel.h:544
struct ast_party_id from
Who is redirecting the call (Sent to the party the call is redirected toward)
Definition: channel.h:529
struct ast_party_id to
Call is redirecting to a new party (Sent to the caller)
Definition: channel.h:532

References ast_sip_pjsip_uri_get_username(), ast_strlen_zero(), diversion_name, ast_party_redirecting::from, id, NULL, ast_party_redirecting::reason, reason_code_to_str(), sip_is_token(), and ast_party_redirecting::to.

Referenced by get_redirecting_add_diversion().

◆ add_history_info_header()

static void add_history_info_header ( pjsip_tx_data *  tdata,
struct ast_party_redirecting data 
)
static

Definition at line 593 of file res_pjsip_diversion.c.

594{
595 static const pj_str_t index_name = { "index", 5 };
596 static const pj_str_t cause_name = { "cause", 5 };
597 static const pj_str_t first_index = { "1", 1 };
598 static const pj_str_t last_index = { "1.1", 3 };
599
600 pjsip_fromto_hdr *hdr;
601 pjsip_name_addr *name_addr;
602 pjsip_sip_uri *uri;
603 pjsip_param *param;
604 pjsip_fromto_hdr *old_hdr;
605 unsigned int cause;
606 char *cause_buf;
607
608 struct ast_party_id *to = &data->to;
609 struct ast_party_id *from = &data->from;
610
611 pjsip_uri *base = PJSIP_MSG_TO_HDR(tdata->msg)->uri;
612
613
614 hdr = pjsip_from_hdr_create(tdata->pool);
615 hdr->type = PJSIP_H_OTHER;
616 hdr->sname = hdr->name = history_info_name;
617
618 name_addr = pjsip_uri_clone(tdata->pool, base);
619 uri = pjsip_uri_get_uri(name_addr->uri);
620
621 /* if no redirecting information, then TO is the original destination */
622 if (from->number.valid && !ast_strlen_zero(from->number.str)) {
623 pj_strdup2(tdata->pool, &name_addr->display, from->name.str);
624 pj_strdup2(tdata->pool, &uri->user, from->number.str);
625 }
626
627 param = PJ_POOL_ALLOC_T(tdata->pool, pjsip_param);
628 param->name = index_name;
629 param->value = first_index;
630
631
632 pj_list_insert_before(&hdr->other_param, param);
633 hdr->uri = (pjsip_uri *) name_addr;
634
635 while ((old_hdr = pjsip_msg_find_hdr_by_name(tdata->msg, &history_info_name, NULL)) != NULL) {
636 pj_list_erase(old_hdr);
637 }
638
639 pjsip_msg_add_hdr(tdata->msg, (pjsip_hdr *)hdr);
640
641 if (!to->number.valid || ast_strlen_zero(to->number.str)) {
642 return;
643 }
644
645 hdr = pjsip_from_hdr_create(tdata->pool);
646 hdr->type = PJSIP_H_OTHER;
647 hdr->sname = hdr->name = history_info_name;
648
649 name_addr = pjsip_uri_clone(tdata->pool, base);
650 uri = pjsip_uri_get_uri(name_addr->uri);
651
652 pj_strdup2(tdata->pool, &name_addr->display, to->name.str);
653 pj_strdup2(tdata->pool, &uri->user, to->number.str);
654
655 param = PJ_POOL_ALLOC_T(tdata->pool, pjsip_param);
656 param->name = index_name;
657 param->value = last_index;
658 pj_list_insert_before(&hdr->other_param, param);
659
660 param = PJ_POOL_ALLOC_T(tdata->pool, pjsip_param);
661 param->name = cause_name;
662 cause = reason_code_to_cause(&data->reason);
663 cause_buf = pj_pool_alloc(tdata->pool, 4);
664 snprintf(cause_buf, 4, "%ud", cause);
665 param->value = pj_str(cause_buf);
666 pj_list_insert_before(&uri->other_param, param);
667 hdr->uri = (pjsip_uri *) name_addr;
668
669 pjsip_msg_add_hdr(tdata->msg, (pjsip_hdr *)hdr);
670}
static const unsigned int reason_code_to_cause(const struct ast_party_redirecting_reason *reason)
static const pj_str_t history_info_name
struct ast_party_name name
Subscriber name.
Definition: channel.h:342
struct ast_party_number number
Subscriber phone number.
Definition: channel.h:344
char * str
Subscriber name (Malloced)
Definition: channel.h:266
unsigned char valid
TRUE if the number information is valid/present.
Definition: channel.h:299
char * str
Subscriber phone number (Malloced)
Definition: channel.h:293

References ast_strlen_zero(), ast_party_redirecting::from, history_info_name, ast_party_id::name, NULL, ast_party_id::number, ast_party_redirecting::reason, reason_code_to_cause(), ast_party_name::str, ast_party_number::str, ast_party_redirecting::to, and ast_party_number::valid.

Referenced by get_redirecting_add_diversion().

◆ add_supported()

static int add_supported ( pjsip_tx_data *  tdata)
static

Definition at line 128 of file res_pjsip_diversion.c.

129{
130 pjsip_supported_hdr *hdr;
131 unsigned int i;
132
133 hdr = pjsip_msg_find_hdr(tdata->msg, PJSIP_H_SUPPORTED, NULL);
134 if (!hdr) {
135 /* insert a new Supported header */
136 hdr = pjsip_supported_hdr_create(tdata->pool);
137 if (!hdr) {
138 return -1;
139 }
140
141 pjsip_msg_add_hdr(tdata->msg, (pjsip_hdr *)hdr);
142 }
143
144 /* Asterisk can send multiple "181 Call forwarded" in a single session,
145 * we might have already modified Supported before
146 */
147 for (i = 0; i < hdr->count; ++i) {
148 if (pj_stricmp(&hdr->values[i], &HISTINFO_SUPPORTED_NAME) == 0) {
149 return 0;
150 }
151 }
152
153 if (hdr->count >= PJSIP_GENERIC_ARRAY_MAX_COUNT) {
154 return -1;
155 }
156
157 /* add on to the existing Supported header */
158 pj_strassign(&hdr->values[hdr->count++], &HISTINFO_SUPPORTED_NAME);
159
160 return 0;
161}
static pj_str_t HISTINFO_SUPPORTED_NAME

References HISTINFO_SUPPORTED_NAME, and NULL.

Referenced by get_redirecting_add_diversion().

◆ AST_MODULE_SELF_SYM()

struct ast_module * AST_MODULE_SELF_SYM ( void  )

Definition at line 762 of file res_pjsip_diversion.c.

◆ cause_to_reason()

static enum AST_REDIRECTING_REASON cause_to_reason ( const unsigned long  cause)
static

Definition at line 110 of file res_pjsip_diversion.c.

110 {
111 switch(cause) {
112 case 302:
114 case 486:
116 case 408:
118 case 480:
119 case 487:
121 case 503:
123 default:
125 }
126}
@ AST_REDIRECTING_REASON_UNKNOWN
Definition: callerid.h:499
@ AST_REDIRECTING_REASON_NO_ANSWER
Definition: callerid.h:501
@ AST_REDIRECTING_REASON_DEFLECTION
Definition: callerid.h:506
@ AST_REDIRECTING_REASON_UNAVAILABLE
Definition: callerid.h:502
@ AST_REDIRECTING_REASON_UNCONDITIONAL
Definition: callerid.h:503
@ AST_REDIRECTING_REASON_USER_BUSY
Definition: callerid.h:500

References AST_REDIRECTING_REASON_DEFLECTION, AST_REDIRECTING_REASON_NO_ANSWER, AST_REDIRECTING_REASON_UNAVAILABLE, AST_REDIRECTING_REASON_UNCONDITIONAL, AST_REDIRECTING_REASON_UNKNOWN, and AST_REDIRECTING_REASON_USER_BUSY.

Referenced by set_redirecting_reason_by_cause().

◆ copy_redirecting_id()

static void copy_redirecting_id ( struct ast_party_id dst,
const struct ast_party_id src,
struct ast_set_party_id update 
)
static

Definition at line 320 of file res_pjsip_diversion.c.

322{
323 ast_party_id_copy(dst, src);
324
325 if (dst->number.valid) {
326 update->number = 1;
327 }
328
329 if (dst->name.valid) {
330 update->name = 1;
331 }
332}
void ast_party_id_copy(struct ast_party_id *dest, const struct ast_party_id *src)
Copy the source party id information to the destination party id.
Definition: channel.c:1733
static void update(int code_size, int y, int wi, int fi, int dq, int sr, int dqsez, struct g726_state *state_ptr)
Definition: codec_g726.c:367
unsigned char valid
TRUE if the name information is valid/present.
Definition: channel.h:281

References ast_party_id_copy(), ast_party_id::name, ast_party_id::number, update(), ast_party_name::valid, and ast_party_number::valid.

Referenced by set_redirecting().

◆ diversion_incoming_request()

static int diversion_incoming_request ( struct ast_sip_session session,
pjsip_rx_data *  rdata 
)
static

Definition at line 436 of file res_pjsip_diversion.c.

437{
438 pjsip_fromto_hdr *hdr = get_diversion_header(rdata);
439
440 if (hdr) {
441 set_redirecting(session, hdr, (pjsip_name_addr*)
442 PJSIP_MSG_TO_HDR(rdata->msg_info.msg)->uri, PJSIP_DIVERSION_SEND_UPDATE);
443 } else {
444 pjsip_fromto_hdr *history_info_to;
445 pjsip_fromto_hdr *history_info_from;
446 history_info_to = get_history_info_header(rdata, 0);
447
448 if (history_info_to) {
449 /* If History-Info is present, then it will also include the original
450 redirected-from in addition to the redirected-to */
451 history_info_from = get_history_info_header(rdata, 1);
452 set_redirecting(session, history_info_from, (pjsip_name_addr*)history_info_to->uri, PJSIP_DIVERSION_SEND_UPDATE);
453 }
454 }
455
456 return 0;
457}
static struct ast_mansession session
static pjsip_fromto_hdr * get_history_info_header(pjsip_rx_data *rdata, const unsigned int first)
static pjsip_fromto_hdr * get_diversion_header(pjsip_rx_data *rdata)
static void set_redirecting(struct ast_sip_session *session, pjsip_fromto_hdr *from_info, pjsip_name_addr *to_info, pjsip_diversion_send_update send_update)

References get_diversion_header(), get_history_info_header(), PJSIP_DIVERSION_SEND_UPDATE, session, and set_redirecting().

◆ diversion_incoming_response()

static void diversion_incoming_response ( struct ast_sip_session session,
pjsip_rx_data *  rdata,
pjsip_diversion_send_update  send_update 
)
static

Definition at line 459 of file res_pjsip_diversion.c.

460{
461 static const pj_str_t contact_name = { "Contact", 7 };
462 static const pj_str_t contact_name_s = { "m", 1 };
463
464 pjsip_status_line status = rdata->msg_info.msg->line.status;
465 pjsip_fromto_hdr *div_hdr;
466 pjsip_fromto_hdr *history_info_to;
467 pjsip_fromto_hdr *history_info_from;
468 pjsip_contact_hdr *contact_hdr;
469
470 if ((status.code != 302) && (status.code != 181)) {
471 return;
472 }
473
474 /* use the diversion header info if there is one. if not one then use the
475 the history-info, if that doesn't exist, use session caller id info. if
476 that doesn't exist use info from the To hdr*/
477 if (!(div_hdr = get_diversion_header(rdata))) {
478 history_info_to = get_history_info_header(rdata, 0);
479
480 if (history_info_to) {
481 /* If History-Info is present, then it will also include the original
482 redirected-from in addition to the redirected-to */
483 history_info_from = get_history_info_header(rdata, 1);
484 set_redirecting(session, history_info_from, (pjsip_name_addr*)history_info_to->uri, send_update);
485 return;
486 }
487 if (!div_hdr && !session->id.number.valid) {
488 div_hdr = PJSIP_MSG_TO_HDR(rdata->msg_info.msg);
489 }
490 }
491
492
493 if (status.code == 302) {
494 /* With 302, Contact indicates the final destination and possibly Diversion indicates the hop before */
495 contact_hdr = pjsip_msg_find_hdr_by_names(rdata->msg_info.msg, &contact_name, &contact_name_s, NULL);
496 set_redirecting(session, div_hdr, contact_hdr ? (pjsip_name_addr*)contact_hdr->uri :
497 (pjsip_name_addr*)PJSIP_MSG_FROM_HDR(rdata->msg_info.msg)->uri, send_update);
498 } else {
499 /* With 181, Diversion is non-standard, but if present indicates the new final destination, and To indicating the original */
500 set_redirecting(session, PJSIP_MSG_TO_HDR(rdata->msg_info.msg),
501 div_hdr ? (pjsip_name_addr*)div_hdr->uri : NULL, send_update);
502 }
503}
jack_status_t status
Definition: app_jack.c:149

References get_diversion_header(), get_history_info_header(), NULL, session, set_redirecting(), and status.

Referenced by diversion_incoming_response_media(), and diversion_incoming_response_redirecting().

◆ diversion_incoming_response_media()

static void diversion_incoming_response_media ( struct ast_sip_session session,
pjsip_rx_data *  rdata 
)
static

Definition at line 505 of file res_pjsip_diversion.c.

506{
507 /* Trigger an update if the event is triggered by the PJSIP AST_SIP_SESSION_BEFORE_MEDIA callback */
509 return;
510}
static void diversion_incoming_response(struct ast_sip_session *session, pjsip_rx_data *rdata, pjsip_diversion_send_update send_update)

References diversion_incoming_response(), PJSIP_DIVERSION_SEND_UPDATE, and session.

◆ diversion_incoming_response_redirecting()

static void diversion_incoming_response_redirecting ( struct ast_sip_session session,
pjsip_rx_data *  rdata 
)
static

Definition at line 512 of file res_pjsip_diversion.c.

513{
514 /* Don't trigger an update if the event is triggered by the PJSIP AST_SIP_SESSION_REDIRECTING callback
515 otherwise, we will send a duplicate 181 to the UAC */
517 return;
518}

References diversion_incoming_response(), PJSIP_DIVERSION_NOSEND_UPDATE, and session.

◆ diversion_outgoing_request()

static void diversion_outgoing_request ( struct ast_sip_session session,
pjsip_tx_data *  tdata 
)
static

Definition at line 696 of file res_pjsip_diversion.c.

697{
699}
static void get_redirecting_add_diversion(struct ast_sip_session *session, pjsip_tx_data *tdata)

References get_redirecting_add_diversion(), and session.

◆ diversion_outgoing_response()

static void diversion_outgoing_response ( struct ast_sip_session session,
pjsip_tx_data *  tdata 
)
static

Definition at line 708 of file res_pjsip_diversion.c.

709{
710 struct pjsip_status_line status = tdata->msg->line.status;
711
712 /* add to 302 and 181 */
713 if (PJSIP_IS_STATUS_IN_CLASS(status.code, 300) || (status.code == 181)) {
715 }
716}

References get_redirecting_add_diversion(), session, and status.

◆ get_diversion_header()

static pjsip_fromto_hdr * get_diversion_header ( pjsip_rx_data *  rdata)
static

Definition at line 198 of file res_pjsip_diversion.c.

199{
200 static const pj_str_t from_name = { "From", 4 };
201
202 pjsip_generic_string_hdr *hdr;
203 pj_str_t value;
204 int size;
205
206 if (!(hdr = pjsip_msg_find_hdr_by_name(rdata->msg_info.msg, &diversion_name, NULL))) {
207 return NULL;
208 }
209
210 pj_strdup_with_null(rdata->tp_info.pool, &value, &hdr->hvalue);
211
212 /* parse as a fromto header */
213 return pjsip_parse_hdr(rdata->tp_info.pool, &from_name, value.ptr,
214 pj_strlen(&value), &size);
215}
int value
Definition: syslog.c:37

References diversion_name, NULL, and value.

Referenced by diversion_incoming_request(), and diversion_incoming_response().

◆ get_history_info_header()

static pjsip_fromto_hdr * get_history_info_header ( pjsip_rx_data *  rdata,
const unsigned int  first 
)
static

Definition at line 223 of file res_pjsip_diversion.c.

224{
225 static const pj_str_t from_name = { "From", 4 };
226 pjsip_fromto_hdr * result_hdr = NULL;
227
228 pjsip_generic_string_hdr *hdr = NULL;
229
230 hdr = pjsip_msg_find_hdr_by_name(rdata->msg_info.msg, &history_info_name, NULL);
231
232 if (!hdr) {
233 return NULL;
234 }
235
236 do {
237 static const pj_str_t index_name = { "index", 5 };
238 pj_str_t value;
239 int size;
240 pjsip_fromto_hdr * fromto_hdr = NULL;
241 pjsip_param * index = NULL;
242
243 pj_strdup_with_null(rdata->tp_info.pool, &value, &hdr->hvalue);
244
245 /* parse as a fromto header */
246 fromto_hdr = pjsip_parse_hdr(rdata->tp_info.pool, &from_name, value.ptr,
247 pj_strlen(&value), &size);
248
249 if (fromto_hdr == NULL) {
250 continue;
251 }
252
253 index = pjsip_param_find(&fromto_hdr->other_param, &index_name);
254
255 if (index) {
256 if (!pj_strcmp2(&index->value, "1")) {
257 if (!first) {
258 continue;
259 } else {
260 return fromto_hdr;
261 }
262 }
263 }
264
265 result_hdr = fromto_hdr;
266
267 } while ((hdr = pjsip_msg_find_hdr_by_name(rdata->msg_info.msg, &history_info_name, hdr->next)));
268
269 return result_hdr;
270}
struct sla_ringing_trunk * first
Definition: app_sla.c:338

References first, history_info_name, NULL, and value.

Referenced by diversion_incoming_request(), and diversion_incoming_response().

◆ get_redirecting_add_diversion()

static void get_redirecting_add_diversion ( struct ast_sip_session session,
pjsip_tx_data *  tdata 
)
static

Definition at line 672 of file res_pjsip_diversion.c.

673{
674 struct ast_party_redirecting *data;
675
676 add_supported(tdata);
677
678 if (session->channel && session->endpoint->id.send_diversion &&
679 (data = ast_channel_redirecting(session->channel))->count) {
680 add_diversion_header(tdata, data);
681 }
682 if (session->channel && session->endpoint->id.send_history_info) {
683 data = ast_channel_redirecting(session->channel);
684 add_history_info_header(tdata, data);
685 }
686}
struct ast_party_redirecting * ast_channel_redirecting(struct ast_channel *chan)
static void add_history_info_header(pjsip_tx_data *tdata, struct ast_party_redirecting *data)
static int add_supported(pjsip_tx_data *tdata)
static void add_diversion_header(pjsip_tx_data *tdata, struct ast_party_redirecting *data)
Redirecting Line information. RDNIS (Redirecting Directory Number Information Service) Where a call d...
Definition: channel.h:524

References add_diversion_header(), add_history_info_header(), add_supported(), ast_channel_redirecting(), and session.

Referenced by diversion_outgoing_request(), and diversion_outgoing_response().

◆ load_module()

static int load_module ( void  )
static

Definition at line 739 of file res_pjsip_diversion.c.

740{
741 /* Because we are passing static memory to pjsip, we need to make sure it
742 * stays valid while we potentially have active sessions */
747}
#define ast_module_shutdown_ref(mod)
Prevent unload of the module before shutdown.
Definition: module.h:478
@ AST_MODULE_LOAD_SUCCESS
Definition: module.h:70
static struct ast_sip_session_supplement diversion_supplement_redirecting
static struct ast_sip_session_supplement diversion_supplement_media
#define ast_sip_session_register_supplement(supplement)
struct ast_module * self
Definition: module.h:356

References AST_MODULE_LOAD_SUCCESS, ast_module_shutdown_ref, ast_sip_session_register_supplement, diversion_supplement_media, diversion_supplement_redirecting, and ast_module_info::self.

◆ reason_code_to_cause()

static const unsigned int reason_code_to_cause ( const struct ast_party_redirecting_reason reason)
static

Definition at line 183 of file res_pjsip_diversion.c.

184{
185 int idx;
186 int code;
187
188 code = reason->code;
189 for (idx = 0; idx < ARRAY_LEN(reason_table); ++idx) {
190 if (code == reason_table[idx].code) {
191 return reason_table[idx].cause;
192 }
193 }
194
195 return 404;
196}
static const struct reasons reason_table[]
int code
enum AST_REDIRECTING_REASON value for redirection
Definition: channel.h:512
const unsigned int cause
#define ARRAY_LEN(a)
Definition: utils.h:703

References ARRAY_LEN, reasons::cause, ast_party_redirecting_reason::code, and reason_table.

Referenced by add_history_info_header().

◆ reason_code_to_str()

static const char * reason_code_to_str ( const struct ast_party_redirecting_reason reason)
static

Definition at line 163 of file res_pjsip_diversion.c.

164{
165 int idx;
166 int code;
167
168 /* use specific string if given */
169 if (!ast_strlen_zero(reason->str)) {
170 return reason->str;
171 }
172
173 code = reason->code;
174 for (idx = 0; idx < ARRAY_LEN(reason_table); ++idx) {
175 if (code == reason_table[idx].code) {
176 return reason_table[idx].text;
177 }
178 }
179
180 return "unknown";
181}
char * str
a string value for the redirecting reason
Definition: channel.h:509
const char * text

References ARRAY_LEN, ast_strlen_zero(), ast_party_redirecting_reason::code, reason_table, ast_party_redirecting_reason::str, and reasons::text.

Referenced by add_diversion_header().

◆ set_redirecting()

static void set_redirecting ( struct ast_sip_session session,
pjsip_fromto_hdr *  from_info,
pjsip_name_addr *  to_info,
pjsip_diversion_send_update  send_update 
)
static

Definition at line 394 of file res_pjsip_diversion.c.

398{
399 struct ast_party_redirecting data;
401
402 if (!session->channel) {
403 return;
404 }
405
407 memset(&update, 0, sizeof(update));
408
409 data.reason.code = AST_REDIRECTING_REASON_UNKNOWN;
410 if (from_info) {
411 set_redirecting_id((pjsip_name_addr*)from_info->uri,
412 &data.from, &update.from);
413 set_redirecting_reason(from_info, to_info, &data.reason);
415 } else {
416 copy_redirecting_id(&data.from, &session->id, &update.from);
417 }
418
419 if (to_info) {
420 set_redirecting_id(to_info, &data.to, &update.to);
421 }
422
423 ast_set_party_id_all(&update.priv_orig);
424 ast_set_party_id_all(&update.priv_from);
426 ++data.count;
427
428 ast_channel_set_redirecting(session->channel, &data, &update);
429 /* Only queue an indication if it was due to a response received pre media*/
430 if (session->inv_session->role == PJSIP_ROLE_UAC && send_update) {
432 }
434}
void ast_party_redirecting_init(struct ast_party_redirecting *init)
Initialize the given redirecting structure.
Definition: channel.c:2090
void ast_channel_set_redirecting(struct ast_channel *chan, const struct ast_party_redirecting *redirecting, const struct ast_set_party_redirecting *update)
Set the redirecting id information in the Asterisk channel.
Definition: channel.c:9133
void ast_channel_queue_redirecting_update(struct ast_channel *chan, const struct ast_party_redirecting *redirecting, const struct ast_set_party_redirecting *update)
Queue a redirecting update frame on a channel.
Definition: channel.c:10311
void ast_set_party_id_all(struct ast_set_party_id *update_id)
Set the update marker to update all information of a corresponding party id.
Definition: channel.c:1718
void ast_party_redirecting_free(struct ast_party_redirecting *doomed)
Destroy the redirecting information contents.
Definition: channel.c:2147
static void set_redirecting_reason(pjsip_fromto_hdr *from_info, pjsip_name_addr *to_info, struct ast_party_redirecting_reason *data)
static void set_redirecting_id(pjsip_name_addr *name_addr, struct ast_party_id *data, struct ast_set_party_id *update)
static void copy_redirecting_id(struct ast_party_id *dst, const struct ast_party_id *src, struct ast_set_party_id *update)
Indicate what information in ast_party_redirecting should be set.
Definition: channel.h:557

References ast_channel_queue_redirecting_update(), ast_channel_set_redirecting(), ast_party_redirecting_free(), ast_party_redirecting_init(), AST_REDIRECTING_REASON_UNKNOWN, ast_set_party_id_all(), ast_party_redirecting_reason::code, copy_redirecting_id(), ast_party_redirecting::count, ast_party_redirecting::from, ast_party_redirecting::reason, session, set_redirecting_id(), set_redirecting_reason(), ast_party_redirecting::to, and update().

Referenced by diversion_incoming_request(), and diversion_incoming_response().

◆ set_redirecting_id()

static void set_redirecting_id ( pjsip_name_addr *  name_addr,
struct ast_party_id data,
struct ast_set_party_id update 
)
static

Definition at line 281 of file res_pjsip_diversion.c.

283{
284 pjsip_sip_uri *uri = pjsip_uri_get_uri(name_addr->uri);
285 char *semi;
286 pj_str_t uri_user;
287
288 uri_user = uri->user;
289
290 /* Always truncate redirecting number at a semicolon. */
291 semi = pj_strchr(&uri_user, ';');
292 if (semi) {
293 /*
294 * We need to be able to handle URI's looking like
295 * "sip:1235557890;phone-context=national@x.x.x.x;user=phone"
296 *
297 * Where the uri->user field will result in:
298 * "1235557890;phone-context=national"
299 *
300 * People don't care about anything after the semicolon
301 * showing up on their displays even though the RFC
302 * allows the semicolon.
303 */
304 pj_strset(&uri_user, (char *) pj_strbuf(&uri_user), semi - pj_strbuf(&uri_user));
305 }
306
307 if (pj_strlen(&uri_user)) {
308 update->number = 1;
309 data->number.valid = 1;
310 set_redirecting_value(&data->number.str, &uri_user);
311 }
312
313 if (pj_strlen(&name_addr->display)) {
314 update->name = 1;
315 data->name.valid = 1;
316 set_redirecting_value(&data->name.str, &name_addr->display);
317 }
318}
static void set_redirecting_value(char **dst, const pj_str_t *src)

References ast_party_id::name, ast_party_id::number, set_redirecting_value(), ast_party_name::str, ast_party_number::str, update(), ast_party_name::valid, and ast_party_number::valid.

Referenced by set_redirecting().

◆ set_redirecting_reason()

static void set_redirecting_reason ( pjsip_fromto_hdr *  from_info,
pjsip_name_addr *  to_info,
struct ast_party_redirecting_reason data 
)
static

Definition at line 359 of file res_pjsip_diversion.c.

361{
362 static const pj_str_t reason_name = { "reason", 6 };
363 pjsip_param *reason = pjsip_param_find(&from_info->other_param, &reason_name);
364 char *reason_str;
365
366 if (!reason) {
367 if (to_info) {
368 set_redirecting_reason_by_cause(to_info, data);
369 }
370 return;
371 }
372
373 set_redirecting_value(&data->str, &reason->value);
374 if (!data->str) {
375 /* Oops, allocation failure */
376 return;
377 }
378 reason_str = ast_strdupa(data->str);
379
380 /* Remove any enclosing double-quotes */
381 if (*reason_str == '"') {
382 reason_str = ast_strip_quoted(reason_str, "\"", "\"");
383 }
384
385 data->code = ast_redirecting_reason_parse(reason_str);
386 if (data->code < 0) {
388 } else {
389 ast_free(data->str);
390 data->str = ast_strdup("");
391 }
392}
#define ast_free(a)
Definition: astmm.h:180
#define ast_strdup(str)
A wrapper for strdup()
Definition: astmm.h:241
#define ast_strdupa(s)
duplicate a string in memory from the stack
Definition: astmm.h:298
int ast_redirecting_reason_parse(const char *data)
Convert redirecting reason text code to value (used in config file parsing)
Definition: callerid.c:1423
static void set_redirecting_reason_by_cause(pjsip_name_addr *name_addr, struct ast_party_redirecting_reason *data)
char * ast_strip_quoted(char *s, const char *beg_quotes, const char *end_quotes)
Strip leading/trailing whitespace and quotes from a string.
Definition: utils.c:1854

References ast_free, ast_redirecting_reason_parse(), AST_REDIRECTING_REASON_UNKNOWN, ast_strdup, ast_strdupa, ast_strip_quoted(), ast_party_redirecting_reason::code, set_redirecting_reason_by_cause(), set_redirecting_value(), and ast_party_redirecting_reason::str.

Referenced by set_redirecting().

◆ set_redirecting_reason_by_cause()

static void set_redirecting_reason_by_cause ( pjsip_name_addr *  name_addr,
struct ast_party_redirecting_reason data 
)
static

Definition at line 334 of file res_pjsip_diversion.c.

336{
337 static const pj_str_t cause_name = { "cause", 5 };
338 pjsip_uri *uri = name_addr->uri;
339 pjsip_param *cause = NULL;
340 unsigned long cause_value = 0;
341
342 if (!ast_sip_is_allowed_uri(uri)) {
343 return;
344 }
345
346 cause = ast_sip_pjsip_uri_get_other_param(uri, &cause_name);
347
348 if (!cause) {
349 return;
350 }
351
352 cause_value = pj_strtoul(&cause->value);
353
354 data->code = cause_to_reason(cause_value);
355 ast_free(data->str);
356 data->str = ast_strdup("");
357}
struct pjsip_param * ast_sip_pjsip_uri_get_other_param(pjsip_uri *uri, const pj_str_t *param_str)
Find an 'other' SIP/SIPS URI parameter by name.
Definition: res_pjsip.c:3511
int ast_sip_is_allowed_uri(pjsip_uri *uri)
Check whether a pjsip_uri is allowed or not.
Definition: res_pjsip.c:3472
static enum AST_REDIRECTING_REASON cause_to_reason(const unsigned long cause)

References ast_free, ast_sip_is_allowed_uri(), ast_sip_pjsip_uri_get_other_param(), ast_strdup, cause_to_reason(), ast_party_redirecting_reason::code, NULL, and ast_party_redirecting_reason::str.

Referenced by set_redirecting_reason().

◆ set_redirecting_value()

static void set_redirecting_value ( char **  dst,
const pj_str_t *  src 
)
static

Definition at line 272 of file res_pjsip_diversion.c.

273{
274 ast_free(*dst);
275 *dst = ast_malloc(pj_strlen(src) + 1);
276 if (*dst) {
277 ast_copy_pj_str(*dst, src, pj_strlen(src) + 1);
278 }
279}
#define ast_malloc(len)
A wrapper for malloc()
Definition: astmm.h:191
void ast_copy_pj_str(char *dest, const pj_str_t *src, size_t size)
Copy a pj_str_t into a standard character buffer.
Definition: res_pjsip.c:2201

References ast_copy_pj_str(), ast_free, and ast_malloc.

Referenced by set_redirecting_id(), and set_redirecting_reason().

◆ sip_is_token()

static int sip_is_token ( const char *  str)
static

Definition at line 61 of file res_pjsip_diversion.c.

62{
63 int is_token;
64
65 if (ast_strlen_zero(str)) {
66 /* An empty string is not a token. */
67 return 0;
68 }
69
70 is_token = 1;
71 do {
72 if (!isalnum(*str)
73 && !strchr("-.!%*_+`'~", *str)) {
74 /* The character is not allowed in a token. */
75 is_token = 0;
76 break;
77 }
78 } while (*++str);
79
80 return is_token;
81}
const char * str
Definition: app_jack.c:150

References ast_strlen_zero(), and str.

Referenced by add_diversion_header().

◆ unload_module()

static int unload_module ( void  )
static

Definition at line 749 of file res_pjsip_diversion.c.

750{
753 return 0;
754}
void ast_sip_session_unregister_supplement(struct ast_sip_session_supplement *supplement)
Unregister a an supplement to SIP session processing.
Definition: pjsip_session.c:63

References ast_sip_session_unregister_supplement(), diversion_supplement_media, and diversion_supplement_redirecting.

Variable Documentation

◆ __mod_info

struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_LOAD_ORDER , .description = "PJSIP Add Diversion Header Support" , .key = "This paragraph is copyright (c) 2006 by Digium, Inc. \In order for your module to load, it must return this \key via a function called \"key\". Any code which \includes this paragraph must be licensed under the GNU \General Public License version 2 or later (at your \option). In addition to Digium's general reservations \of rights, Digium expressly reserves the right to \allow other parties to license this paragraph under \different terms. Any use of Digium, Inc. trademarks or \logos (including \"Asterisk\" or \"Digium\") without \express written permission of Digium, Inc. is prohibited.\n" , .buildopt_sum = AST_BUILDOPT_SUM, .support_level = AST_MODULE_SUPPORT_CORE, .load = load_module, .unload = unload_module, .load_pri = AST_MODPRI_APP_DEPEND, .requires = "res_pjsip,res_pjsip_session", }
static

Definition at line 762 of file res_pjsip_diversion.c.

◆ ast_module_info

const struct ast_module_info* ast_module_info = &__mod_info
static

Definition at line 762 of file res_pjsip_diversion.c.

◆ diversion_name

const pj_str_t diversion_name = { "Diversion", 9 }
static

Definition at line 38 of file res_pjsip_diversion.c.

Referenced by add_diversion_header(), and get_diversion_header().

◆ diversion_supplement_media

struct ast_sip_session_supplement diversion_supplement_media
static

Definition at line 718 of file res_pjsip_diversion.c.

Referenced by load_module(), and unload_module().

◆ diversion_supplement_redirecting

struct ast_sip_session_supplement diversion_supplement_redirecting
static

Definition at line 727 of file res_pjsip_diversion.c.

Referenced by load_module(), and unload_module().

◆ HISTINFO_SUPPORTED_NAME

pj_str_t HISTINFO_SUPPORTED_NAME = { "histinfo", 8 }
static

Definition at line 40 of file res_pjsip_diversion.c.

Referenced by add_supported().

◆ history_info_name

const pj_str_t history_info_name = { "History-Info", 12 }
static

Definition at line 39 of file res_pjsip_diversion.c.

Referenced by add_history_info_header(), and get_history_info_header().

◆ reason_table

const struct reasons reason_table[]
static