Asterisk - The Open Source Telephony Project  18.5.0
Data Structures | Macros | Enumerations | Functions | Variables
res_pjsip_history.c File Reference

PJSIP History. More...

#include "asterisk.h"
#include <pjsip.h>
#include <regex.h>
#include "asterisk/res_pjsip.h"
#include "asterisk/module.h"
#include "asterisk/logger.h"
#include "asterisk/cli.h"
#include "asterisk/netsock2.h"
#include "asterisk/vector.h"
#include "asterisk/lock.h"
#include "asterisk/res_pjproject.h"
Include dependency graph for res_pjsip_history.c:

Go to the source code of this file.

Data Structures

struct  allowed_field
 A field that we understand and can perform operations on. More...
 
struct  expression_token
 A token in the expression or an evaluated part of the expression. More...
 
struct  pjsip_history_entry
 An item in the history. More...
 

Macros

#define APPEND_TO_OUTPUT(output, token)
 
#define HISTORY_INITIAL_SIZE   256
 

Enumerations

enum  expression_token_type { TOKEN_TYPE_FIELD, TOKEN_TYPE_OPERATOR, TOKEN_TYPE_RESULT }
 The type of token that has been parsed out of an expression. More...
 

Functions

static void __reg_module (void)
 
static void __unreg_module (void)
 
struct ast_moduleAST_MODULE_SELF_SYM (void)
 
static AST_VECTOR (vector_history_t, struct pjsip_history_entry *)
 The one and only history that we've captured. More...
 
static struct expression_tokenbuild_expression_queue (struct ast_cli_args *a)
 Build a reverse polish notation expression queue. More...
 
static int clear_history_entries (void *obj)
 Remove all entries from vector_history. More...
 
static void clear_history_entry_cb (struct pjsip_history_entry *entry)
 Vector callback that releases the reference for the entry in a history vector. More...
 
static void display_entry_list (struct ast_cli_args *a, struct vector_history_t *vec)
 Print a list of the entries to the CLI. More...
 
static void display_single_entry (struct ast_cli_args *a, struct pjsip_history_entry *entry)
 Print a detailed view of a single entry in the history to the CLI. More...
 
static void * entry_get_addr (struct pjsip_history_entry *entry)
 Callback to retrieve the entry's destination address. More...
 
static void * entry_get_number (struct pjsip_history_entry *entry)
 Callback to retrieve the entry index number. More...
 
static void * entry_get_sip_msg_call_id (struct pjsip_history_entry *entry)
 Callback to retrieve the entry's SIP Call-ID header. More...
 
static void * entry_get_sip_msg_request_method (struct pjsip_history_entry *entry)
 Callback to retrieve the entry's SIP request method type. More...
 
static void * entry_get_timestamp (struct pjsip_history_entry *entry)
 Callback to retrieve the entry's timestamp. More...
 
static int evaluate_and (struct operator*op, enum aco_option_type type, void *op_left, struct expression_token *op_right)
 
static int evaluate_equal (struct operator*op, enum aco_option_type type, void *op_left, struct expression_token *op_right)
 Operator callback for determining equality. More...
 
static int evaluate_greater_than (struct operator*op, enum aco_option_type type, void *op_left, struct expression_token *op_right)
 
static int evaluate_greater_than_or_equal (struct operator*op, enum aco_option_type type, void *op_left, struct expression_token *op_right)
 
static int evaluate_history_entry (struct pjsip_history_entry *entry, struct expression_token *queue)
 Evaluate a single entry in this history using a RPN expression. More...
 
static int evaluate_less_than (struct operator*op, enum aco_option_type type, void *op_left, struct expression_token *op_right)
 
static int evaluate_less_than_or_equal (struct operator*op, enum aco_option_type type, void *op_left, struct expression_token *op_right)
 
static int evaluate_like (struct operator*op, enum aco_option_type type, void *op_left, struct expression_token *op_right)
 
static int evaluate_not (struct operator*op, enum aco_option_type type, void *operand)
 
static int evaluate_not_equal (struct operator*op, enum aco_option_type type, void *op_left, struct expression_token *op_right)
 Operator callback for determining inequality. More...
 
static int evaluate_or (struct operator*op, enum aco_option_type type, void *op_left, struct expression_token *op_right)
 
static struct expression_tokenexpression_token_alloc (enum expression_token_type token_type, void *value)
 Allocate an expression token. More...
 
static struct expression_tokenexpression_token_free (struct expression_token *token)
 Free an expression token and all others it references. More...
 
static struct vector_history_t * filter_history (struct ast_cli_args *a)
 Create a filtered history based on a user provided expression. More...
 
static struct allowed_fieldget_allowed_field (struct expression_token *token)
 Determine if the expression token matches a field in allowed_fields. More...
 
static pj_bool_t history_on_rx_msg (pjsip_rx_data *rdata)
 PJSIP callback when a SIP message is received. More...
 
static pj_status_t history_on_tx_msg (pjsip_tx_data *tdata)
 PJSIP callback when a SIP message is transmitted. More...
 
static int load_module (void)
 
static struct pjsip_history_entrypjsip_history_entry_alloc (pjsip_msg *msg)
 Create a pjsip_history_entry AO2 object. More...
 
static void pjsip_history_entry_dtor (void *obj)
 AO2 destructor for pjsip_history_entry. More...
 
static char * pjsip_set_history (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 
static char * pjsip_show_history (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 
static int safe_vector_cleanup (void *obj)
 Cleanup routine for a history vector, serviced on a registered PJSIP thread. More...
 
static void sprint_list_entry (struct pjsip_history_entry *entry, char *line, int len)
 Format single line history entry. More...
 
static int unload_module (void)
 

Variables

static struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_LOAD_ORDER , .description = "PJSIP History" , .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_EXTENDED, .load = load_module, .unload = unload_module, .load_pri = AST_MODPRI_APP_DEPEND, .requires = "res_pjsip", }
 
static struct allowed_field allowed_fields []
 The fields we allow. More...
 
static struct operator allowed_operators []
 Our allowed operations. More...
 
static const struct ast_module_infoast_module_info = &__mod_info
 
static pj_caching_pool cachingpool
 Pool factory used by pjlib to allocate memory. More...
 
static struct ast_cli_entry cli_pjsip []
 
static int enabled
 Whether or not we are storing history. More...
 
static ast_mutex_t history_lock = { PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP , NULL, {1, 0} }
 Mutex that protects vector_history. More...
 
static struct operator left_paren
 Operator token for a left parenthesis. More...
 
static int log_level = -1
 Log level for history output. More...
 
static pjsip_module logging_module
 
static int packet_number
 Packet count. More...
 

Detailed Description

PJSIP History.

Author
Matt Jordan mjord.nosp@m.an@d.nosp@m.igium.nosp@m..com

Definition in file res_pjsip_history.c.

Macro Definition Documentation

◆ APPEND_TO_OUTPUT

#define APPEND_TO_OUTPUT (   output,
  token 
)

Referenced by build_expression_queue().

◆ HISTORY_INITIAL_SIZE

#define HISTORY_INITIAL_SIZE   256

Definition at line 47 of file res_pjsip_history.c.

Referenced by filter_history(), and load_module().

Enumeration Type Documentation

◆ expression_token_type

The type of token that has been parsed out of an expression.

Enumerator
TOKEN_TYPE_FIELD 

The expression_token contains a field

TOKEN_TYPE_OPERATOR 

The expression_token contains an operator

TOKEN_TYPE_RESULT 

The expression_token contains a previous result

Definition at line 138 of file res_pjsip_history.c.

138  {
139  /*! The \c expression_token contains a field */
141  /*! The \c expression_token contains an operator */
143  /*! The \c expression_token contains a previous result */
145 };

Function Documentation

◆ __reg_module()

static void __reg_module ( void  )
static

Definition at line 1407 of file res_pjsip_history.c.

◆ __unreg_module()

static void __unreg_module ( void  )
static

Definition at line 1407 of file res_pjsip_history.c.

◆ AST_MODULE_SELF_SYM()

struct ast_module* AST_MODULE_SELF_SYM ( void  )

Definition at line 1407 of file res_pjsip_history.c.

◆ AST_VECTOR()

static AST_VECTOR ( vector_history_t  ,
struct pjsip_history_entry  
)
static

The one and only history that we've captured.

An operator that we understand in an expression

Our operator's symbol

Precedence of the symbol

Non-zero if the operator is evaluated right-to-left

Number of operands the operator takes

Evaluation function for unary operators

Parameters
opThe operator being evaluated
typeThe type of value contained in operand
operandA pointer to the value to evaluate
Return values
-1error
0evaluation is False
1evaluation is True

Evaluation function for binary operators

Parameters
opThe operator being evaluated
typeThe type of value contained in op_left
op_leftA pointer to the value to evaluate (a result or extracted from an entry)
op_rightThe expression token containing the other value (a result or user-provided)
Return values
-1error
0evaluation is False
1evaluation is True

Definition at line 80 of file res_pjsip_history.c.

Referenced by build_expression_queue(), and evaluate_history_entry().

85  {
86  /*! \brief Our operator's symbol */
87  const char *symbol;
88  /*! \brief Precedence of the symbol */
89  int precedence;
90  /*! \brief Non-zero if the operator is evaluated right-to-left */
91  int right_to_left;
92  /*! \brief Number of operands the operator takes */
93  int operands;
94  /*!
95  * \brief Evaluation function for unary operators
96  *
97  * \param op The operator being evaluated
98  * \param type The type of value contained in \c operand
99  * \param operand A pointer to the value to evaluate
100  *
101  * \retval -1 error
102  * \retval 0 evaluation is False
103  * \retval 1 evaluation is True
104  */
105  int (* const evaluate_unary)(struct operator *op, enum aco_option_type type, void *operand);
106  /*!
107  * \brief Evaluation function for binary operators
108  *
109  * \param op The operator being evaluated
110  * \param type The type of value contained in \c op_left
111  * \param op_left A pointer to the value to evaluate (a result or extracted from an entry)
112  * \param op_right The expression token containing the other value (a result or user-provided)
113  *
114  * \retval -1 error
115  * \retval 0 evaluation is False
116  * \retval 1 evaluation is True
117  */
118  int (* const evaluate)(struct operator *op, enum aco_option_type type, void *op_left, struct expression_token *op_right);
119 };
static const char type[]
Definition: chan_ooh323.c:109
aco_option_type
The option types.
A token in the expression or an evaluated part of the expression.

◆ build_expression_queue()

static struct expression_token* build_expression_queue ( struct ast_cli_args a)
static

Build a reverse polish notation expression queue.

