Asterisk - The Open Source Telephony Project  21.4.1
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"

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  operator
 An operator that we understand in an expression. More...
 
struct  pjsip_history_entry
 An item in the history. More...
 
struct  vector_history_t
 The one and only history that we've captured. 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 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.
 
static void display_entry_list (struct ast_cli_args *a, struct vector_history_t *vec)
 Print a list of the entries to the CLI.
 
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.
 
static void * entry_get_addr (struct pjsip_history_entry *entry)
 Callback to retrieve the entry's destination address.
 
static void * entry_get_number (struct pjsip_history_entry *entry)
 Callback to retrieve the entry index number.
 
static void * entry_get_sip_msg_call_id (struct pjsip_history_entry *entry)
 Callback to retrieve the entry's SIP Call-ID header.
 
static void * entry_get_sip_msg_request_method (struct pjsip_history_entry *entry)
 Callback to retrieve the entry's SIP request method type.
 
static void * entry_get_timestamp (struct pjsip_history_entry *entry)
 Callback to retrieve the entry's timestamp.
 
static int evaluate_and (struct operator*op, enum aco_option_type type, void *op_left, struct expression_token *op_right)
 Operator callback for determining logical AND.
 
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.
 
static int evaluate_greater_than (struct operator*op, enum aco_option_type type, void *op_left, struct expression_token *op_right)
 Operator callback for determining if one operand is greater than another.
 
static int evaluate_greater_than_or_equal (struct operator*op, enum aco_option_type type, void *op_left, struct expression_token *op_right)
 Operator callback for determining if one operand is greater than or equal to another.
 
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)
 Operator callback for determining if one operand is less than another.
 
static int evaluate_less_than_or_equal (struct operator*op, enum aco_option_type type, void *op_left, struct expression_token *op_right)
 Operator callback for determining if one operand is less than or equal to another.
 
static int evaluate_like (struct operator*op, enum aco_option_type type, void *op_left, struct expression_token *op_right)
 Operator callback for regex 'like'.
 
static int evaluate_not (struct operator*op, enum aco_option_type type, void *operand)
 Operator callback for determining logical NOT.
 
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.
 
static int evaluate_or (struct operator*op, enum aco_option_type type, void *op_left, struct expression_token *op_right)
 Operator callback for determining logical OR.
 
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.
 
static struct vector_history_tfilter_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.
 
static pj_bool_t history_on_rx_msg (pjsip_rx_data *rdata)
 PJSIP callback when a SIP message is received.
 
static pj_status_t history_on_tx_msg (pjsip_tx_data *tdata)
 PJSIP callback when a SIP message is transmitted.
 
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.
 
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.
 
static void sprint_list_entry (struct pjsip_history_entry *entry, char *line, int len)
 Format single line history entry.
 
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 = "da6642af068ee5e6490c5b1d2cc1d238" , .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.
 
static struct operator allowed_operators []
 Our allowed operations.
 
static const struct ast_module_infoast_module_info = &__mod_info
 
static pj_caching_pool cachingpool
 Pool factory used by pjlib to allocate memory.
 
static struct ast_cli_entry cli_pjsip []
 
static int enabled
 Whether or not we are storing history.
 
static ast_mutex_t history_lock = { PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP , NULL, {1, 0} }
 Mutex that protects vector_history.
 
static struct operator left_paren
 Operator token for a left parenthesis. More...
 
static int log_level = -1
 Log level for history output.
 
static pjsip_module logging_module
 
static int packet_number
 Packet count.
 
static struct vector_history_t vector_history
 

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.

Enumeration Type Documentation

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 135 of file res_pjsip_history.c.

135  {
136  /*! The \c expression_token contains a field */
138  /*! The \c expression_token contains an operator */
140  /*! The \c expression_token contains a previous result */
142 };

Function Documentation

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.

Parameters
aThe CLI arguments provided by the User, containing the infix expression
Return values
NULLerror
expression_tokenA 'queue' of expression tokens in RPN

