Asterisk - The Open Source Telephony Project GIT-master-27fb039
Loading...
Searching...
No Matches
Data Structures | Macros | Enumerations | Functions | Variables
res_pjsip_header_funcs.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/channel.h"
#include "asterisk/pbx.h"
#include "asterisk/app.h"
#include "asterisk/module.h"
#include "asterisk/utils.h"
Include dependency graph for res_pjsip_header_funcs.c:

Go to the source code of this file.

Data Structures

struct  hdr_list
 
struct  hdr_list_entry
 Linked list for accumulating headers. More...
 
struct  header_data
 Data structure used for ast_sip_push_task_wait_serializer
More...
 
struct  param_data
 

Macros

#define param_add(pool, list, pname, pvalue)
 

Enumerations

enum  param_type { PARAMETER_HEADER , PARAMETER_URI }
 

Functions

static void __reg_module (void)
 
static void __unreg_module (void)
 
static int add_header (void *obj)
 
static int add_param (void *obj)
 
struct ast_moduleAST_MODULE_SELF_SYM (void)
 
static pjsip_hdr * find_header (struct hdr_list *list, const char *header_name, int header_number)
 
static int func_read_header (struct ast_channel *chan, const char *function, char *data, char *buf, size_t len)
 Implements PJSIP_HEADER function 'read' callback.
 
static int func_read_headers (struct ast_channel *chan, const char *function, char *data, char *buf, size_t len)
 Read list of unique SIP headers.
 
static int func_read_param (struct ast_channel *chan, const char *function, char *data, char *buf, size_t len)
 
static int func_response_read_header (struct ast_channel *chan, const char *function, char *data, char *buf, size_t len)
 Implements PJSIP_RESPONSE_HEADER function 'read' callback.
 
static int func_response_read_headers (struct ast_channel *chan, const char *function, char *data, char *buf, size_t len)
 Read list of unique SIP response headers.
 
static int func_write_header (struct ast_channel *chan, const char *cmd, char *data, const char *value)
 Implements PJSIP_HEADER function 'write' callback.
 
static int func_write_param (struct ast_channel *chan, const char *cmd, char *data, const char *value)
 
static int incoming_request (struct ast_sip_session *session, pjsip_rx_data *rdata)
 
static void incoming_response (struct ast_sip_session *session, pjsip_rx_data *rdata)
 
static int insert_headers (pj_pool_t *pool, struct hdr_list *list, pjsip_msg *msg)
 
static int load_module (void)
 
static void outgoing_request (struct ast_sip_session *session, pjsip_tx_data *tdata)
 
static int read_header (void *obj)
 
static int read_headers (void *obj)
 
static int read_param (void *obj)
 
static int remove_header (void *obj)
 
static int unload_module (void)
 
static int update_header (void *obj)
 

Variables

static struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_LOAD_ORDER , .description = "PJSIP Header Functions" , .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 struct ast_datastore_info header_datastore
 Datastore for saving headers.
 
static struct ast_sip_session_supplement header_funcs_supplement
 
static struct ast_custom_function pjsip_header_function
 
static struct ast_custom_function pjsip_header_param_function
 
static struct ast_custom_function pjsip_headers_function
 
static struct ast_custom_function pjsip_response_header_function
 
static struct ast_custom_function pjsip_response_headers_function
 
static const struct ast_datastore_info response_header_datastore
 Datastore for saving response headers.
 

Macro Definition Documentation

◆ param_add

#define param_add (   pool,
  list,
  pname,
  pvalue 
)

Enumeration Type Documentation

◆ param_type

enum param_type
Enumerator
PARAMETER_HEADER 
PARAMETER_URI 

Definition at line 1063 of file res_pjsip_header_funcs.c.

1063 {
1066};

Function Documentation

◆ __reg_module()

static void __reg_module ( void  )
static

Definition at line 1311 of file res_pjsip_header_funcs.c.

◆ __unreg_module()

static void __unreg_module ( void  )
static

Definition at line 1311 of file res_pjsip_header_funcs.c.

◆ add_header()

static int add_header ( void *  obj)
static

Definition at line 643 of file res_pjsip_header_funcs.c.

644{
645 struct header_data *data = obj;
646 struct ast_sip_session *session = data->channel->session;
647 pj_pool_t *pool = session->inv_session->dlg->pool;
648 pj_str_t pj_header_name;
649 pj_str_t pj_header_value;
650 struct hdr_list_entry *le;
651 struct hdr_list *list;
652
653 RAII_VAR(struct ast_datastore *, datastore,
655
656 if (!datastore) {
658 data->header_datastore->type))
659 || !(datastore->data = pj_pool_alloc(pool, sizeof(struct hdr_list)))
660 || ast_sip_session_add_datastore(session, datastore)) {
661 ast_log(AST_LOG_ERROR, "Unable to create datastore for header functions.\n");
662 return -1;
663 }
664 AST_LIST_HEAD_INIT_NOLOCK((struct hdr_list *) datastore->data);
665 }
666
667 ast_debug(1, "Adding header %s with value %s\n", data->header_name,
668 data->header_value);
669
670 pj_cstr(&pj_header_name, data->header_name);
671 pj_cstr(&pj_header_value, data->header_value);
672 le = pj_pool_zalloc(pool, sizeof(struct hdr_list_entry));
673 le->hdr = (pjsip_hdr *) pjsip_generic_string_hdr_create(pool, &pj_header_name,
674 &pj_header_value);
675 list = datastore->data;
676
677 AST_LIST_INSERT_TAIL(list, le, nextptr);
678
679 return 0;
680}
static struct ast_mansession session
#define ast_log
Definition astobj2.c:42
#define ao2_cleanup(obj)
Definition astobj2.h:1934
#define AST_LOG_ERROR
#define ast_debug(level,...)
Log a DEBUG message.
#define AST_LIST_HEAD_INIT_NOLOCK(head)
Initializes a list head structure.
#define AST_LIST_INSERT_TAIL(head, elm, field)
Appends a list entry to the tail of a list.
struct ast_datastore * ast_sip_session_get_datastore(struct ast_sip_session *session, const char *name)
Retrieve a session datastore.
int ast_sip_session_add_datastore(struct ast_sip_session *session, struct ast_datastore *datastore)
Add a datastore to a SIP session.
struct ast_datastore * ast_sip_session_alloc_datastore(const struct ast_datastore_info *info, const char *uid)
Alternative for ast_datastore_alloc()
const char * type
Definition datastore.h:32
Structure for a data store object.
Definition datastore.h:64
struct ast_sip_session * session
Pointer to session.
A structure describing a SIP session.
Linked list for accumulating headers.
pjsip_hdr * hdr
Data structure used for ast_sip_push_task_wait_serializer
struct ast_sip_channel_pvt * channel
const struct ast_datastore_info * header_datastore
const char * header_value
#define RAII_VAR(vartype, varname, initval, dtor)
Declare a variable that will call a destructor function when it goes out of scope.
Definition utils.h:981