This function is an implementation of the Shunting-Yard Algorithm. It takes a user provided infix-notation expression and converts it into a reverse polish notation expression, which is a queue of tokens that can be easily parsed.

a The CLI arguments provided by the User, containing the infix expression

Return values
NULLerror
expression_tokenA 'queue' of expression tokens in RPN

Definition at line 802 of file res_pjsip_history.c.

References APPEND_TO_OUTPUT, ast_cli_args::argc, ast_cli_args::argv, ARRAY_LEN, ast_log, ast_strdupa, AST_VECTOR(), AST_VECTOR_APPEND, AST_VECTOR_FREE, AST_VECTOR_GET, AST_VECTOR_INIT, AST_VECTOR_REMOVE, AST_VECTOR_SIZE, error(), expression_token_alloc(), expression_token_free(), LOG_WARNING, NULL, TOKEN_TYPE_FIELD, and TOKEN_TYPE_OPERATOR.

Referenced by filter_history().

803 {
804  AST_VECTOR(, struct operator *) operators; /* A stack of saved operators */
805  struct expression_token *output = NULL; /* The output queue */
806  struct expression_token *head = NULL; /* Pointer to the head of /c output */
807  int i;
808 
809 #define APPEND_TO_OUTPUT(output, token) do { \
810  if ((output)) { \
811  (output)->next = (token); \
812  (output) = (token); \
813  } else { \
814  (output) = (token); \
815  head = (output); \
816  } \
817 } while (0)
818 
819  if (AST_VECTOR_INIT(&operators, 8)) {
820  return NULL;
821  }
822 
823  for (i = 4; i < a->argc; i++) {
824  struct expression_token *out_token;
825  char *token = ast_strdupa(a->argv[i]);
826  int j;
827 
828  /* Strip off and append any left parentheses */
829  if (token[0] == '(') {
830  AST_VECTOR_APPEND(&operators, &left_paren);
831  if (!token[1]) {
832  continue;
833  }
834  token = &token[1];
835  }
836 
837  /* Handle the case where the token is an operator */
838  for (j = 0; j < ARRAY_LEN(allowed_operators); j++) {
839  int k;
840 
841  if (strcasecmp(token, allowed_operators[j].symbol)) {
842  continue;
843  }
844 
845  for (k = AST_VECTOR_SIZE(&operators) - 1; k >= 0; k--) {
846  struct operator *top = AST_VECTOR_GET(&operators, k);
847 
848  /* Remove and push queued up operators, if they are of
849  * less precedence than this operator
850  */
851  if ((allowed_operators[j].right_to_left && allowed_operators[j].precedence >= top->precedence)
852  || (!allowed_operators[j].right_to_left && allowed_operators[j].precedence > top->precedence)) {
853 
854  if (!(out_token = expression_token_alloc(TOKEN_TYPE_OPERATOR, top))) {
855  goto error;
856  }
857  APPEND_TO_OUTPUT(output, out_token);
858  AST_VECTOR_REMOVE(&operators, k, 1);
859  }
860  }
861 
862  AST_VECTOR_APPEND(&operators, &allowed_operators[j]);
863  token = NULL;
864  break;
865  }
866 
867  /* Token was an operator; continue to next token */
868  if (!token) {
869  continue;
870  }
871 
872  /* Handle a right parentheses either by itself or as part of the token.
873  * If part of the token, push the token onto the output queue first
874  */
875  if (token[0] == ')' || token[strlen(token) - 1] == ')') {
876 
877  if (token[strlen(token) - 1] == ')') {
878  token[strlen(token) - 1] = '\0';
879 
880  if (!(out_token = expression_token_alloc(TOKEN_TYPE_FIELD, token))) {
881  goto error;
882  }
883  APPEND_TO_OUTPUT(output, out_token);
884  token = NULL;
885  }
886 
887  for (j = AST_VECTOR_SIZE(&operators) - 1; j >= 0; j--) {
888  struct operator *top = AST_VECTOR_GET(&operators, j);
889 
890  AST_VECTOR_REMOVE(&operators, j, 1);
891  if (top == &left_paren) {
892  break;
893  }
894 
895  if (!(out_token = expression_token_alloc(TOKEN_TYPE_OPERATOR, top))) {
896  goto error;
897  }
898  APPEND_TO_OUTPUT(output, out_token);
899  }
900  }
901 
902  /* Just a plain token, push to the output queue */
903  if (token) {
904  if (!(out_token = expression_token_alloc(TOKEN_TYPE_FIELD, token))) {
905  goto error;
906  }
907  APPEND_TO_OUTPUT(output, out_token);
908  }
909  }
910 
911  /* Remove any non-applied operators that remain, applying them
912  * to the output queue
913  */
914  for (i = AST_VECTOR_SIZE(&operators) - 1; i >= 0; i--) {
915  struct operator *top = AST_VECTOR_GET(&operators, i);
916  struct expression_token *out_token;
917 
918  AST_VECTOR_REMOVE(&operators, i, 1);
919  if (top == &left_paren) {
920  ast_log(LOG_WARNING, "Unbalanced '(' parentheses in expression!\n");
921  continue;
922  }
923 
924  if (!(out_token = expression_token_alloc(TOKEN_TYPE_OPERATOR, top))) {
925  goto error;
926  }
927  APPEND_TO_OUTPUT(output, out_token);
928  }
929 
930  AST_VECTOR_FREE(&operators);
931  return head;
932 
933 error:
934  AST_VECTOR_FREE(&operators);
935  expression_token_free(output);
936  return NULL;
937 }
#define AST_VECTOR_FREE(vec)
Deallocates this vector.
Definition: vector.h:174
#define ARRAY_LEN(a)
Definition: isdn_lib.c:42
#define APPEND_TO_OUTPUT(output, token)
const int argc
Definition: cli.h:160
#define LOG_WARNING
Definition: logger.h:274
static AST_VECTOR(vector_history_t, struct pjsip_history_entry *)
The one and only history that we&#39;ve captured.
#define AST_VECTOR_APPEND(vec, elem)
Append an element to a vector, growing the vector if needed.
Definition: vector.h:256
static struct operator allowed_operators[]
Our allowed operations.
#define NULL
Definition: resample.c:96
static struct operator left_paren
Operator token for a left parenthesis.
#define ast_log
Definition: astobj2.c:42
#define AST_VECTOR_INIT(vec, size)
Initialize a vector.
Definition: vector.h:113
#define ast_strdupa(s)
duplicate a string in memory from the stack
Definition: astmm.h:300
const char *const * argv
Definition: cli.h:161
static struct expression_token * expression_token_free(struct expression_token *token)
Free an expression token and all others it references.
A token in the expression or an evaluated part of the expression.
#define AST_VECTOR_GET(vec, idx)
Get an element from a vector.
Definition: vector.h:682
int error(const char *format,...)
Definition: utils/frame.c:999
static struct expression_token * expression_token_alloc(enum expression_token_type token_type, void *value)
Allocate an expression token.
#define AST_VECTOR_REMOVE(vec, idx, preserve_ordered)
Remove an element from a vector by index.
Definition: vector.h:412
#define AST_VECTOR_SIZE(vec)
Get the number of elements in a vector.
Definition: vector.h:611

◆ clear_history_entries()

static int clear_history_entries ( void *  obj)
static

Remove all entries from vector_history.

This must be called from a registered PJSIP thread

Definition at line 779 of file res_pjsip_history.c.

References ast_mutex_lock, ast_mutex_unlock, AST_VECTOR_RESET, clear_history_entry_cb(), history_lock, and packet_number.

Referenced by pjsip_set_history(), and unload_module().

780 {
782  AST_VECTOR_RESET(&vector_history, clear_history_entry_cb);
783  packet_number = 0;
785 
786  return 0;
787 }
static int packet_number
Packet count.
static ast_mutex_t history_lock
Mutex that protects vector_history.
#define ast_mutex_lock(a)
Definition: lock.h:187
#define AST_VECTOR_RESET(vec, cleanup)
Reset vector.
Definition: vector.h:627
static void clear_history_entry_cb(struct pjsip_history_entry *entry)
Vector callback that releases the reference for the entry in a history vector.
#define ast_mutex_unlock(a)
Definition: lock.h:188

◆ clear_history_entry_cb()

static void clear_history_entry_cb ( struct pjsip_history_entry entry)
static

Vector callback that releases the reference for the entry in a history vector.

Definition at line 769 of file res_pjsip_history.c.

References ao2_ref.

Referenced by clear_history_entries(), filter_history(), and safe_vector_cleanup().

770 {
771  ao2_ref(entry, -1);
772 }
#define ao2_ref(o, delta)
Definition: astobj2.h:464

◆ display_entry_list()

static void display_entry_list ( struct ast_cli_args a,
struct vector_history_t *  vec 
)
static

Print a list of the entries to the CLI.

Definition at line 1183 of file res_pjsip_history.c.

References ast_cli(), AST_VECTOR_GET, AST_VECTOR_SIZE, ast_cli_args::fd, and sprint_list_entry().

Referenced by pjsip_show_history().

1184 {
1185  int i;
1186 
1187  ast_cli(a->fd, "%-5.5s %-10.10s %-30.30s %-35.35s\n",
1188  "No.",
1189  "Timestamp",
1190  "(Dir) Address",
1191  "SIP Message");
1192  ast_cli(a->fd, "===== ========== ============================== ===================================\n");
1193 
1194  for (i = 0; i < AST_VECTOR_SIZE(vec); i++) {
1195  struct pjsip_history_entry *entry;
1196  char line[256];
1197 
1198  entry = AST_VECTOR_GET(vec, i);
1199  sprint_list_entry(entry, line, sizeof(line));
1200 
1201  ast_cli(a->fd, "%s\n", line);
1202  }
1203 }
static void sprint_list_entry(struct pjsip_history_entry *entry, char *line, int len)
Format single line history entry.
void ast_cli(int fd, const char *fmt,...)
Definition: clicompat.c:6
const int fd
Definition: cli.h:159
#define AST_VECTOR_GET(vec, idx)
Get an element from a vector.
Definition: vector.h:682
Definition: search.h:40
An item in the history.
#define AST_VECTOR_SIZE(vec)
Get the number of elements in a vector.
Definition: vector.h:611

◆ display_single_entry()

static void display_single_entry ( struct ast_cli_args a,
struct pjsip_history_entry entry 
)
static

Print a detailed view of a single entry in the history to the CLI.

Definition at line 1150 of file res_pjsip_history.c.

References ast_calloc, ast_cli(), ast_free, ast_log, buf, pjsip_history_entry::dst, ast_cli_args::fd, LOG_WARNING, pjsip_history_entry::msg, pjsip_history_entry::number, pjsip_history_entry::src, pjsip_history_entry::timestamp, and pjsip_history_entry::transmitted.