Definition at line 804 of file res_pjsip_history.c.

References ast_strdupa, AST_VECTOR, AST_VECTOR_APPEND, AST_VECTOR_FREE, AST_VECTOR_GET, AST_VECTOR_INIT, AST_VECTOR_REMOVE, AST_VECTOR_SIZE, expression_token_alloc(), expression_token_free(), operator::precedence, operator::right_to_left, TOKEN_TYPE_FIELD, and TOKEN_TYPE_OPERATOR.

Referenced by filter_history().

805 {
806  AST_VECTOR(, struct operator *) operators; /* A stack of saved operators */
807  struct expression_token *output = NULL; /* The output queue */
808  struct expression_token *head = NULL; /* Pointer to the head of /c output */
809  int i;
810 
811 #define APPEND_TO_OUTPUT(output, token) do { \
812  if ((output)) { \
813  (output)->next = (token); \
814  (output) = (token); \
815  } else { \
816  (output) = (token); \
817  head = (output); \
818  } \
819 } while (0)
820 
821  if (AST_VECTOR_INIT(&operators, 8)) {
822  return NULL;
823  }
824 
825  for (i = 4; i < a->argc; i++) {
826  struct expression_token *out_token;
827  char *token = ast_strdupa(a->argv[i]);
828  int j;
829 
830  /* Strip off and append any left parentheses */
831  if (token[0] == '(') {
832  AST_VECTOR_APPEND(&operators, &left_paren);
833  if (!token[1]) {
834  continue;
835  }
836  token = &token[1];
837  }
838 
839  /* Handle the case where the token is an operator */
840  for (j = 0; j < ARRAY_LEN(allowed_operators); j++) {
841  int k;
842 
843  if (strcasecmp(token, allowed_operators[j].symbol)) {
844  continue;
845  }
846 
847  for (k = AST_VECTOR_SIZE(&operators) - 1; k >= 0; k--) {
848  struct operator *top = AST_VECTOR_GET(&operators, k);
849 
850  /* Remove and push queued up operators, if they are of
851  * less precedence than this operator
852  */
855 
856  if (!(out_token = expression_token_alloc(TOKEN_TYPE_OPERATOR, top))) {
857  goto error;
858  }
859  APPEND_TO_OUTPUT(output, out_token);
860  AST_VECTOR_REMOVE(&operators, k, 1);
861  }
862  }
863 
864  AST_VECTOR_APPEND(&operators, &allowed_operators[j]);
865  token = NULL;
866  break;
867  }
868 
869  /* Token was an operator; continue to next token */
870  if (!token) {
871  continue;
872  }
873 
874  /* Handle a right parentheses either by itself or as part of the token.
875  * If part of the token, push the token onto the output queue first
876  */
877  if (token[0] == ')' || token[strlen(token) - 1] == ')') {
878 
879  if (token[strlen(token) - 1] == ')') {
880  token[strlen(token) - 1] = '\0';
881 
882  if (!(out_token = expression_token_alloc(TOKEN_TYPE_FIELD, token))) {
883  goto error;
884  }
885  APPEND_TO_OUTPUT(output, out_token);
886  token = NULL;
887  }
888 
889  for (j = AST_VECTOR_SIZE(&operators) - 1; j >= 0; j--) {
890  struct operator *top = AST_VECTOR_GET(&operators, j);
891 
892  AST_VECTOR_REMOVE(&operators, j, 1);
893  if (top == &left_paren) {
894  break;
895  }
896 
897  if (!(out_token = expression_token_alloc(TOKEN_TYPE_OPERATOR, top))) {
898  goto error;
899  }
900  APPEND_TO_OUTPUT(output, out_token);
901  }
902  }
903 
904  /* Just a plain token, push to the output queue */
905  if (token) {
906  if (!(out_token = expression_token_alloc(TOKEN_TYPE_FIELD, token))) {
907  goto error;
908  }
909  APPEND_TO_OUTPUT(output, out_token);
910  }
911  }
912 
913  /* Remove any non-applied operators that remain, applying them
914  * to the output queue
915  */
916  for (i = AST_VECTOR_SIZE(&operators) - 1; i >= 0; i--) {
917  struct operator *top = AST_VECTOR_GET(&operators, i);
918  struct expression_token *out_token;
919 
920  AST_VECTOR_REMOVE(&operators, i, 1);
921  if (top == &left_paren) {
922  ast_log(LOG_WARNING, "Unbalanced '(' parentheses in expression!\n");
923  continue;
924  }
925 
926  if (!(out_token = expression_token_alloc(TOKEN_TYPE_OPERATOR, top))) {
927  goto error;
928  }
929  APPEND_TO_OUTPUT(output, out_token);
930  }
931 
932  AST_VECTOR_FREE(&operators);
933  return head;
934 
935 error:
936  AST_VECTOR_FREE(&operators);
937  expression_token_free(output);
938  return NULL;
939 }
#define AST_VECTOR_FREE(vec)
Deallocates this vector.
Definition: vector.h:174
int right_to_left
Non-zero if the operator is evaluated right-to-left.
#define AST_VECTOR_APPEND(vec, elem)
Append an element to a vector, growing the vector if needed.
Definition: vector.h:256
An operator that we understand in an expression.
static struct operator allowed_operators[]
Our allowed operations.
static struct operator left_paren
Operator token for a left parenthesis.
int precedence
Precedence of the symbol.
#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:298
#define AST_VECTOR(name, type)
Define a vector structure.
Definition: vector.h:44
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:680
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:609
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 781 of file res_pjsip_history.c.

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

