Asterisk - The Open Source Telephony Project GIT-master-b023714
Loading...
Searching...
No Matches
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  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.
 
static int clear_history_entries (void *obj)
 Remove all entries from vector_history.
 
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.
 
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.
 
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.
 
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.
 
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 = ASTERISK_GPL_KEY , .buildopt_sum = AST_BUILDOPT_SUM, .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 = AST_MUTEX_INIT_VALUE
 Mutex that protects vector_history.
 
static struct operator left_paren
 Operator token for a left parenthesis.
 
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.

Macro Definition Documentation

◆ APPEND_TO_OUTPUT

#define APPEND_TO_OUTPUT (   output,
  token 
)

◆ HISTORY_INITIAL_SIZE

#define HISTORY_INITIAL_SIZE   256

Definition at line 47 of file res_pjsip_history.c.

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 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};
@ TOKEN_TYPE_FIELD
@ TOKEN_TYPE_RESULT
@ TOKEN_TYPE_OPERATOR

Function Documentation

◆ __reg_module()

static void __reg_module ( void  )
static

Definition at line 1410 of file res_pjsip_history.c.

◆ __unreg_module()

static void __unreg_module ( void  )
static

Definition at line 1410 of file res_pjsip_history.c.

◆ AST_MODULE_SELF_SYM()

struct ast_module * AST_MODULE_SELF_SYM ( void  )

Definition at line 1410 of file res_pjsip_history.c.

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

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.

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
935error:
936 AST_VECTOR_FREE(&operators);
937 expression_token_free(output);
938 return NULL;
939}
#define ast_strdupa(s)
duplicate a string in memory from the stack
Definition astmm.h:298
#define ast_log
Definition astobj2.c:42
#define LOG_WARNING
static struct operator allowed_operators[]
Our allowed operations.
static struct expression_token * expression_token_alloc(enum expression_token_type token_type, void *value)
Allocate an expression token.
#define APPEND_TO_OUTPUT(output, token)
static struct expression_token * expression_token_free(struct expression_token *token)
Free an expression token and all others it references.
static struct operator left_paren
Operator token for a left parenthesis.
#define NULL
Definition resample.c:96
A token in the expression or an evaluated part of the expression.
An operator that we understand in an expression.
int precedence
Precedence of the symbol.
int right_to_left
Non-zero if the operator is evaluated right-to-left.
static struct test_val a
int error(const char *format,...)
#define ARRAY_LEN(a)
Definition utils.h:703
#define AST_VECTOR_SIZE(vec)
Get the number of elements in a vector.
Definition vector.h:620
#define AST_VECTOR_FREE(vec)
Deallocates this vector.
Definition vector.h:185
#define AST_VECTOR_REMOVE(vec, idx, preserve_ordered)
Remove an element from a vector by index.
Definition vector.h:423
#define AST_VECTOR_INIT(vec, size)
Initialize a vector.
Definition vector.h:124
#define AST_VECTOR_APPEND(vec, elem)
Append an element to a vector, growing the vector if needed.
Definition vector.h:267
#define AST_VECTOR(name, type)
Define a vector structure.
Definition vector.h:44
#define AST_VECTOR_GET(vec, idx)
Get an element from a vector.
Definition vector.h:691

References a, allowed_operators, APPEND_TO_OUTPUT, 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(), left_paren, LOG_WARNING, NULL, operator::precedence, operator::right_to_left, TOKEN_TYPE_FIELD, and TOKEN_TYPE_OPERATOR.

Referenced by filter_history().

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

782{
785 packet_number = 0;
787
788 return 0;
789}
#define ast_mutex_unlock(a)
Definition lock.h:197
#define ast_mutex_lock(a)
Definition lock.h:196
static int packet_number
Packet count.
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 ast_mutex_t history_lock
Mutex that protects vector_history.
static struct vector_history_t vector_history
#define AST_VECTOR_RESET(vec, cleanup)
Reset vector.
Definition vector.h:636

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

Referenced by pjsip_set_history(), and unload_module().

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