Referenced by pjsip_show_history().

1151 {
1152  char addr[64];
1153  char *buf;
1154 
1155  buf = ast_calloc(1, PJSIP_MAX_PKT_LEN * sizeof(char));
1156  if (!buf) {
1157  return;
1158  }
1159 
1160  if (pjsip_msg_print(entry->msg, buf, PJSIP_MAX_PKT_LEN) == -1) {
1161  ast_log(LOG_WARNING, "Unable to print SIP message %d: packet too large!\n", entry->number);
1162  ast_free(buf);
1163  return;
1164  }
1165 
1166  if (entry->transmitted) {
1167  pj_sockaddr_print(&entry->dst, addr, sizeof(addr), 3);
1168  } else {
1169  pj_sockaddr_print(&entry->src, addr, sizeof(addr), 3);
1170  }
1171 
1172  ast_cli(a->fd, "<--- History Entry %d %s %s at %-10.10ld --->\n",
1173  entry->number,
1174  entry->transmitted ? "Sent to" : "Received from",
1175  addr,
1176  entry->timestamp.tv_sec);
1177  ast_cli(a->fd, "%s\n", buf);
1178 
1179  ast_free(buf);
1180 }
char buf[BUFSIZE]
Definition: eagi_proxy.c:66
#define LOG_WARNING
Definition: logger.h:274
int transmitted
Whether or not we transmitted the packet.
pj_sockaddr dst
Destination address.
int number
Packet number.
struct timeval timestamp
Time the packet was transmitted/received.
void ast_cli(int fd, const char *fmt,...)
Definition: clicompat.c:6
pj_sockaddr src
Source address.
#define ast_log
Definition: astobj2.c:42
const int fd
Definition: cli.h:159
pjsip_msg * msg
The actual SIP message.
#define ast_free(a)
Definition: astmm.h:182
#define ast_calloc(num, len)
A wrapper for calloc()
Definition: astmm.h:204

◆ entry_get_addr()

static void* entry_get_addr ( struct pjsip_history_entry entry)
static

Callback to retrieve the entry's destination address.

Definition at line 483 of file res_pjsip_history.c.

References pjsip_history_entry::dst, pjsip_history_entry::src, and pjsip_history_entry::transmitted.

484 {
485  if (entry->transmitted) {
486  return &entry->dst;
487  } else {
488  return &entry->src;
489  }
490 }
int transmitted
Whether or not we transmitted the packet.
pj_sockaddr dst
Destination address.
pj_sockaddr src
Source address.

◆ entry_get_number()

static void* entry_get_number ( struct pjsip_history_entry entry)
static

Callback to retrieve the entry index number.

Definition at line 471 of file res_pjsip_history.c.

References pjsip_history_entry::number.

472 {
473  return &entry->number;
474 }
int number
Packet number.

◆ entry_get_sip_msg_call_id()

static void* entry_get_sip_msg_call_id ( struct pjsip_history_entry entry)
static

Callback to retrieve the entry's SIP Call-ID header.

Definition at line 503 of file res_pjsip_history.c.

References pjsip_history_entry::msg.

504 {
505  pjsip_cid_hdr *cid_hdr;
506 
507  cid_hdr = PJSIP_MSG_CID_HDR(entry->msg);
508 
509  return &cid_hdr->id;
510 }
pjsip_msg * msg
The actual SIP message.

◆ entry_get_sip_msg_request_method()

static void* entry_get_sip_msg_request_method ( struct pjsip_history_entry entry)
static

Callback to retrieve the entry's SIP request method type.

Definition at line 493 of file res_pjsip_history.c.

References pjsip_history_entry::msg, and NULL.

494 {
495  if (entry->msg->type != PJSIP_REQUEST_MSG) {
496  return NULL;
497  }
498 
499  return &entry->msg->line.req.method.name;
500 }
#define NULL
Definition: resample.c:96
pjsip_msg * msg
The actual SIP message.

◆ entry_get_timestamp()

static void* entry_get_timestamp ( struct pjsip_history_entry entry)
static

Callback to retrieve the entry's timestamp.

Definition at line 477 of file res_pjsip_history.c.

References pjsip_history_entry::timestamp.

478 {
479  return &entry->timestamp;
480 }
struct timeval timestamp
Time the packet was transmitted/received.

◆ evaluate_and()

static int evaluate_and ( struct operator*  op,
enum aco_option_type  type,
void *  op_left,
struct expression_token op_right 
)
static

Definition at line 374 of file res_pjsip_history.c.

References ast_log, LOG_WARNING, OPT_BOOL_T, OPT_BOOLFLAG_T, OPT_INT_T, OPT_UINT_T, and expression_token::result.

375 {
376  switch (type) {
377  case OPT_BOOL_T:
378  case OPT_BOOLFLAG_T:
379  case OPT_INT_T:
380  case OPT_UINT_T:
381  return (*(int *)op_left && op_right->result);
382  default:
383  ast_log(LOG_WARNING, "Cannot evaluate: invalid operand type for operator '%s'\n", op->symbol);
384  }
385 
386  return -1;
387 }
static const char type[]
Definition: chan_ooh323.c:109
#define LOG_WARNING
Definition: logger.h:274
Type for default option handler for bools (ast_true/ast_false) that are stored in a flag...
#define ast_log
Definition: astobj2.c:42
Type for default option handler for unsigned integers.
int result
The result of an evaluated expression.
Type for default option handler for bools (ast_true/ast_false)
Type for default option handler for signed integers.

◆ evaluate_equal()

static int evaluate_equal ( struct operator*  op,
enum aco_option_type  type,
void *  op_left,
struct expression_token op_right 
)
static

Operator callback for determining equality.

Definition at line 167 of file res_pjsip_history.c.

References ast_log, ast_tvcmp(), expression_token::field, LOG_WARNING, OPT_BOOL_T, OPT_BOOLFLAG_T, OPT_CHAR_ARRAY_T, OPT_DOUBLE_T, OPT_INT_T, OPT_NOOP_T, OPT_SOCKADDR_T, OPT_STRINGFIELD_T, and OPT_UINT_T.

Referenced by evaluate_not_equal().

168 {
169  switch (type) {
170  case OPT_BOOL_T:
171  case OPT_BOOLFLAG_T:
172  case OPT_INT_T:
173  case OPT_UINT_T:
174  {
175  int right;
176 
177  if (sscanf(op_right->field, "%30d", &right) != 1) {
178  ast_log(LOG_WARNING, "Unable to extract field '%s': not an integer\n", op_right->field);
179  return -1;
180  }
181  return (*(int *)op_left) == right;
182  }
183  case OPT_DOUBLE_T:
184  {
185  double right;
186 
187  if (sscanf(op_right->field, "%lf", &right) != 1) {
188  ast_log(LOG_WARNING, "Unable to extract field '%s': not a double\n", op_right->field);
189  return -1;
190  }
191  return (*(double *)op_left) == right;
192  }
193  case OPT_CHAR_ARRAY_T:
194  case OPT_STRINGFIELD_T:
195  /* In our case, we operate on pj_str_t */
196  return pj_strcmp2(op_left, op_right->field) == 0;
197  case OPT_NOOP_T:
198  /* Used for timeval */
199  {
200  struct timeval right = { 0, };
201 
202  if (sscanf(op_right->field, "%ld", &right.tv_sec) != 1) {
203  ast_log(LOG_WARNING, "Unable to extract field '%s': not a timestamp\n", op_right->field);
204  return -1;
205  }
206 
207  return ast_tvcmp(*(struct timeval *)op_left, right) == 0;
208  }
209  case OPT_SOCKADDR_T:
210  /* In our case, we operate only on pj_sockaddr_t */
211  {
212  pj_sockaddr right;
213  pj_str_t str_right;
214 
215  pj_cstr(&str_right, op_right->field);
216  if (pj_sockaddr_parse(pj_AF_UNSPEC(), 0, &str_right, &right) != PJ_SUCCESS) {
217  ast_log(LOG_WARNING, "Unable to convert field '%s': not an IPv4 or IPv6 address\n", op_right->field);
218  return -1;
219  }
220 
221  return pj_sockaddr_cmp(op_left, &right) == 0;
222  }
223  default:
224  ast_log(LOG_WARNING, "Cannot evaluate field '%s': invalid type for operator '%s'\n",
225  op_right->field, op->symbol);
226  }
227 
228  return -1;
229 }
Type for default handler for ast_sockaddrs.
static const char type[]
Definition: chan_ooh323.c:109
#define LOG_WARNING
Definition: logger.h:274
char field[]
The field in the expression.
Type for a default handler that should do nothing.
Type for default option handler for bools (ast_true/ast_false) that are stored in a flag...
Type for default option handler for character array strings.
#define ast_log
Definition: astobj2.c:42
Type for default option handler for unsigned integers.
int ast_tvcmp(struct timeval _a, struct timeval _b)
Compres two struct timeval instances returning -1, 0, 1 if the first arg is smaller, equal or greater to the second.
Definition: time.h:128
Type for default option handler for bools (ast_true/ast_false)
Type for default option handler for doubles.
Type for default option handler for stringfields.
Type for default option handler for signed integers.

◆ evaluate_greater_than()

static int evaluate_greater_than ( struct operator*  op,
enum aco_option_type  type,
void *  op_left,
struct expression_token op_right 
)
static

Definition at line 291 of file res_pjsip_history.c.

References ast_log, ast_tvcmp(), expression_token::field, LOG_WARNING, OPT_BOOL_T, OPT_BOOLFLAG_T, OPT_DOUBLE_T, OPT_INT_T, OPT_NOOP_T, and OPT_UINT_T.

Referenced by evaluate_less_than_or_equal().

