Asterisk - The Open Source Telephony Project GIT-master-d856a3e
Data Structures | 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...
 

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)
 
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)
 
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
 
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 []
 

Function Documentation

◆ __reg_module()

static void __reg_module ( void  )
static

Definition at line 728 of file res_pjsip_diversion.c.

◆ __unreg_module()

static void __unreg_module ( void  )
static

Definition at line 728 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 504 of file res_pjsip_diversion.c.

505{
506 static const pj_str_t reason_name = { "reason", 6 };
507
508 pjsip_fromto_hdr *hdr;
509 pjsip_name_addr *name_addr;
510 pjsip_param *param;
511 pjsip_fromto_hdr *old_hdr;
512 const char *reason_str;
513 const char *quote_str;
514 char *reason_buf;
515 pjsip_uri *base;
516
517 struct ast_party_id *id = NULL;
518 if (tdata->msg->type == PJSIP_REQUEST_MSG) {
519 id = &data->from;
520 } else {
521 /* In responses indicate the new destination */
522 id = &data->to;
523 }
524
525 base = PJSIP_MSG_FROM_HDR(tdata->msg)->uri;
526
527 if (!id->number.valid || ast_strlen_zero(id->number.str)) {
528 return;
529 }
530
531 hdr = pjsip_from_hdr_create(tdata->pool);
532 hdr->type = PJSIP_H_OTHER;
533 hdr->sname = hdr->name = diversion_name;
534
535 name_addr = pjsip_uri_clone(tdata->pool, base);
536
537 pj_strdup2(tdata->pool, &name_addr->display, id->name.str);
538 pj_strdup2(tdata->pool, (pj_str_t *)ast_sip_pjsip_uri_get_username(name_addr->uri), id->number.str);
539
540 param = PJ_POOL_ALLOC_T(tdata->pool, pjsip_param);
541 param->name = reason_name;
542
543 reason_str = reason_code_to_str(&data->reason);
544
545 /* Reason is either already quoted or it is a token to not need quotes added. */
546 quote_str = *reason_str == '\"' || sip_is_token(reason_str) ? "" : "\"";
547
548 reason_buf = pj_pool_alloc(tdata->pool, strlen(reason_str) + 3);
549 sprintf(reason_buf, "%s%s%s", quote_str, reason_str, quote_str);/* Safe */
550
551 param->value = pj_str(reason_buf);
552
553 pj_list_insert_before(&hdr->other_param, param);
554
555 hdr->uri = (pjsip_uri *) name_addr;
556 old_hdr = pjsip_msg_find_hdr_by_name(tdata->msg, &diversion_name, NULL);
557 if (old_hdr) {
558 pj_list_erase(old_hdr);
559 }
560 pjsip_msg_add_hdr(tdata->msg, (pjsip_hdr *)hdr);
561}
enum queue_result id
Definition: app_queue.c:1638
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 570 of file res_pjsip_diversion.c.