772{
773 ao2_ref(entry, -1);
774}
#define ao2_ref(o, delta)
Reference/unreference an object and return the old refcount.
Definition astobj2.h:459

References ao2_ref.

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

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

1187{
1188 int i;
1189
1190 ast_cli(a->fd, "%-5.5s %-10.10s %-30.30s %-35.35s\n",
1191 "No.",
1192 "Timestamp",
1193 "(Dir) Address",
1194 "SIP Message");
1195 ast_cli(a->fd, "===== ========== ============================== ===================================\n");
1196
1197 for (i = 0; i < AST_VECTOR_SIZE(vec); i++) {
1198 struct pjsip_history_entry *entry;
1199 char line[256];
1200
1201 entry = AST_VECTOR_GET(vec, i);
1202 sprint_list_entry(entry, line, sizeof(line));
1203
1204 ast_cli(a->fd, "%s\n", line);
1205 }
1206}
void ast_cli(int fd, const char *fmt,...)
Definition clicompat.c:6
static void sprint_list_entry(struct pjsip_history_entry *entry, char *line, int len)
Format single line history entry.
An item in the history.

References a, ast_cli(), AST_VECTOR_GET, AST_VECTOR_SIZE, and sprint_list_entry().

Referenced by pjsip_show_history().

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

1153{
1154 char addr[64], secs[AST_TIME_T_LEN];
1155 char *buf;
1156
1157 buf = ast_calloc(1, PJSIP_MAX_PKT_LEN * sizeof(char));
1158 if (!buf) {
1159 return;
1160 }
1161
1162 if (pjsip_msg_print(entry->msg, buf, PJSIP_MAX_PKT_LEN) == -1) {
1163 ast_log(LOG_WARNING, "Unable to print SIP message %d: packet too large!\n", entry->number);
1164 ast_free(buf);
1165 return;
1166 }
1167
1168 if (entry->transmitted) {
1169 pj_sockaddr_print(&entry->dst, addr, sizeof(addr), 3);
1170 } else {
1171 pj_sockaddr_print(&entry->src, addr, sizeof(addr), 3);
1172 }
1173
1174 ast_time_t_to_string(entry->timestamp.tv_sec, secs, sizeof(secs));
1175 ast_cli(a->fd, "<--- History Entry %d %s %s at %-10.10s --->\n",
1176 entry->number,
1177 entry->transmitted ? "Sent to" : "Received from",
1178 addr,
1179 secs);
1180 ast_cli(a->fd, "%s\n", buf);
1181
1182 ast_free(buf);
1183}
#define ast_free(a)
Definition astmm.h:180
#define ast_calloc(num, len)
A wrapper for calloc()
Definition astmm.h:202
char buf[BUFSIZE]
Definition eagi_proxy.c:66
pjsip_msg * msg
The actual SIP message.
struct timeval timestamp
Time the packet was transmitted/received.
int number
Packet number.
pj_sockaddr src
Source address.
int transmitted
Whether or not we transmitted the packet.
pj_sockaddr dst
Destination address.
int ast_time_t_to_string(time_t time, char *buf, size_t length)
Converts to a string representation of a time_t as decimal seconds since the epoch....
Definition time.c:152
#define AST_TIME_T_LEN
Definition time.h:45

References a, ast_calloc, ast_cli(), ast_free, ast_log, AST_TIME_T_LEN, ast_time_t_to_string(), buf, pjsip_history_entry::dst, 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().

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

484{
485 if (entry->transmitted) {
486 return &entry->dst;
487 } else {
488 return &entry->src;
489 }
490}

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

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

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

References pjsip_history_entry::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.

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

References pjsip_history_entry::msg.

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

494{
495 if (entry->msg->type != PJSIP_REQUEST_MSG) {
496 return NULL;
497 }
498
499 return &entry->msg->line.req.method.name;
500}

References pjsip_history_entry::msg, and NULL.

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

478{
479 return &entry->timestamp;
480}

References pjsip_history_entry::timestamp.