782 {
783  ast_mutex_lock(&history_lock);
784  AST_VECTOR_RESET(&vector_history, clear_history_entry_cb);
785  packet_number = 0;
786  ast_mutex_unlock(&history_lock);
787 
788  return 0;
789 }
static int packet_number
Packet count.
static ast_mutex_t history_lock
Mutex that protects vector_history.
#define AST_VECTOR_RESET(vec, cleanup)
Reset vector.
Definition: vector.h:625
static void clear_history_entry_cb(struct pjsip_history_entry *entry)
Vector callback that releases the reference for the entry in a history vector.
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 951 of file res_pjsip_history.c.

References AST_VECTOR, AST_VECTOR_APPEND, AST_VECTOR_FREE, AST_VECTOR_GET, AST_VECTOR_INIT, AST_VECTOR_REMOVE, AST_VECTOR_SIZE, operator::evaluate, operator::evaluate_unary, expression_token_alloc(), expression_token_free(), expression_token::field, get_allowed_field(), allowed_field::get_field, expression_token::next, expression_token::op, operator::operands, OPT_INT_T, expression_token::result, allowed_field::return_type, operator::symbol, expression_token::token_type, TOKEN_TYPE_FIELD, and TOKEN_TYPE_RESULT.

Referenced by filter_history().