571{
572 static const pj_str_t index_name = { "index", 5 };
573 static const pj_str_t cause_name = { "cause", 5 };
574 static const pj_str_t first_index = { "1", 1 };
575 static const pj_str_t last_index = { "1.1", 3 };
576
577 pjsip_fromto_hdr *hdr;
578 pjsip_name_addr *name_addr;
579 pjsip_sip_uri *uri;
580 pjsip_param *param;
581 pjsip_fromto_hdr *old_hdr;
582 unsigned int cause;
583 char *cause_buf;
584
585 struct ast_party_id *to = &data->to;
586 struct ast_party_id *from = &data->from;
587
588 pjsip_uri *base = PJSIP_MSG_TO_HDR(tdata->msg)->uri;
589
590
591 hdr = pjsip_from_hdr_create(tdata->pool);
592 hdr->type = PJSIP_H_OTHER;
593 hdr->sname = hdr->name = history_info_name;
594
595 name_addr = pjsip_uri_clone(tdata->pool, base);
596 uri = pjsip_uri_get_uri(name_addr->uri);
597
598 /* if no redirecting information, then TO is the original destination */
599 if (from->number.valid && !ast_strlen_zero(from->number.str)) {
600 pj_strdup2(tdata->pool, &name_addr->display, from->name.str);
601 pj_strdup2(tdata->pool, &uri->user, from->number.str);
602 }
603
604 param = PJ_POOL_ALLOC_T(tdata->pool, pjsip_param);
605 param->name = index_name;
606 param->value = first_index;
607
608
609 pj_list_insert_before(&hdr->other_param, param);
610 hdr->uri = (pjsip_uri *) name_addr;
611
612 while ((old_hdr = pjsip_msg_find_hdr_by_name(tdata->msg, &history_info_name, NULL)) != NULL) {
613 pj_list_erase(old_hdr);
614 }
615
616 pjsip_msg_add_hdr(tdata->msg, (pjsip_hdr *)hdr);
617
618 if (!to->number.valid || ast_strlen_zero(to->number.str)) {
619 return;
620 }
621
622 hdr = pjsip_from_hdr_create(tdata->pool);
623 hdr->type = PJSIP_H_OTHER;
624 hdr->sname = hdr->name = history_info_name;
625
626 name_addr = pjsip_uri_clone(tdata->pool, base);
627 uri = pjsip_uri_get_uri(name_addr->uri);
628
629 pj_strdup2(tdata->pool, &name_addr->display, to->name.str);
630 pj_strdup2(tdata->pool, &uri->user, to->number.str);
631
632 param = PJ_POOL_ALLOC_T(tdata->pool, pjsip_param);
633 param->name = index_name;
634 param->value = last_index;
635 pj_list_insert_before(&hdr->other_param, param);
636
637 param = PJ_POOL_ALLOC_T(tdata->pool, pjsip_param);
638 param->name = cause_name;
639 cause = reason_code_to_cause(&data->reason);
640 cause_buf = pj_pool_alloc(tdata->pool, 4);
641 snprintf(cause_buf, 4, "%ud", cause);
642 param->value = pj_str(cause_buf);
643 pj_list_insert_before(&uri->other_param, param);
644 hdr->uri = (pjsip_uri *) name_addr;
645
646 pjsip_msg_add_hdr(tdata->msg, (pjsip_hdr *)hdr);
647}
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 120 of file res_pjsip_diversion.c.

121{
122 pjsip_supported_hdr *hdr;
123 unsigned int i;
124
125 hdr = pjsip_msg_find_hdr(tdata->msg, PJSIP_H_SUPPORTED, NULL);
126 if (!hdr) {
127 /* insert a new Supported header */
128 hdr = pjsip_supported_hdr_create(tdata->pool);
129 if (!hdr) {
130 return -1;
131 }
132
133 pjsip_msg_add_hdr(tdata->msg, (pjsip_hdr *)hdr);
134 }
135
136 /* Asterisk can send multiple "181 Call forwarded" in a single session,
137 * we might have already modified Supported before
138 */
139 for (i = 0; i < hdr->count; ++i) {
140 if (pj_stricmp(&hdr->values[i], &HISTINFO_SUPPORTED_NAME) == 0) {
141 return 0;
142 }
143 }
144
145 if (hdr->count >= PJSIP_GENERIC_ARRAY_MAX_COUNT) {
146 return -1;
147 }
148
149 /* add on to the existing Supported header */
150 pj_strassign(&hdr->values[hdr->count++], &HISTINFO_SUPPORTED_NAME);
151
152 return 0;
153}
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 728 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 102 of file res_pjsip_diversion.c.

102 {
103 switch(cause) {
104 case 302:
106 case 486:
108 case 408:
110 case 480:
111 case 487:
113 case 503:
115 default:
117 }
118}
@ 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 312 of file res_pjsip_diversion.c.

314{
315 ast_party_id_copy(dst, src);
316
317 if (dst->number.valid) {
318 update->number = 1;
319 }
320
321 if (dst->name.valid) {
322 update->name = 1;
323 }
324}
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:1784
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 427 of file res_pjsip_diversion.c.

428{
429 pjsip_fromto_hdr *hdr = get_diversion_header(rdata);
430
431 if (hdr) {
432 set_redirecting(session, hdr, (pjsip_name_addr*)
433 PJSIP_MSG_TO_HDR(rdata->msg_info.msg)->uri);
434 } else {
435 pjsip_fromto_hdr *history_info_to;
436 pjsip_fromto_hdr *history_info_from;
437 history_info_to = get_history_info_header(rdata, 0);
438
439 if (history_info_to) {
440 /* If History-Info is present, then it will also include the original
441 redirected-from in addition to the redirected-to */
442 history_info_from = get_history_info_header(rdata, 1);
443 set_redirecting(session, history_info_from, (pjsip_name_addr*)history_info_to->uri);
444 }
445 }
446
447 return 0;
448}
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)

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

