Asterisk - The Open Source Telephony Project  18.5.0
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 = "30ef0c93b36035ec78c9cfd712d36d9b" , .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 730 of file res_pjsip_diversion.c.

◆ __unreg_module()

static void __unreg_module ( void  )
static

Definition at line 730 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.

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

Referenced by get_redirecting_add_diversion().

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_sip_uri *uri;
511  pjsip_param *param;
512  pjsip_fromto_hdr *old_hdr;
513  const char *reason_str;
514  const char *quote_str;
515  char *reason_buf;
516  pjsip_uri *base;
517 
518  struct ast_party_id *id = NULL;
519  if (tdata->msg->type == PJSIP_REQUEST_MSG) {
520  id = &data->from;
521  } else {
522  /* In responses indicate the new destination */
523  id = &data->to;
524  }
525 
526  base = PJSIP_MSG_FROM_HDR(tdata->msg)->uri;
527 
528  if (!id->number.valid || ast_strlen_zero(id->number.str)) {
529  return;
530  }
531 
532  hdr = pjsip_from_hdr_create(tdata->pool);
533  hdr->type = PJSIP_H_OTHER;
534  hdr->sname = hdr->name = diversion_name;
535 
536  name_addr = pjsip_uri_clone(tdata->pool, base);
537  uri = pjsip_uri_get_uri(name_addr->uri);
538 
539  pj_strdup2(tdata->pool, &name_addr->display, id->name.str);
540  pj_strdup2(tdata->pool, &uri->user, id->number.str);
541 
542  param = PJ_POOL_ALLOC_T(tdata->pool, pjsip_param);
543  param->name = reason_name;
544 
545  reason_str = reason_code_to_str(&data->reason);
546 
547  /* Reason is either already quoted or it is a token to not need quotes added. */
548  quote_str = *reason_str == '\"' || sip_is_token(reason_str) ? "" : "\"";
549 
550  reason_buf = pj_pool_alloc(tdata->pool, strlen(reason_str) + 3);
551  sprintf(reason_buf, "%s%s%s", quote_str, reason_str, quote_str);/* Safe */
552 
553  param->value = pj_str(reason_buf);
554 
555  pj_list_insert_before(&hdr->other_param, param);
556 
557  hdr->uri = (pjsip_uri *) name_addr;
558  old_hdr = pjsip_msg_find_hdr_by_name(tdata->msg, &diversion_name, NULL);
559  if (old_hdr) {
560  pj_list_erase(old_hdr);
561  }
562  pjsip_msg_add_hdr(tdata->msg, (pjsip_hdr *)hdr);
563 }
Information needed to identify an endpoint in a call.
Definition: channel.h:339
char * str
Subscriber phone number (Malloced)
Definition: channel.h:292
static const char * reason_code_to_str(const struct ast_party_redirecting_reason *reason)
static int sip_is_token(const char *str)
struct ast_party_name name
Subscriber name.
Definition: channel.h:341
struct ast_party_id from
Who is redirecting the call (Sent to the party the call is redirected toward)
Definition: channel.h:528
char * str
Subscriber name (Malloced)
Definition: channel.h:265
#define NULL
Definition: resample.c:96
#define ast_strlen_zero(foo)
Definition: strings.h:52
struct ast_party_redirecting_reason reason
Reason for the redirection.
Definition: channel.h:543
struct ast_party_id to
Call is redirecting to a new party (Sent to the caller)
Definition: channel.h:531
static const pj_str_t diversion_name
unsigned char valid
TRUE if the number information is valid/present.
Definition: channel.h:298
struct ast_party_number number
Subscriber phone number.
Definition: channel.h:343

◆ add_history_info_header()

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

Definition at line 572 of file res_pjsip_diversion.c.

References ast_strlen_zero, reasons::cause, 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().