◆ evaluate_and()

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

Operator callback for determining logical AND.

Definition at line 374 of file res_pjsip_history.c.

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[]
@ OPT_UINT_T
Type for default option handler for unsigned integers.
@ OPT_BOOL_T
Type for default option handler for bools (ast_true/ast_false)
@ OPT_BOOLFLAG_T
Type for default option handler for bools (ast_true/ast_false) that are stored in a flag.
@ OPT_INT_T
Type for default option handler for signed integers.
int result
The result of an evaluated expression.
const char * symbol
Our operator's symbol.

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

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

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:
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 ((right.tv_sec = ast_string_to_time_t(op_right->field)) == -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}
@ OPT_NOOP_T
Type for a default handler that should do nothing.
@ OPT_CHAR_ARRAY_T
Type for default option handler for character array strings.
@ OPT_SOCKADDR_T
Type for default handler for ast_sockaddrs.
@ OPT_DOUBLE_T
Type for default option handler for doubles.
@ OPT_STRINGFIELD_T
Type for default option handler for stringfields.
char field[]
The field in the expression.
time_t ast_string_to_time_t(const char *str)
Returns a time_t from a string containing seconds since the epoch.
Definition time.c:163
int ast_tvcmp(struct timeval _a, struct timeval _b)
Compress two struct timeval instances returning -1, 0, 1 if the first arg is smaller,...
Definition time.h:137

References ast_log, ast_string_to_time_t(), 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, OPT_UINT_T, and type.

Referenced by evaluate_not_equal().

◆ 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

Operator callback for determining if one operand is greater than another.

Definition at line 291 of file res_pjsip_history.c.

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 ((right.tv_sec = ast_string_to_time_t(op_right->field)) == -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}

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

Referenced by evaluate_less_than_or_equal().

◆ 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

Operator callback for determining if one operand is greater than or equal to another.

Definition at line 348 of file res_pjsip_history.c.

349{
350 return !evaluate_less_than(op, type, op_left, op_right);
351}
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.

References evaluate_less_than(), and type.

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

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;
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 */
1046 if (!result) {
1047 goto error;
1048 }
1049 if (AST_VECTOR_APPEND(&stack, 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
1078error:
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}
static PGresult * result
Definition cel_pgsql.c:84
aco_option_type
The option types.
static struct allowed_field * get_allowed_field(struct expression_token *token)
Determine if the expression token matches a field in allowed_fields.
A field that we understand and can perform operations on.
enum aco_option_type return_type
The type /c get_field returns.
void *(*const get_field)(struct pjsip_history_entry *entry)
Function that returns the field from a pjsip_history_entry.
struct expression_token * next
The next expression token in the queue.
enum expression_token_type token_type
The type of value stored in the expression token.
struct operator* op
An operator that evaluates expressions.
int(*const evaluate)(struct operator*op, enum aco_option_type type, void *op_left, struct expression_token *op_right)
Evaluation function for binary operators.
int(*const evaluate_unary)(struct operator*op, enum aco_option_type type, void *operand)
Evaluation function for unary operators.
int operands
Number of operands the operator takes.
int value
Definition syslog.c:37
#define ast_assert(a)
Definition utils.h:776

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(), operator::evaluate, operator::evaluate_unary, 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, operator::operands, OPT_INT_T, result, expression_token::result, allowed_field::return_type, operator::symbol, expression_token::token_type, TOKEN_TYPE_FIELD, TOKEN_TYPE_RESULT, type, and value.

Referenced by filter_history().

◆ 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

Operator callback for determining if one operand is less than another.

Definition at line 242 of file res_pjsip_history.c.

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 ((right.tv_sec = ast_string_to_time_t(op_right->field)) == -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}

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

Referenced by evaluate_greater_than_or_equal().

◆ 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

Operator callback for determining if one operand is less than or equal to another.

Definition at line 340 of file res_pjsip_history.c.

341{
342 return !evaluate_greater_than(op, type, op_left, op_right);
343}
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.

References evaluate_greater_than(), and type.

◆ evaluate_like()

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

Operator callback for regex 'like'.

Definition at line 410 of file res_pjsip_history.c.

411{
412 switch (type) {
413 case OPT_CHAR_ARRAY_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}
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:2201

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

◆ evaluate_not()

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

Operator callback for determining logical NOT.

Definition at line 356 of file res_pjsip_history.c.

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}

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

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

235{
236 return !evaluate_equal(op, type, op_left, op_right);
237}
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.

References evaluate_equal(), and type.

◆ evaluate_or()

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

Operator callback for determining logical OR.

Definition at line 392 of file res_pjsip_history.c.

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}

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