952 {
953  AST_VECTOR(, struct expression_token *) stack; /* Our stack of results and operands */
954  struct expression_token *it_queue;
955  struct expression_token *final;
956  int result;
957  int i;
958 
959  if (AST_VECTOR_INIT(&stack, 16)) {
960  return -1;
961  }
962 
963  for (it_queue = queue; it_queue; it_queue = it_queue->next) {
964  struct expression_token *op_one;
965  struct expression_token *op_two = NULL;
966  struct expression_token *result;
967  int res = 0;
968 
969  /* If this is not an operator, push it to the stack */
970  if (!it_queue->op) {
971  if (AST_VECTOR_APPEND(&stack, it_queue)) {
972  goto error;
973  }
974  continue;
975  }
976 
977  if (AST_VECTOR_SIZE(&stack) < it_queue->op->operands) {
978  ast_log(LOG_WARNING, "Unable to evaluate expression operator '%s': not enough operands\n",
979  it_queue->op->symbol);
980  goto error;
981  }
982 
983  if (it_queue->op->operands == 1) {
984  /* Unary operators currently consist only of 'not', which can only act
985  * upon an evaluated condition result.
986  */
987  ast_assert(it_queue->op->evaluate_unary != NULL);
988 
989  op_one = AST_VECTOR_REMOVE(&stack, AST_VECTOR_SIZE(&stack) - 1, 1);
990  if (op_one->token_type != TOKEN_TYPE_RESULT) {
991  ast_log(LOG_WARNING, "Unable to evaluate '%s': operand is not the result of an operation\n",
992  it_queue->op->symbol);
993  goto error;
994  }
995 
996  res = it_queue->op->evaluate_unary(it_queue->op, OPT_INT_T, &op_one->result) == 0 ? 0 : 1;
997  } else if (it_queue->op->operands == 2) {
998  struct allowed_field *field;
999  enum aco_option_type type;
1000  void *value;
1001 
1002  ast_assert(it_queue->op->evaluate != NULL);
1003 
1004  op_one = AST_VECTOR_REMOVE(&stack, AST_VECTOR_SIZE(&stack) - 1, 1);
1005  op_two = AST_VECTOR_REMOVE(&stack, AST_VECTOR_SIZE(&stack) - 1, 1);
1006 
1007  /* If operand two is a field, then it must be a field we recognize. */
1008  if (op_two->token_type == TOKEN_TYPE_FIELD) {
1009  field = get_allowed_field(op_two);
1010  if (!field) {
1011  ast_log(LOG_WARNING, "Unknown or unrecognized field: %s\n", op_two->field);
1012  goto error;
1013  }
1014 
1015  type = field->return_type;
1016  value = field->get_field(entry);
1017  } else if (op_two->token_type == TOKEN_TYPE_RESULT) {
1018  type = OPT_INT_T;
1019  value = &op_two->result;
1020  } else {
1021  ast_log(LOG_WARNING, "Attempting to evaluate an operator: %s\n", op_two->op->symbol);
1022  goto error;
1023  }
1024 
1025  if (value) {
1026  res = it_queue->op->evaluate(it_queue->op, type, value, op_one) == 0 ? 0 : 1;
1027  } else {
1028  res = 0;
1029  }
1030  } else {
1031  ast_log(LOG_WARNING, "Operator '%s' has an invalid number of operands\n", it_queue->op->symbol);
1032  ast_assert(0);
1033  goto error;
1034  }
1035 
1036  /* Results are temporary; clean used ones up */
1037  if (op_one && op_one->token_type == TOKEN_TYPE_RESULT) {
1038  ast_free(op_one);
1039  }
1040  if (op_two && op_two->token_type == TOKEN_TYPE_RESULT) {
1041  ast_free(op_two);
1042  }
1043 
1044  /* Push the result onto the stack */
1045  result = expression_token_alloc(TOKEN_TYPE_RESULT, &res);
1046  if (!result) {
1047  goto error;
1048  }
1049  if (AST_VECTOR_APPEND(&stack, result)) {
1050  expression_token_free(result);
1051 
1052  goto error;
1053  }
1054  }
1055 
1056  /*
1057  * When the evaluation is complete, we must have:
1058  * - A single result remaining on the stack
1059  * - An actual result
1060  */
1061  if (AST_VECTOR_SIZE(&stack) != 1) {
1062  ast_log(LOG_WARNING, "Expression was unbalanced: %zu results remained after evaluation\n",
1063  AST_VECTOR_SIZE(&stack));
1064  goto error;
1065  }
1066 
1067  final = AST_VECTOR_GET(&stack, 0);
1068  if (final->token_type != TOKEN_TYPE_RESULT) {
1069  ast_log(LOG_WARNING, "Expression did not create a usable result\n");
1070  goto error;
1071  }
1072  result = final->result;
1073  ast_free(final);
1074  AST_VECTOR_FREE(&stack);
1075 
1076  return result;
1077 
1078 error:
1079  /* Clean out any remaining result expression tokens */
1080  for (i = 0; i < AST_VECTOR_SIZE(&stack); i++) {
1081  struct expression_token *failed_token = AST_VECTOR_GET(&stack, i);
1082 
1083  if (failed_token->token_type == TOKEN_TYPE_RESULT) {
1084  ast_free(failed_token);
1085  }
1086  }
1087  AST_VECTOR_FREE(&stack);
1088  return -1;
1089 }
#define AST_VECTOR_FREE(vec)
Deallocates this vector.
Definition: vector.h:174
char field[]
The field in the expression.
#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.
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_VECTOR_INIT(vec, size)
Initialize a vector.
Definition: vector.h:113
enum aco_option_type return_type
The type /c get_field returns.
#define AST_VECTOR(name, type)
Define a vector structure.
Definition: vector.h:44
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.
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:680
const char * symbol
Our operator's symbol.
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:609
struct expression_token * next
The next expression token in the queue.
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
expression_tokenon success