292 {
293  switch (type) {
294  case OPT_BOOL_T:
295  case OPT_BOOLFLAG_T:
296  case OPT_INT_T:
297  case OPT_UINT_T:
298  {
299  int right;
300 
301  if (sscanf(op_right->field, "%30d", &right) != 1) {
302  ast_log(LOG_WARNING, "Unable to extract field '%s': not an integer\n", op_right->field);
303  return -1;
304  }
305  return (*(int *)op_left) > right;
306  }
307  case OPT_DOUBLE_T:
308  {
309  double right;
310 
311  if (sscanf(op_right->field, "%lf", &right) != 1) {
312  ast_log(LOG_WARNING, "Unable to extract field '%s': not a double\n", op_right->field);
313  return -1;
314  }
315  return (*(double *)op_left) > right;
316  }
317  case OPT_NOOP_T:
318  /* Used for timeval */
319  {
320  struct timeval right = { 0, };
321 
322  if (sscanf(op_right->field, "%ld", &right.tv_sec) != 1) {
323  ast_log(LOG_WARNING, "Unable to extract field '%s': not a timestamp\n", op_right->field);
324  return -1;
325  }
326 
327  return ast_tvcmp(*(struct timeval *)op_left, right) == 1;
328  }
329  default:
330  ast_log(LOG_WARNING, "Cannot evaluate field '%s': invalid type for operator '%s'\n",
331  op_right->field, op->symbol);
332  }
333 
334  return -1;
335 }
static const char type[]
Definition: chan_ooh323.c:109
#define LOG_WARNING
Definition: logger.h:274
char field[]
The field in the expression.
Type for a default handler that should do nothing.
Type for default option handler for bools (ast_true/ast_false) that are stored in a flag...
#define ast_log
Definition: astobj2.c:42
Type for default option handler for unsigned integers.
int ast_tvcmp(struct timeval _a, struct timeval _b)
Compres two struct timeval instances returning -1, 0, 1 if the first arg is smaller, equal or greater to the second.
Definition: time.h:128
Type for default option handler for bools (ast_true/ast_false)
Type for default option handler for doubles.
Type for default option handler for signed integers.

◆ evaluate_greater_than_or_equal()

static int evaluate_greater_than_or_equal ( struct operator*  op,
enum aco_option_type  type,
void *  op_left,
struct expression_token op_right 
)
static

Definition at line 348 of file res_pjsip_history.c.

References evaluate_less_than().

349 {
350  return !evaluate_less_than(op, type, op_left, op_right);
351 }
static const char type[]
Definition: chan_ooh323.c:109
static int evaluate_less_than(struct operator*op, enum aco_option_type type, void *op_left, struct expression_token *op_right)

◆ evaluate_history_entry()

static int evaluate_history_entry ( struct pjsip_history_entry entry,
struct expression_token queue 
)
static

Evaluate a single entry in this history using a RPN expression.

Parameters
entryThe entry in the history to evaluate
queueThe RPN expression
Return values
0The expression evaluated FALSE on entry
1The expression evaluated TRUE on entry
-1The expression errored

Definition at line 949 of file res_pjsip_history.c.

References ast_assert, ast_free, ast_log, AST_VECTOR(), AST_VECTOR_APPEND, AST_VECTOR_FREE, AST_VECTOR_GET, AST_VECTOR_INIT, AST_VECTOR_REMOVE, AST_VECTOR_SIZE, error(), expression_token_alloc(), expression_token_free(), expression_token::field, get_allowed_field(), allowed_field::get_field, LOG_WARNING, expression_token::next, NULL, expression_token::op, OPT_INT_T, result, expression_token::result, allowed_field::return_type, expression_token::token_type, TOKEN_TYPE_FIELD, TOKEN_TYPE_RESULT, type, and value.

Referenced by filter_history().

950 {
951  AST_VECTOR(, struct expression_token *) stack; /* Our stack of results and operands */
952  struct expression_token *it_queue;
953  struct expression_token *final;
954  int result;
955  int i;
956 
957  if (AST_VECTOR_INIT(&stack, 16)) {
958  return -1;
959  }
960 
961  for (it_queue = queue; it_queue; it_queue = it_queue->next) {
962  struct expression_token *op_one;
963  struct expression_token *op_two = NULL;
964  struct expression_token *result;
965  int res = 0;
966 
967  /* If this is not an operator, push it to the stack */
968  if (!it_queue->op) {
969  if (AST_VECTOR_APPEND(&stack, it_queue)) {
970  goto error;
971  }
972  continue;
973  }
974 
975  if (AST_VECTOR_SIZE(&stack) < it_queue->op->operands) {
976  ast_log(LOG_WARNING, "Unable to evaluate expression operator '%s': not enough operands\n",
977  it_queue->op->symbol);
978  goto error;
979  }
980 
981  if (it_queue->op->operands == 1) {
982  /* Unary operators currently consist only of 'not', which can only act
983  * upon an evaluated condition result.
984  */
985  ast_assert(it_queue->op->evaluate_unary != NULL);
986 
987  op_one = AST_VECTOR_REMOVE(&stack, AST_VECTOR_SIZE(&stack) - 1, 1);
988  if (op_one->token_type != TOKEN_TYPE_RESULT) {
989  ast_log(LOG_WARNING, "Unable to evaluate '%s': operand is not the result of an operation\n",
990  it_queue->op->symbol);
991  goto error;
992  }
993 
994  res = it_queue->op->evaluate_unary(it_queue->op, OPT_INT_T, &op_one->result) == 0 ? 0 : 1;
995  } else if (it_queue->op->operands == 2) {
996  struct allowed_field *field;
997  enum aco_option_type type;
998  void *value;
999 
1000  ast_assert(it_queue->op->evaluate != NULL);
1001 
1002  op_one = AST_VECTOR_REMOVE(&stack, AST_VECTOR_SIZE(&stack) - 1, 1);
1003  op_two = AST_VECTOR_REMOVE(&stack, AST_VECTOR_SIZE(&stack) - 1, 1);
1004 
1005  /* If operand two is a field, then it must be a field we recognize. */
1006  if (op_two->token_type == TOKEN_TYPE_FIELD) {
1007  field = get_allowed_field(op_two);
1008  if (!field) {
1009  ast_log(LOG_WARNING, "Unknown or unrecognized field: %s\n", op_two->field);
1010  goto error;
1011  }
1012 
1013  type = field->return_type;
1014  value = field->get_field(entry);
1015  } else if (op_two->token_type == TOKEN_TYPE_RESULT) {
1016  type = OPT_INT_T;
1017  value = &op_two->result;
1018  } else {
1019  ast_log(LOG_WARNING, "Attempting to evaluate an operator: %s\n", op_two->op->symbol);
1020  goto error;
1021  }
1022 
1023  if (value) {
1024  res = it_queue->op->evaluate(it_queue->op, type, value, op_one) == 0 ? 0 : 1;
1025  } else {
1026  res = 0;
1027  }
1028  } else {
1029  ast_log(LOG_WARNING, "Operator '%s' has an invalid number of operands\n", it_queue->op->symbol);
1030  ast_assert(0);
1031  goto error;
1032  }
1033 
1034  /* Results are temporary; clean used ones up */
1035  if (op_one && op_one->token_type == TOKEN_TYPE_RESULT) {
1036  ast_free(op_one);
1037  }
1038  if (op_two && op_two->token_type == TOKEN_TYPE_RESULT) {
1039  ast_free(op_two);
1040  }
1041 
1042  /* Push the result onto the stack */
1043  result = expression_token_alloc(TOKEN_TYPE_RESULT, &res);
1044  if (!result) {
1045  goto error;
1046  }
1047  if (AST_VECTOR_APPEND(&stack, result)) {
1048  expression_token_free(result);
1049 
1050  goto error;
1051  }
1052  }
1053 
1054  /*
1055  * When the evaluation is complete, we must have:
1056  * - A single result remaining on the stack
1057  * - An actual result
1058  */
1059  if (AST_VECTOR_SIZE(&stack) != 1) {
1060  ast_log(LOG_WARNING, "Expression was unbalanced: %zu results remained after evaluation\n",
1061  AST_VECTOR_SIZE(&stack));
1062  goto error;
1063  }
1064 
1065  final = AST_VECTOR_GET(&stack, 0);
1066  if (final->token_type != TOKEN_TYPE_RESULT) {
1067  ast_log(LOG_WARNING, "Expression did not create a usable result\n");
1068  goto error;
1069  }
1070  result = final->result;
1071  ast_free(final);
1072  AST_VECTOR_FREE(&stack);
1073 
1074  return result;
1075 
1076 error:
1077  /* Clean out any remaining result expression tokens */
1078  for (i = 0; i < AST_VECTOR_SIZE(&stack); i++) {
1079  struct expression_token *failed_token = AST_VECTOR_GET(&stack, i);
1080 
1081  if (failed_token->token_type == TOKEN_TYPE_RESULT) {
1082  ast_free(failed_token);
1083  }
1084  }
1085  AST_VECTOR_FREE(&stack);
1086  return -1;
1087 }
#define AST_VECTOR_FREE(vec)
Deallocates this vector.
Definition: vector.h:174
static const char type[]
Definition: chan_ooh323.c:109
#define LOG_WARNING
Definition: logger.h:274
char field[]
The field in the expression.
static AST_VECTOR(vector_history_t, struct pjsip_history_entry *)
The one and only history that we&#39;ve captured.
#define AST_VECTOR_APPEND(vec, elem)
Append an element to a vector, growing the vector if needed.
Definition: vector.h:256
void *(*const get_field)(struct pjsip_history_entry *entry)
Function that returns the field from a pjsip_history_entry.
#define ast_assert(a)
Definition: utils.h:695
#define NULL
Definition: resample.c:96
int value
Definition: syslog.c:37
struct operator* op
An operator that evaluates expressions.
enum expression_token_type token_type
The type of value stored in the expression token.
A field that we understand and can perform operations on.
#define ast_log
Definition: astobj2.c:42
#define AST_VECTOR_INIT(vec, size)
Initialize a vector.
Definition: vector.h:113
enum aco_option_type return_type
The type /c get_field returns.
aco_option_type
The option types.
int result
The result of an evaluated expression.
static struct allowed_field * get_allowed_field(struct expression_token *token)
Determine if the expression token matches a field in allowed_fields.
static struct expression_token * expression_token_free(struct expression_token *token)
Free an expression token and all others it references.
#define ast_free(a)
Definition: astmm.h:182
A token in the expression or an evaluated part of the expression.
#define AST_VECTOR_GET(vec, idx)
Get an element from a vector.
Definition: vector.h:682
static PGresult * result
Definition: cel_pgsql.c:88
int error(const char *format,...)
Definition: utils/frame.c:999
static struct expression_token * expression_token_alloc(enum expression_token_type token_type, void *value)
Allocate an expression token.
Type for default option handler for signed integers.
#define AST_VECTOR_REMOVE(vec, idx, preserve_ordered)
Remove an element from a vector by index.
Definition: vector.h:412
#define AST_VECTOR_SIZE(vec)
Get the number of elements in a vector.
Definition: vector.h:611
struct expression_token * next
The next expression token in the queue.

◆ evaluate_less_than()

static int evaluate_less_than ( struct operator*  op,
enum aco_option_type  type,
void *  op_left,
struct expression_token op_right 
)
static

Definition at line 242 of file res_pjsip_history.c.

