33 #include "asterisk/res_pjsip.h"
34 #include "asterisk/res_pjsip_session.h"
312 .
type =
"header_datastore",
316 .
type =
"response_header_datastore",
323 const char *header_value;
337 static int insert_headers(pj_pool_t *
pool,
struct hdr_list *list, pjsip_msg * msg)
339 pjsip_hdr *hdr = msg->hdr.next;
342 while (hdr && hdr != &msg->hdr) {
344 le->hdr = pjsip_hdr_clone(pool, hdr);
360 static int incoming_request(
struct ast_sip_session *session, pjsip_rx_data * rdata)
364 ast_sip_session_get_datastore(session, header_datastore.
type), ao2_cleanup);
368 ast_sip_session_alloc_datastore(&header_datastore, header_datastore.
type))
370 !(datastore->data = pj_pool_alloc(pool,
sizeof(
struct hdr_list))) ||
371 ast_sip_session_add_datastore(session, datastore)) {
372 ast_log(AST_LOG_ERROR,
"Unable to create datastore for header functions.\n");
377 insert_headers(pool, (
struct hdr_list *) datastore->data, rdata->msg_info.msg);
390 static void incoming_response(
struct ast_sip_session *session, pjsip_rx_data * rdata)
394 ast_sip_session_get_datastore(session, response_header_datastore.
type), ao2_cleanup);
395 pjsip_status_line status = rdata->msg_info.msg->line.status;
398 if (session->
inv_session->state != PJSIP_INV_STATE_CONNECTING || status.code!=200) {
404 ast_sip_session_alloc_datastore(&response_header_datastore, response_header_datastore.
type))
406 !(datastore->data = pj_pool_alloc(pool,
sizeof(
struct hdr_list))) ||
407 ast_sip_session_add_datastore(session, datastore)) {
408 ast_log(AST_LOG_ERROR,
"Unable to create datastore for header functions.\n");
413 insert_headers(pool, (
struct hdr_list *) datastore->data, rdata->msg_info.msg);
422 static pjsip_hdr *find_header(
struct hdr_list *list,
const char *header_name,
426 pjsip_hdr *hdr = NULL;
429 if (!list || ast_strlen_zero(header_name) || header_number < 1) {
434 if (pj_stricmp2(&le->hdr->name, header_name) == 0 && i++ == header_number) {
453 static int read_headers(
void *obj)
456 size_t len = !ast_strlen_zero(data->header_name) ? strlen(data->header_name) : 0;
457 pjsip_hdr *hdr = NULL;
459 int pj_hdr_string_len;
462 size_t plen, wlen = 0;
467 ast_sip_session_get_datastore(data->channel->
session, data->header_datastore->
type),
470 if (!datastore || !datastore->data) {
471 ast_debug(1,
"There was no datastore from which to read headers.\n");
475 list = datastore->data;
478 if (!len || pj_strnicmp2(&le->hdr->name, data->header_name, len) == 0) {
482 pj_hdr_string_len = pjsip_hdr_print_on(hdr, pj_hdr_string, data->len - 1);
483 if (pj_hdr_string_len == -1) {
484 ast_log(AST_LOG_ERROR,
485 "Not enough buffer space in pjsip_hdr_print_on\n");
488 pj_hdr_string[pj_hdr_string_len] =
'\0';
489 p = strchr(pj_hdr_string,
':');
491 ast_log(AST_LOG_WARNING,
492 "A malformed header was returned from pjsip_hdr_print_on\n");
496 pj_hdr_string[p - pj_hdr_string] =
'\0';
499 if (wlen + plen + 1 > data->len) {
500 ast_log(AST_LOG_ERROR,
501 "Buffer isn't big enough to hold header value. %zu > %zu\n", plen + 1,
505 pos = strstr(data->buf, p);
506 if (pos && pos[1] ==
',') {
507 if (pos == data->buf) {
509 }
else if (pos[-1] ==
',') {
525 ast_debug(1,
"There was no header beginning with %s.\n", data->header_name);
529 data->buf[wlen-1] =
'\0';
544 static int read_header(
void *obj)
547 size_t len = strlen(data->header_name);
548 pjsip_hdr *hdr = NULL;
550 int pj_hdr_string_len;
557 ast_sip_session_get_datastore(data->channel->
session, data->header_datastore->
type),
560 if (!datastore || !datastore->data) {
561 ast_debug(1,
"There was no datastore from which to read headers.\n");
565 list = datastore->data;
567 if (data->header_name[len - 1] ==
'*') {
568 if (pj_strnicmp2(&le->hdr->name, data->header_name, len - 1) == 0 && i++ == data->header_number) {
573 if (pj_stricmp2(&le->hdr->name, data->header_name) == 0 && i++ == data->header_number) {
581 ast_debug(1,
"There was no header named %s.\n", data->header_name);
586 pj_hdr_string_len = pjsip_hdr_print_on(hdr, pj_hdr_string, data->len - 1);
587 if (pj_hdr_string_len == -1) {
588 ast_log(AST_LOG_ERROR,
589 "Not enough buffer space in pjsip_hdr_print_on\n");
593 pj_hdr_string[pj_hdr_string_len] =
'\0';
595 p = strchr(pj_hdr_string,
':');
597 ast_log(AST_LOG_ERROR,
598 "A malformed header was returned from pjsip_hdr_print_on.\n");
605 if (plen + 1 > data->len) {
606 ast_log(AST_LOG_ERROR,
607 "Buffer isn't big enough to hold header value. %zu > %zu\n", plen + 1,
627 static int add_header(
void *obj)
632 pj_str_t pj_header_name;
633 pj_str_t pj_header_value;
638 ast_sip_session_get_datastore(session, data->header_datastore->
type), ao2_cleanup);
641 if (!(datastore = ast_sip_session_alloc_datastore(data->header_datastore,
642 data->header_datastore->
type))
643 || !(datastore->data = pj_pool_alloc(pool,
sizeof(
struct hdr_list)))
644 || ast_sip_session_add_datastore(session, datastore)) {
645 ast_log(AST_LOG_ERROR,
"Unable to create datastore for header functions.\n");
651 ast_debug(1,
"Adding header %s with value %s\n", data->header_name,
654 pj_cstr(&pj_header_name, data->header_name);
655 pj_cstr(&pj_header_value, data->header_value);
657 le->hdr = (pjsip_hdr *) pjsip_generic_string_hdr_create(pool, &pj_header_name,
659 list = datastore->data;
676 static int update_header(
void *obj)
680 pjsip_hdr *hdr = NULL;
682 ast_sip_session_get_datastore(data->channel->
session, data->header_datastore->
type),
685 if (!datastore || !datastore->data) {
686 ast_log(AST_LOG_ERROR,
"No headers had been previously added to this session.\n");
690 hdr = find_header((
struct hdr_list *) datastore->data, data->header_name,
691 data->header_number);
694 ast_log(AST_LOG_ERROR,
"There was no header named %s.\n", data->header_name);
698 pj_strdup2(pool, &((pjsip_generic_string_hdr *) hdr)->hvalue, data->header_value);
711 static int remove_header(
void *obj)
714 size_t len = strlen(data->header_name);
717 int removed_count = 0;
719 ast_sip_session_get_datastore(data->channel->
session, data->header_datastore->
type),
722 if (!datastore || !datastore->data) {
723 ast_log(AST_LOG_ERROR,
"No headers had been previously added to this session.\n");
727 list = datastore->data;
729 if (data->header_name[len - 1] ==
'*') {
730 if (pj_strnicmp2(&le->hdr->name, data->header_name, len - 1) == 0) {
735 if (pj_stricmp2(&le->hdr->name, data->header_name) == 0) {
743 if (data->buf && data->len) {
744 snprintf(data->buf, data->len,
"%d", removed_count);
753 static int func_read_headers(
struct ast_channel *chan,
const char *
function,
char *data,
char *buf,
size_t len)
762 if (!chan || strncmp(ast_channel_name(chan),
"PJSIP/", 6)) {
763 ast_log(LOG_ERROR,
"This function requires a PJSIP channel.\n");
781 static int func_response_read_headers(
struct ast_channel *chan,
const char *
function,
char *data,
char *buf,
size_t len)
790 if (!chan || strncmp(ast_channel_name(chan),
"PJSIP/", 6)) {
791 ast_log(LOG_ERROR,
"This function requires a PJSIP channel.\n");
795 if (ast_strlen_zero(args.header_pattern)) {
796 ast_log(AST_LOG_ERROR,
"This function requires a pattern.\n");
805 header_data.header_datastore = &response_header_datastore;
816 static int func_read_header(
struct ast_channel *chan,
const char *
function,
char *data,
char *buf,
size_t len)
826 if (!channel || strncmp(ast_channel_name(chan),
"PJSIP/", 6)) {
827 ast_log(LOG_ERROR,
"This function requires a PJSIP channel.\n");
831 if (ast_strlen_zero(args.action)) {
832 ast_log(AST_LOG_ERROR,
"This function requires an action.\n");
835 if (ast_strlen_zero(args.header_name)) {
836 ast_log(AST_LOG_ERROR,
"This function requires a header name.\n");
839 if (!args.header_number) {
842 sscanf(args.header_number,
"%30d", &number);
856 if (!strcasecmp(args.action,
"read")) {
858 }
else if (!strcasecmp(args.action,
"remove")) {
862 ast_log(AST_LOG_ERROR,
863 "Unknown action '%s' is not valid, must be 'read' or 'remove'.\n",
874 static int func_response_read_header(
struct ast_channel *chan,
const char *
function,
char *data,
char *buf,
size_t len)
884 if (!channel || strncmp(ast_channel_name(chan),
"PJSIP/", 6)) {
885 ast_log(LOG_ERROR,
"This function requires a PJSIP channel.\n");
889 if (ast_strlen_zero(args.action)) {
890 ast_log(AST_LOG_ERROR,
"This function requires an action.\n");
893 if (ast_strlen_zero(args.header_name)) {
894 ast_log(AST_LOG_ERROR,
"This function requires a header name.\n");
897 if (!args.header_number) {
900 sscanf(args.header_number,
"%30d", &number);
912 header_data.header_datastore = &response_header_datastore;
914 if (!strcasecmp(args.action,
"read")) {
917 ast_log(AST_LOG_ERROR,
918 "Unknown action '%s' is not valid, must be 'read'.\n",
929 static int func_write_header(
struct ast_channel *chan,
const char *cmd,
char *data,
940 if (!channel || strncmp(ast_channel_name(chan),
"PJSIP/", 6)) {
941 ast_log(LOG_ERROR,
"This function requires a PJSIP channel.\n");
945 if (ast_strlen_zero(args.action)) {
946 ast_log(AST_LOG_ERROR,
"This function requires an action.\n");
949 if (ast_strlen_zero(args.header_name)) {
950 ast_log(AST_LOG_ERROR,
"This function requires a header name.\n");
953 if (!args.header_number) {
956 sscanf(args.header_number,
"%30d", &header_number);
957 if (header_number < 1) {
970 if (!strcasecmp(args.action,
"add")) {
973 }
else if (!strcasecmp(args.action,
"update")) {
976 }
else if (!strcasecmp(args.action,
"remove")) {
980 ast_log(AST_LOG_ERROR,
981 "Unknown action '%s' is not valid, must be 'add', 'update', or 'remove'.\n",
988 .
name =
"PJSIP_HEADER",
989 .read = func_read_header,
990 .write = func_write_header,
994 .
name =
"PJSIP_HEADERS",
995 .read = func_read_headers
999 .
name =
"PJSIP_RESPONSE_HEADER",
1000 .read = func_response_read_header
1004 .
name =
"PJSIP_RESPONSE_HEADERS",
1005 .read = func_response_read_headers
1020 static void outgoing_request(
struct ast_sip_session *session, pjsip_tx_data * tdata)
1025 ast_sip_session_get_datastore(session, header_datastore.
type), ao2_cleanup);
1027 if (!datastore || !datastore->data ||
1028 (session->
inv_session->state >= PJSIP_INV_STATE_CONFIRMED)) {
1032 list = datastore->data;
1034 pjsip_msg_add_hdr(tdata->msg, (pjsip_hdr *) pjsip_hdr_clone(tdata->pool, le->hdr));
1036 ast_sip_session_remove_datastore(session, datastore->uid);
1041 .priority = AST_SIP_SUPPLEMENT_PRIORITY_CHANNEL - 1000,
1056 const char *param_value;
1057 enum param_type paramtype;
1063 static int read_param(
void *obj)
1067 pj_str_t param_name;
1069 pjsip_fromto_hdr *dlg_info;
1070 pjsip_name_addr *dlg_info_name_addr;
1071 pjsip_sip_uri *dlg_info_uri;
1075 dlg_info = session->
inv_session->dlg->remote.info;
1076 dlg_info_name_addr = (pjsip_name_addr *) dlg_info->uri;
1077 dlg_info_uri = pjsip_uri_get_uri(dlg_info_name_addr);
1079 pj_cstr(¶m_name, data->param_name);
1081 if (data->paramtype == PARAMETER_URI) {
1082 param = pjsip_param_find(&dlg_info_uri->other_param, ¶m_name);
1084 param = pjsip_param_find(&dlg_info->other_param, ¶m_name);
1088 ast_debug(1,
"No %s parameter found named %s\n",
1089 data->paramtype == PARAMETER_URI ?
"URI" :
"header", data->param_name);
1093 param_len = pj_strlen(¶m->value);
1094 if (param_len >= data->len) {
1095 ast_log(LOG_ERROR,
"Buffer is too small for parameter value (%zu > %zu)\n", param_len, data->len);
1099 ast_debug(2,
"Successfully read %s parameter %s (length %zu)\n",
1100 data->paramtype == PARAMETER_URI ?
"URI" :
"header", data->param_name, param_len);
1104 data->buf[param_len] =
'\0';
1115 static int add_param(
void *obj)
1119 pj_pool_t *pool = session->
inv_session->dlg->pool;
1121 pjsip_fromto_hdr *dlg_info;
1122 pjsip_name_addr *dlg_info_name_addr;
1123 pjsip_sip_uri *dlg_info_uri;
1126 dlg_info_name_addr = (pjsip_name_addr *) dlg_info->uri;
1127 dlg_info_uri = pjsip_uri_get_uri(dlg_info_name_addr);
1128 if (!PJSIP_URI_SCHEME_IS_SIP(dlg_info_uri) && !PJSIP_URI_SCHEME_IS_SIPS(dlg_info_uri)) {
1129 ast_log(LOG_WARNING,
"Non SIP/SIPS URI\n");
1133 ast_debug(1,
"Adding custom %s param %s = %s\n",
1134 data->paramtype == PARAMETER_URI ?
"URI" :
"header", data->param_name, data->param_value);
1146 #define param_add(pool, list, pname, pvalue) { \
1147 pjsip_param *param; \
1148 param = PJ_POOL_ALLOC_T(pool, pjsip_param); \
1149 pj_strdup2(pool, ¶m->name, pname); \
1150 pj_strdup2(pool, ¶m->value, pvalue); \
1151 pj_list_insert_before(list, param); \
1154 if (data->paramtype == PARAMETER_URI) {
1155 param_add(pool, &dlg_info_uri->other_param, data->param_name,
S_OR(data->param_value,
""));
1157 param_add(pool, &dlg_info->other_param, data->param_name,
S_OR(data->param_value,
""));
1163 static int func_read_param(
struct ast_channel *chan,
const char *
function,
char *data,
char *buf,
size_t len)
1178 if (!channel || strncmp(ast_channel_name(chan),
"PJSIP/", 6)) {
1179 ast_log(LOG_ERROR,
"This function requires a PJSIP channel.\n");
1182 if (ast_strlen_zero(args.param_type)) {
1183 ast_log(AST_LOG_ERROR,
"This function requires a parameter type.\n");
1186 if (ast_strlen_zero(args.param_name)) {
1187 ast_log(AST_LOG_ERROR,
"This function requires a parameter name.\n");
1192 if (ast_strlen_zero(args.header_name) || strcasecmp(args.header_name,
"From")) {
1193 ast_log(LOG_WARNING,
"Only the From header is currently supported\n");
1198 if (!strcasecmp(args.param_type,
"header")) {
1200 }
else if (!strcasecmp(args.param_type,
"uri")) {
1203 ast_log(LOG_WARNING,
"Parameter type '%s' is invalid: must be 'header' or 'uri'\n", args.param_type);
1213 static int func_write_param(
struct ast_channel *chan,
const char *cmd,
char *data,
const char *value)
1227 if (!channel || strncmp(ast_channel_name(chan),
"PJSIP/", 6)) {
1228 ast_log(LOG_ERROR,
"This function requires a PJSIP channel.\n");
1231 if (ast_strlen_zero(args.param_type)) {
1232 ast_log(AST_LOG_ERROR,
"This function requires a parameter type.\n");
1235 if (ast_strlen_zero(args.param_name)) {
1236 ast_log(AST_LOG_ERROR,
"This function requires a parameter name.\n");
1241 if (ast_strlen_zero(args.header_name) || strcasecmp(args.header_name,
"From")) {
1242 ast_log(LOG_WARNING,
"Only the From header is currently supported\n");
1247 if (!strcasecmp(args.param_type,
"header")) {
1249 }
else if (!strcasecmp(args.param_type,
"uri")) {
1252 ast_log(LOG_WARNING,
"Parameter type '%s' is invalid: must be 'header' or 'uri'\n", args.param_type);
1261 .
name =
"PJSIP_HEADER_PARAM",
1262 .read = func_read_param,
1263 .write = func_write_param,
1266 static int load_module(
void)
1268 ast_sip_session_register_supplement(&header_funcs_supplement);
1278 static int unload_module(
void)
1285 ast_sip_session_unregister_supplement(&header_funcs_supplement);
1289 AST_MODULE_INFO(
ASTERISK_GPL_KEY, AST_MODFLAG_LOAD_ORDER,
"PJSIP Header Functions",
1290 .support_level = AST_MODULE_SUPPORT_CORE,
1291 .load = load_module,
1292 .unload = unload_module,
1294 .requires =
"res_pjsip,res_pjsip_session",
Main Channel structure associated with a channel.
Asterisk main include file. File version handling, generic pbx functions.
#define AST_STANDARD_APP_ARGS(args, parse)
Performs the 'standard' argument separation process for an application.
int(* incoming_request)(struct ast_sip_session *session, struct pjsip_rx_data *rdata)
Called on incoming SIP request This method can indicate a failure in processing in its return...
static pj_pool_t * pool
Global memory pool for configuration and timers.
Structure for a data store type.
A structure which contains a channel implementation and session.
struct ast_sip_session * session
Pointer to session.
Structure for a data store object.
struct pjsip_inv_session * inv_session
#define AST_LIST_TRAVERSE_SAFE_END
Closes a safe loop traversal block.
A structure describing a SIP session.
void(* outgoing_request)(struct ast_sip_session *session, struct pjsip_tx_data *tdata)
Called on an outgoing SIP request This method is always called from a SIP servant thread...
int ast_custom_function_unregister(struct ast_custom_function *acf)
Unregister a custom function.
General Asterisk PBX channel definitions.
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.
Data structure associated with a custom dialplan function.
char * ast_strip(char *s)
Strip leading/trailing whitespace from a string.
#define AST_LIST_REMOVE_CURRENT(field)
Removes the current entry from a list during a traversal.
void(* incoming_response)(struct ast_sip_session *session, struct pjsip_rx_data *rdata)
Called on an incoming SIP response This method is always called from a SIP servant thread...
#define ast_debug(level,...)
Log a DEBUG message.
Core PBX routines and definitions.
struct ast_taskprocessor * serializer
#define ast_alloca(size)
call __builtin_alloca to ensure we get gcc builtin semantics
#define AST_LIST_HEAD_NOLOCK(name, type)
Defines a structure to be used to hold a list of specified type (with no lock).
#define AST_LIST_INSERT_TAIL(head, elm, field)
Appends a list entry to the tail of a list.
#define AST_LIST_TRAVERSE(head, var, field)
Loops over (traverses) the entries in a list.
#define AST_LIST_ENTRY(type)
Declare a forward link structure inside a list entry.
A supplement to SIP message processing.
#define AST_LIST_HEAD_INIT_NOLOCK(head)
Initializes a list head structure.
Linked list for accumulating headers.
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
#define S_OR(a, b)
returns the equivalent of logic or for strings: first one if not empty, otherwise second one...
#define AST_LIST_TRAVERSE_SAFE_BEGIN(head, var, field)
Loops safely over (traverses) the entries in a list.
#define ASTERISK_GPL_KEY
The text the key() function should return.
Asterisk module definitions.
#define RAII_VAR(vartype, varname, initval, dtor)
Declare a variable that will call a destructor function when it goes out of scope.
#define AST_DECLARE_APP_ARGS(name, arglist)
Declare a structure to hold an application's arguments.
Application convenience functions, designed to give consistent look and feel to Asterisk apps...
#define ast_custom_function_register(acf)
Register a custom function.
#define AST_APP_ARG(name)
Define an application argument.