References ao2_cleanup, ast_debug, AST_LIST_HEAD_INIT_NOLOCK, AST_LIST_INSERT_TAIL, ast_log, AST_LOG_ERROR, ast_sip_session_add_datastore(), ast_sip_session_alloc_datastore(), ast_sip_session_get_datastore(), header_data::channel, hdr_list_entry::hdr, header_data::header_datastore, header_data::header_name, header_data::header_value, RAII_VAR, ast_sip_channel_pvt::session, session, and ast_datastore_info::type.

Referenced by func_write_header().

◆ add_param()

static int add_param ( void *  obj)
static

Definition at line 1131 of file res_pjsip_header_funcs.c.

1132{
1133 struct param_data *data = obj;
1134 struct ast_sip_session *session = data->channel->session;
1135 pj_pool_t *pool = session->inv_session->dlg->pool;
1136
1137 pjsip_fromto_hdr *dlg_info;
1138 pjsip_name_addr *dlg_info_name_addr;
1139 pjsip_sip_uri *dlg_info_uri;
1140
1141 dlg_info = session->inv_session->dlg->local.info; /* Local for outgoing */
1142 dlg_info_name_addr = (pjsip_name_addr *) dlg_info->uri;
1143 dlg_info_uri = pjsip_uri_get_uri(dlg_info_name_addr);
1144 if (!PJSIP_URI_SCHEME_IS_SIP(dlg_info_uri) && !PJSIP_URI_SCHEME_IS_SIPS(dlg_info_uri)) {
1145 ast_log(LOG_WARNING, "Non SIP/SIPS URI\n");
1146 return -1;
1147 }
1148
1149 ast_debug(1, "Adding custom %s param %s = %s\n",
1150 data->paramtype == PARAMETER_URI ? "URI" : "header", data->param_name, data->param_value);
1151
1152 /* This works the same as doing this in set_from_header in res_pjsip_session.c
1153 * The way that this maps to pjproject is a little confusing.
1154 * Say we have <sip:foo@bar.com;p1=abc;p2=def?h1=qrs&h2=tuv>;o1=foo;o2=bar
1155 * p1 and p2 are URI parameters.
1156 * (h1 and h2 are URI headers)
1157 * o1 and o2 are header parameters (and don't have anything to do with the URI)
1158 * In pjproject, other_param is used for adding all custom parameters.
1159 * We use the URI for URI stuff, including URI parameters, and the header directly for header parameters.
1160 */
1161
1162#define param_add(pool, list, pname, pvalue) { \
1163 pjsip_param *param; \
1164 param = PJ_POOL_ALLOC_T(pool, pjsip_param); \
1165 pj_strdup2(pool, &param->name, pname); \
1166 pj_strdup2(pool, &param->value, pvalue); \
1167 pj_list_insert_before(list, param); \
1168}
1169
1170 if (data->paramtype == PARAMETER_URI) { /* URI parameter */
1171 param_add(pool, &dlg_info_uri->other_param, data->param_name, S_OR(data->param_value, ""));
1172 } else { /* Header parameter */
1173 param_add(pool, &dlg_info->other_param, data->param_name, S_OR(data->param_value, ""));
1174 }
1175
1176 return 0;
1177}
#define LOG_WARNING
#define param_add(pool, list, pname, pvalue)
#define S_OR(a, b)
returns the equivalent of logic or for strings: first one if not empty, otherwise second one.
Definition strings.h:80
struct ast_sip_channel_pvt * channel

References ast_debug, ast_log, param_data::channel, LOG_WARNING, param_add, param_data::param_name, param_data::param_value, PARAMETER_URI, param_data::paramtype, S_OR, ast_sip_channel_pvt::session, and session.

Referenced by func_write_param().

◆ AST_MODULE_SELF_SYM()

struct ast_module * AST_MODULE_SELF_SYM ( void  )

Definition at line 1311 of file res_pjsip_header_funcs.c.

◆ find_header()

static pjsip_hdr * find_header ( struct hdr_list list,
const char *  header_name,
int  header_number 
)
static

Definition at line 438 of file res_pjsip_header_funcs.c.

440{
441 struct hdr_list_entry *le;
442 pjsip_hdr *hdr = NULL;
443 int i = 1;
444
445 if (!list || ast_strlen_zero(header_name) || header_number < 1) {
446 return NULL;
447 }
448
449 AST_LIST_TRAVERSE(list, le, nextptr) {
450 if (pj_stricmp2(&le->hdr->name, header_name) == 0 && i++ == header_number) {
451 hdr = le->hdr;
452 break;
453 }
454 }
455
456 return hdr;
457}
#define AST_LIST_TRAVERSE(head, var, field)
Loops over (traverses) the entries in a list.
#define NULL
Definition resample.c:96
static force_inline int attribute_pure ast_strlen_zero(const char *s)
Definition strings.h:65
struct hdr_list_entry::@495 nextptr

References AST_LIST_TRAVERSE, ast_strlen_zero(), hdr_list_entry::hdr, hdr_list_entry::nextptr, and NULL.

Referenced by update_header().

◆ func_read_header()

static int func_read_header ( struct ast_channel chan,
const char *  function,
char *  data,
char *  buf,
size_t  len 
)
static