573 {
574  static const pj_str_t index_name = { "index", 5 };
575  static const pj_str_t cause_name = { "cause", 5 };
576  static const pj_str_t first_index = { "1", 1 };
577  static const pj_str_t last_index = { "1.1", 3 };
578 
579  pjsip_fromto_hdr *hdr;
580  pjsip_name_addr *name_addr;
581  pjsip_sip_uri *uri;
582  pjsip_param *param;
583  pjsip_fromto_hdr *old_hdr;
584  unsigned int cause;
585  char *cause_buf;
586 
587  struct ast_party_id *to = &data->to;
588  struct ast_party_id *from = &data->from;
589 
590  pjsip_uri *base = PJSIP_MSG_TO_HDR(tdata->msg)->uri;
591 
592 
593  hdr = pjsip_from_hdr_create(tdata->pool);
594  hdr->type = PJSIP_H_OTHER;
595  hdr->sname = hdr->name = history_info_name;
596 
597  name_addr = pjsip_uri_clone(tdata->pool, base);
598  uri = pjsip_uri_get_uri(name_addr->uri);
599 
600  /* if no redirecting information, then TO is the original destination */
601  if (from->number.valid && !ast_strlen_zero(from->number.str)) {
602  pj_strdup2(tdata->pool, &name_addr->display, from->name.str);
603  pj_strdup2(tdata->pool, &uri->user, from->number.str);
604  }
605 
606  param = PJ_POOL_ALLOC_T(tdata->pool, pjsip_param);
607  param->name = index_name;
608  param->value = first_index;
609 
610 
611  pj_list_insert_before(&hdr->other_param, param);
612  hdr->uri = (pjsip_uri *) name_addr;
613 
614  while ((old_hdr = pjsip_msg_find_hdr_by_name(tdata->msg, &history_info_name, NULL)) != NULL) {
615  pj_list_erase(old_hdr);
616  }
617 
618  pjsip_msg_add_hdr(tdata->msg, (pjsip_hdr *)hdr);
619 
620  if (!to->number.valid || ast_strlen_zero(to->number.str)) {
621  return;
622  }
623 
624  hdr = pjsip_from_hdr_create(tdata->pool);
625  hdr->type = PJSIP_H_OTHER;
626  hdr->sname = hdr->name = history_info_name;
627 
628  name_addr = pjsip_uri_clone(tdata->pool, base);
629  uri = pjsip_uri_get_uri(name_addr->uri);
630 
631  pj_strdup2(tdata->pool, &name_addr->display, to->name.str);
632  pj_strdup2(tdata->pool, &uri->user, to->number.str);
633 
634  param = PJ_POOL_ALLOC_T(tdata->pool, pjsip_param);
635  param->name = index_name;
636  param->value = last_index;
637  pj_list_insert_before(&hdr->other_param, param);
638 
639  param = PJ_POOL_ALLOC_T(tdata->pool, pjsip_param);
640  param->name = cause_name;
641  cause = reason_code_to_cause(&data->reason);
642  cause_buf = pj_pool_alloc(tdata->pool, 4);
643  snprintf(cause_buf, 4, "%ud", cause);
644  param->value = pj_str(cause_buf);
645  pj_list_insert_before(&uri->other_param, param);
646  hdr->uri = (pjsip_uri *) name_addr;
647 
648  pjsip_msg_add_hdr(tdata->msg, (pjsip_hdr *)hdr);
649 }
Information needed to identify an endpoint in a call.
Definition: channel.h:339
char * str
Subscriber phone number (Malloced)
Definition: channel.h:292
static const unsigned int reason_code_to_cause(const struct ast_party_redirecting_reason *reason)
struct ast_party_name name
Subscriber name.
Definition: channel.h:341
struct ast_party_id from
Who is redirecting the call (Sent to the party the call is redirected toward)
Definition: channel.h:528
char * str
Subscriber name (Malloced)
Definition: channel.h:265
#define NULL
Definition: resample.c:96
#define ast_strlen_zero(foo)
Definition: strings.h:52
static const pj_str_t history_info_name
struct ast_party_redirecting_reason reason
Reason for the redirection.
Definition: channel.h:543
struct ast_party_id to
Call is redirecting to a new party (Sent to the caller)
Definition: channel.h:531
unsigned char valid
TRUE if the number information is valid/present.
Definition: channel.h:298
struct ast_party_number number
Subscriber phone number.
Definition: channel.h:343

◆ add_supported()

static int add_supported ( pjsip_tx_data *  tdata)
static