◆ 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
expression_tokenon success

Definition at line 547 of file res_pjsip_history.c.

548{
549 struct expression_token *token;
550
551 switch (token_type) {
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) {
571 token->result = *(int *)value;
572 break;
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}

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

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

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}

References ast_free, expression_token::next, and NULL.

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

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

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
1122 for (i = 0; i < AST_VECTOR_SIZE(&vector_history); i++) {
1124 int res;
1125
1126 res = evaluate_history_entry(entry, queue);
1127 if (res == -1) {
1128 /* Error in expression evaluation; bail */
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 }
1145
1146 expression_token_free(queue);
1147
1148 return output;
1149}
#define ast_malloc(len)
A wrapper for malloc()
Definition astmm.h:191
#define ao2_cleanup(obj)
Definition astobj2.h:1934
#define ao2_bump(obj)
Bump refcount on an AO2 object by one, returning the object.
Definition astobj2.h:480
#define HISTORY_INITIAL_SIZE
static struct expression_token * build_expression_queue(struct ast_cli_args *a)
Build a reverse polish notation expression queue.
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.
The one and only history that we've captured.
#define AST_VECTOR_PTR_FREE(vec)
Deallocates this vector pointer.
Definition vector.h:200

References a, 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, NULL, and vector_history.

Referenced by pjsip_show_history().

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

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}
static struct allowed_field allowed_fields[]
The fields we allow.

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

Referenced by evaluate_history_entry().

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

729{
730 struct pjsip_history_entry *entry;
731
732 if (!enabled) {
733 return PJ_FALSE;
734 }
735
736 if (!rdata->msg_info.msg) {
737 return PJ_FALSE;
738 }
739
740 entry = pjsip_history_entry_alloc(rdata->msg_info.msg);
741 if (!entry) {
742 return PJ_FALSE;
743 }
744
745 if (rdata->tp_info.transport->addr_len) {
746 pj_sockaddr_cp(&entry->dst, &rdata->tp_info.transport->local_addr);
747 }
748
749 if (rdata->pkt_info.src_addr_len) {
750 pj_sockaddr_cp(&entry->src, &rdata->pkt_info.src_addr);
751 }
752
754 if (AST_VECTOR_APPEND(&vector_history, entry)) {
755 ao2_ref(entry, -1);
756 entry = NULL;
757 }
759
760 if (log_level != -1 && entry) {
761 char line[256];
762
763 sprint_list_entry(entry, line, sizeof(line));
764 ast_log_dynamic_level(log_level, "%s\n", line);
765 }
766
767 return PJ_FALSE;
768}
#define ast_log_dynamic_level(level,...)
Send a log message to a dynamically registered log level.
static int enabled
Whether or not we are storing history.
static struct pjsip_history_entry * pjsip_history_entry_alloc(pjsip_msg *msg)
Create a pjsip_history_entry AO2 object.
static int log_level
Log level for history output.

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

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