References ast_log, ast_tvcmp(), expression_token::field, LOG_WARNING, OPT_BOOL_T, OPT_BOOLFLAG_T, OPT_DOUBLE_T, OPT_INT_T, OPT_NOOP_T, and OPT_UINT_T.

Referenced by evaluate_greater_than_or_equal().

243 {
244  switch (type) {
245  case OPT_BOOL_T:
246  case OPT_BOOLFLAG_T:
247  case OPT_INT_T:
248  case OPT_UINT_T:
249  {
250  int right;
251 
252  if (sscanf(op_right->field, "%30d", &right) != 1) {
253  ast_log(LOG_WARNING, "Unable to extract field '%s': not an integer\n", op_right->field);
254  return -1;
255  }
256  return (*(int *)op_left) < right;
257  }
258  case OPT_DOUBLE_T:
259  {
260  double right;
261 
262  if (sscanf(op_right->field, "%lf", &right) != 1) {
263  ast_log(LOG_WARNING, "Unable to extract field '%s': not a double\n", op_right->field);
264  return -1;
265  }
266  return (*(double *)op_left) < right;
267  }
268  case OPT_NOOP_T:
269  /* Used for timeval */
270  {
271  struct timeval right = { 0, };
272 
273  if (sscanf(op_right->field, "%ld", &right.tv_sec) != 1) {
274  ast_log(LOG_WARNING, "Unable to extract field '%s': not a timestamp\n", op_right->field);
275  return -1;
276  }
277 
278  return ast_tvcmp(*(struct timeval *)op_left, right) == -1;
279  }
280  default:
281  ast_log(LOG_WARNING, "Cannot evaluate field '%s': invalid type for operator '%s'\n",
282  op_right->field, op->symbol);
283  }
284 
285  return -1;
286 }
static const char type[]
Definition: chan_ooh323.c:109
#define LOG_WARNING
Definition: logger.h:274
char field[]
The field in the expression.
Type for a default handler that should do nothing.
Type for default option handler for bools (ast_true/ast_false) that are stored in a flag...
#define ast_log
Definition: astobj2.c:42
Type for default option handler for unsigned integers.
int ast_tvcmp(struct timeval _a, struct timeval _b)
Compres two struct timeval instances returning -1, 0, 1 if the first arg is smaller, equal or greater to the second.
Definition: time.h:128
Type for default option handler for bools (ast_true/ast_false)
Type for default option handler for doubles.
Type for default option handler for signed integers.

◆ evaluate_less_than_or_equal()

static int evaluate_less_than_or_equal ( struct operator*  op,
enum aco_option_type  type,
void *  op_left,
struct expression_token op_right 
)
static

Definition at line 340 of file res_pjsip_history.c.

References evaluate_greater_than().

341 {
342  return !evaluate_greater_than(op, type, op_left, op_right);
343 }
static const char type[]
Definition: chan_ooh323.c:109
static int evaluate_greater_than(struct operator*op, enum aco_option_type type, void *op_left, struct expression_token *op_right)

◆ evaluate_like()

static int evaluate_like ( struct operator*  op,
enum aco_option_type  type,
void *  op_left,
struct expression_token op_right 
)
static

Definition at line 410 of file res_pjsip_history.c.

References ast_copy_pj_str(), ast_log, buf, expression_token::field, LOG_WARNING, NULL, OPT_CHAR_ARRAY_T, OPT_STRINGFIELD_T, and result.

411 {
412  switch (type) {
413  case OPT_CHAR_ARRAY_T:
414  case OPT_STRINGFIELD_T:
415  /* In our case, we operate on pj_str_t */
416  {
417  int result;
418  regex_t regexbuf;
419  char buf[pj_strlen(op_left) + 1];
420 
421  ast_copy_pj_str(buf, op_left, pj_strlen(op_left));
422  if (regcomp(&regexbuf, op_right->field, REG_EXTENDED | REG_NOSUB)) {
423  ast_log(LOG_WARNING, "Failed to compile '%s' into a regular expression\n", op_right->field);
424  return -1;
425  }
426 
427  result = (regexec(&regexbuf, buf, 0, NULL, 0) == 0);
428  regfree(&regexbuf);
429 
430  return result;
431  }
432  default:
433  ast_log(LOG_WARNING, "Cannot evaluate: invalid operand type for operator '%s'\n", op->symbol);
434  }
435 
436  return -1;
437 }
static const char type[]
Definition: chan_ooh323.c:109
char buf[BUFSIZE]
Definition: eagi_proxy.c:66
#define LOG_WARNING
Definition: logger.h:274
char field[]
The field in the expression.
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 NULL
Definition: resample.c:96
Type for default option handler for character array strings.
#define ast_log
Definition: astobj2.c:42
static PGresult * result
Definition: cel_pgsql.c:88
Type for default option handler for stringfields.

◆ evaluate_not()

static int evaluate_not ( struct operator*  op,
enum aco_option_type  type,
void *  operand 
)
static

Definition at line 356 of file res_pjsip_history.c.

References ast_log, LOG_WARNING, OPT_BOOL_T, OPT_BOOLFLAG_T, OPT_INT_T, and OPT_UINT_T.

357 {
358  switch (type) {
359  case OPT_BOOL_T:
360  case OPT_BOOLFLAG_T:
361  case OPT_INT_T:
362  case OPT_UINT_T:
363  return !(*(int *)operand);
364  default:
365  ast_log(LOG_WARNING, "Cannot evaluate: invalid operand type for operator '%s'\n", op->symbol);
366  }
367 
368  return -1;
369 }
static const char type[]
Definition: chan_ooh323.c:109
#define LOG_WARNING
Definition: logger.h:274
Type for default option handler for bools (ast_true/ast_false) that are stored in a flag...
#define ast_log
Definition: astobj2.c:42
Type for default option handler for unsigned integers.
Type for default option handler for bools (ast_true/ast_false)
Type for default option handler for signed integers.

◆ evaluate_not_equal()

static int evaluate_not_equal ( struct operator*  op,
enum aco_option_type  type,
void *  op_left,
struct expression_token op_right 
)
static

Operator callback for determining inequality.

Definition at line 234 of file res_pjsip_history.c.

References evaluate_equal().

235 {
236  return !evaluate_equal(op, type, op_left, op_right);
237 }
static const char type[]
Definition: chan_ooh323.c:109
static int evaluate_equal(struct operator*op, enum aco_option_type type, void *op_left, struct expression_token *op_right)
Operator callback for determining equality.

◆ evaluate_or()

static int evaluate_or ( struct operator*  op,
enum aco_option_type  type,
void *  op_left,
struct expression_token op_right 
)
static

Definition at line 392 of file res_pjsip_history.c.

References ast_log, LOG_WARNING, OPT_BOOL_T, OPT_BOOLFLAG_T, OPT_INT_T, OPT_UINT_T, and expression_token::result.

393 {
394  switch (type) {
395  case OPT_BOOL_T:
396  case OPT_BOOLFLAG_T:
397  case OPT_INT_T:
398  case OPT_UINT_T:
399  return (*(int *)op_left || op_right->result);
400  default:
401  ast_log(LOG_WARNING, "Cannot evaluate: invalid operand type for operator '%s'\n", op->symbol);
402  }
403 
404  return -1;
405 }
static const char type[]
Definition: chan_ooh323.c:109
#define LOG_WARNING
Definition: logger.h:274
Type for default option handler for bools (ast_true/ast_false) that are stored in a flag...
#define ast_log
Definition: astobj2.c:42
Type for default option handler for unsigned integers.
int result
The result of an evaluated expression.
Type for default option handler for bools (ast_true/ast_false)
Type for default option handler for signed integers.

◆ expression_token_alloc()

static struct expression_token* expression_token_alloc ( enum expression_token_type  token_type,
void *  value 
)
static

Allocate an expression token.

Parameters
token_typeThe type of token in the expression
valueThe value/operator/result to pack into the token
Return values
NULLon failure

Definition at line 547 of file res_pjsip_history.c.

References ast_assert, ast_calloc, expression_token::field, NULL, expression_token::op, expression_token::result, expression_token::token_type, TOKEN_TYPE_FIELD, TOKEN_TYPE_OPERATOR, TOKEN_TYPE_RESULT, and value.

Referenced by build_expression_queue(), and evaluate_history_entry().

548 {
549  struct expression_token *token;
550 
551  switch (token_type) {
552  case TOKEN_TYPE_RESULT:
553  case TOKEN_TYPE_OPERATOR:
554  token = ast_calloc(1, sizeof(*token));
555  break;
556  case TOKEN_TYPE_FIELD:
557  token = ast_calloc(1, sizeof(*token) + strlen((const char *)value) + 1);
558  break;
559  default:
560  ast_assert(0);
561  return NULL;
562  }
563 
564  if (!token) {
565  return NULL;
566  }
567  token->token_type = token_type;
568 
569  switch (token_type) {
570  case TOKEN_TYPE_RESULT:
571  token->result = *(int *)value;
572  break;
573  case TOKEN_TYPE_OPERATOR:
574  token->op = value;
575  break;
576  case TOKEN_TYPE_FIELD:
577  strcpy(token->field, value); /* safe */
578  break;
579  default:
580  ast_assert(0);
581  }
582 
583  return token;
584 }
char field[]
The field in the expression.
#define ast_assert(a)
Definition: utils.h:695
#define NULL
Definition: resample.c:96
int value
Definition: syslog.c:37
struct operator* op
An operator that evaluates expressions.
enum expression_token_type token_type
The type of value stored in the expression token.
int result
The result of an evaluated expression.
#define ast_calloc(num, len)
A wrapper for calloc()
Definition: astmm.h:204
A token in the expression or an evaluated part of the expression.

◆ expression_token_free()

static struct expression_token* expression_token_free ( struct expression_token token)
static

Free an expression token and all others it references.

Definition at line 523 of file res_pjsip_history.c.

References ast_free, expression_token::next, and NULL.

Referenced by build_expression_queue(), evaluate_history_entry(), and filter_history().

524 {
525  struct expression_token *it_token;
526 
527  it_token = token;
528  while (it_token) {
529  struct expression_token *prev = it_token;
530 
531  it_token = it_token->next;
532  ast_free(prev);
533  }
534 
535  return NULL;
536 }
#define NULL
Definition: resample.c:96
#define ast_free(a)
Definition: astmm.h:182
A token in the expression or an evaluated part of the expression.
struct expression_token * next
The next expression token in the queue.

◆ filter_history()

static struct vector_history_t* filter_history ( struct ast_cli_args a)
static

Create a filtered history based on a user provided expression.

Parameters
aThe CLI arguments containing the expression
Return values
NULLon error
Avector containing the filtered history on success

Definition at line 1097 of file res_pjsip_history.c.