Definition at line 120 of file res_pjsip_diversion.c.

References HISTINFO_SUPPORTED_NAME, and NULL.

Referenced by get_redirecting_add_diversion().

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
#define NULL
Definition: resample.c:96

◆ AST_MODULE_SELF_SYM()

struct ast_module* AST_MODULE_SELF_SYM ( void  )

Definition at line 730 of file res_pjsip_diversion.c.

◆ cause_to_reason()

static enum AST_REDIRECTING_REASON cause_to_reason ( const unsigned long  cause)
static

◆ 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.

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

Referenced by set_redirecting().

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 }
struct ast_party_name name
Subscriber name.
Definition: channel.h:341
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:1765
unsigned char number
Definition: channel.h:366
unsigned char name
Definition: channel.h:364
unsigned char valid
TRUE if the name information is valid/present.
Definition: channel.h:280
unsigned char valid
TRUE if the number information is valid/present.
Definition: channel.h:298
struct ast_party_number number
Subscriber phone number.
Definition: channel.h:343

◆ 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.

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

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 pjsip_fromto_hdr * get_history_info_header(pjsip_rx_data *rdata, const unsigned int first)
static void set_redirecting(struct ast_sip_session *session, pjsip_fromto_hdr *from_info, pjsip_name_addr *to_info)
static pjsip_fromto_hdr * get_diversion_header(pjsip_rx_data *rdata)

◆ 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.

References get_diversion_header(), get_history_info_header(), ast_sip_session::id, NULL, ast_party_id::number, set_redirecting(), status, and ast_party_number::valid.

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 }
static pjsip_fromto_hdr * get_history_info_header(pjsip_rx_data *rdata, const unsigned int first)
#define NULL
Definition: resample.c:96
static void set_redirecting(struct ast_sip_session *session, pjsip_fromto_hdr *from_info, pjsip_name_addr *to_info)
static pjsip_fromto_hdr * get_diversion_header(pjsip_rx_data *rdata)
struct ast_party_id id
unsigned char valid
TRUE if the number information is valid/present.
Definition: channel.h:298
jack_status_t status
Definition: app_jack.c:146
struct ast_party_number number
Subscriber phone number.
Definition: channel.h:343

◆ diversion_outgoing_request()

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

Definition at line 675 of file res_pjsip_diversion.c.

References get_redirecting_add_diversion().

676 {
677  get_redirecting_add_diversion(session, tdata);
678 }
static void get_redirecting_add_diversion(struct ast_sip_session *session, pjsip_tx_data *tdata)

◆ diversion_outgoing_response()

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

Definition at line 687 of file res_pjsip_diversion.c.

References get_redirecting_add_diversion().

688 {
689  struct pjsip_status_line status = tdata->msg->line.status;
690 
691  /* add to 302 and 181 */
692  if (PJSIP_IS_STATUS_IN_CLASS(status.code, 300) || (status.code == 181)) {
693  get_redirecting_add_diversion(session, tdata);
694  }
695 }
static void get_redirecting_add_diversion(struct ast_sip_session *session, pjsip_tx_data *tdata)
jack_status_t status
Definition: app_jack.c:146

◆ 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.

References diversion_name, NULL, and value.

Referenced by diversion_incoming_request(), and diversion_incoming_response().

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 }
#define NULL
Definition: resample.c:96
int value
Definition: syslog.c:37
static const pj_str_t diversion_name

◆ 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.

References history_info_name, NULL, and value.

Referenced by diversion_incoming_request(), and diversion_incoming_response().

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 }
#define NULL
Definition: resample.c:96
int value
Definition: syslog.c:37
static const pj_str_t history_info_name
struct sla_ringing_trunk * first
Definition: app_meetme.c:1092

◆ get_redirecting_add_diversion()

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

Definition at line 651 of file res_pjsip_diversion.c.

References add_diversion_header(), add_history_info_header(), add_supported(), ast_channel_redirecting(), ast_sip_session::channel, ast_sip_session::endpoint, ast_sip_endpoint::id, ast_sip_endpoint_id_configuration::send_diversion, and ast_sip_endpoint_id_configuration::send_history_info.

