pjproject: Add cache_pools debugging option.
[asterisk/asterisk.git] / res / res_pjsip_history.c
1 /*
2  * Asterisk -- An open source telephony toolkit.
3  *
4  * Copyright (C) 1999 - 2015, Digium, Inc.
5  *
6  * Matt Jordan <mjordan@digium.com>
7  *
8  * See http://www.asterisk.org for more information about
9  * the Asterisk project. Please do not directly contact
10  * any of the maintainers of this project for assistance;
11  * the project provides a web site, mailing lists and IRC
12  * channels for your use.
13  *
14  * This program is free software, distributed under the terms of
15  * the GNU General Public License Version 2. See the LICENSE file
16  * at the top of the source tree.
17  */
18
19 /*!
20  * \file
21  * \brief PJSIP History
22  *
23  * \author Matt Jordan <mjordan@digium.com>
24  *
25  */
26
27 /*** MODULEINFO
28         <depend>pjproject</depend>
29         <depend>res_pjsip</depend>
30         <support_level>extended</support_level>
31  ***/
32
33 #include "asterisk.h"
34
35 #include <pjsip.h>
36 #include <regex.h>
37
38 #include "asterisk/res_pjsip.h"
39 #include "asterisk/module.h"
40 #include "asterisk/logger.h"
41 #include "asterisk/cli.h"
42 #include "asterisk/netsock2.h"
43 #include "asterisk/vector.h"
44 #include "asterisk/lock.h"
45 #include "asterisk/res_pjproject.h"
46
47 #define HISTORY_INITIAL_SIZE 256
48
49 /*! \brief Pool factory used by pjlib to allocate memory. */
50 static pj_caching_pool cachingpool;
51
52 /*! \brief Whether or not we are storing history */
53 static int enabled;
54
55 /*! \brief Packet count */
56 static int packet_number;
57
58 /*! \brief An item in the history */
59 struct pjsip_history_entry {
60         /*! \brief Packet number */
61         int number;
62         /*! \brief Whether or not we transmitted the packet */
63         int transmitted;
64         /*! \brief Time the packet was transmitted/received */
65         struct timeval timestamp;
66         /*! \brief Source address */
67         pj_sockaddr_in src;
68         /*! \brief Destination address */
69         pj_sockaddr_in dst;
70         /*! \brief Memory pool used to allocate \c msg */
71         pj_pool_t *pool;
72         /*! \brief The actual SIP message */
73         pjsip_msg *msg;
74 };
75
76 /*! \brief Mutex that protects \ref vector_history */
77 AST_MUTEX_DEFINE_STATIC(history_lock);
78
79 /*! \brief The one and only history that we've captured */
80 static AST_VECTOR(vector_history_t, struct pjsip_history_entry *) vector_history;
81
82 struct expression_token;
83
84 /*! \brief An operator that we understand in an expression */
85 struct operator {
86         /*! \brief Our operator's symbol */
87         const char *symbol;
88         /*! \brief Precedence of the symbol */
89         int precedence;
90         /*! \brief Non-zero if the operator is evaluated right-to-left */
91         int right_to_left;
92         /*! \brief Number of operands the operator takes */
93         int operands;
94         /*!
95          * \brief Evaluation function for unary operators
96          *
97          * \param op The operator being evaluated
98          * \param type The type of value contained in \c operand
99          * \param operand A pointer to the value to evaluate
100          *
101          * \retval -1 error
102          * \retval 0 evaluation is False
103          * \retval 1 evaluation is True
104          */
105         int (* const evaluate_unary)(struct operator *op, enum aco_option_type type, void *operand);
106         /*!
107          * \brief Evaluation function for binary operators
108          *
109          * \param op The operator being evaluated
110          * \param type The type of value contained in \c op_left
111          * \param op_left A pointer to the value to evaluate (a result or extracted from an entry)
112          * \param op_right The expression token containing the other value (a result or user-provided)
113          *
114          * \retval -1 error
115          * \retval 0 evaluation is False
116          * \retval 1 evaluation is True
117          */
118         int (* const evaluate)(struct operator *op, enum aco_option_type type, void *op_left, struct expression_token *op_right);
119 };
120
121 /*! \brief A field that we understand and can perform operations on */
122 struct allowed_field {
123         /*! \brief The representation of the field */
124         const char *symbol;
125         /*! \brief The type /c get_field returns */
126         enum aco_option_type return_type;
127         /*!
128          * \brief Function that returns the field from a pjsip_history_entry
129          *
130          * Note that the function must return a pointer to the location in
131          * \c pjsip_history_entry - no memory should be allocated as the caller
132          * will not dispose of any
133          */
134         void *(* const get_field)(struct pjsip_history_entry *entry);
135 };
136
137 /*! \brief The type of token that has been parsed out of an expression */
138 enum expression_token_type {
139         /*! The \c expression_token contains a field */
140         TOKEN_TYPE_FIELD,
141         /*! The \c expression_token contains an operator */
142         TOKEN_TYPE_OPERATOR,
143         /*! The \c expression_token contains a previous result */
144         TOKEN_TYPE_RESULT
145 };
146
147 /*! \brief A token in the expression or an evaluated part of the expression */
148 struct expression_token {
149         /*! \brief The next expression token in the queue */
150         struct expression_token *next;
151         /*! \brief The type of value stored in the expression token */
152         enum expression_token_type token_type;
153         /*! \brief An operator that evaluates expressions */
154         struct operator *op;
155         /*! \brief The result of an evaluated expression */
156         int result;
157         /*! \brief The field in the expression */
158         char field[];
159 };
160
161 /*! \brief Log level for history output */
162 static int log_level = -1;
163
164 /*!
165  * \brief Operator callback for determining equality
166  */
167 static int evaluate_equal(struct operator *op, enum aco_option_type type, void *op_left, struct expression_token *op_right)
168 {
169         switch (type) {
170         case OPT_BOOL_T:
171         case OPT_BOOLFLAG_T:
172         case OPT_INT_T:
173         case OPT_UINT_T:
174         {
175                 int right;
176
177                 if (sscanf(op_right->field, "%30d", &right) != 1) {
178                         ast_log(LOG_WARNING, "Unable to extract field '%s': not an integer\n", op_right->field);
179                         return -1;
180                 }
181                 return (*(int *)op_left) == right;
182         }
183         case OPT_DOUBLE_T:
184         {
185                 double right;
186
187                 if (sscanf(op_right->field, "%lf", &right) != 1) {
188                         ast_log(LOG_WARNING, "Unable to extract field '%s': not a double\n", op_right->field);
189                         return -1;
190                 }
191                 return (*(double *)op_left) == right;
192         }
193         case OPT_CHAR_ARRAY_T:
194         case OPT_STRINGFIELD_T:
195                 /* In our case, we operate on pj_str_t */
196                 return pj_strcmp2(op_left, op_right->field) == 0;
197         case OPT_NOOP_T:
198         /* Used for timeval */
199         {
200                 struct timeval right = { 0, };
201
202                 if (sscanf(op_right->field, "%ld", &right.tv_sec) != 1) {
203                         ast_log(LOG_WARNING, "Unable to extract field '%s': not a timestamp\n", op_right->field);
204                         return -1;
205                 }
206
207                 return ast_tvcmp(*(struct timeval *)op_left, right) == 0;
208         }
209         case OPT_SOCKADDR_T:
210         /* In our case, we operate only on pj_sockaddr_t */
211         {
212                 pj_sockaddr right;
213                 pj_str_t str_right;
214
215                 pj_cstr(&str_right, op_right->field);
216                 if (pj_sockaddr_parse(pj_AF_UNSPEC(), 0, &str_right, &right) != PJ_SUCCESS) {
217                         ast_log(LOG_WARNING, "Unable to convert field '%s': not an IPv4 or IPv6 address\n", op_right->field);
218                         return -1;
219                 }
220
221                 return pj_sockaddr_cmp(op_left, &right) == 0;
222         }
223         default:
224                 ast_log(LOG_WARNING, "Cannot evaluate field '%s': invalid type for operator '%s'\n",
225                         op_right->field, op->symbol);
226         }
227
228         return -1;
229 }
230
231 /*!
232  * \brief Operator callback for determining inequality
233  */
234 static int evaluate_not_equal(struct operator *op, enum aco_option_type type, void *op_left, struct expression_token *op_right)
235 {
236         return !evaluate_equal(op, type, op_left, op_right);
237 }
238
239 /*
240  * \brief Operator callback for determining if one operand is less than another
241  */
242 static int evaluate_less_than(struct operator *op, enum aco_option_type type, void *op_left, struct expression_token *op_right)
243 {
244         switch (type) {
245         case OPT_BOOL_T:
246         case OPT_BOOLFLAG_T:
247         case OPT_INT_T:
248         case OPT_UINT_T:
249         {
250                 int right;
251
252                 if (sscanf(op_right->field, "%30d", &right) != 1) {
253                         ast_log(LOG_WARNING, "Unable to extract field '%s': not an integer\n", op_right->field);
254                         return -1;
255                 }
256                 return (*(int *)op_left) < right;
257         }
258         case OPT_DOUBLE_T:
259         {
260                 double right;
261
262                 if (sscanf(op_right->field, "%lf", &right) != 1) {
263                         ast_log(LOG_WARNING, "Unable to extract field '%s': not a double\n", op_right->field);
264                         return -1;
265                 }
266                 return (*(double *)op_left) < right;
267         }
268         case OPT_NOOP_T:
269         /* Used for timeval */
270         {
271                 struct timeval right = { 0, };
272
273                 if (sscanf(op_right->field, "%ld", &right.tv_sec) != 1) {
274                         ast_log(LOG_WARNING, "Unable to extract field '%s': not a timestamp\n", op_right->field);
275                         return -1;
276                 }
277
278                 return ast_tvcmp(*(struct timeval *)op_left, right) == -1;
279         }
280         default:
281                 ast_log(LOG_WARNING, "Cannot evaluate field '%s': invalid type for operator '%s'\n",
282                         op_right->field, op->symbol);
283         }
284
285         return -1;
286 }
287
288 /*
289  * \brief Operator callback for determining if one operand is greater than another
290  */
291 static int evaluate_greater_than(struct operator *op, enum aco_option_type type, void *op_left, struct expression_token *op_right)
292 {
293         switch (type) {
294         case OPT_BOOL_T:
295         case OPT_BOOLFLAG_T:
296         case OPT_INT_T:
297         case OPT_UINT_T:
298         {
299                 int right;
300
301                 if (sscanf(op_right->field, "%30d", &right) != 1) {
302                         ast_log(LOG_WARNING, "Unable to extract field '%s': not an integer\n", op_right->field);
303                         return -1;
304                 }
305                 return (*(int *)op_left) > right;
306         }
307         case OPT_DOUBLE_T:
308         {
309                 double right;
310
311                 if (sscanf(op_right->field, "%lf", &right) != 1) {
312                         ast_log(LOG_WARNING, "Unable to extract field '%s': not a double\n", op_right->field);
313                         return -1;
314                 }
315                 return (*(double *)op_left) > right;
316         }
317         case OPT_NOOP_T:
318         /* Used for timeval */
319         {
320                 struct timeval right = { 0, };
321
322                 if (sscanf(op_right->field, "%ld", &right.tv_sec) != 1) {
323                         ast_log(LOG_WARNING, "Unable to extract field '%s': not a timestamp\n", op_right->field);
324                         return -1;
325                 }
326
327                 return ast_tvcmp(*(struct timeval *)op_left, right) == 1;
328         }
329         default:
330                 ast_log(LOG_WARNING, "Cannot evaluate field '%s': invalid type for operator '%s'\n",
331                         op_right->field, op->symbol);
332         }
333
334         return -1;
335 }
336
337 /*
338  * \brief Operator callback for determining if one operand is less than or equal to another
339  */
340 static int evaluate_less_than_or_equal(struct operator *op, enum aco_option_type type, void *op_left, struct expression_token *op_right)
341 {
342         return !evaluate_greater_than(op, type, op_left, op_right);
343 }
344
345 /*
346  * \brief Operator callback for determining if one operand is greater than or equal to another
347  */
348 static int evaluate_greater_than_or_equal(struct operator *op, enum aco_option_type type, void *op_left, struct expression_token *op_right)
349 {
350         return !evaluate_less_than(op, type, op_left, op_right);
351 }
352
353 /*
354  * \brief Operator callback for determining logical NOT
355  */
356 static int evaluate_not(struct operator *op, enum aco_option_type type, void *operand)
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 }
370
371 /*
372  * \brief Operator callback for determining logical AND
373  */
374 static int evaluate_and(struct operator *op, enum aco_option_type type, void *op_left, struct expression_token *op_right)
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 }
388
389 /*
390  * \brief Operator callback for determining logical OR
391  */
392 static int evaluate_or(struct operator *op, enum aco_option_type type, void *op_left, struct expression_token *op_right)
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 }
406
407 /*
408  * \brief Operator callback for regex 'like'
409  */
410 static int evaluate_like(struct operator *op, enum aco_option_type type, void *op_left, struct expression_token *op_right)
411 {
412         switch (type) {
413         case OPT_CHAR_ARRAY_T:
414         case OPT_STRINGFIELD_T:
415         /* In our case, we operate on pj_str_t */
416         {
417                 int result;
418                 regex_t regexbuf;
419                 char buf[pj_strlen(op_left) + 1];
420
421                 ast_copy_pj_str(buf, op_left, pj_strlen(op_left));
422                 if (regcomp(&regexbuf, op_right->field, REG_EXTENDED | REG_NOSUB)) {
423                         ast_log(LOG_WARNING, "Failed to compile '%s' into a regular expression\n", op_right->field);
424                         return -1;
425                 }
426
427                 result = (regexec(&regexbuf, buf, 0, NULL, 0) == 0);
428                 regfree(&regexbuf);
429
430                 return result;
431         }
432         default:
433                 ast_log(LOG_WARNING, "Cannot evaluate: invalid operand type for operator '%s'\n", op->symbol);
434         }
435
436         return -1;
437 }
438
439 /*!
440  * \brief Operator token for a left parenthesis.
441  *
442  * While this is used by the shunting-yard algorithm implementation,
443  * it should never appear in the resulting RPN queue of expression tokens
444  */
445 static struct operator left_paren = {
446         .symbol = "(",
447         .precedence = 15
448 };
449
450 /*!
451  * \brief Our allowed operations
452  */
453 static struct operator allowed_operators[] = {
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 };
469
470 /*! \brief Callback to retrieve the entry index number */
471 static void *entry_get_number(struct pjsip_history_entry *entry)
472 {
473         return &entry->number;
474 }
475
476 /*! \brief Callback to retrieve the entry's timestamp */
477 static void *entry_get_timestamp(struct pjsip_history_entry *entry)
478 {
479         return &entry->timestamp;
480 }
481
482 /*! \brief Callback to retrieve the entry's destination address */
483 static void *entry_get_addr(struct pjsip_history_entry *entry)
484 {
485         if (entry->transmitted) {
486                 return &entry->dst;
487         } else {
488                 return &entry->src;
489         }
490 }
491
492 /*! \brief Callback to retrieve the entry's SIP request method type */
493 static void *entry_get_sip_msg_request_method(struct pjsip_history_entry *entry)
494 {
495         if (entry->msg->type != PJSIP_REQUEST_MSG) {
496                 return NULL;
497         }
498
499         return &entry->msg->line.req.method.name;
500 }
501
502 /*! \brief Callback to retrieve the entry's SIP Call-ID header */
503 static void *entry_get_sip_msg_call_id(struct pjsip_history_entry *entry)
504 {
505         pjsip_cid_hdr *cid_hdr;
506
507         cid_hdr = PJSIP_MSG_CID_HDR(entry->msg);
508
509         return &cid_hdr->id;
510 }
511
512 /*! \brief The fields we allow */
513 static struct allowed_field allowed_fields[] = {
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 };
521
522 /*! \brief Free an expression token and all others it references */
523 static struct expression_token *expression_token_free(struct expression_token *token)
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 }
537
538 /*!
539  * \brief Allocate an expression token
540  *
541  * \param token_type The type of token in the expression
542  * \param value The value/operator/result to pack into the token
543  *
544  * \retval NULL on failure
545  * \retval \c expression_token on success
546  */
547 static struct expression_token *expression_token_alloc(enum expression_token_type token_type, void *value)
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 }
585
586 /*! \brief Determine if the expression token matches a field in \c allowed_fields */
587 static struct allowed_field *get_allowed_field(struct expression_token *token)
588 {
589         int i;
590
591         ast_assert(token->token_type == TOKEN_TYPE_FIELD);
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 }
603
604 /*! \brief AO2 destructor for \c pjsip_history_entry */
605 static void pjsip_history_entry_dtor(void *obj)
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 }
619
620 /*!
621  * \brief Create a \c pjsip_history_entry AO2 object
622  *
623  * \param msg The PJSIP message that this history entry wraps
624  *
625  * \retval An AO2 \c pjsip_history_entry object on success
626  * \retval NULL on failure
627  */
628 static struct pjsip_history_entry *pjsip_history_entry_alloc(pjsip_msg *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         }
636         entry->number = ast_atomic_fetchadd_int(&packet_number, 1);
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 }
655
656 /*! \brief Format single line history entry */
657 static void sprint_list_entry(struct pjsip_history_entry *entry, char *line, int len)
658 {
659         char addr[64];
660
661         if (entry->transmitted) {
662                 pj_sockaddr_print(&entry->dst, addr, sizeof(addr), 3);
663         } else {
664                 pj_sockaddr_print(&entry->src, addr, sizeof(addr), 3);
665         }
666
667         if (entry->msg->type == PJSIP_REQUEST_MSG) {
668                 char uri[128];
669
670                 pjsip_uri_print(PJSIP_URI_IN_REQ_URI, entry->msg->line.req.uri, uri, sizeof(uri));
671                 snprintf(line, len, "%-5.5d %-10.10ld %-5.5s %-24.24s %.*s %s SIP/2.0",
672                         entry->number,
673                         entry->timestamp.tv_sec,
674                         entry->transmitted ? "* ==>" : "* <==",
675                         addr,
676                         (int)pj_strlen(&entry->msg->line.req.method.name),
677                         pj_strbuf(&entry->msg->line.req.method.name),
678                         uri);
679         } else {
680                 snprintf(line, len, "%-5.5d %-10.10ld %-5.5s %-24.24s SIP/2.0 %u %.*s",
681                         entry->number,
682                         entry->timestamp.tv_sec,
683                         entry->transmitted ? "* ==>" : "* <==",
684                         addr,
685                         entry->msg->line.status.code,
686                         (int)pj_strlen(&entry->msg->line.status.reason),
687                         pj_strbuf(&entry->msg->line.status.reason));
688         }
689 }
690
691 /*! \brief PJSIP callback when a SIP message is transmitted */
692 static pj_status_t history_on_tx_msg(pjsip_tx_data *tdata)
693 {
694         struct pjsip_history_entry *entry;
695
696         if (!enabled) {
697                 return PJ_SUCCESS;
698         }
699
700         entry = pjsip_history_entry_alloc(tdata->msg);
701         if (!entry) {
702                 return PJ_SUCCESS;
703         }
704         entry->transmitted = 1;
705         pj_sockaddr_cp(&entry->src, &tdata->tp_info.transport->local_addr);
706         pj_sockaddr_cp(&entry->dst, &tdata->tp_info.dst_addr);
707
708         ast_mutex_lock(&history_lock);
709         if (AST_VECTOR_APPEND(&vector_history, entry)) {
710                 ao2_ref(entry, -1);
711                 entry = NULL;
712         }
713         ast_mutex_unlock(&history_lock);
714
715         if (log_level != -1 && entry) {
716                 char line[256];
717
718                 sprint_list_entry(entry, line, sizeof(line));
719                 ast_log_dynamic_level(log_level, "%s\n", line);
720         }
721
722         return PJ_SUCCESS;
723 }
724
725 /*! \brief PJSIP callback when a SIP message is received */
726 static pj_bool_t history_on_rx_msg(pjsip_rx_data *rdata)
727 {
728         struct pjsip_history_entry *entry;
729
730         if (!enabled) {
731                 return PJ_FALSE;
732         }
733
734         if (!rdata->msg_info.msg) {
735                 return PJ_FALSE;
736         }
737
738         entry = pjsip_history_entry_alloc(rdata->msg_info.msg);
739         if (!entry) {
740                 return PJ_FALSE;
741         }
742
743         if (rdata->tp_info.transport->addr_len) {
744                 pj_sockaddr_cp(&entry->dst, &rdata->tp_info.transport->local_addr);
745         }
746
747         if (rdata->pkt_info.src_addr_len) {
748                 pj_sockaddr_cp(&entry->src, &rdata->pkt_info.src_addr);
749         }
750
751         ast_mutex_lock(&history_lock);
752         if (AST_VECTOR_APPEND(&vector_history, entry)) {
753                 ao2_ref(entry, -1);
754                 entry = NULL;
755         }
756         ast_mutex_unlock(&history_lock);
757
758         if (log_level != -1 && entry) {
759                 char line[256];
760
761                 sprint_list_entry(entry, line, sizeof(line));
762                 ast_log_dynamic_level(log_level, "%s\n", line);
763         }
764
765         return PJ_FALSE;
766 }
767
768 /*! \brief Vector callback that releases the reference for the entry in a history vector */
769 static void clear_history_entry_cb(struct pjsip_history_entry *entry)
770 {
771         ao2_ref(entry, -1);
772 }
773
774 /*!
775  * \brief Remove all entries from \ref vector_history
776  *
777  * This must be called from a registered PJSIP thread
778  */
779 static int clear_history_entries(void *obj)
780 {
781         ast_mutex_lock(&history_lock);
782         AST_VECTOR_RESET(&vector_history, clear_history_entry_cb);
783         packet_number = 0;
784         ast_mutex_unlock(&history_lock);
785
786         return 0;
787 }
788
789 /*!
790  * \brief Build a reverse polish notation expression queue
791  *
792  * This function is an implementation of the Shunting-Yard Algorithm. It takes
793  * a user provided infix-notation expression and converts it into a reverse
794  * polish notation expression, which is a queue of tokens that can be easily
795  * parsed.
796  *
797  * \params a The CLI arguments provided by the User, containing the infix expression
798  *
799  * \retval NULL error
800  * \retval expression_token A 'queue' of expression tokens in RPN
801  */
802 static struct expression_token *build_expression_queue(struct ast_cli_args *a)
803 {
804         AST_VECTOR(, struct operator *) operators; /* A stack of saved operators */
805         struct expression_token *output = NULL;    /* The output queue */
806         struct expression_token *head = NULL;      /* Pointer to the head of /c output */
807         int i;
808
809 #define APPEND_TO_OUTPUT(output, token) do { \
810         if ((output)) { \
811                 (output)->next = (token); \
812                 (output) = (token); \
813         } else { \
814                 (output) = (token); \
815                 head = (output); \
816         } \
817 } while (0)
818
819         if (AST_VECTOR_INIT(&operators, 8)) {
820                 return NULL;
821         }
822
823         for (i = 4; i < a->argc; i++) {
824                 struct expression_token *out_token;
825                 char *token = ast_strdupa(a->argv[i]);
826                 int j;
827
828                 /* Strip off and append any left parentheses */
829                 if (token[0] == '(') {
830                         AST_VECTOR_APPEND(&operators, &left_paren);
831                         if (!token[1]) {
832                                 continue;
833                         }
834                         token = &token[1];
835                 }
836
837                 /* Handle the case where the token is an operator */
838                 for (j = 0; j < ARRAY_LEN(allowed_operators); j++) {
839                         int k;
840
841                         if (strcasecmp(token, allowed_operators[j].symbol)) {
842                                 continue;
843                         }
844
845                         for (k = AST_VECTOR_SIZE(&operators) - 1; k >= 0; k--) {
846                                 struct operator *top = AST_VECTOR_GET(&operators, k);
847
848                                 /* Remove and push queued up operators, if they are of
849                                  * less precedence than this operator
850                                  */
851                                 if ((allowed_operators[j].right_to_left && allowed_operators[j].precedence >= top->precedence)
852                                         || (!allowed_operators[j].right_to_left && allowed_operators[j].precedence > top->precedence)) {
853
854                                         if (!(out_token = expression_token_alloc(TOKEN_TYPE_OPERATOR, top))) {
855                                                 goto error;
856                                         }
857                                         APPEND_TO_OUTPUT(output, out_token);
858                                         AST_VECTOR_REMOVE(&operators, k, 1);
859                                 }
860                         }
861
862                         AST_VECTOR_APPEND(&operators, &allowed_operators[j]);
863                         token = NULL;
864                         break;
865                 }
866
867                 /* Token was an operator; continue to next token */
868                 if (!token) {
869                         continue;
870                 }
871
872                 /* Handle a right parentheses either by itself or as part of the token.
873                  * If part of the token, push the token onto the output queue first
874                  */
875                 if (token[0] == ')' || token[strlen(token) - 1] == ')') {
876
877                         if (token[strlen(token) - 1] == ')') {
878                                 token[strlen(token) - 1] = '\0';
879
880                                 if (!(out_token = expression_token_alloc(TOKEN_TYPE_FIELD, token))) {
881                                         goto error;
882                                 }
883                                 APPEND_TO_OUTPUT(output, out_token);
884                                 token = NULL;
885                         }
886
887                         for (j = AST_VECTOR_SIZE(&operators) - 1; j >= 0; j--) {
888                                 struct operator *top = AST_VECTOR_GET(&operators, j);
889
890                                 AST_VECTOR_REMOVE(&operators, j, 1);
891                                 if (top == &left_paren) {
892                                         break;
893                                 }
894
895                                 if (!(out_token = expression_token_alloc(TOKEN_TYPE_OPERATOR, top))) {
896                                         goto error;
897                                 }
898                                 APPEND_TO_OUTPUT(output, out_token);
899                         }
900                 }
901
902                 /* Just a plain token, push to the output queue */
903                 if (token) {
904                         if (!(out_token = expression_token_alloc(TOKEN_TYPE_FIELD, token))) {
905                                 goto error;
906                         }
907                         APPEND_TO_OUTPUT(output, out_token);
908                 }
909         }
910
911         /* Remove any non-applied operators that remain, applying them
912          * to the output queue
913          */
914         for (i = AST_VECTOR_SIZE(&operators) - 1; i >= 0; i--) {
915                 struct operator *top = AST_VECTOR_GET(&operators, i);
916                 struct expression_token *out_token;
917
918                 AST_VECTOR_REMOVE(&operators, i, 1);
919                 if (top == &left_paren) {
920                         ast_log(LOG_WARNING, "Unbalanced '(' parentheses in expression!\n");
921                         continue;
922                 }
923
924                 if (!(out_token = expression_token_alloc(TOKEN_TYPE_OPERATOR, top))) {
925                         goto error;
926                 }
927                 APPEND_TO_OUTPUT(output, out_token);
928         }
929
930         AST_VECTOR_FREE(&operators);
931         return head;
932
933 error:
934         AST_VECTOR_FREE(&operators);
935         expression_token_free(output);
936         return NULL;
937 }
938
939 /*!
940  * \brief Evaluate a single entry in this history using a RPN expression
941  *
942  * \param entry The entry in the history to evaluate
943  * \param queue The RPN expression
944  *
945  * \retval 0 The expression evaluated FALSE on \c entry
946  * \retval 1 The expression evaluated TRUE on \c entry
947  * \retval -1 The expression errored
948  */
949 static int evaluate_history_entry(struct pjsip_history_entry *entry, struct expression_token *queue)
950 {
951         AST_VECTOR(, struct expression_token *) stack; /* Our stack of results and operands */
952         struct expression_token *it_queue;
953         struct expression_token *final;
954         int result;
955         int i;
956
957         if (AST_VECTOR_INIT(&stack, 16)) {
958                 return -1;
959         }
960
961         for (it_queue = queue; it_queue; it_queue = it_queue->next) {
962                 struct expression_token *op_one;
963                 struct expression_token *op_two = NULL;
964                 struct expression_token *result;
965                 int res = 0;
966
967                 /* If this is not an operator, push it to the stack */
968                 if (!it_queue->op) {
969                         if (AST_VECTOR_APPEND(&stack, it_queue)) {
970                                 goto error;
971                         }
972                         continue;
973                 }
974
975                 if (AST_VECTOR_SIZE(&stack) < it_queue->op->operands) {
976                         ast_log(LOG_WARNING, "Unable to evaluate expression operator '%s': not enough operands\n",
977                                 it_queue->op->symbol);
978                         goto error;
979                 }
980
981                 if (it_queue->op->operands == 1) {
982                         /* Unary operators currently consist only of 'not', which can only act
983                          * upon an evaluated condition result.
984                          */
985                         ast_assert(it_queue->op->evaluate_unary != NULL);
986
987                         op_one = AST_VECTOR_REMOVE(&stack, AST_VECTOR_SIZE(&stack) - 1, 1);
988                         if (op_one->token_type != TOKEN_TYPE_RESULT) {
989                                 ast_log(LOG_WARNING, "Unable to evaluate '%s': operand is not the result of an operation\n",
990                                         it_queue->op->symbol);
991                                 goto error;
992                         }
993
994                         res = it_queue->op->evaluate_unary(it_queue->op, OPT_INT_T, &op_one->result) == 0 ? 0 : 1;
995                 } else if (it_queue->op->operands == 2) {
996                         struct allowed_field *field;
997                         enum aco_option_type type;
998                         void *value;
999
1000                         ast_assert(it_queue->op->evaluate != NULL);
1001
1002                         op_one = AST_VECTOR_REMOVE(&stack, AST_VECTOR_SIZE(&stack) - 1, 1);
1003                         op_two = AST_VECTOR_REMOVE(&stack, AST_VECTOR_SIZE(&stack) - 1, 1);
1004
1005                         /* If operand two is a field, then it must be a field we recognize. */
1006                         if (op_two->token_type == TOKEN_TYPE_FIELD) {
1007                                 field = get_allowed_field(op_two);
1008                                 if (!field) {
1009                                         ast_log(LOG_WARNING, "Unknown or unrecognized field: %s\n", op_two->field);
1010                                         goto error;
1011                                 }
1012
1013                                 type = field->return_type;
1014                                 value = field->get_field(entry);
1015                         } else if (op_two->token_type == TOKEN_TYPE_RESULT) {
1016                                 type = OPT_INT_T;
1017                                 value = &op_two->result;
1018                         } else {
1019                                 ast_log(LOG_WARNING, "Attempting to evaluate an operator: %s\n", op_two->op->symbol);
1020                                 goto error;
1021                         }
1022
1023                         if (value) {
1024                                 res = it_queue->op->evaluate(it_queue->op, type, value, op_one) == 0 ? 0 : 1;
1025                         } else {
1026                                 res = 0;
1027                         }
1028                 } else {
1029                         ast_log(LOG_WARNING, "Operator '%s' has an invalid number of operands\n", it_queue->op->symbol);
1030                         ast_assert(0);
1031                         goto error;
1032                 }
1033
1034                 /* Results are temporary; clean used ones up */
1035                 if (op_one && op_one->token_type == TOKEN_TYPE_RESULT) {
1036                         ast_free(op_one);
1037                 }
1038                 if (op_two && op_two->token_type == TOKEN_TYPE_RESULT) {
1039                         ast_free(op_two);
1040                 }
1041
1042                 /* Push the result onto the stack */
1043                 result = expression_token_alloc(TOKEN_TYPE_RESULT, &res);
1044                 if (!result) {
1045                         goto error;
1046                 }
1047                 if (AST_VECTOR_APPEND(&stack, result)) {
1048                         expression_token_free(result);
1049
1050                         goto error;
1051                 }
1052         }
1053
1054         /*
1055          * When the evaluation is complete, we must have:
1056          *  - A single result remaining on the stack
1057          *  - An actual result
1058          */
1059         if (AST_VECTOR_SIZE(&stack) != 1) {
1060                 ast_log(LOG_WARNING, "Expression was unbalanced: %zu results remained after evaluation\n",
1061                         AST_VECTOR_SIZE(&stack));
1062                 goto error;
1063         }
1064
1065         final = AST_VECTOR_GET(&stack, 0);
1066         if (final->token_type != TOKEN_TYPE_RESULT) {
1067                 ast_log(LOG_WARNING, "Expression did not create a usable result\n");
1068                 goto error;
1069         }
1070         result = final->result;
1071         ast_free(final);
1072         AST_VECTOR_FREE(&stack);
1073
1074         return result;
1075
1076 error:
1077         /* Clean out any remaining result expression tokens */
1078         for (i = 0; i < AST_VECTOR_SIZE(&stack); i++) {
1079                 struct expression_token *failed_token = AST_VECTOR_GET(&stack, i);
1080
1081                 if (failed_token->token_type == TOKEN_TYPE_RESULT) {
1082                         ast_free(failed_token);
1083                 }
1084         }
1085         AST_VECTOR_FREE(&stack);
1086         return -1;
1087 }
1088
1089 /*!
1090  * \brief Create a filtered history based on a user provided expression
1091  *
1092  * \param a The CLI arguments containing the expression
1093  *
1094  * \retval NULL on error
1095  * \retval A vector containing the filtered history on success
1096  */
1097 static struct vector_history_t *filter_history(struct ast_cli_args *a)
1098 {
1099         struct vector_history_t *output;
1100         struct expression_token *queue;
1101         int i;
1102
1103         output = ast_malloc(sizeof(*output));
1104         if (!output) {
1105                 return NULL;
1106         }
1107
1108         if (AST_VECTOR_INIT(output, HISTORY_INITIAL_SIZE / 2)) {
1109                 ast_free(output);
1110                 return NULL;
1111         }
1112
1113         queue = build_expression_queue(a);
1114         if (!queue) {
1115                 AST_VECTOR_PTR_FREE(output);
1116                 return NULL;
1117         }
1118
1119         ast_mutex_lock(&history_lock);
1120         for (i = 0; i < AST_VECTOR_SIZE(&vector_history); i++) {
1121                 struct pjsip_history_entry *entry = AST_VECTOR_GET(&vector_history, i);
1122                 int res;
1123
1124                 res = evaluate_history_entry(entry, queue);
1125                 if (res == -1) {
1126                         /* Error in expression evaluation; bail */
1127                         ast_mutex_unlock(&history_lock);
1128                         AST_VECTOR_RESET(output, clear_history_entry_cb);
1129                         AST_VECTOR_FREE(output);
1130                         ast_free(output);
1131                         expression_token_free(queue);
1132                         return NULL;
1133                 } else if (!res) {
1134                         continue;
1135                 } else {
1136                         if (AST_VECTOR_APPEND(output, ao2_bump(entry))) {
1137                                 ao2_cleanup(entry);
1138                         }
1139                 }
1140         }
1141         ast_mutex_unlock(&history_lock);
1142
1143         expression_token_free(queue);
1144
1145         return output;
1146 }
1147
1148 /*! \brief Print a detailed view of a single entry in the history to the CLI */
1149 static void display_single_entry(struct ast_cli_args *a, struct pjsip_history_entry *entry)
1150 {
1151         char addr[64];
1152         char *buf;
1153
1154         buf = ast_calloc(1, PJSIP_MAX_PKT_LEN * sizeof(char));
1155         if (!buf) {
1156                 return;
1157         }
1158
1159         if (pjsip_msg_print(entry->msg, buf, PJSIP_MAX_PKT_LEN) == -1) {
1160                 ast_log(LOG_WARNING, "Unable to print SIP message %d: packet too large!\n", entry->number);
1161                 ast_free(buf);
1162                 return;
1163         }
1164
1165         if (entry->transmitted) {
1166                 pj_sockaddr_print(&entry->dst, addr, sizeof(addr), 3);
1167         } else {
1168                 pj_sockaddr_print(&entry->src, addr, sizeof(addr), 3);
1169         }
1170
1171         ast_cli(a->fd, "<--- History Entry %d %s %s at %-10.10ld --->\n",
1172                 entry->number,
1173                 entry->transmitted ? "Sent to" : "Received from",
1174                 addr,
1175                 entry->timestamp.tv_sec);
1176         ast_cli(a->fd, "%s\n", buf);
1177
1178         ast_free(buf);
1179 }
1180
1181 /*! \brief Print a list of the entries to the CLI */
1182 static void display_entry_list(struct ast_cli_args *a, struct vector_history_t *vec)
1183 {
1184         int i;
1185
1186         ast_cli(a->fd, "%-5.5s %-10.10s %-30.30s %-35.35s\n",
1187                 "No.",
1188                 "Timestamp",
1189                 "(Dir) Address",
1190                 "SIP Message");
1191         ast_cli(a->fd, "===== ========== ============================== ===================================\n");
1192
1193         for (i = 0; i < AST_VECTOR_SIZE(vec); i++) {
1194                 struct pjsip_history_entry *entry;
1195                 char line[256];
1196
1197                 entry = AST_VECTOR_GET(vec, i);
1198                 sprint_list_entry(entry, line, sizeof(line));
1199
1200                 ast_cli(a->fd, "%s\n", line);
1201         }
1202 }
1203
1204 /*! \brief Cleanup routine for a history vector, serviced on a registered PJSIP thread */
1205 static int safe_vector_cleanup(void *obj)
1206 {
1207         struct vector_history_t *vec = obj;
1208
1209         AST_VECTOR_RESET(vec, clear_history_entry_cb);
1210         AST_VECTOR_FREE(vec);
1211         ast_free(vec);
1212
1213         return 0;
1214 }
1215
1216 static char *pjsip_show_history(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
1217 {
1218         struct vector_history_t *vec = &vector_history;
1219         struct pjsip_history_entry *entry = NULL;
1220
1221         if (cmd == CLI_INIT) {
1222                 e->command = "pjsip show history";
1223                 e->usage =
1224                         "Usage: pjsip show history [entry <num>|where [...]]\n"
1225                         "       Displays the currently collected history or an\n"
1226                         "       entry within the history.\n\n"
1227                         "       * Running the command with no options will display\n"
1228                         "         the entire history.\n"
1229                         "       * Providing 'entry <num>' will display the full\n"
1230                         "         detail of a particular entry in this history.\n"
1231                         "       * Providing 'where ...' will allow for filtering\n"
1232                         "         the history. The history can be filtered using\n"
1233                         "         any of the following fields:\n"
1234                         "         - number: The history entry number\n"
1235                         "         - timestamp: The time associated with the history entry\n"
1236                         "         - addr: The source/destination address of the SIP message\n"
1237                         "         - sip.msg.request.method: The request method type\n"
1238                         "         - sip.msg.call-id: The Call-ID header of the SIP message\n"
1239                         "\n"
1240                         "         When filtering, standard Boolean operators can be used,\n"
1241                         "         as well as 'like' for regexs.\n"
1242                         "\n"
1243                         "         Example:\n"
1244                         "         'pjsip show history where number > 5 and (addr = \"192.168.0.3:5060\" or addr = \"192.168.0.5:5060\")'\n";
1245                 return NULL;
1246         } else if (cmd == CLI_GENERATE) {
1247                 return NULL;
1248         }
1249
1250         if (a->argc > 3) {
1251                 if (!strcasecmp(a->argv[3], "entry") && a->argc == 5) {
1252                         int num;
1253
1254                         if (sscanf(a->argv[4], "%30d", &num) != 1) {
1255                                 ast_cli(a->fd, "'%s' is not a valid entry number\n", a->argv[4]);
1256                                 return CLI_FAILURE;
1257                         }
1258
1259                         /* Get the entry at the provided position */
1260                         ast_mutex_lock(&history_lock);
1261                         if (num >= AST_VECTOR_SIZE(&vector_history) || num < 0) {
1262                                 ast_cli(a->fd, "Entry '%d' does not exist\n", num);
1263                                 ast_mutex_unlock(&history_lock);
1264                                 return CLI_FAILURE;
1265                         }
1266                         entry = ao2_bump(AST_VECTOR_GET(&vector_history, num));
1267                         ast_mutex_unlock(&history_lock);
1268                 } else if (!strcasecmp(a->argv[3], "where")) {
1269                         vec = filter_history(a);
1270                         if (!vec) {
1271                                 return CLI_FAILURE;
1272                         }
1273                 } else {
1274                         return CLI_SHOWUSAGE;
1275                 }
1276         }
1277
1278         if (AST_VECTOR_SIZE(vec) == 1) {
1279                 if (vec == &vector_history) {
1280                         ast_mutex_lock(&history_lock);
1281                 }
1282                 entry = ao2_bump(AST_VECTOR_GET(vec, 0));
1283                 if (vec == &vector_history) {
1284                         ast_mutex_unlock(&history_lock);
1285                 }
1286         }
1287
1288         if (entry) {
1289                 display_single_entry(a, entry);
1290         } else {
1291                 if (vec == &vector_history) {
1292                         ast_mutex_lock(&history_lock);
1293                 }
1294
1295                 display_entry_list(a, vec);
1296
1297                 if (vec == &vector_history) {
1298                         ast_mutex_unlock(&history_lock);
1299                 }
1300         }
1301
1302         if (vec != &vector_history) {
1303                 ast_sip_push_task(NULL, safe_vector_cleanup, vec);
1304         }
1305         ao2_cleanup(entry);
1306
1307         return CLI_SUCCESS;
1308 }
1309
1310 static char *pjsip_set_history(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
1311 {
1312         const char *what;
1313
1314         if (cmd == CLI_INIT) {
1315                 e->command = "pjsip set history {on|off|clear}";
1316                 e->usage =
1317                         "Usage: pjsip set history {on|off|clear}\n"
1318                         "       Enables/disables/clears the PJSIP history.\n\n"
1319                         "       Enabling the history will start recording transmitted/received\n"
1320                         "       packets. Disabling the history will stop recording, but keep\n"
1321                         "       the already received packets. Clearing the history will wipe\n"
1322                         "       the received packets from memory.\n\n"
1323                         "       As the PJSIP history is maintained in memory, and includes\n"
1324                         "       all received/transmitted requests and responses, it should\n"
1325                         "       only be enabled for debugging purposes, and cleared when done.\n";
1326                 return NULL;
1327         } else if (cmd == CLI_GENERATE) {
1328                 return NULL;
1329         }
1330
1331         what = a->argv[e->args - 1];    /* Guaranteed to exist */
1332
1333         if (a->argc == e->args) {
1334                 if (!strcasecmp(what, "on")) {
1335                         enabled = 1;
1336                         ast_cli(a->fd, "PJSIP History enabled\n");
1337                         return CLI_SUCCESS;
1338                 } else if (!strcasecmp(what, "off")) {
1339                         enabled = 0;
1340                         ast_cli(a->fd, "PJSIP History disabled\n");
1341                         return CLI_SUCCESS;
1342                 } else if (!strcasecmp(what, "clear")) {
1343                         ast_sip_push_task(NULL, clear_history_entries, NULL);
1344                         ast_cli(a->fd, "PJSIP History cleared\n");
1345                         return CLI_SUCCESS;
1346                 }
1347         }
1348
1349         return CLI_SHOWUSAGE;
1350 }
1351
1352 static pjsip_module logging_module = {
1353         .name = { "History Module", 14 },
1354         .priority = 0,
1355         .on_rx_request = history_on_rx_msg,
1356         .on_rx_response = history_on_rx_msg,
1357         .on_tx_request = history_on_tx_msg,
1358         .on_tx_response = history_on_tx_msg,
1359 };
1360
1361 static struct ast_cli_entry cli_pjsip[] = {
1362         AST_CLI_DEFINE(pjsip_set_history, "Enable/Disable PJSIP History"),
1363         AST_CLI_DEFINE(pjsip_show_history, "Display PJSIP History"),
1364 };
1365
1366 static int load_module(void)
1367 {
1368         log_level = ast_logger_register_level("PJSIP_HISTORY");
1369         if (log_level < 0) {
1370                 ast_log(LOG_WARNING, "Unable to register history log level\n");
1371         }
1372
1373         ast_pjproject_caching_pool_init(&cachingpool, &pj_pool_factory_default_policy, 0);
1374
1375         AST_VECTOR_INIT(&vector_history, HISTORY_INITIAL_SIZE);
1376
1377         ast_sip_register_service(&logging_module);
1378         ast_cli_register_multiple(cli_pjsip, ARRAY_LEN(cli_pjsip));
1379
1380         return AST_MODULE_LOAD_SUCCESS;
1381 }
1382
1383 static int unload_module(void)
1384 {
1385         ast_cli_unregister_multiple(cli_pjsip, ARRAY_LEN(cli_pjsip));
1386         ast_sip_unregister_service(&logging_module);
1387
1388         ast_sip_push_task_synchronous(NULL, clear_history_entries, NULL);
1389         AST_VECTOR_FREE(&vector_history);
1390
1391         ast_pjproject_caching_pool_destroy(&cachingpool);
1392
1393         if (log_level != -1) {
1394                 ast_logger_unregister_level("PJSIP_HISTORY");
1395         }
1396
1397         return 0;
1398 }
1399
1400 AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_LOAD_ORDER, "PJSIP History",
1401                 .support_level = AST_MODULE_SUPPORT_EXTENDED,
1402                 .load = load_module,
1403                 .unload = unload_module,
1404                 .load_pri = AST_MODPRI_APP_DEPEND,
1405                 .requires = "res_pjsip",
1406         );