695{
696 struct pjsip_history_entry *entry;
697
698 if (!enabled) {
699 return PJ_SUCCESS;
700 }
701
702 entry = pjsip_history_entry_alloc(tdata->msg);
703 if (!entry) {
704 return PJ_SUCCESS;
705 }
706 entry->transmitted = 1;
707 pj_sockaddr_cp(&entry->src, &tdata->tp_info.transport->local_addr);
708 pj_sockaddr_cp(&entry->dst, &tdata->tp_info.dst_addr);
709
711 if (AST_VECTOR_APPEND(&vector_history, entry)) {
712 ao2_ref(entry, -1);
713 entry = NULL;
714 }
716
717 if (log_level != -1 && entry) {
718 char line[256];
719
720 sprint_list_entry(entry, line, sizeof(line));
721 ast_log_dynamic_level(log_level, "%s\n", line);
722 }
723
724 return PJ_SUCCESS;
725}

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, pjsip_history_entry::transmitted, and vector_history.

◆ load_module()

static int load_module ( void  )
static

Definition at line 1370 of file res_pjsip_history.c.

1371{
1372 log_level = ast_logger_register_level("PJSIP_HISTORY");
1373 if (log_level < 0) {
1374 ast_log(LOG_WARNING, "Unable to register history log level\n");
1375 }
1376
1377 ast_pjproject_caching_pool_init(&cachingpool, &pj_pool_factory_default_policy, 0);
1378
1380
1383
1385}
#define ast_cli_register_multiple(e, len)
Register multiple commands.
Definition cli.h:265
int ast_logger_register_level(const char *name)
Register a new logger level.
Definition logger.c:2821
@ AST_MODULE_LOAD_SUCCESS
Definition module.h:70
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.
int ast_sip_register_service(pjsip_module *module)
Register a SIP service in Asterisk.
Definition res_pjsip.c:117
static pj_caching_pool cachingpool
Pool factory used by pjlib to allocate memory.
static struct ast_cli_entry cli_pjsip[]
static pjsip_module logging_module

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, cli_pjsip, HISTORY_INITIAL_SIZE, log_level, LOG_WARNING, logging_module, and vector_history.

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

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}
@ AO2_ALLOC_OPT_LOCK_NOLOCK
Definition astobj2.h:367
#define ao2_alloc_options(data_size, destructor_fn, options)
Definition astobj2.h:404
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:764
static void pjsip_history_entry_dtor(void *obj)
AO2 destructor for pjsip_history_entry.
pj_pool_t * pool
Memory pool used to allocate msg.
struct timeval ast_tvnow(void)
Returns current timeval. Meant to replace calls to gettimeofday().
Definition time.h:159

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

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

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}

References NULL, and pjsip_history_entry::pool.

Referenced by pjsip_history_entry_alloc().

◆ pjsip_set_history()

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

Definition at line 1314 of file res_pjsip_history.c.

1315{
1316 const char *what;
1317
1318 if (cmd == CLI_INIT) {
1319 e->command = "pjsip set history {on|off|clear}";
1320 e->usage =
1321 "Usage: pjsip set history {on|off|clear}\n"
1322 " Enables/disables/clears the PJSIP history.\n\n"
1323 " Enabling the history will start recording transmitted/received\n"
1324 " packets. Disabling the history will stop recording, but keep\n"
1325 " the already received packets. Clearing the history will wipe\n"
1326 " the received packets from memory.\n\n"
1327 " As the PJSIP history is maintained in memory, and includes\n"
1328 " all received/transmitted requests and responses, it should\n"
1329 " only be enabled for debugging purposes, and cleared when done.\n";
1330 return NULL;
1331 } else if (cmd == CLI_GENERATE) {
1332 return NULL;
1333 }
1334
1335 what = a->argv[e->args - 1]; /* Guaranteed to exist */
1336
1337 if (a->argc == e->args) {
1338 if (!strcasecmp(what, "on")) {
1339 enabled = 1;
1340 ast_cli(a->fd, "PJSIP History enabled\n");
1341 return CLI_SUCCESS;
1342 } else if (!strcasecmp(what, "off")) {
1343 enabled = 0;
1344 ast_cli(a->fd, "PJSIP History disabled\n");
1345 return CLI_SUCCESS;
1346 } else if (!strcasecmp(what, "clear")) {
1348 ast_cli(a->fd, "PJSIP History cleared\n");
1349 return CLI_SUCCESS;
1350 }
1351 }
1352
1353 return CLI_SHOWUSAGE;
1354}
#define CLI_SHOWUSAGE
Definition cli.h:45
#define CLI_SUCCESS
Definition cli.h:44
@ CLI_INIT
Definition cli.h:152
@ CLI_GENERATE
Definition cli.h:153
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:2099
static int clear_history_entries(void *obj)
Remove all entries from vector_history.
int args
This gets set in ast_cli_register()
Definition cli.h:185
char * command
Definition cli.h:186
const char * usage
Definition cli.h:177

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