Referenced by diversion_outgoing_request(), and diversion_outgoing_response().

652 {
653  struct ast_party_redirecting *data;
654 
655  add_supported(tdata);
656 
657  if (session->channel && session->endpoint->id.send_diversion &&
658  (data = ast_channel_redirecting(session->channel))->count) {
659  add_diversion_header(tdata, data);
660  }
661  if (session->channel && session->endpoint->id.send_history_info) {
662  data = ast_channel_redirecting(session->channel);
663  add_history_info_header(tdata, data);
664  }
665 }
struct ast_sip_endpoint * endpoint
static void add_history_info_header(pjsip_tx_data *tdata, struct ast_party_redirecting *data)
static void add_diversion_header(pjsip_tx_data *tdata, struct ast_party_redirecting *data)
static int add_supported(pjsip_tx_data *tdata)
struct ast_channel * channel
struct ast_sip_endpoint_id_configuration id
Definition: res_pjsip.h:847
Redirecting Line information. RDNIS (Redirecting Directory Number Information Service) Where a call d...
Definition: channel.h:523
struct ast_party_redirecting * ast_channel_redirecting(struct ast_channel *chan)

◆ load_module()

static int load_module ( void  )
static

Definition at line 709 of file res_pjsip_diversion.c.

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

Referenced by unload_module().

710 {
711  /* Because we are passing static memory to pjsip, we need to make sure it
712  * stays valid while we potentially have active sessions */
716 }
struct ast_module * self
Definition: module.h:342
#define ast_module_shutdown_ref(mod)
Prevent unload of the module before shutdown.
Definition: module.h:464
static struct ast_sip_session_supplement diversion_supplement
#define ast_sip_session_register_supplement(supplement)

◆ 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.

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

Referenced by add_history_info_header().

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 }
#define ARRAY_LEN(a)
Definition: isdn_lib.c:42
static const struct reasons reason_table[]
int code
enum AST_REDIRECTING_REASON value for redirection
Definition: channel.h:511
const unsigned int cause

◆ 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.

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

Referenced by add_diversion_header().

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 }
const char * text
#define ARRAY_LEN(a)
Definition: isdn_lib.c:42
static const struct reasons reason_table[]
int code
enum AST_REDIRECTING_REASON value for redirection
Definition: channel.h:511
#define ast_strlen_zero(foo)
Definition: strings.h:52
char * str
a string value for the redirecting reason
Definition: channel.h:508

◆ 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.

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_sip_session::channel, ast_party_redirecting_reason::code, copy_redirecting_id(), ast_party_redirecting::count, ast_party_redirecting::from, ast_set_party_redirecting::from, ast_sip_session::id, ast_sip_session::inv_session, ast_set_party_redirecting::priv_from, ast_set_party_redirecting::priv_orig, ast_set_party_redirecting::priv_to, ast_party_redirecting::reason, set_redirecting_id(), set_redirecting_reason(), ast_party_redirecting::to, and ast_set_party_redirecting::to.

Referenced by diversion_incoming_request(), and diversion_incoming_response().

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);
405  ast_set_party_id_all(&update.priv_to);
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);
416  ast_set_party_id_all(&update.priv_to);
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 }
static void copy_redirecting_id(struct ast_party_id *dst, const struct ast_party_id *src, struct ast_set_party_id *update)
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
struct pjsip_inv_session * inv_session
struct ast_channel * channel
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:9215
Redirecting Line information. RDNIS (Redirecting Directory Number Information Service) Where a call d...
Definition: channel.h:523
static void set_redirecting_reason(pjsip_fromto_hdr *from_info, pjsip_name_addr *to_info, struct ast_party_redirecting_reason *data)
void ast_party_redirecting_free(struct ast_party_redirecting *doomed)
Destroy the redirecting information contents.
Definition: channel.c:2179
Indicate what information in ast_party_redirecting should be set.
Definition: channel.h:556
void ast_party_redirecting_init(struct ast_party_redirecting *init)
Initialize the given redirecting structure.
Definition: channel.c:2122
static void set_redirecting_id(pjsip_name_addr *name_addr, struct ast_party_id *data, struct ast_set_party_id *update)
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:10392
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:1750
struct ast_party_id id