References ao2_bump, ao2_cleanup, ast_free, ast_malloc, ast_mutex_lock, ast_mutex_unlock, AST_VECTOR_APPEND, AST_VECTOR_FREE, AST_VECTOR_GET, AST_VECTOR_INIT, AST_VECTOR_PTR_FREE, AST_VECTOR_RESET, AST_VECTOR_SIZE, build_expression_queue(), clear_history_entry_cb(), evaluate_history_entry(), expression_token_free(), HISTORY_INITIAL_SIZE, history_lock, and NULL.

Referenced by pjsip_show_history().

1098 {
1099  struct vector_history_t *output;
1100  struct expression_token *queue;
1101  int i;
1102 
1103  output = ast_malloc(sizeof(*output));
1104  if (!output) {
1105  return NULL;
1106  }
1107 
1108  if (AST_VECTOR_INIT(output, HISTORY_INITIAL_SIZE / 2)) {
1109  ast_free(output);
1110  return NULL;
1111  }
1112 
1113  queue = build_expression_queue(a);
1114  if (!queue) {
1115  AST_VECTOR_PTR_FREE(output);
1116  return NULL;
1117  }
1118 
1120  for (i = 0; i < AST_VECTOR_SIZE(&vector_history); i++) {
1121  struct pjsip_history_entry *entry = AST_VECTOR_GET(&vector_history, i);
1122  int res;
1123 
1124  res = evaluate_history_entry(entry, queue);
1125  if (res == -1) {
1126  /* Error in expression evaluation; bail */
1129  AST_VECTOR_FREE(output);
1130  ast_free(output);
1131  expression_token_free(queue);
1132  return NULL;
1133  } else if (!res) {
1134  continue;
1135  } else {
1136  ao2_bump(entry);
1137  if (AST_VECTOR_APPEND(output, entry)) {
1138  ao2_cleanup(entry);
1139  }
1140  }
1141  }
1143 
1144  expression_token_free(queue);
1145 
1146  return output;
1147 }
#define AST_VECTOR_FREE(vec)
Deallocates this vector.
Definition: vector.h:174
static int evaluate_history_entry(struct pjsip_history_entry *entry, struct expression_token *queue)
Evaluate a single entry in this history using a RPN expression.
#define AST_VECTOR_APPEND(vec, elem)
Append an element to a vector, growing the vector if needed.
Definition: vector.h:256
static ast_mutex_t history_lock
Mutex that protects vector_history.
#define ast_mutex_lock(a)
Definition: lock.h:187
#define NULL
Definition: resample.c:96
#define ao2_bump(obj)
Definition: astobj2.h:491
#define AST_VECTOR_INIT(vec, size)
Initialize a vector.
Definition: vector.h:113
#define ast_malloc(len)
A wrapper for malloc()
Definition: astmm.h:193
static struct expression_token * expression_token_free(struct expression_token *token)
Free an expression token and all others it references.
#define ast_free(a)
Definition: astmm.h:182
#define AST_VECTOR_RESET(vec, cleanup)
Reset vector.
Definition: vector.h:627
#define AST_VECTOR_PTR_FREE(vec)
Deallocates this vector pointer.
Definition: vector.h:189
A token in the expression or an evaluated part of the expression.
#define AST_VECTOR_GET(vec, idx)
Get an element from a vector.
Definition: vector.h:682
static void clear_history_entry_cb(struct pjsip_history_entry *entry)
Vector callback that releases the reference for the entry in a history vector.
#define ao2_cleanup(obj)
Definition: astobj2.h:1958
Definition: search.h:40
An item in the history.
static struct expression_token * build_expression_queue(struct ast_cli_args *a)
Build a reverse polish notation expression queue.
#define AST_VECTOR_SIZE(vec)
Get the number of elements in a vector.
Definition: vector.h:611
#define HISTORY_INITIAL_SIZE
#define ast_mutex_unlock(a)
Definition: lock.h:188

◆ get_allowed_field()

static struct allowed_field* get_allowed_field ( struct expression_token token)
static

Determine if the expression token matches a field in allowed_fields.

Definition at line 587 of file res_pjsip_history.c.

References ARRAY_LEN, ast_assert, expression_token::field, NULL, allowed_field::symbol, expression_token::token_type, and TOKEN_TYPE_FIELD.

Referenced by evaluate_history_entry().

588 {
589  int i;
590 
592 
593  for (i = 0; i < ARRAY_LEN(allowed_fields); i++) {
594  if (strcasecmp(allowed_fields[i].symbol, token->field)) {
595  continue;
596  }
597 
598  return &allowed_fields[i];
599  }
600 
601  return NULL;
602 }
#define ARRAY_LEN(a)
Definition: isdn_lib.c:42
static struct allowed_field allowed_fields[]
The fields we allow.
char field[]
The field in the expression.
#define ast_assert(a)
Definition: utils.h:695
#define NULL
Definition: resample.c:96
enum expression_token_type token_type
The type of value stored in the expression token.

◆ history_on_rx_msg()

static pj_bool_t history_on_rx_msg ( pjsip_rx_data *  rdata)
static

PJSIP callback when a SIP message is received.

Definition at line 726 of file res_pjsip_history.c.

References ao2_ref, ast_log_dynamic_level, ast_mutex_lock, ast_mutex_unlock, AST_VECTOR_APPEND, pjsip_history_entry::dst, enabled, history_lock, log_level, NULL, pjsip_history_entry_alloc(), sprint_list_entry(), and pjsip_history_entry::src.

727 {
728  struct pjsip_history_entry *entry;
729 
730  if (!enabled) {
731  return PJ_FALSE;
732  }
733 
734  if (!rdata->msg_info.msg) {
735  return PJ_FALSE;
736  }
737 
738  entry = pjsip_history_entry_alloc(rdata->msg_info.msg);
739  if (!entry) {
740  return PJ_FALSE;
741  }
742 
743  if (rdata->tp_info.transport->addr_len) {
744  pj_sockaddr_cp(&entry->dst, &rdata->tp_info.transport->local_addr);
745  }
746 
747  if (rdata->pkt_info.src_addr_len) {
748  pj_sockaddr_cp(&entry->src, &rdata->pkt_info.src_addr);
749  }
750 
752  if (AST_VECTOR_APPEND(&vector_history, entry)) {
753  ao2_ref(entry, -1);
754  entry = NULL;
755  }
757 
758  if (log_level != -1 && entry) {
759  char line[256];
760 
761  sprint_list_entry(entry, line, sizeof(line));
762  ast_log_dynamic_level(log_level, "%s\n", line);
763  }
764 
765  return PJ_FALSE;
766 }
static void sprint_list_entry(struct pjsip_history_entry *entry, char *line, int len)
Format single line history entry.
#define AST_VECTOR_APPEND(vec, elem)
Append an element to a vector, growing the vector if needed.
Definition: vector.h:256
static ast_mutex_t history_lock
Mutex that protects vector_history.
pj_sockaddr dst
Destination address.
#define ast_log_dynamic_level(level,...)
Send a log message to a dynamically registered log level.
Definition: logger.h:439
#define ast_mutex_lock(a)
Definition: lock.h:187
#define NULL
Definition: resample.c:96
static int log_level
Log level for history output.
pj_sockaddr src
Source address.
#define ao2_ref(o, delta)
Definition: astobj2.h:464
static struct pjsip_history_entry * pjsip_history_entry_alloc(pjsip_msg *msg)
Create a pjsip_history_entry AO2 object.
static int enabled
Whether or not we are storing history.
Definition: search.h:40
An item in the history.
#define ast_mutex_unlock(a)
Definition: lock.h:188

◆ history_on_tx_msg()

static pj_status_t history_on_tx_msg ( pjsip_tx_data *  tdata)
static

PJSIP callback when a SIP message is transmitted.

Definition at line 692 of file res_pjsip_history.c.

References ao2_ref, ast_log_dynamic_level, ast_mutex_lock, ast_mutex_unlock, AST_VECTOR_APPEND, pjsip_history_entry::dst, enabled, history_lock, log_level, NULL, pjsip_history_entry_alloc(), sprint_list_entry(), pjsip_history_entry::src, and pjsip_history_entry::transmitted.

693 {
694  struct pjsip_history_entry *entry;
695 
696  if (!enabled) {
697  return PJ_SUCCESS;
698  }
699 
700  entry = pjsip_history_entry_alloc(tdata->msg);
701  if (!entry) {
702  return PJ_SUCCESS;
703  }
704  entry->transmitted = 1;
705  pj_sockaddr_cp(&entry->src, &tdata->tp_info.transport->local_addr);
706  pj_sockaddr_cp(&entry->dst, &tdata->tp_info.dst_addr);
707 
709  if (AST_VECTOR_APPEND(&vector_history, entry)) {
710  ao2_ref(entry, -1);
711  entry = NULL;
712  }
714 
715  if (log_level != -1 && entry) {
716  char line[256];
717 
718  sprint_list_entry(entry, line, sizeof(line));
719  ast_log_dynamic_level(log_level, "%s\n", line);
720  }
721 
722  return PJ_SUCCESS;
723 }
static void sprint_list_entry(struct pjsip_history_entry *entry, char *line, int len)
Format single line history entry.
#define AST_VECTOR_APPEND(vec, elem)
Append an element to a vector, growing the vector if needed.
Definition: vector.h:256
static ast_mutex_t history_lock
Mutex that protects vector_history.
int transmitted
Whether or not we transmitted the packet.
pj_sockaddr dst
Destination address.
#define ast_log_dynamic_level(level,...)
Send a log message to a dynamically registered log level.
Definition: logger.h:439
#define ast_mutex_lock(a)
Definition: lock.h:187
#define NULL
Definition: resample.c:96
static int log_level
Log level for history output.
pj_sockaddr src
Source address.
#define ao2_ref(o, delta)
Definition: astobj2.h:464
static struct pjsip_history_entry * pjsip_history_entry_alloc(pjsip_msg *msg)
Create a pjsip_history_entry AO2 object.
static int enabled
Whether or not we are storing history.
Definition: search.h:40
An item in the history.
#define ast_mutex_unlock(a)
Definition: lock.h:188

◆ load_module()

static int load_module ( void  )
static

Definition at line 1367 of file res_pjsip_history.c.

References ARRAY_LEN, ast_cli_register_multiple, ast_log, ast_logger_register_level(), AST_MODULE_LOAD_SUCCESS, ast_pjproject_caching_pool_init(), ast_sip_register_service(), AST_VECTOR_INIT, cachingpool, HISTORY_INITIAL_SIZE, log_level, LOG_WARNING, and logging_module.

Referenced by unload_module().