◆ diversion_incoming_response()

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

Definition at line 450 of file res_pjsip_diversion.c.

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

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

◆ diversion_outgoing_request()

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

Definition at line 673 of file res_pjsip_diversion.c.

674{
676}
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 685 of file res_pjsip_diversion.c.

686{
687 struct pjsip_status_line status = tdata->msg->line.status;
688
689 /* add to 302 and 181 */
690 if (PJSIP_IS_STATUS_IN_CLASS(status.code, 300) || (status.code == 181)) {
692 }
693}

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 190 of file res_pjsip_diversion.c.

191{
192 static const pj_str_t from_name = { "From", 4 };
193
194 pjsip_generic_string_hdr *hdr;
195 pj_str_t value;
196 int size;
197
198 if (!(hdr = pjsip_msg_find_hdr_by_name(rdata->msg_info.msg, &diversion_name, NULL))) {
199 return NULL;
200 }
201
202 pj_strdup_with_null(rdata->tp_info.pool, &value, &hdr->hvalue);
203
204 /* parse as a fromto header */
205 return pjsip_parse_hdr(rdata->tp_info.pool, &from_name, value.ptr,
206 pj_strlen(&value), &size);
207}
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 215 of file res_pjsip_diversion.c.

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

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 649 of file res_pjsip_diversion.c.

650{
651 struct ast_party_redirecting *data;
652
653 add_supported(tdata);
654
655 if (session->channel && session->endpoint->id.send_diversion &&
656 (data = ast_channel_redirecting(session->channel))->count) {
657 add_diversion_header(tdata, data);
658 }
659 if (session->channel && session->endpoint->id.send_history_info) {
660 data = ast_channel_redirecting(session->channel);
661 add_history_info_header(tdata, data);
662 }
663}
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 707 of file res_pjsip_diversion.c.

708{
709 /* Because we are passing static memory to pjsip, we need to make sure it
710 * stays valid while we potentially have active sessions */
714}
#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
#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, 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 175 of file res_pjsip_diversion.c.

176{
177 int idx;
178 int code;
179
180 code = reason->code;
181 for (idx = 0; idx < ARRAY_LEN(reason_table); ++idx) {
182 if (code == reason_table[idx].code) {
183 return reason_table[idx].cause;
184 }
185 }
186
187 return 404;
188}
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:666

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 155 of file res_pjsip_diversion.c.

156{
157 int idx;
158 int code;
159
160 /* use specific string if given */
161 if (!ast_strlen_zero(reason->str)) {
162 return reason->str;
163 }
164
165 code = reason->code;
166 for (idx = 0; idx < ARRAY_LEN(reason_table); ++idx) {
167 if (code == reason_table[idx].code) {
168 return reason_table[idx].text;
169 }
170 }
171
172 return "unknown";
173}
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 
)
static

Definition at line 386 of file res_pjsip_diversion.c.

389{
390 struct ast_party_redirecting data;
392
393 if (!session->channel) {
394 return;
395 }
396
398 memset(&update, 0, sizeof(update));
399
400 data.reason.code = AST_REDIRECTING_REASON_UNKNOWN;
401 if (from_info) {
402 set_redirecting_id((pjsip_name_addr*)from_info->uri,
403 &data.from, &update.from);
404 set_redirecting_reason(from_info, to_info, &data.reason);
406 } else {
407 copy_redirecting_id(&data.from, &session->id, &update.from);
408 }
409
410 if (to_info) {
411 set_redirecting_id(to_info, &data.to, &update.to);
412 }
413
414 ast_set_party_id_all(&update.priv_orig);
415 ast_set_party_id_all(&update.priv_from);
417 ++data.count;
418
419 ast_channel_set_redirecting(session->channel, &data, &update);
420 /* Only queue an indication if it was due to a response */
421 if (session->inv_session->role == PJSIP_ROLE_UAC) {
423 }
425}
void ast_party_redirecting_init(struct ast_party_redirecting *init)
Initialize the given redirecting structure.
Definition: channel.c:2141
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:9141
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:10319
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:1769
void ast_party_redirecting_free(struct ast_party_redirecting *doomed)
Destroy the redirecting information contents.
Definition: channel.c:2198
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 273 of file res_pjsip_diversion.c.