◆ 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.

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

Referenced by set_redirecting().

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;[email protected];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 }
char * str
Subscriber phone number (Malloced)
Definition: channel.h:292
struct ast_party_name name
Subscriber name.
Definition: channel.h:341
char * str
Subscriber name (Malloced)
Definition: channel.h:265
static void set_redirecting_value(char **dst, const pj_str_t *src)
unsigned char number
Definition: channel.h:366
unsigned char name
Definition: channel.h:364
unsigned char valid
TRUE if the name information is valid/present.
Definition: channel.h:280
unsigned char valid
TRUE if the number information is valid/present.
Definition: channel.h:298
struct ast_party_number number
Subscriber phone number.
Definition: channel.h:343

◆ 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.

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().

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 }
static void set_redirecting_reason_by_cause(pjsip_name_addr *name_addr, struct ast_party_redirecting_reason *data)
int ast_redirecting_reason_parse(const char *data)
Convert redirecting reason text code to value (used in config file parsing)
Definition: callerid.c:1223
#define ast_strdup(str)
A wrapper for strdup()
Definition: astmm.h:243
int code
enum AST_REDIRECTING_REASON value for redirection
Definition: channel.h:511
static void set_redirecting_value(char **dst, const pj_str_t *src)
char * ast_strip_quoted(char *s, const char *beg_quotes, const char *end_quotes)
Strip leading/trailing whitespace and quotes from a string.
Definition: main/utils.c:1639
#define ast_strdupa(s)
duplicate a string in memory from the stack
Definition: astmm.h:300
char * str
a string value for the redirecting reason
Definition: channel.h:508
#define ast_free(a)
Definition: astmm.h:182

◆ 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.

References ast_free, ast_strdup, reasons::cause, cause_to_reason(), ast_party_redirecting_reason::code, NULL, and ast_party_redirecting_reason::str.

Referenced by set_redirecting_reason().

328 {
329  static const pj_str_t cause_name = { "cause", 5 };
330  pjsip_sip_uri *uri = pjsip_uri_get_uri(name_addr);
331  pjsip_param *cause = NULL;
332  unsigned long cause_value = 0;
333 
334  if (!PJSIP_URI_SCHEME_IS_SIP(uri) && !PJSIP_URI_SCHEME_IS_SIPS(uri)) {
335  return;
336  }
337 
338  cause = pjsip_param_find(&uri->other_param, &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 }
#define ast_strdup(str)
A wrapper for strdup()
Definition: astmm.h:243
#define NULL
Definition: resample.c:96
int code
enum AST_REDIRECTING_REASON value for redirection
Definition: channel.h:511
char * str
a string value for the redirecting reason
Definition: channel.h:508
#define ast_free(a)
Definition: astmm.h:182
static enum AST_REDIRECTING_REASON cause_to_reason(const unsigned long cause)

◆ 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.

References ast_copy_pj_str(), ast_free, and ast_malloc.

Referenced by set_redirecting_id(), and set_redirecting_reason().

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 }
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:5240
#define ast_malloc(len)
A wrapper for malloc()
Definition: astmm.h:193
#define ast_free(a)
Definition: astmm.h:182

◆ sip_is_token()

static int sip_is_token ( const char *  str)
static

Definition at line 53 of file res_pjsip_diversion.c.

References ast_strlen_zero.

Referenced by add_diversion_header().

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
#define ast_strlen_zero(foo)
Definition: strings.h:52

◆ unload_module()

static int unload_module ( void  )
static

Definition at line 718 of file res_pjsip_diversion.c.

References AST_MODFLAG_LOAD_ORDER, AST_MODPRI_APP_DEPEND, AST_MODULE_INFO(), AST_MODULE_SUPPORT_CORE, ast_sip_session_unregister_supplement(), ASTERISK_GPL_KEY, and load_module().

719 {
721  return 0;
722 }
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
static struct ast_sip_session_supplement 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 = "30ef0c93b36035ec78c9cfd712d36d9b" , .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 730 of file res_pjsip_diversion.c.

◆ ast_module_info

const struct ast_module_info* ast_module_info = &__mod_info
static

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

◆ 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