1368 {
1369  log_level = ast_logger_register_level("PJSIP_HISTORY");
1370  if (log_level < 0) {
1371  ast_log(LOG_WARNING, "Unable to register history log level\n");
1372  }
1373 
1374  ast_pjproject_caching_pool_init(&cachingpool, &pj_pool_factory_default_policy, 0);
1375 
1376  AST_VECTOR_INIT(&vector_history, HISTORY_INITIAL_SIZE);
1377 
1380 
1381  return AST_MODULE_LOAD_SUCCESS;
1382 }
#define ARRAY_LEN(a)
Definition: isdn_lib.c:42
#define LOG_WARNING
Definition: logger.h:274
#define ast_cli_register_multiple(e, len)
Register multiple commands.
Definition: cli.h:265
static int log_level
Log level for history output.
#define ast_log
Definition: astobj2.c:42
#define AST_VECTOR_INIT(vec, size)
Initialize a vector.
Definition: vector.h:113
static pjsip_module logging_module
int ast_sip_register_service(pjsip_module *module)
Register a SIP service in Asterisk.
Definition: res_pjsip.c:3315
int ast_logger_register_level(const char *name)
Register a new logger level.
Definition: logger.c:2503
void ast_pjproject_caching_pool_init(pj_caching_pool *cp, const pj_pool_factory_policy *policy, pj_size_t max_capacity)
Initialize the caching pool factory.
static struct ast_cli_entry cli_pjsip[]
#define HISTORY_INITIAL_SIZE
static pj_caching_pool cachingpool
Pool factory used by pjlib to allocate memory.

◆ pjsip_history_entry_alloc()

static struct pjsip_history_entry* pjsip_history_entry_alloc ( pjsip_msg *  msg)
static

Create a pjsip_history_entry AO2 object.

Parameters
msgThe PJSIP message that this history entry wraps
Return values
AnAO2 pjsip_history_entry object on success
NULLon failure

Definition at line 628 of file res_pjsip_history.c.

References AO2_ALLOC_OPT_LOCK_NOLOCK, ao2_alloc_options, ao2_ref, ast_atomic_fetchadd_int(), ast_tvnow(), cachingpool, pjsip_history_entry::msg, NULL, pjsip_history_entry::number, packet_number, pjsip_history_entry_dtor(), pjsip_history_entry::pool, and pjsip_history_entry::timestamp.

Referenced by history_on_rx_msg(), and history_on_tx_msg().

629 {
630  struct pjsip_history_entry *entry;
631 
633  if (!entry) {
634  return NULL;
635  }
637  entry->timestamp = ast_tvnow();
638  entry->timestamp.tv_usec = 0;
639 
640  entry->pool = pj_pool_create(&cachingpool.factory, NULL, PJSIP_POOL_RDATA_LEN,
641  PJSIP_POOL_RDATA_INC, NULL);
642  if (!entry->pool) {
643  ao2_ref(entry, -1);
644  return NULL;
645  }
646 
647  entry->msg = pjsip_msg_clone(entry->pool, msg);
648  if (!entry->msg) {
649  ao2_ref(entry, -1);
650  return NULL;
651  }
652 
653  return entry;
654 }
static int packet_number
Packet count.
int number
Packet number.
struct timeval ast_tvnow(void)
Returns current timeval. Meant to replace calls to gettimeofday().
Definition: time.h:150
#define ao2_alloc_options(data_size, destructor_fn, options)
Definition: astobj2.h:406
struct timeval timestamp
Time the packet was transmitted/received.
#define NULL
Definition: resample.c:96
int ast_atomic_fetchadd_int(volatile int *p, int v)
Atomically add v to *p and return the previous value of *p.
Definition: lock.h:755
#define ao2_ref(o, delta)
Definition: astobj2.h:464
pjsip_msg * msg
The actual SIP message.
pj_pool_t * pool
Memory pool used to allocate msg.
Definition: search.h:40
An item in the history.
static void pjsip_history_entry_dtor(void *obj)
AO2 destructor for pjsip_history_entry.
static pj_caching_pool cachingpool
Pool factory used by pjlib to allocate memory.

◆ pjsip_history_entry_dtor()

static void pjsip_history_entry_dtor ( void *  obj)
static

AO2 destructor for pjsip_history_entry.

Definition at line 605 of file res_pjsip_history.c.

References NULL, and pjsip_history_entry::pool.

Referenced by pjsip_history_entry_alloc().

606 {
607  struct pjsip_history_entry *entry = obj;
608 
609  if (entry->pool) {
610  /* This mimics the behavior of pj_pool_safe_release
611  * which was introduced in pjproject 2.6.
612  */
613  pj_pool_t *temp_pool = entry->pool;
614 
615  entry->pool = NULL;
616  pj_pool_release(temp_pool);
617  }
618 }
#define NULL
Definition: resample.c:96
pj_pool_t * pool
Memory pool used to allocate msg.
Definition: search.h:40
An item in the history.

◆ pjsip_set_history()

static char* pjsip_set_history ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
)
static

Definition at line 1311 of file res_pjsip_history.c.

References ast_cli_args::argc, ast_cli_entry::args, ast_cli_args::argv, ast_cli(), ast_sip_push_task(), clear_history_entries(), CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, enabled, ast_cli_args::fd, NULL, and ast_cli_entry::usage.

1312 {
1313  const char *what;
1314 
1315  if (cmd == CLI_INIT) {
1316  e->command = "pjsip set history {on|off|clear}";
1317  e->usage =
1318  "Usage: pjsip set history {on|off|clear}\n"
1319  " Enables/disables/clears the PJSIP history.\n\n"
1320  " Enabling the history will start recording transmitted/received\n"
1321  " packets. Disabling the history will stop recording, but keep\n"
1322  " the already received packets. Clearing the history will wipe\n"
1323  " the received packets from memory.\n\n"
1324  " As the PJSIP history is maintained in memory, and includes\n"
1325  " all received/transmitted requests and responses, it should\n"
1326  " only be enabled for debugging purposes, and cleared when done.\n";
1327  return NULL;
1328  } else if (cmd == CLI_GENERATE) {
1329  return NULL;
1330  }
1331 
1332  what = a->argv[e->args - 1]; /* Guaranteed to exist */
1333 
1334  if (a->argc == e->args) {
1335  if (!strcasecmp(what, "on")) {
1336  enabled = 1;
1337  ast_cli(a->fd, "PJSIP History enabled\n");
1338  return CLI_SUCCESS;
1339  } else if (!strcasecmp(what, "off")) {
1340  enabled = 0;
1341  ast_cli(a->fd, "PJSIP History disabled\n");
1342  return CLI_SUCCESS;
1343  } else if (!strcasecmp(what, "clear")) {
1345  ast_cli(a->fd, "PJSIP History cleared\n");
1346  return CLI_SUCCESS;
1347  }
1348  }
1349 
1350  return CLI_SHOWUSAGE;
1351 }
const int argc
Definition: cli.h:160
static int clear_history_entries(void *obj)
Remove all entries from vector_history.
Definition: cli.h:152
#define NULL
Definition: resample.c:96
void ast_cli(int fd, const char *fmt,...)
Definition: clicompat.c:6
int args
This gets set in ast_cli_register()
Definition: cli.h:185
const int fd
Definition: cli.h:159
const char *const * argv
Definition: cli.h:161
#define CLI_SHOWUSAGE
Definition: cli.h:45
int ast_sip_push_task(struct ast_taskprocessor *serializer, int(*sip_task)(void *), void *task_data)
Pushes a task to SIP servants.
Definition: res_pjsip.c:5138
char * command
Definition: cli.h:186
const char * usage
Definition: cli.h:177
#define CLI_SUCCESS
Definition: cli.h:44
static int enabled
Whether or not we are storing history.

◆ pjsip_show_history()

static char* pjsip_show_history ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
)
static

Definition at line 1217 of file res_pjsip_history.c.

References ao2_bump, ao2_cleanup, ast_cli_args::argc, ast_cli_args::argv, ast_cli(), ast_mutex_lock, ast_mutex_unlock, ast_sip_push_task(), AST_VECTOR_GET, AST_VECTOR_SIZE, CLI_FAILURE, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, display_entry_list(), display_single_entry(), ast_cli_args::fd, filter_history(), history_lock, NULL, safe_vector_cleanup(), and ast_cli_entry::usage.