Definition at line 547 of file res_pjsip_history.c.

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

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.
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:202
A token in the expression or an evaluated part of the expression.
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 1099 of file res_pjsip_history.c.

References ao2_bump, ast_malloc, 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(), and history_lock.

1100 {
1101  struct vector_history_t *output;
1102  struct expression_token *queue;
1103  int i;
1104 
1105  output = ast_malloc(sizeof(*output));
1106  if (!output) {
1107  return NULL;
1108  }
1109 
1110  if (AST_VECTOR_INIT(output, HISTORY_INITIAL_SIZE / 2)) {
1111  ast_free(output);
1112  return NULL;
1113  }
1114 
1115  queue = build_expression_queue(a);
1116  if (!queue) {
1117  AST_VECTOR_PTR_FREE(output);
1118  return NULL;
1119  }
1120 
1121  ast_mutex_lock(&history_lock);
1122  for (i = 0; i < AST_VECTOR_SIZE(&vector_history); i++) {
1123  struct pjsip_history_entry *entry = AST_VECTOR_GET(&vector_history, i);
1124  int res;
1125 
1126  res = evaluate_history_entry(entry, queue);
1127  if (res == -1) {
1128  /* Error in expression evaluation; bail */
1129  ast_mutex_unlock(&history_lock);
1131  AST_VECTOR_FREE(output);
1132  ast_free(output);
1133  expression_token_free(queue);
1134  return NULL;
1135  } else if (!res) {
1136  continue;
1137  } else {
1138  ao2_bump(entry);
1139  if (AST_VECTOR_APPEND(output, entry)) {
1140  ao2_cleanup(entry);
1141  }
1142  }
1143  }
1144  ast_mutex_unlock(&history_lock);
1145 
1146  expression_token_free(queue);
1147 
1148  return output;
1149 }
#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.
The one and only history that we've captured.
#define ao2_bump(obj)
Bump refcount on an AO2 object by one, returning the object.
Definition: astobj2.h:480
#define AST_VECTOR_INIT(vec, size)
Initialize a vector.
Definition: vector.h:113
#define ast_malloc(len)
A wrapper for malloc()
Definition: astmm.h:191
static struct expression_token * expression_token_free(struct expression_token *token)
Free an expression token and all others it references.
#define AST_VECTOR_RESET(vec, cleanup)
Reset vector.
Definition: vector.h:625
#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:680
static void clear_history_entry_cb(struct pjsip_history_entry *entry)
Vector callback that releases the reference for the entry in a history vector.
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:609
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_ref, ast_atomic_fetchadd_int(), ast_tvnow(), cachingpool, pjsip_history_entry::msg, 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 
632  entry = ao2_alloc_options(sizeof(*entry), pjsip_history_entry_dtor, AO2_ALLOC_OPT_LOCK_NOLOCK);
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:159
struct timeval timestamp
Time the packet was transmitted/received.
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:757
#define ao2_ref(o, delta)
Reference/unreference an object and return the old refcount.
Definition: astobj2.h:459
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.

Variable Documentation

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" ,},
}

Definition at line 1365 of file res_pjsip_history.c.

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.