Asterisk - The Open Source Telephony Project GIT-master-27fb039
Loading...
Searching...
No Matches
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 = ASTERISK_GPL_KEY , .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:1771
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:1751
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:706

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:2108
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:9163
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:10341
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:1736
void ast_party_redirecting_free(struct ast_party_redirecting *doomed)
Destroy the redirecting information contents.
Definition channel.c:2165
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.

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 = ASTERISK_GPL_KEY , .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.

38{ "Diversion", 9 };

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.

718 {
719 .method = "INVITE",
720 /* this supplement needs to be called after caller id
721 and after the channel has been created */
722 .priority = AST_SIP_SUPPLEMENT_PRIORITY_CHANNEL + 100,
723 .incoming_response = diversion_incoming_response_media,
724 .response_priority = AST_SIP_SESSION_BEFORE_MEDIA,
725};
@ AST_SIP_SUPPLEMENT_PRIORITY_CHANNEL
Definition res_pjsip.h:3339
static void diversion_incoming_response_media(struct ast_sip_session *session, pjsip_rx_data *rdata)
@ AST_SIP_SESSION_BEFORE_MEDIA

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.

727 {
728 .method = "INVITE",
729 /* this supplement needs to be called after caller id
730 and after the channel has been created */
731 .priority = AST_SIP_SUPPLEMENT_PRIORITY_CHANNEL + 100,
732 .incoming_request = diversion_incoming_request,
733 .incoming_response = diversion_incoming_response_redirecting,
734 .outgoing_request = diversion_outgoing_request,
735 .outgoing_response = diversion_outgoing_response,
736 .response_priority = AST_SIP_SESSION_BEFORE_REDIRECTING,
737};
static void diversion_incoming_response_redirecting(struct ast_sip_session *session, pjsip_rx_data *rdata)
static int diversion_incoming_request(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)
@ AST_SIP_SESSION_BEFORE_REDIRECTING

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.

40{ "histinfo", 8 };

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.

39{ "History-Info", 12 };

Referenced by add_history_info_header(), and get_history_info_header().

◆ reason_table

const struct reasons reason_table[]
static