1218 {
1219  struct vector_history_t *vec = &vector_history;
1220  struct pjsip_history_entry *entry = NULL;
1221 
1222  if (cmd == CLI_INIT) {
1223  e->command = "pjsip show history";
1224  e->usage =
1225  "Usage: pjsip show history [entry <num>|where [...]]\n"
1226  " Displays the currently collected history or an\n"
1227  " entry within the history.\n\n"
1228  " * Running the command with no options will display\n"
1229  " the entire history.\n"
1230  " * Providing 'entry <num>' will display the full\n"
1231  " detail of a particular entry in this history.\n"
1232  " * Providing 'where ...' will allow for filtering\n"
1233  " the history. The history can be filtered using\n"
1234  " any of the following fields:\n"
1235  " - number: The history entry number\n"
1236  " - timestamp: The time associated with the history entry\n"
1237  " - addr: The source/destination address of the SIP message\n"
1238  " - sip.msg.request.method: The request method type\n"
1239  " - sip.msg.call-id: The Call-ID header of the SIP message\n"
1240  "\n"
1241  " When filtering, standard Boolean operators can be used,\n"
1242  " as well as 'like' for regexs.\n"
1243  "\n"
1244  " Example:\n"
1245  " 'pjsip show history where number > 5 and (addr = \"192.168.0.3:5060\" or addr = \"192.168.0.5:5060\")'\n";
1246  return NULL;
1247  } else if (cmd == CLI_GENERATE) {
1248  return NULL;
1249  }
1250 
1251  if (a->argc > 3) {
1252  if (!strcasecmp(a->argv[3], "entry") && a->argc == 5) {
1253  int num;
1254 
1255  if (sscanf(a->argv[4], "%30d", &num) != 1) {
1256  ast_cli(a->fd, "'%s' is not a valid entry number\n", a->argv[4]);
1257  return CLI_FAILURE;
1258  }
1259 
1260  /* Get the entry at the provided position */
1262  if (num >= AST_VECTOR_SIZE(&vector_history) || num < 0) {
1263  ast_cli(a->fd, "Entry '%d' does not exist\n", num);
1265  return CLI_FAILURE;
1266  }
1267  entry = ao2_bump(AST_VECTOR_GET(&vector_history, num));
1269  } else if (!strcasecmp(a->argv[3], "where")) {
1270  vec = filter_history(a);
1271  if (!vec) {
1272  return CLI_FAILURE;
1273  }
1274  } else {
1275  return CLI_SHOWUSAGE;
1276  }
1277  }
1278 
1279  if (AST_VECTOR_SIZE(vec) == 1) {
1280  if (vec == &vector_history) {
1282  }
1283  entry = ao2_bump(AST_VECTOR_GET(vec, 0));
1284  if (vec == &vector_history) {
1286  }
1287  }
1288 
1289  if (entry) {
1290  display_single_entry(a, entry);
1291  } else {
1292  if (vec == &vector_history) {
1294  }
1295 
1296  display_entry_list(a, vec);
1297 
1298  if (vec == &vector_history) {
1300  }
1301  }
1302 
1303  if (vec != &vector_history) {
1305  }
1306  ao2_cleanup(entry);
1307 
1308  return CLI_SUCCESS;
1309 }
const int argc
Definition: cli.h:160
static ast_mutex_t history_lock
Mutex that protects vector_history.
Definition: cli.h:152
#define ast_mutex_lock(a)
Definition: lock.h:187
#define NULL
Definition: resample.c:96
void ast_cli(int fd, const char *fmt,...)
Definition: clicompat.c:6
#define ao2_bump(obj)
Definition: astobj2.h:491
const int fd
Definition: cli.h:159
static struct vector_history_t * filter_history(struct ast_cli_args *a)
Create a filtered history based on a user provided expression.
const char *const * argv
Definition: cli.h:161
#define CLI_SHOWUSAGE
Definition: cli.h:45
int ast_sip_push_task(struct ast_taskprocessor *serializer, int(*sip_task)(void *), void *task_data)
Pushes a task to SIP servants.
Definition: res_pjsip.c:5138
#define CLI_FAILURE
Definition: cli.h:46
char * command
Definition: cli.h:186
static void display_entry_list(struct ast_cli_args *a, struct vector_history_t *vec)
Print a list of the entries to the CLI.
const char * usage
Definition: cli.h:177
#define CLI_SUCCESS
Definition: cli.h:44
#define AST_VECTOR_GET(vec, idx)
Get an element from a vector.
Definition: vector.h:682
#define ao2_cleanup(obj)
Definition: astobj2.h:1958
static int safe_vector_cleanup(void *obj)
Cleanup routine for a history vector, serviced on a registered PJSIP thread.
static void display_single_entry(struct ast_cli_args *a, struct pjsip_history_entry *entry)
Print a detailed view of a single entry in the history to the CLI.
Definition: search.h:40
An item in the history.
#define AST_VECTOR_SIZE(vec)
Get the number of elements in a vector.
Definition: vector.h:611
#define ast_mutex_unlock(a)
Definition: lock.h:188

◆ safe_vector_cleanup()

static int safe_vector_cleanup ( void *  obj)
static

Cleanup routine for a history vector, serviced on a registered PJSIP thread.

Definition at line 1206 of file res_pjsip_history.c.

References ast_free, AST_VECTOR_FREE, AST_VECTOR_RESET, and clear_history_entry_cb().

Referenced by pjsip_show_history().

1207 {
1208  struct vector_history_t *vec = obj;
1209 
1211  AST_VECTOR_FREE(vec);
1212  ast_free(vec);
1213 
1214  return 0;
1215 }
#define AST_VECTOR_FREE(vec)
Deallocates this vector.
Definition: vector.h:174
#define ast_free(a)
Definition: astmm.h:182
#define AST_VECTOR_RESET(vec, cleanup)
Reset vector.
Definition: vector.h:627
static void clear_history_entry_cb(struct pjsip_history_entry *entry)
Vector callback that releases the reference for the entry in a history vector.

◆ sprint_list_entry()

static void sprint_list_entry ( struct pjsip_history_entry entry,
char *  line,
int  len 
)
static

Format single line history entry.

Definition at line 657 of file res_pjsip_history.c.

References pjsip_history_entry::dst, pjsip_history_entry::msg, pjsip_history_entry::number, pjsip_history_entry::src, pjsip_history_entry::timestamp, and pjsip_history_entry::transmitted.

Referenced by display_entry_list(), history_on_rx_msg(), and history_on_tx_msg().

658 {
659  char addr[64];
660 
661  if (entry->transmitted) {
662  pj_sockaddr_print(&entry->dst, addr, sizeof(addr), 3);
663  } else {
664  pj_sockaddr_print(&entry->src, addr, sizeof(addr), 3);
665  }
666 
667  if (entry->msg->type == PJSIP_REQUEST_MSG) {
668  char uri[128];
669 
670  pjsip_uri_print(PJSIP_URI_IN_REQ_URI, entry->msg->line.req.uri, uri, sizeof(uri));
671  snprintf(line, len, "%-5.5d %-10.10ld %-5.5s %-24.24s %.*s %s SIP/2.0",
672  entry->number,
673  entry->timestamp.tv_sec,
674  entry->transmitted ? "* ==>" : "* <==",
675  addr,
676  (int)pj_strlen(&entry->msg->line.req.method.name),
677  pj_strbuf(&entry->msg->line.req.method.name),
678  uri);
679  } else {
680  snprintf(line, len, "%-5.5d %-10.10ld %-5.5s %-24.24s SIP/2.0 %u %.*s",
681  entry->number,
682  entry->timestamp.tv_sec,
683  entry->transmitted ? "* ==>" : "* <==",
684  addr,
685  entry->msg->line.status.code,
686  (int)pj_strlen(&entry->msg->line.status.reason),
687  pj_strbuf(&entry->msg->line.status.reason));
688  }
689 }
int transmitted
Whether or not we transmitted the packet.
pj_sockaddr dst
Destination address.
int number
Packet number.
struct timeval timestamp
Time the packet was transmitted/received.
pj_sockaddr src
Source address.
pjsip_msg * msg
The actual SIP message.
static int len(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t buflen)

◆ unload_module()

static int unload_module ( void  )
static

Definition at line 1384 of file res_pjsip_history.c.

References ARRAY_LEN, ast_cli_unregister_multiple(), ast_logger_unregister_level(), AST_MODFLAG_LOAD_ORDER, AST_MODPRI_APP_DEPEND, AST_MODULE_INFO(), AST_MODULE_SUPPORT_EXTENDED, ast_pjproject_caching_pool_destroy(), ast_sip_push_task_wait_servant(), ast_sip_unregister_service(), AST_VECTOR_FREE, ASTERISK_GPL_KEY, cachingpool, clear_history_entries(), load_module(), log_level, logging_module, and NULL.

1385 {
1388 
1390  AST_VECTOR_FREE(&vector_history);
1391 
1393 
1394  if (log_level != -1) {
1395  ast_logger_unregister_level("PJSIP_HISTORY");
1396  }
1397 
1398  return 0;
1399 }
#define AST_VECTOR_FREE(vec)
Deallocates this vector.
Definition: vector.h:174
#define ARRAY_LEN(a)
Definition: isdn_lib.c:42
void ast_pjproject_caching_pool_destroy(pj_caching_pool *cp)
Destroy caching pool factory and all cached pools.
int ast_cli_unregister_multiple(struct ast_cli_entry *e, int len)
Unregister multiple commands.
Definition: clicompat.c:30
static int clear_history_entries(void *obj)
Remove all entries from vector_history.
#define NULL
Definition: resample.c:96
int ast_sip_push_task_wait_servant(struct ast_taskprocessor *serializer, int(*sip_task)(void *), void *task_data)
Push a task to SIP servants and wait for it to complete.
Definition: res_pjsip.c:5204
static int log_level
Log level for history output.
void ast_logger_unregister_level(const char *name)
Unregister a previously registered logger level.
Definition: logger.c:2536
static pjsip_module logging_module
static struct ast_cli_entry cli_pjsip[]
void ast_sip_unregister_service(pjsip_module *module)
Definition: res_pjsip.c:3331
static pj_caching_pool cachingpool
Pool factory used by pjlib to allocate memory.

Variable Documentation

◆ __mod_info

struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_LOAD_ORDER , .description = "PJSIP History" , .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_EXTENDED, .load = load_module, .unload = unload_module, .load_pri = AST_MODPRI_APP_DEPEND, .requires = "res_pjsip", }
static

Definition at line 1407 of file res_pjsip_history.c.

◆ allowed_fields

struct allowed_field allowed_fields[]
static

The fields we allow.

Definition at line 513 of file res_pjsip_history.c.

◆ allowed_operators

struct operator allowed_operators[]
static

Our allowed operations.

Definition at line 453 of file res_pjsip_history.c.

◆ ast_module_info

const struct ast_module_info* ast_module_info = &__mod_info
static

Definition at line 1407 of file res_pjsip_history.c.

◆ cachingpool

pj_caching_pool cachingpool
static

Pool factory used by pjlib to allocate memory.

Definition at line 50 of file res_pjsip_history.c.

Referenced by load_module(), pjsip_history_entry_alloc(), and unload_module().

◆ cli_pjsip

struct ast_cli_entry cli_pjsip[]
static
Initial value:
= {
{ .handler = pjsip_set_history , .summary = "Enable/Disable PJSIP History" ,},
{ .handler = pjsip_show_history , .summary = "Display PJSIP History" ,},
}
static char * pjsip_show_history(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static char * pjsip_set_history(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)

Definition at line 1362 of file res_pjsip_history.c.

◆ enabled

int enabled
static

Whether or not we are storing history.

Definition at line 53 of file res_pjsip_history.c.

Referenced by history_on_rx_msg(), history_on_tx_msg(), and pjsip_set_history().

◆ history_lock

ast_mutex_t history_lock = { PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP , NULL, {1, 0} }
static

Mutex that protects vector_history.

Definition at line 77 of file res_pjsip_history.c.

Referenced by clear_history_entries(), filter_history(), history_on_rx_msg(), history_on_tx_msg(), and pjsip_show_history().

◆ left_paren

struct operator left_paren
static
Initial value:
= {
.symbol = "(",
.precedence = 15
}

Operator token for a left parenthesis.

While this is used by the shunting-yard algorithm implementation, it should never appear in the resulting RPN queue of expression tokens

Definition at line 445 of file res_pjsip_history.c.

◆ log_level

int log_level = -1
static

Log level for history output.

Definition at line 162 of file res_pjsip_history.c.

Referenced by history_on_rx_msg(), history_on_tx_msg(), load_module(), and unload_module().

◆ logging_module

pjsip_module logging_module
static

Definition at line 1353 of file res_pjsip_history.c.

Referenced by load_module(), and unload_module().

◆ packet_number

int packet_number
static

Packet count.

Definition at line 56 of file res_pjsip_history.c.

Referenced by clear_history_entries(), and pjsip_history_entry_alloc().