Implements PJSIP_HEADER function 'read' callback.

Valid actions are 'read' and 'remove'.

Definition at line 832 of file res_pjsip_header_funcs.c.

833{
834 struct ast_sip_channel_pvt *channel = chan ? ast_channel_tech_pvt(chan) : NULL;
836 int number;
838 AST_APP_ARG(action);
841
842 if (!channel || strncmp(ast_channel_name(chan), "PJSIP/", 6)) {
843 ast_log(LOG_ERROR, "This function requires a PJSIP channel.\n");
844 return -1;
845 }
846
847 if (ast_strlen_zero(args.action)) {
848 ast_log(AST_LOG_ERROR, "This function requires an action.\n");
849 return -1;
850 }
851 if (ast_strlen_zero(args.header_name)) {
852 ast_log(AST_LOG_ERROR, "This function requires a header name.\n");
853 return -1;
854 }
855 if (!args.header_number) {
856 number = 1;
857 } else {
858 sscanf(args.header_number, "%30d", &number);
859 if (number < 1) {
860 number = 1;
861 }
862 }
863
865 header_data.header_name = args.header_name;
871
872 if (!strcasecmp(args.action, "read")) {
874 } else if (!strcasecmp(args.action, "remove")) {
877 } else {
879 "Unknown action '%s' is not valid, must be 'read' or 'remove'.\n",
880 args.action);
881 return -1;
882 }
883}
const char * ast_channel_name(const struct ast_channel *chan)
void * ast_channel_tech_pvt(const struct ast_channel *chan)
char buf[BUFSIZE]
Definition eagi_proxy.c:66
static int len(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t buflen)
int ast_sip_push_task_wait_serializer(struct ast_taskprocessor *serializer, int(*sip_task)(void *), void *task_data)
Push a task to the serializer and wait for it to complete.
Definition res_pjsip.c:2179
#define AST_APP_ARG(name)
Define an application argument.
#define AST_DECLARE_APP_ARGS(name, arglist)
Declare a structure to hold an application's arguments.
#define AST_STANDARD_APP_ARGS(args, parse)
Performs the 'standard' argument separation process for an application.
#define LOG_ERROR
static int remove_header(void *obj)
static const struct ast_datastore_info header_datastore
Datastore for saving headers.
static int read_header(void *obj)
static struct @519 args
A structure which contains a channel implementation and session.
struct ast_taskprocessor * serializer
Number structure.

References args, AST_APP_ARG, ast_channel_name(), ast_channel_tech_pvt(), AST_DECLARE_APP_ARGS, ast_log, AST_LOG_ERROR, ast_sip_push_task_wait_serializer(), AST_STANDARD_APP_ARGS, ast_strlen_zero(), buf, header_data::buf, header_data::channel, header_datastore, header_data::header_datastore, header_data::header_name, header_data::header_number, header_data::header_value, len(), header_data::len, LOG_ERROR, NULL, read_header(), remove_header(), ast_sip_session::serializer, and ast_sip_channel_pvt::session.

◆ func_read_headers()

static int func_read_headers ( struct ast_channel chan,
const char *  function,
char *  data,
char *  buf,
size_t  len 
)
static

◆ func_read_param()

static int func_read_param ( struct ast_channel chan,
const char *  function,
char *  data,
char *  buf,
size_t  len 
)
static

Definition at line 1179 of file res_pjsip_header_funcs.c.

1180{
1181 struct ast_sip_channel_pvt *channel = chan ? ast_channel_tech_pvt(chan) : NULL;
1182 struct param_data param_data;
1183
1188 );
1189
1191
1193
1194 if (!channel || strncmp(ast_channel_name(chan), "PJSIP/", 6)) {
1195 ast_log(LOG_ERROR, "This function requires a PJSIP channel.\n");
1196 return -1;
1197 }
1198 if (ast_strlen_zero(args.param_type)) {
1199 ast_log(AST_LOG_ERROR, "This function requires a parameter type.\n");
1200 return -1;
1201 }
1202 if (ast_strlen_zero(args.param_name)) {
1203 ast_log(AST_LOG_ERROR, "This function requires a parameter name.\n");
1204 return -1;
1205 }
1206
1207 /* Currently, only From is supported, but this could be extended in the future. */
1208 if (ast_strlen_zero(args.header_name) || strcasecmp(args.header_name, "From")) {
1209 ast_log(LOG_WARNING, "Only the From header is currently supported\n");
1210 return -1;
1211 }
1212
1213 param_data.param_name = args.param_name;
1214 if (!strcasecmp(args.param_type, "header")) {
1216 } else if (!strcasecmp(args.param_type, "uri")) {
1218 } else {
1219 ast_log(LOG_WARNING, "Parameter type '%s' is invalid: must be 'header' or 'uri'\n", args.param_type);
1220 return -1;
1221 }
1222
1223 param_data.buf = buf;
1224 param_data.len = len;
1225
1227}
static int read_param(void *obj)
enum param_type paramtype

References args, AST_APP_ARG, ast_channel_name(), ast_channel_tech_pvt(), AST_DECLARE_APP_ARGS, ast_log, AST_LOG_ERROR, ast_sip_push_task_wait_serializer(), AST_STANDARD_APP_ARGS, ast_strlen_zero(), buf, param_data::buf, param_data::channel, param_data::header_name, len(), param_data::len, LOG_ERROR, LOG_WARNING, NULL, param_data::param_name, PARAMETER_HEADER, PARAMETER_URI, param_data::paramtype, read_param(), ast_sip_session::serializer, and ast_sip_channel_pvt::session.

◆ func_response_read_header()

static int func_response_read_header ( struct ast_channel chan,
const char *  function,
char *  data,
char *  buf,
size_t  len 
)
static

Implements PJSIP_RESPONSE_HEADER function 'read' callback.

Valid actions are 'read'

Definition at line 890 of file res_pjsip_header_funcs.c.