◆ pjsip_show_history()

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

Definition at line 1220 of file res_pjsip_history.c.

1221{
1222 struct vector_history_t *vec = &vector_history;
1223 struct pjsip_history_entry *entry = NULL;
1224
1225 if (cmd == CLI_INIT) {
1226 e->command = "pjsip show history";
1227 e->usage =
1228 "Usage: pjsip show history [entry <num>|where [...]]\n"
1229 " Displays the currently collected history or an\n"
1230 " entry within the history.\n\n"
1231 " * Running the command with no options will display\n"
1232 " the entire history.\n"
1233 " * Providing 'entry <num>' will display the full\n"
1234 " detail of a particular entry in this history.\n"
1235 " * Providing 'where ...' will allow for filtering\n"
1236 " the history. The history can be filtered using\n"
1237 " any of the following fields:\n"
1238 " - number: The history entry number\n"
1239 " - timestamp: The time associated with the history entry\n"
1240 " - addr: The source/destination address of the SIP message\n"
1241 " - sip.msg.request.method: The request method type\n"
1242 " - sip.msg.call-id: The Call-ID header of the SIP message\n"
1243 "\n"
1244 " When filtering, standard Boolean operators can be used,\n"
1245 " as well as 'like' for regexs.\n"
1246 "\n"
1247 " Example:\n"
1248 " 'pjsip show history where number > 5 and (addr = \"192.168.0.3:5060\" or addr = \"192.168.0.5:5060\")'\n";
1249 return NULL;
1250 } else if (cmd == CLI_GENERATE) {
1251 return NULL;
1252 }
1253
1254 if (a->argc > 3) {
1255 if (!strcasecmp(a->argv[3], "entry") && a->argc == 5) {
1256 int num;
1257
1258 if (sscanf(a->argv[4], "%30d", &num) != 1) {
1259 ast_cli(a->fd, "'%s' is not a valid entry number\n", a->argv[4]);
1260 return CLI_FAILURE;
1261 }
1262
1263 /* Get the entry at the provided position */
1265 if (num >= AST_VECTOR_SIZE(&vector_history) || num < 0) {
1266 ast_cli(a->fd, "Entry '%d' does not exist\n", num);
1268 return CLI_FAILURE;
1269 }
1270 entry = ao2_bump(AST_VECTOR_GET(&vector_history, num));
1272 } else if (!strcasecmp(a->argv[3], "where")) {
1273 vec = filter_history(a);
1274 if (!vec) {
1275 return CLI_FAILURE;
1276 }
1277 } else {
1278 return CLI_SHOWUSAGE;
1279 }
1280 }
1281
1282 if (AST_VECTOR_SIZE(vec) == 1) {
1283 if (vec == &vector_history) {
1285 }
1286 entry = ao2_bump(AST_VECTOR_GET(vec, 0));
1287 if (vec == &vector_history) {
1289 }
1290 }
1291
1292 if (entry) {
1293 display_single_entry(a, entry);
1294 } else {
1295 if (vec == &vector_history) {
1297 }
1298
1299 display_entry_list(a, vec);
1300
1301 if (vec == &vector_history) {
1303 }
1304 }
1305
1306 if (vec != &vector_history) {
1308 }
1309 ao2_cleanup(entry);
1310
1311 return CLI_SUCCESS;
1312}
#define CLI_FAILURE
Definition cli.h:46
static int safe_vector_cleanup(void *obj)
Cleanup routine for a history vector, serviced on a registered PJSIP thread.
static struct vector_history_t * filter_history(struct ast_cli_args *a)
Create a filtered history based on a user provided expression.
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 display_entry_list(struct ast_cli_args *a, struct vector_history_t *vec)
Print a list of the entries to the CLI.

