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