891{
892 struct ast_sip_channel_pvt *channel = chan ? ast_channel_tech_pvt(chan) : NULL;
894 int number;
896 AST_APP_ARG(action);
899
900 if (!channel || strncmp(ast_channel_name(chan), "PJSIP/", 6)) {
901 ast_log(LOG_ERROR, "This function requires a PJSIP channel.\n");
902 return -1;
903 }
904
905 if (ast_strlen_zero(args.action)) {
906 ast_log(AST_LOG_ERROR, "This function requires an action.\n");
907 return -1;
908 }
909 if (ast_strlen_zero(args.header_name)) {
910 ast_log(AST_LOG_ERROR, "This function requires a header name.\n");
911 return -1;
912 }
913 if (!args.header_number) {
914 number = 1;
915 } else {
916 sscanf(args.header_number, "%30d", &number);
917 if (number < 1) {
918 number = 1;
919 }
920 }
921
923 header_data.header_name = args.header_name;
929
930 if (!strcasecmp(args.action, "read")) {
932 } else {
934 "Unknown action '%s' is not valid, must be 'read'.\n",
935 args.action);
936 return -1;
937 }
938}
static const struct ast_datastore_info response_header_datastore
Datastore for saving response headers.

References args, AST_APP_ARG, ast_channel_name(), ast_channel_tech_pvt(), AST_DECLARE_APP_ARGS, ast_log, AST_LOG_ERROR, ast_sip_push_task_wait_serializer(), AST_STANDARD_APP_ARGS, ast_strlen_zero(), buf, header_data::buf, header_data::channel, header_data::header_datastore, header_data::header_name, header_data::header_number, header_data::header_value, len(), header_data::len, LOG_ERROR, NULL, read_header(), response_header_datastore, ast_sip_session::serializer, and ast_sip_channel_pvt::session.

◆ func_response_read_headers()

static int func_response_read_headers ( struct ast_channel chan,
const char *  function,
char *  data,
char *  buf,
size_t  len 
)
static

Read list of unique SIP response headers.

Definition at line 797 of file res_pjsip_header_funcs.c.

798{
799 struct ast_sip_channel_pvt *channel = chan ? ast_channel_tech_pvt(chan) : NULL;
802 AST_APP_ARG(header_pattern);
803 );
805
806 if (!chan || strncmp(ast_channel_name(chan), "PJSIP/", 6)) {
807 ast_log(LOG_ERROR, "This function requires a PJSIP channel.\n");
808 return -1;
809 }
810
811 if (ast_strlen_zero(args.header_pattern)) {
812 ast_log(AST_LOG_ERROR, "This function requires a pattern.\n");
813 return -1;
814 }
815
817 header_data.header_name = args.header_pattern;
822
824
825}

References args, AST_APP_ARG, ast_channel_name(), ast_channel_tech_pvt(), AST_DECLARE_APP_ARGS, ast_log, AST_LOG_ERROR, ast_sip_push_task_wait_serializer(), AST_STANDARD_APP_ARGS, ast_strlen_zero(), buf, header_data::buf, header_data::channel, header_data::header_datastore, header_data::header_name, header_data::header_value, len(), header_data::len, LOG_ERROR, NULL, read_headers(), response_header_datastore, ast_sip_session::serializer, and ast_sip_channel_pvt::session.

◆ func_write_header()

static int func_write_header ( struct ast_channel chan,
const char *  cmd,
char *  data,
const char *  value 
)
static

Implements PJSIP_HEADER function 'write' callback.

Valid actions are 'add', 'update' and 'remove'.

Definition at line 945 of file res_pjsip_header_funcs.c.

947{
948 struct ast_sip_channel_pvt *channel = chan ? ast_channel_tech_pvt(chan) : NULL;
950 int header_number;
952 AST_APP_ARG(action);
955
956 if (!channel || strncmp(ast_channel_name(chan), "PJSIP/", 6)) {
957 ast_log(LOG_ERROR, "This function requires a PJSIP channel.\n");
958 return -1;
959 }
960
961 if (ast_strlen_zero(args.action)) {
962 ast_log(AST_LOG_ERROR, "This function requires an action.\n");
963 return -1;
964 }
965 if (ast_strlen_zero(args.header_name)) {
966 ast_log(AST_LOG_ERROR, "This function requires a header name.\n");
967 return -1;
968 }
969 if (!args.header_number) {
970 header_number = 1;
971 } else {
972 sscanf(args.header_number, "%30d", &header_number);
973 if (header_number < 1) {
974 header_number = 1;
975 }
976 }
977
979 header_data.header_name = args.header_name;
983 header_data.len = 0;
985
986 if (!strcasecmp(args.action, "add")) {
989 } else if (!strcasecmp(args.action, "update")) {
992 } else if (!strcasecmp(args.action, "remove")) {
995 } else {
997 "Unknown action '%s' is not valid, must be 'add', 'update', or 'remove'.\n",
998 args.action);
999 return -1;
1000 }
1001}
static int add_header(void *obj)
static int update_header(void *obj)
int value
Definition syslog.c:37

References add_header(), args, AST_APP_ARG, ast_channel_name(), ast_channel_tech_pvt(), AST_DECLARE_APP_ARGS, ast_log, AST_LOG_ERROR, ast_sip_push_task_wait_serializer(), AST_STANDARD_APP_ARGS, ast_strlen_zero(), header_data::buf, header_data::channel, header_datastore, header_data::header_datastore, header_data::header_name, header_data::header_number, header_data::header_value, header_data::len, LOG_ERROR, NULL, remove_header(), ast_sip_session::serializer, ast_sip_channel_pvt::session, update_header(), and value.

◆ func_write_param()

static int func_write_param ( struct ast_channel chan,
const char *  cmd,
char *  data,
const char *  value 
)
static

Definition at line 1229 of file res_pjsip_header_funcs.c.