References a, ao2_bump, ao2_cleanup, 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(), filter_history(), history_lock, NULL, safe_vector_cleanup(), ast_cli_entry::usage, and vector_history.

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

1210{
1211 struct vector_history_t *vec = obj;
1212
1214 AST_VECTOR_FREE(vec);
1215 ast_free(vec);
1216
1217 return 0;
1218}

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

Referenced by pjsip_show_history().

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

658{
659 char addr[64], secs[AST_TIME_T_LEN];
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 ast_time_t_to_string(entry->timestamp.tv_sec, secs, sizeof(secs));
668
669 if (entry->msg->type == PJSIP_REQUEST_MSG) {
670 char uri[128];
671
672 pjsip_uri_print(PJSIP_URI_IN_REQ_URI, entry->msg->line.req.uri, uri, sizeof(uri));
673 snprintf(line, len, "%-5.5d %-10.10s %-5.5s %-24.24s %.*s %s SIP/2.0",
674 entry->number,
675 secs,
676 entry->transmitted ? "* ==>" : "* <==",
677 addr,
678 (int)pj_strlen(&entry->msg->line.req.method.name),
679 pj_strbuf(&entry->msg->line.req.method.name),
680 uri);
681 } else {
682 snprintf(line, len, "%-5.5d %-10.10s %-5.5s %-24.24s SIP/2.0 %u %.*s",
683 entry->number,
684 secs,
685 entry->transmitted ? "* ==>" : "* <==",
686 addr,
687 entry->msg->line.status.code,
688 (int)pj_strlen(&entry->msg->line.status.reason),
689 pj_strbuf(&entry->msg->line.status.reason));
690 }
691}
jack_status_t status
Definition app_jack.c:149
static const char name[]
Definition format_mp3.c:68
static int len(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t buflen)
const char * method
Definition res_pjsip.c:1279

References AST_TIME_T_LEN, ast_time_t_to_string(), pjsip_history_entry::dst, len(), 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().

◆ unload_module()

static int unload_module ( void  )
static

Definition at line 1387 of file res_pjsip_history.c.

1388{
1391
1394
1396
1397 if (log_level != -1) {
1398 ast_logger_unregister_level("PJSIP_HISTORY");
1399 }
1400
1401 return 0;
1402}
void ast_cli_unregister_multiple(void)
Definition ael_main.c:408
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:2165
void ast_logger_unregister_level(const char *name)
Unregister a previously registered logger level.
Definition logger.c:2879
void ast_pjproject_caching_pool_destroy(pj_caching_pool *cp)
Destroy caching pool factory and all cached pools.
void ast_sip_unregister_service(pjsip_module *module)
Definition res_pjsip.c:133

References ARRAY_LEN, ast_cli_unregister_multiple(), ast_logger_unregister_level(), ast_pjproject_caching_pool_destroy(), ast_sip_push_task_wait_servant(), ast_sip_unregister_service(), AST_VECTOR_FREE, cachingpool, clear_history_entries(), cli_pjsip, log_level, logging_module, NULL, and vector_history.

Variable Documentation

◆ __mod_info

struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_LOAD_ORDER , .description = "PJSIP History" , .key = ASTERISK_GPL_KEY , .buildopt_sum = AST_BUILDOPT_SUM, .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 1410 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.