275{
276 pjsip_sip_uri *uri = pjsip_uri_get_uri(name_addr->uri);
277 char *semi;
278 pj_str_t uri_user;
279
280 uri_user = uri->user;
281
282 /* Always truncate redirecting number at a semicolon. */
283 semi = pj_strchr(&uri_user, ';');
284 if (semi) {
285 /*
286 * We need to be able to handle URI's looking like
287 * "sip:1235557890;phone-context=national@x.x.x.x;user=phone"
288 *
289 * Where the uri->user field will result in:
290 * "1235557890;phone-context=national"
291 *
292 * People don't care about anything after the semicolon
293 * showing up on their displays even though the RFC
294 * allows the semicolon.
295 */
296 pj_strset(&uri_user, (char *) pj_strbuf(&uri_user), semi - pj_strbuf(&uri_user));
297 }
298
299 if (pj_strlen(&uri_user)) {
300 update->number = 1;
301 data->number.valid = 1;
302 set_redirecting_value(&data->number.str, &uri_user);
303 }
304
305 if (pj_strlen(&name_addr->display)) {
306 update->name = 1;
307 data->name.valid = 1;
308 set_redirecting_value(&data->name.str, &name_addr->display);
309 }
310}
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 351 of file res_pjsip_diversion.c.

353{
354 static const pj_str_t reason_name = { "reason", 6 };
355 pjsip_param *reason = pjsip_param_find(&from_info->other_param, &reason_name);
356 char *reason_str;
357
358 if (!reason) {
359 if (to_info) {
360 set_redirecting_reason_by_cause(to_info, data);
361 }
362 return;
363 }
364
365 set_redirecting_value(&data->str, &reason->value);
366 if (!data->str) {
367 /* Oops, allocation failure */
368 return;
369 }
370 reason_str = ast_strdupa(data->str);
371
372 /* Remove any enclosing double-quotes */
373 if (*reason_str == '"') {
374 reason_str = ast_strip_quoted(reason_str, "\"", "\"");
375 }
376
377 data->code = ast_redirecting_reason_parse(reason_str);
378 if (data->code < 0) {
380 } else {
381 ast_free(data->str);
382 data->str = ast_strdup("");
383 }
384}
#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:1818

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 326 of file res_pjsip_diversion.c.

328{
329 static const pj_str_t cause_name = { "cause", 5 };
330 pjsip_uri *uri = name_addr->uri;
331 pjsip_param *cause = NULL;
332 unsigned long cause_value = 0;
333
334 if (!ast_sip_is_allowed_uri(uri)) {
335 return;
336 }
337
338 cause = ast_sip_pjsip_uri_get_other_param(uri, &cause_name);
339
340 if (!cause) {
341 return;
342 }
343
344 cause_value = pj_strtoul(&cause->value);
345
346 data->code = cause_to_reason(cause_value);
347 ast_free(data->str);
348 data->str = ast_strdup("");
349}
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 264 of file res_pjsip_diversion.c.

265{
266 ast_free(*dst);
267 *dst = ast_malloc(pj_strlen(src) + 1);
268 if (*dst) {
269 ast_copy_pj_str(*dst, src, pj_strlen(src) + 1);
270 }
271}
#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 53 of file res_pjsip_diversion.c.

54{
55 int is_token;
56
57 if (ast_strlen_zero(str)) {
58 /* An empty string is not a token. */
59 return 0;
60 }
61
62 is_token = 1;
63 do {
64 if (!isalnum(*str)
65 && !strchr("-.!%*_+`'~", *str)) {
66 /* The character is not allowed in a token. */
67 is_token = 0;
68 break;
69 }
70 } while (*++str);
71
72 return is_token;
73}
const char * str
Definition: app_jack.c:147

References ast_strlen_zero(), and str.

Referenced by add_diversion_header().

◆ unload_module()

static int unload_module ( void  )
static

Definition at line 716 of file res_pjsip_diversion.c.

717{
719 return 0;
720}
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(), and diversion_supplement.

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 728 of file res_pjsip_diversion.c.

◆ ast_module_info

const struct ast_module_info* ast_module_info = &__mod_info
static

Definition at line 728 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

struct ast_sip_session_supplement diversion_supplement
static

Definition at line 695 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