1230{
1231 struct ast_sip_channel_pvt *channel = chan ? ast_channel_tech_pvt(chan) : NULL;
1232 struct param_data param_data;
1237 );
1238
1240
1242
1243 if (!channel || strncmp(ast_channel_name(chan), "PJSIP/", 6)) {
1244 ast_log(LOG_ERROR, "This function requires a PJSIP channel.\n");
1245 return -1;
1246 }
1247 if (ast_strlen_zero(args.param_type)) {
1248 ast_log(AST_LOG_ERROR, "This function requires a parameter type.\n");
1249 return -1;
1250 }
1251 if (ast_strlen_zero(args.param_name)) {
1252 ast_log(AST_LOG_ERROR, "This function requires a parameter name.\n");
1253 return -1;
1254 }
1255
1256 /* Currently, only From is supported, but this could be extended in the future. */
1257 if (ast_strlen_zero(args.header_name) || strcasecmp(args.header_name, "From")) {
1258 ast_log(LOG_WARNING, "Only the From header is currently supported\n");
1259 return -1;
1260 }
1261
1262 param_data.param_name = args.param_name;
1263 if (!strcasecmp(args.param_type, "header")) {
1265 } else if (!strcasecmp(args.param_type, "uri")) {
1267 } else {
1268 ast_log(LOG_WARNING, "Parameter type '%s' is invalid: must be 'header' or 'uri'\n", args.param_type);
1269 return -1;
1270 }
1272
1274}
static int add_param(void *obj)
const char * param_value

References add_param(), args, AST_APP_ARG, ast_channel_name(), ast_channel_tech_pvt(), AST_DECLARE_APP_ARGS, ast_log, AST_LOG_ERROR, ast_sip_push_task_wait_serializer(), AST_STANDARD_APP_ARGS, ast_strlen_zero(), param_data::channel, param_data::header_name, LOG_ERROR, LOG_WARNING, NULL, param_data::param_name, param_data::param_value, PARAMETER_HEADER, PARAMETER_URI, param_data::paramtype, ast_sip_session::serializer, ast_sip_channel_pvt::session, and value.

◆ incoming_request()

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

Definition at line 376 of file res_pjsip_header_funcs.c.