513 {
514 { .symbol = "number", .return_type = OPT_INT_T, .get_field = entry_get_number, },
515 /* We co-op the NOOP type here for timeval */
516 { .symbol = "timestamp", .return_type = OPT_NOOP_T, .get_field = entry_get_timestamp, },
517 { .symbol = "addr", .return_type = OPT_SOCKADDR_T, .get_field = entry_get_addr, },
518 { .symbol = "sip.msg.request.method", .return_type = OPT_CHAR_ARRAY_T, .get_field = entry_get_sip_msg_request_method, },
519 { .symbol = "sip.msg.call-id", .return_type = OPT_CHAR_ARRAY_T, .get_field = entry_get_sip_msg_call_id, },
520};
static void * entry_get_addr(struct pjsip_history_entry *entry)
Callback to retrieve the entry's destination address.
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_sip_msg_call_id(struct pjsip_history_entry *entry)
Callback to retrieve the entry's SIP Call-ID header.
static void * entry_get_timestamp(struct pjsip_history_entry *entry)
Callback to retrieve the entry's timestamp.
static void * entry_get_number(struct pjsip_history_entry *entry)
Callback to retrieve the entry index number.

Referenced by get_allowed_field().

◆ allowed_operators

struct operator allowed_operators[]
static

Our allowed operations.

Definition at line 453 of file res_pjsip_history.c.

453 {
454 { .symbol = "=", .precedence = 7, .operands = 2, .evaluate = evaluate_equal, },
455 { .symbol = "==", .precedence = 7, .operands = 2, .evaluate = evaluate_equal, },
456 { .symbol = "!=", .precedence = 7, .operands = 2, .evaluate = evaluate_not_equal, },
457 { .symbol = "<", .precedence = 6, .operands = 2, .evaluate = evaluate_less_than, },
458 { .symbol = ">", .precedence = 6, .operands = 2, .evaluate = evaluate_greater_than, },
459 { .symbol = "<=", .precedence = 6, .operands = 2, .evaluate = evaluate_less_than_or_equal, },
460 { .symbol = ">=", .precedence = 6, .operands = 2, .evaluate = evaluate_greater_than_or_equal, },
461 { .symbol = "!", .precedence = 2, .operands = 1, .right_to_left = 1, .evaluate_unary = evaluate_not, },
462 { .symbol = "&&", .precedence = 11, .operands = 2, .evaluate = evaluate_and, },
463 { .symbol = "||", .precedence = 12, .operands = 2, .evaluate = evaluate_or, },
464 { .symbol = "like", .precedence = 7, .operands = 2, .evaluate = evaluate_like, },
465 { .symbol = "and", .precedence = 11, .operands = 2, .evaluate = evaluate_and, },
466 { .symbol = "or", .precedence = 11, .operands = 2, .evaluate = evaluate_or, },
467 { .symbol = "not", .precedence = 2, .operands = 1, .right_to_left = 1, .evaluate_unary = evaluate_not, },
468};
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_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_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_not(struct operator*op, enum aco_option_type type, void *operand)
Operator callback for determining logical NOT.
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_or(struct operator*op, enum aco_option_type type, void *op_left, struct expression_token *op_right)
Operator callback for determining logical OR.
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.

Referenced by build_expression_queue().

◆ ast_module_info

const struct ast_module_info* ast_module_info = &__mod_info
static

Definition at line 1410 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(), 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 1365 of file res_pjsip_history.c.

1365 {
1366 AST_CLI_DEFINE(pjsip_set_history, "Enable/Disable PJSIP History"),
1367 AST_CLI_DEFINE(pjsip_show_history, "Display PJSIP History"),
1368};
#define AST_CLI_DEFINE(fn, txt,...)
Definition cli.h:197

Referenced by load_module(), and unload_module().

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

445 {
446 .symbol = "(",
447 .precedence = 15
448};

Referenced by build_expression_queue().

◆ log_level

int log_level = -1
static

Log level for history output.

Definition at line 159 of file res_pjsip_history.c.

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

◆ logging_module

pjsip_module logging_module
static

Definition at line 1356 of file res_pjsip_history.c.

1356 {
1357 .name = { "History Module", 14 },
1358 .priority = 0,
1359 .on_rx_request = history_on_rx_msg,
1360 .on_rx_response = history_on_rx_msg,
1361 .on_tx_request = history_on_tx_msg,
1362 .on_tx_response = history_on_tx_msg,
1363};
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.

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

◆ vector_history

struct vector_history_t vector_history
static