377{
378 pj_pool_t *pool = session->inv_session->dlg->pool;
379 RAII_VAR(struct ast_datastore *, datastore,
381
382 if (!datastore) {
383 if (!(datastore =
385 ||
386 !(datastore->data = pj_pool_alloc(pool, sizeof(struct hdr_list))) ||
388 ast_log(AST_LOG_ERROR, "Unable to create datastore for header functions.\n");
389 return 0;
390 }
391 AST_LIST_HEAD_INIT_NOLOCK((struct hdr_list *) datastore->data);
392 }
393 insert_headers(pool, (struct hdr_list *) datastore->data, rdata->msg_info.msg);
394
395 return 0;
396}
static int insert_headers(pj_pool_t *pool, struct hdr_list *list, pjsip_msg *msg)

References ao2_cleanup, AST_LIST_HEAD_INIT_NOLOCK, ast_log, AST_LOG_ERROR, ast_sip_session_add_datastore(), ast_sip_session_alloc_datastore(), ast_sip_session_get_datastore(), header_datastore, insert_headers(), RAII_VAR, session, and ast_datastore_info::type.

◆ incoming_response()

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

Definition at line 406 of file res_pjsip_header_funcs.c.

407{
408 pj_pool_t *pool = session->inv_session->dlg->pool;
409 RAII_VAR(struct ast_datastore *, datastore,
411 pjsip_status_line status = rdata->msg_info.msg->line.status;
412
413 /* Skip responses different of 200 OK, when 2xx is received. */
414 if (session->inv_session->state != PJSIP_INV_STATE_CONNECTING || status.code!=200) {
415 return;
416 }
417
418 if (!datastore) {
419 if (!(datastore =
421 ||
422 !(datastore->data = pj_pool_alloc(pool, sizeof(struct hdr_list))) ||
424 ast_log(AST_LOG_ERROR, "Unable to create datastore for header functions.\n");
425 return;
426 }
427 AST_LIST_HEAD_INIT_NOLOCK((struct hdr_list *) datastore->data);
428 }
429 insert_headers(pool, (struct hdr_list *) datastore->data, rdata->msg_info.msg);
430
431 return;
432}
jack_status_t status
Definition app_jack.c:149

References ao2_cleanup, AST_LIST_HEAD_INIT_NOLOCK, ast_log, AST_LOG_ERROR, ast_sip_session_add_datastore(), ast_sip_session_alloc_datastore(), ast_sip_session_get_datastore(), insert_headers(), RAII_VAR, response_header_datastore, session, status, and ast_datastore_info::type.

◆ insert_headers()

static int insert_headers ( pj_pool_t *  pool,
struct hdr_list list,
pjsip_msg *  msg 
)
static

Definition at line 353 of file res_pjsip_header_funcs.c.

354{
355 pjsip_hdr *hdr = msg->hdr.next;
356 struct hdr_list_entry *le;
357
358 while (hdr && hdr != &msg->hdr) {
359 le = pj_pool_zalloc(pool, sizeof(struct hdr_list_entry));
360 le->hdr = pjsip_hdr_clone(pool, hdr);
361 AST_LIST_INSERT_TAIL(list, le, nextptr);
362 hdr = hdr->next;
363 }
364
365 return 0;
366}

References AST_LIST_INSERT_TAIL, hdr_list_entry::hdr, and hdr_list_entry::nextptr.

Referenced by incoming_request(), and incoming_response().

◆ load_module()

static int load_module ( void  )
static

Definition at line 1282 of file res_pjsip_header_funcs.c.

1283{
1290
1292}
@ AST_MODULE_LOAD_SUCCESS
Definition module.h:70
#define ast_custom_function_register(acf)
Register a custom function.
Definition pbx.h:1562
static struct ast_custom_function pjsip_header_function
static struct ast_custom_function pjsip_response_headers_function
static struct ast_sip_session_supplement header_funcs_supplement
static struct ast_custom_function pjsip_header_param_function
static struct ast_custom_function pjsip_response_header_function
static struct ast_custom_function pjsip_headers_function
#define ast_sip_session_register_supplement(supplement)

References ast_custom_function_register, AST_MODULE_LOAD_SUCCESS, ast_sip_session_register_supplement, header_funcs_supplement, pjsip_header_function, pjsip_header_param_function, pjsip_headers_function, pjsip_response_header_function, and pjsip_response_headers_function.

◆ outgoing_request()

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

Definition at line 1036 of file res_pjsip_header_funcs.c.

1037{
1038 struct hdr_list *list;
1039 struct hdr_list_entry *le;
1040 RAII_VAR(struct ast_datastore *, datastore,
1042
1043 if (!datastore || !datastore->data ||
1044 (session->inv_session->state >= PJSIP_INV_STATE_CONFIRMED)) {
1045 return;
1046 }
1047
1048 list = datastore->data;
1049 AST_LIST_TRAVERSE(list, le, nextptr) {
1050 pjsip_msg_add_hdr(tdata->msg, (pjsip_hdr *) pjsip_hdr_clone(tdata->pool, le->hdr));
1051 }
1053}
void ast_sip_session_remove_datastore(struct ast_sip_session *session, const char *name)
Remove a session datastore from the session.

References ao2_cleanup, AST_LIST_TRAVERSE, ast_sip_session_get_datastore(), ast_sip_session_remove_datastore(), hdr_list_entry::hdr, header_datastore, hdr_list_entry::nextptr, RAII_VAR, session, and ast_datastore_info::type.

◆ read_header()

static int read_header ( void *  obj)
static

Definition at line 560 of file res_pjsip_header_funcs.c.

561{
562 struct header_data *data = obj;
563 size_t len = strlen(data->header_name);
564 pjsip_hdr *hdr = NULL;
565 char *pj_hdr_string;
566 int pj_hdr_string_len;
567 char *p;
568 size_t plen;
569 struct hdr_list_entry *le;
570 struct hdr_list *list;
571 int i = 1;
572 RAII_VAR(struct ast_datastore *, datastore,
575
576 if (!datastore || !datastore->data) {
577 ast_debug(1, "There was no datastore from which to read headers.\n");
578 return -1;
579 }
580
581 list = datastore->data;
582 AST_LIST_TRAVERSE(list, le, nextptr) {
583 if (data->header_name[len - 1] == '*') {
584 if (pj_strnicmp2(&le->hdr->name, data->header_name, len - 1) == 0 && i++ == data->header_number) {
585 hdr = le->hdr;
586 break;
587 }
588 } else {
589 if (pj_stricmp2(&le->hdr->name, data->header_name) == 0 && i++ == data->header_number) {
590 hdr = le->hdr;
591 break;
592 }
593 }
594 }
595
596 if (!hdr) {
597 ast_debug(1, "There was no header named %s.\n", data->header_name);
598 return -1;
599 }
600
601 pj_hdr_string = ast_alloca(data->len);
602 pj_hdr_string_len = pjsip_hdr_print_on(hdr, pj_hdr_string, data->len - 1);
603 if (pj_hdr_string_len == -1) {
605 "Not enough buffer space in pjsip_hdr_print_on\n");
606 return -1;
607 }
608
609 pj_hdr_string[pj_hdr_string_len] = '\0';
610
611 p = strchr(pj_hdr_string, ':');
612 if (!p) {
614 "A malformed header was returned from pjsip_hdr_print_on.\n");
615 return -1;
616 }
617
618 ++p;
619 p = ast_strip(p);
620 plen = strlen(p);
621 if (plen + 1 > data->len) {
623 "Buffer isn't big enough to hold header value. %zu > %zu\n", plen + 1,
624 data->len);
625 return -1;
626 }
627
628 ast_copy_string(data->buf, p, data->len);
629
630 return 0;
631}
#define ast_alloca(size)
call __builtin_alloca to ensure we get gcc builtin semantics
Definition astmm.h:288
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition strings.h:425
char * ast_strip(char *s)
Strip leading/trailing whitespace from a string.
Definition strings.h:223

References ao2_cleanup, ast_alloca, ast_copy_string(), ast_debug, AST_LIST_TRAVERSE, ast_log, AST_LOG_ERROR, ast_sip_session_get_datastore(), ast_strip(), header_data::buf, header_data::channel, hdr_list_entry::hdr, header_data::header_datastore, header_data::header_name, header_data::header_number, len(), header_data::len, NULL, RAII_VAR, ast_sip_channel_pvt::session, and ast_datastore_info::type.

Referenced by func_read_header(), and func_response_read_header().

◆ read_headers()

static int read_headers ( void *  obj)
static

Definition at line 469 of file res_pjsip_header_funcs.c.

470{
471 struct header_data *data = obj;
472 size_t len = !ast_strlen_zero(data->header_name) ? strlen(data->header_name) : 0;
473 pjsip_hdr *hdr = NULL;
474 char *pj_hdr_string;
475 int pj_hdr_string_len;
476 char *p;
477 char *pos;
478 size_t plen, wlen = 0;
479 struct hdr_list_entry *le;
480 struct hdr_list *list;
481
482 RAII_VAR(struct ast_datastore *, datastore,
485
486 if (!datastore || !datastore->data) {
487 ast_debug(1, "There was no datastore from which to read headers.\n");
488 return -1;
489 }
490
491 list = datastore->data;
492 pj_hdr_string = ast_alloca(data->len);
493 AST_LIST_TRAVERSE(list, le, nextptr) {
494 if (!len || pj_strnicmp2(&le->hdr->name, data->header_name, len) == 0) {
495 /* Found matched header, append to buf */
496 hdr = le->hdr;
497
498 pj_hdr_string_len = pjsip_hdr_print_on(hdr, pj_hdr_string, data->len - 1);
499 if (pj_hdr_string_len == -1) {
501 "Not enough buffer space in pjsip_hdr_print_on\n");
502 return -1;
503 }
504 pj_hdr_string[pj_hdr_string_len] = '\0';
505 p = strchr(pj_hdr_string, ':');
506 if (!p) {
508 "A malformed header was returned from pjsip_hdr_print_on\n");
509 continue;
510 }
511
512 pj_hdr_string[p - pj_hdr_string] = '\0';
513 p = ast_strip(pj_hdr_string);
514 plen = strlen(p);
515 if (wlen + plen + 1 > data->len) {
517 "Buffer isn't big enough to hold header value. %zu > %zu\n", plen + 1,
518 data->len);
519 return -1;
520 }
521 pos = strstr(data->buf, p);
522 if (pos && pos[1] == ',') {
523 if (pos == data->buf) {
524 continue;
525 } else if (pos[-1] == ',') {
526 continue;
527 }
528 }
529 ast_copy_string(data->buf + wlen, p, data->len - wlen);
530 wlen += plen;
531 ast_copy_string(data->buf + wlen, ",", data->len - wlen);
532 wlen++;
533 }
534 }
535
536 if (wlen == 0) {
537 if (!len) {
538 /* No headers at all on this channel */
539 return 0;
540 } else {
541 ast_debug(1, "There was no header beginning with %s.\n", data->header_name);
542 return -1;
543 }
544 } else {
545 data->buf[wlen-1] = '\0';
546 }
547 return 0;
548}
#define AST_LOG_WARNING

References ao2_cleanup, ast_alloca, ast_copy_string(), ast_debug, AST_LIST_TRAVERSE, ast_log, AST_LOG_ERROR, AST_LOG_WARNING, ast_sip_session_get_datastore(), ast_strip(), ast_strlen_zero(), header_data::buf, header_data::channel, hdr_list_entry::hdr, header_data::header_datastore, header_data::header_name, len(), header_data::len, NULL, RAII_VAR, ast_sip_channel_pvt::session, and ast_datastore_info::type.

Referenced by func_read_headers(), and func_response_read_headers().

◆ read_param()

static int read_param ( void *  obj)
static

Definition at line 1079 of file res_pjsip_header_funcs.c.

1080{
1081 struct param_data *data = obj;
1082 struct ast_sip_session *session = data->channel->session;
1083 pj_str_t param_name;
1084
1085 pjsip_fromto_hdr *dlg_info;
1086 pjsip_name_addr *dlg_info_name_addr;
1087 pjsip_sip_uri *dlg_info_uri;
1088 pjsip_param *param;
1089 size_t param_len;
1090
1091 dlg_info = session->inv_session->dlg->remote.info; /* Remote dialog for incoming */
1092 dlg_info_name_addr = (pjsip_name_addr *) dlg_info->uri;
1093 dlg_info_uri = pjsip_uri_get_uri(dlg_info_name_addr);
1094
1095 pj_cstr(&param_name, data->param_name);
1096
1097 if (data->paramtype == PARAMETER_URI) { /* URI parameter */
1098 param = pjsip_param_find(&dlg_info_uri->other_param, &param_name);
1099 } else { /* Header parameter */
1100 param = pjsip_param_find(&dlg_info->other_param, &param_name);
1101 }
1102
1103 if (!param) {
1104 ast_debug(1, "No %s parameter found named %s\n",
1105 data->paramtype == PARAMETER_URI ? "URI" : "header", data->param_name);
1106 return -1;
1107 }
1108
1109 param_len = pj_strlen(&param->value);
1110 if (param_len >= data->len) {
1111 ast_log(LOG_ERROR, "Buffer is too small for parameter value (%zu > %zu)\n", param_len, data->len);
1112 return -1;
1113 }
1114
1115 ast_debug(2, "Successfully read %s parameter %s (length %zu)\n",
1116 data->paramtype == PARAMETER_URI ? "URI" : "header", data->param_name, param_len);
1117 if (param_len) {
1118 ast_copy_string(data->buf, pj_strbuf(&param->value), data->len);
1119 }
1120 data->buf[param_len] = '\0';
1121
1122 return 0;
1123}

References ast_copy_string(), ast_debug, ast_log, param_data::buf, param_data::channel, param_data::len, LOG_ERROR, param_data::param_name, PARAMETER_URI, param_data::paramtype, ast_sip_channel_pvt::session, and session.

Referenced by func_read_param().

◆ remove_header()

static int remove_header ( void *  obj)
static

Definition at line 727 of file res_pjsip_header_funcs.c.

728{
729 struct header_data *data = obj;
730 size_t len = strlen(data->header_name);
731 struct hdr_list *list;
732 struct hdr_list_entry *le;
733 int removed_count = 0;
734 RAII_VAR(struct ast_datastore *, datastore,
737
738 if (!datastore || !datastore->data) {
739 ast_log(AST_LOG_ERROR, "No headers had been previously added to this session.\n");
740 return -1;
741 }
742
743 list = datastore->data;
745 if (data->header_name[len - 1] == '*') {
746 if (pj_strnicmp2(&le->hdr->name, data->header_name, len - 1) == 0) {
748 removed_count++;
749 }
750 } else {
751 if (pj_stricmp2(&le->hdr->name, data->header_name) == 0) {
753 removed_count++;
754 }
755 }
756 }
758
759 if (data->buf && data->len) {
760 snprintf(data->buf, data->len, "%d", removed_count);
761 }
762
763 return 0;
764}
#define AST_LIST_TRAVERSE_SAFE_END
Closes a safe loop traversal block.
#define AST_LIST_TRAVERSE_SAFE_BEGIN(head, var, field)
Loops safely over (traverses) the entries in a list.
#define AST_LIST_REMOVE_CURRENT(field)
Removes the current entry from a list during a traversal.

References ao2_cleanup, AST_LIST_REMOVE_CURRENT, AST_LIST_TRAVERSE_SAFE_BEGIN, AST_LIST_TRAVERSE_SAFE_END, ast_log, AST_LOG_ERROR, ast_sip_session_get_datastore(), header_data::buf, header_data::channel, hdr_list_entry::hdr, header_data::header_datastore, header_data::header_name, len(), header_data::len, hdr_list_entry::nextptr, RAII_VAR, ast_sip_channel_pvt::session, and ast_datastore_info::type.

Referenced by func_read_header(), and func_write_header().

◆ unload_module()

static int unload_module ( void  )
static

◆ update_header()

static int update_header ( void *  obj)
static

Definition at line 692 of file res_pjsip_header_funcs.c.

693{
694 struct header_data *data = obj;
695 pj_pool_t *pool = data->channel->session->inv_session->dlg->pool;
696 pjsip_hdr *hdr = NULL;
697 RAII_VAR(struct ast_datastore *, datastore,
700
701 if (!datastore || !datastore->data) {
702 ast_log(AST_LOG_ERROR, "No headers had been previously added to this session.\n");
703 return -1;
704 }
705
706 hdr = find_header((struct hdr_list *) datastore->data, data->header_name,
707 data->header_number);
708
709 if (!hdr) {
710 ast_log(AST_LOG_ERROR, "There was no header named %s.\n", data->header_name);
711 return -1;
712 }
713
714 pj_strdup2(pool, &((pjsip_generic_string_hdr *) hdr)->hvalue, data->header_value);
715
716 return 0;
717}
static pjsip_hdr * find_header(struct hdr_list *list, const char *header_name, int header_number)
struct pjsip_inv_session * inv_session

References ao2_cleanup, ast_log, AST_LOG_ERROR, ast_sip_session_get_datastore(), header_data::channel, find_header(), header_data::header_datastore, header_data::header_name, header_data::header_number, header_data::header_value, ast_sip_session::inv_session, NULL, RAII_VAR, ast_sip_channel_pvt::session, and ast_datastore_info::type.

Referenced by func_write_header().

Variable Documentation

◆ __mod_info

struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_LOAD_ORDER , .description = "PJSIP Header Functions" , .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 1311 of file res_pjsip_header_funcs.c.

◆ ast_module_info

const struct ast_module_info* ast_module_info = &__mod_info
static

Definition at line 1311 of file res_pjsip_header_funcs.c.

◆ header_datastore

const struct ast_datastore_info header_datastore
static
Initial value:
= {
.type = "header_datastore",
}

Datastore for saving headers.

Definition at line 327 of file res_pjsip_header_funcs.c.

327 {
328 .type = "header_datastore",
329};

Referenced by func_read_header(), func_read_headers(), func_write_header(), incoming_request(), and outgoing_request().

◆ header_funcs_supplement

struct ast_sip_session_supplement header_funcs_supplement
static

Definition at line 1055 of file res_pjsip_header_funcs.c.

1055 {
1056 .method = "INVITE",
1057 .priority = AST_SIP_SUPPLEMENT_PRIORITY_CHANNEL - 1000,
1058 .incoming_request = incoming_request,
1059 .outgoing_request = outgoing_request,
1060 .incoming_response = incoming_response,
1061};
@ AST_SIP_SUPPLEMENT_PRIORITY_CHANNEL
Definition res_pjsip.h:3339
static void incoming_response(struct ast_sip_session *session, pjsip_rx_data *rdata)
static int incoming_request(struct ast_sip_session *session, pjsip_rx_data *rdata)
static void outgoing_request(struct ast_sip_session *session, pjsip_tx_data *tdata)

Referenced by load_module(), and unload_module().

◆ pjsip_header_function

struct ast_custom_function pjsip_header_function
static
Initial value:
= {
.name = "PJSIP_HEADER",
}
static int func_read_header(struct ast_channel *chan, const char *function, char *data, char *buf, size_t len)
Implements PJSIP_HEADER function 'read' callback.
static int func_write_header(struct ast_channel *chan, const char *cmd, char *data, const char *value)
Implements PJSIP_HEADER function 'write' callback.

Definition at line 1003 of file res_pjsip_header_funcs.c.

1003 {
1004 .name = "PJSIP_HEADER",
1005 .read = func_read_header,
1006 .write = func_write_header,
1007};

Referenced by load_module(), and unload_module().

◆ pjsip_header_param_function

struct ast_custom_function pjsip_header_param_function
static
Initial value:
= {
.name = "PJSIP_HEADER_PARAM",
.read = func_read_param,
.write = func_write_param,
}
static int func_write_param(struct ast_channel *chan, const char *cmd, char *data, const char *value)
static int func_read_param(struct ast_channel *chan, const char *function, char *data, char *buf, size_t len)

Definition at line 1276 of file res_pjsip_header_funcs.c.

1276 {
1277 .name = "PJSIP_HEADER_PARAM",
1278 .read = func_read_param,
1279 .write = func_write_param,
1280};

Referenced by load_module(), and unload_module().

◆ pjsip_headers_function

struct ast_custom_function pjsip_headers_function
static
Initial value:
= {
.name = "PJSIP_HEADERS",
}
static int func_read_headers(struct ast_channel *chan, const char *function, char *data, char *buf, size_t len)
Read list of unique SIP headers.

Definition at line 1009 of file res_pjsip_header_funcs.c.

1009 {
1010 .name = "PJSIP_HEADERS",
1011 .read = func_read_headers
1012};

Referenced by load_module(), and unload_module().

◆ pjsip_response_header_function

struct ast_custom_function pjsip_response_header_function
static
Initial value:
= {
.name = "PJSIP_RESPONSE_HEADER",
}
static int func_response_read_header(struct ast_channel *chan, const char *function, char *data, char *buf, size_t len)
Implements PJSIP_RESPONSE_HEADER function 'read' callback.

Definition at line 1014 of file res_pjsip_header_funcs.c.

1014 {
1015 .name = "PJSIP_RESPONSE_HEADER",
1017};

Referenced by load_module(), and unload_module().

◆ pjsip_response_headers_function

struct ast_custom_function pjsip_response_headers_function
static
Initial value:
= {
.name = "PJSIP_RESPONSE_HEADERS",
}
static int func_response_read_headers(struct ast_channel *chan, const char *function, char *data, char *buf, size_t len)
Read list of unique SIP response headers.

Definition at line 1019 of file res_pjsip_header_funcs.c.

1019 {
1020 .name = "PJSIP_RESPONSE_HEADERS",
1022};

Referenced by load_module(), and unload_module().

◆ response_header_datastore

const struct ast_datastore_info response_header_datastore
static
Initial value:
= {
.type = "response_header_datastore",
}

Datastore for saving response headers.

Definition at line 331 of file res_pjsip_header_funcs.c.

331 {
332 .type = "response_header_datastore",
333};

Referenced by func_response_read_header(), func_response_read_headers(), and incoming_response().