Asterisk - The Open Source Telephony Project GIT-master-a358458
location.c
Go to the documentation of this file.
1/*
2 * Asterisk -- An open source telephony toolkit.
3 *
4 * Copyright (C) 2013, Digium, Inc.
5 *
6 * Joshua Colp <jcolp@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#include "asterisk.h"
20#include <pjsip.h>
21#include <pjlib.h>
22
23#include "asterisk/res_pjsip.h"
24#include "asterisk/logger.h"
25#include "asterisk/astobj2.h"
26#include "asterisk/paths.h"
27#include "asterisk/sorcery.h"
31#include "asterisk/statsd.h"
33
35
36static int pj_max_hostname = PJ_MAX_HOSTNAME;
37static int pjsip_max_url_size = PJSIP_MAX_URL_SIZE;
38
39/*! \brief Destructor for AOR */
40static void aor_destroy(void *obj)
41{
42 struct ast_sip_aor *aor = obj;
43
47}
48
49/*! \brief Allocator for AOR */
50static void *aor_alloc(const char *name)
51{
52 void *lock;
53 struct ast_sip_aor *aor;
54
56 if (!lock) {
57 return NULL;
58 }
59
61 ao2_ref(lock, -1);
62
63 if (!aor) {
64 return NULL;
65 }
66 ast_string_field_init(aor, 128);
67
68 return aor;
69}
70
71/*! \brief Internal callback function which destroys the specified contact */
72static int destroy_contact(void *obj, void *arg, int flags)
73{
74 struct ast_sip_contact *contact = obj;
75
77
78 return CMP_MATCH;
79}
80
81static void aor_deleted_observer(const void *object)
82{
83 const struct ast_sip_aor *aor = object;
84 const char *aor_id = ast_sorcery_object_get_id(object);
85 /* Give enough space for ;@ at the end, since that is our object naming scheme */
86 size_t prefix_len = strlen(aor_id) + sizeof(";@") - 1;
87 char prefix[prefix_len + 1];
88 struct ao2_container *contacts;
89
90 if (aor->permanent_contacts) {
92 }
93
94 sprintf(prefix, "%s;@", aor_id); /* Safe */
95 if (!(contacts = ast_sorcery_retrieve_by_prefix(ast_sip_get_sorcery(), "contact", prefix, prefix_len))) {
96 return;
97 }
98 /* Destroy any contacts that may still exist that were made for this AoR */
100
101 ao2_ref(contacts, -1);
102}
103
104/*! \brief Observer for contacts so state can be updated on respective endpoints */
105static const struct ast_sorcery_observer aor_observer = {
107};
108
109
110/*! \brief Destructor for contact */
111static void contact_destroy(void *obj)
112{
113 struct ast_sip_contact *contact = obj;
114
116 ao2_cleanup(contact->endpoint);
117}
118
119/*! \brief Allocator for contact */
120static void *contact_alloc(const char *name)
121{
122 struct ast_sip_contact *contact = ast_sorcery_generic_alloc(sizeof(*contact), contact_destroy);
123 char *id = ast_strdupa(name);
124 char *aor = id;
125 char *aor_separator = NULL;
126
127 if (!contact) {
128 return NULL;
129 }
130
131 if (ast_string_field_init(contact, 256)) {
132 ao2_cleanup(contact);
133 return NULL;
134 }
135
136 /* Dynamic contacts are delimited with ";@" and static ones with "@@" */
137 if ((aor_separator = strstr(id, ";@")) || (aor_separator = strstr(id, "@@"))) {
138 *aor_separator = '\0';
139 }
140 ast_assert(aor_separator != NULL);
141
142 ast_string_field_set(contact, aor, aor);
143
144 return contact;
145}
146
147struct ast_sip_aor *ast_sip_location_retrieve_aor(const char *aor_name)
148{
149 return ast_sorcery_retrieve_by_id(ast_sip_get_sorcery(), "aor", aor_name);
150}
151
152/*! \brief Internal callback function which deletes and unlinks any expired contacts */
153static int contact_expire(void *obj, void *arg, int flags)
154{
155 struct ast_sip_contact *contact = obj;
156
157 /* If the contact has not yet expired it is valid */
158 if (ast_tvdiff_ms(contact->expiration_time, ast_tvnow()) > 0) {
159 return 0;
160 }
161
163
164 return CMP_MATCH;
165}
166
167/*! \brief Internal callback function which links static contacts into another container */
168static int contact_link_static(void *obj, void *arg, int flags)
169{
170 struct ao2_container *dest = arg;
171
172 ao2_link(dest, obj);
173 return 0;
174}
175
176/*! \brief Internal callback function which removes any contact which is unreachable */
177static int contact_remove_unreachable(void *obj, void *arg, int flags)
178{
179 struct ast_sip_contact *contact = obj;
181 int unreachable;
182
184 if (!status) {
185 return 0;
186 }
187
188 unreachable = (status->status == UNAVAILABLE);
189 ao2_ref(status, -1);
190
191 return unreachable ? CMP_MATCH : 0;
192}
193
195{
197}
198
200 unsigned int flags)
201{
202 struct ao2_container *contacts;
203 struct ast_sip_contact *contact = NULL;
204
206 if (contacts && ao2_container_count(contacts)) {
207 /* Get the first AOR contact in the container. */
208 contact = ao2_callback(contacts, 0, NULL, NULL);
209 }
210 ao2_cleanup(contacts);
211 return contact;
212}
213
215{
217}
218
220 unsigned int flags)
221{
222 /* Give enough space for ;@ at the end, since that is our object naming scheme */
223 size_t prefix_len = strlen(ast_sorcery_object_get_id(aor)) + sizeof(";@") - 1;
224 char prefix[prefix_len + 1];
225 struct ao2_container *contacts;
226
227 sprintf(prefix, "%s;@", ast_sorcery_object_get_id(aor)); /* Safe */
228 if (!(contacts = ast_sorcery_retrieve_by_prefix(ast_sip_get_sorcery(), "contact", prefix, prefix_len))) {
229 return NULL;
230 }
231
232 /* Prune any expired contacts and delete them, we do this first because static contacts can never expire */
234
235 /* Add any permanent contacts from the AOR */
236 if (aor->permanent_contacts) {
238 }
239
242 }
243
244 return contacts;
245}
246
248{
250}
251
253 unsigned int flags)
254{
255 struct ao2_container *contacts;
256
257 /* ao2_lock / ao2_unlock do not actually write aor since it has an ao2 lockobj. */
258 ao2_lock((void*)aor);
260 ao2_unlock((void*)aor);
261
262 return contacts;
263}
264
265
267 struct ast_sip_contact **contact)
268{
270}
271
272void ast_sip_location_retrieve_contact_and_aor_from_list_filtered(const char *aor_list, unsigned int flags,
273 struct ast_sip_aor **aor, struct ast_sip_contact **contact)
274{
275 char *aor_name;
276 char *rest;
277
278 /* If the location is still empty we have nowhere to go */
279 if (ast_strlen_zero(aor_list) || !(rest = ast_strdupa(aor_list))) {
280 ast_log(LOG_WARNING, "Unable to determine contacts from empty aor list\n");
281 return;
282 }
283
284 *aor = NULL;
285 *contact = NULL;
286
287 while ((aor_name = ast_strip(strsep(&rest, ",")))) {
288 *aor = ast_sip_location_retrieve_aor(aor_name);
289
290 if (!(*aor)) {
291 continue;
292 }
294 /* If a valid contact is available use its URI for dialing */
295 if (*contact) {
296 break;
297 }
298
299 ao2_ref(*aor, -1);
300 *aor = NULL;
301 }
302}
303
305{
306 struct ast_sip_aor *aor;
307 struct ast_sip_contact *contact;
308
310
312
313 return contact;
314}
315
316static int permanent_uri_sort_fn(const void *obj_left, const void *obj_right, int flags);
317static int cli_contact_populate_container(void *obj, void *arg, int flags);
318
319static int gather_contacts_for_aor(void *obj, void *arg, int flags)
320{
321 struct ao2_container *aor_contacts;
322 struct ast_sip_aor *aor = obj;
323 struct ao2_container *container = arg;
324
325 aor_contacts = ast_sip_location_retrieve_aor_contacts(aor);
326 if (!aor_contacts) {
327 return 0;
328 }
330 container);
331 ao2_ref(aor_contacts, -1);
332 return CMP_MATCH;
333}
334
336{
337 struct ao2_container *contacts;
338
341 if (!contacts) {
342 return NULL;
343 }
344
346
347 return contacts;
348}
349
350struct ast_sip_contact *ast_sip_location_retrieve_contact(const char *contact_name)
351{
352 return ast_sorcery_retrieve_by_id(ast_sip_get_sorcery(), "contact", contact_name);
353}
354
356 const char *uri, struct timeval expiration_time, const char *path_info,
357 const char *user_agent, const char *via_addr, int via_port, const char *call_id,
359{
360 struct ast_sip_contact *contact;
361 char name[MAX_OBJECT_FIELD * 2 + 3];
362 char hash[33];
363
364 ast_md5_hash(hash, uri);
365 snprintf(name, sizeof(name), "%s;@%s", ast_sorcery_object_get_id(aor), hash);
366
367 contact = ast_sorcery_alloc(ast_sip_get_sorcery(), "contact", name);
368 if (!contact) {
369 return NULL;
370 }
371
372 ast_string_field_set(contact, uri, uri);
374 contact->qualify_frequency = aor->qualify_frequency;
375 contact->qualify_timeout = aor->qualify_timeout;
376 contact->authenticate_qualify = aor->authenticate_qualify;
377 if (path_info && aor->support_path) {
378 ast_string_field_set(contact, path, path_info);
379 }
380
381 if (!ast_strlen_zero(aor->outbound_proxy)) {
382 ast_string_field_set(contact, outbound_proxy, aor->outbound_proxy);
383 }
384
387 }
388
391 }
392
395 }
396 contact->via_port = via_port;
397
398 if (!ast_strlen_zero(call_id)) {
400 }
401
402 contact->endpoint = ao2_bump(endpoint);
403 if (endpoint) {
405 }
406
407 contact->prune_on_boot = prune_on_boot;
408
409 if (ast_sorcery_create(ast_sip_get_sorcery(), contact)) {
410 ao2_ref(contact, -1);
411 return NULL;
412 }
413 return contact;
414}
415
417 struct timeval expiration_time, const char *path_info, const char *user_agent,
418 const char *via_addr, int via_port, const char *call_id,
420{
421 struct ast_sip_contact *contact;
422
425 ao2_cleanup(contact);
426 return contact ? 0 : -1;
427}
428
430 struct timeval expiration_time, const char *path_info, const char *user_agent,
431 const char *via_addr, int via_port, const char *call_id,
433{
434 int res;
435
436 ao2_lock(aor);
439 endpoint);
441
442 return res;
443}
444
446{
447 return ast_sorcery_update(ast_sip_get_sorcery(), contact);
448}
449
451{
452 return ast_sorcery_delete(ast_sip_get_sorcery(), contact);
453}
454
455static int prune_boot_contacts_cb(void *obj, void *arg, int flags)
456{
457 struct ast_sip_contact *contact = obj;
458
459 if (contact->prune_on_boot
460 && !strcmp(contact->reg_server, ast_config_AST_SYSTEM_NAME ?: "")) {
461 ast_verb(3, "Removed contact '%s' from AOR '%s' due to system boot\n",
462 contact->uri, contact->aor);
464 }
465
466 return 0;
467}
468
470{
471 struct ao2_container *contacts;
472
475 if (contacts) {
477 ao2_ref(contacts, -1);
478 }
479}
480
481/*! \brief Custom handler for translating from a string timeval to actual structure */
482static int expiration_str2struct(const struct aco_option *opt, struct ast_variable *var, void *obj)
483{
484 struct ast_sip_contact *contact = obj;
485 return ast_get_timeval(var->value, &contact->expiration_time, ast_tv(0, 0), NULL);
486}
487
488/*! \brief Custom handler for translating from an actual structure timeval to string */
489static int expiration_struct2str(const void *obj, const intptr_t *args, char **buf)
490{
491 const struct ast_sip_contact *contact = obj;
492 char secs[AST_TIME_T_LEN];
493
494 ast_time_t_to_string(contact->expiration_time.tv_sec, secs, sizeof(secs));
495 return (ast_asprintf(buf, "%s", secs) < 0) ? -1 : 0;
496}
497
498static int permanent_uri_sort_fn(const void *obj_left, const void *obj_right, int flags)
499{
500 const struct ast_sip_contact *object_left = obj_left;
501 const struct ast_sip_contact *object_right = obj_right;
502 const char *right_key = obj_right;
503 int cmp;
504
505 switch (flags & OBJ_SEARCH_MASK) {
507 right_key = ast_sorcery_object_get_id(object_right);
508 /* Fall through */
509 case OBJ_SEARCH_KEY:
510 cmp = strcmp(ast_sorcery_object_get_id(object_left), right_key);
511 break;
513 /*
514 * We could also use a partial key struct containing a length
515 * so strlen() does not get called for every comparison instead.
516 */
517 cmp = strncmp(ast_sorcery_object_get_id(object_left), right_key, strlen(right_key));
518 break;
519 default:
520 /* Sort can only work on something with a full or partial key. */
521 ast_assert(0);
522 cmp = 0;
523 break;
524 }
525 return cmp;
526}
527
528int ast_sip_validate_uri_length(const char *contact_uri)
529{
530 int max_length = pj_max_hostname - 1;
531 char *contact = ast_strdupa(contact_uri);
532 char *host;
533 char *at;
534 int theres_a_port = 0;
535
536 if (strlen(contact_uri) > pjsip_max_url_size - 1) {
537 return -1;
538 }
539
540 contact = ast_strip_quoted(contact, "<", ">");
541
542 if (!strncasecmp(contact, "sip:", 4)) {
543 host = contact + 4;
544 } else if (!strncasecmp(contact, "sips:", 5)) {
545 host = contact + 5;
546 } else {
547 /* Not a SIP URI */
548 return -1;
549 }
550
551 at = strchr(contact, '@');
552 if (at) {
553 /* sip[s]:user@host */
554 host = at + 1;
555 }
556
557 if (host[0] == '[') {
558 /* Host is an IPv6 address. Just get up to the matching bracket */
559 char *close_bracket;
560
561 close_bracket = strchr(host, ']');
562 if (!close_bracket) {
563 return -1;
564 }
565 close_bracket++;
566 if (*close_bracket == ':') {
567 theres_a_port = 1;
568 }
569 *close_bracket = '\0';
570 } else {
571 /* uri parameters could contain ';' so trim them off first */
572 host = strsep(&host, ";?");
573 /* Host is FQDN or IPv4 address. Need to find closing delimiter */
574 if (strchr(host, ':')) {
575 theres_a_port = 1;
576 host = strsep(&host, ":");
577 }
578 }
579
580 if (!theres_a_port) {
581 max_length -= strlen("_sips.tcp.");
582 }
583
584 if (strlen(host) > max_length) {
585 return -1;
586 }
587
588 return 0;
589}
590
591/*! \brief Custom handler for permanent URIs */
592static int permanent_uri_handler(const struct aco_option *opt, struct ast_variable *var, void *obj)
593{
594 struct ast_sip_aor *aor = obj;
595 const char *aor_id = ast_sorcery_object_get_id(aor);
596 char *contacts;
597 char *contact_uri;
598
599 if (ast_strlen_zero(var->value)) {
600 return 0;
601 }
602
603 contacts = ast_strdupa(var->value);
604 while ((contact_uri = ast_strip(strsep(&contacts, ",")))) {
605 struct ast_sip_contact *contact;
607 char hash[33];
608 char contact_id[strlen(aor_id) + sizeof(hash) + 2];
609
610 if (ast_strlen_zero(contact_uri)) {
611 continue;
612 }
613
614 if (ast_sip_validate_uri_length(contact_uri)) {
615 ast_log(LOG_ERROR, "Contact uri or hostname length exceeds pjproject limit or is not a sip(s) uri: %s\n", contact_uri);
616 return -1;
617 }
618
619 if (!aor->permanent_contacts) {
622 if (!aor->permanent_contacts) {
623 return -1;
624 }
625 }
626
627 ast_md5_hash(hash, contact_uri);
628 snprintf(contact_id, sizeof(contact_id), "%s@@%s", aor_id, hash);
629 contact = ast_sorcery_alloc(ast_sip_get_sorcery(), "contact", contact_id);
630 if (!contact) {
631 return -1;
632 }
633
634 ast_string_field_set(contact, uri, contact_uri);
635
637 if (!status) {
638 ao2_ref(contact, -1);
639 return -1;
640 }
641 ao2_ref(status, -1);
642
643 ao2_link(aor->permanent_contacts, contact);
644 ao2_ref(contact, -1);
645 }
646
647 return 0;
648}
649
650static int contact_to_var_list(void *object, void *arg, int flags)
651{
652 struct ast_sip_contact_wrapper *wrapper = object;
653 struct ast_variable **var = arg;
654
655 ast_variable_list_append(&*var, ast_variable_new("contact", wrapper->contact->uri, ""));
656
657 return 0;
658}
659
660static int contacts_to_var_list(const void *obj, struct ast_variable **fields)
661{
662 const struct ast_sip_aor *aor = obj;
663
665
666 return 0;
667}
668
669static int voicemail_extension_handler(const struct aco_option *opt, struct ast_variable *var, void *obj)
670{
671 struct ast_sip_aor *aor = obj;
672
673 aor->voicemail_extension = ast_strdup(var->value);
674
675 return aor->voicemail_extension ? 0 : -1;
676}
677
678static int voicemail_extension_to_str(const void *obj, const intptr_t *args, char **buf)
679{
680 const struct ast_sip_aor *aor = obj;
681
683
684 return 0;
685}
686
687int ast_sip_for_each_aor(const char *aors, ao2_callback_fn on_aor, void *arg)
688{
689 char *copy;
690 char *name;
691 int res;
692
693 if (!on_aor || ast_strlen_zero(aors)) {
694 return 0;
695 }
696
697 copy = ast_strdupa(aors);
698 while ((name = ast_strip(strsep(&copy, ",")))) {
699 struct ast_sip_aor *aor;
700
702 if (aor) {
703 res = on_aor(aor, arg, 0);
704 ao2_ref(aor, -1);
705 if (res) {
706 return -1;
707 }
708 }
709 }
710 return 0;
711}
712
713static void contact_wrapper_destroy(void *obj)
714{
715 struct ast_sip_contact_wrapper *wrapper = obj;
716
717 ast_free(wrapper->aor_id);
718 ast_free(wrapper->contact_id);
719 ao2_cleanup(wrapper->contact);
720}
721
723 ao2_callback_fn on_contact, void *arg)
724{
725 struct ao2_container *contacts;
726 struct ao2_iterator i;
727 int res = 0;
728 void *object = NULL;
729
730 if (!on_contact ||
731 !(contacts = ast_sip_location_retrieve_aor_contacts(aor))) {
732 return 0;
733 }
734
735 i = ao2_iterator_init(contacts, 0);
736 while ((object = ao2_iterator_next(&i))) {
737 RAII_VAR(struct ast_sip_contact *, contact, object, ao2_cleanup);
739 const char *aor_id = ast_sorcery_object_get_id(aor);
740
741 wrapper = ao2_alloc_options(sizeof(struct ast_sip_contact_wrapper),
743 if (!wrapper) {
744 res = -1;
745 break;
746 }
747 wrapper->contact_id = ast_malloc(strlen(aor_id) + strlen(contact->uri) + 2);
748 if (!wrapper->contact_id) {
749 res = -1;
750 break;
751 }
752 sprintf(wrapper->contact_id, "%s/%s", aor_id, contact->uri);
753 wrapper->aor_id = ast_strdup(aor_id);
754 if (!wrapper->aor_id) {
755 res = -1;
756 break;
757 }
758 wrapper->contact = contact;
759 ao2_bump(wrapper->contact);
760
761 if ((res = on_contact(wrapper, arg, 0))) {
762 break;
763 }
764 }
766 ao2_ref(contacts, -1);
767 return res;
768}
769
770int ast_sip_contact_to_str(void *object, void *arg, int flags)
771{
772 struct ast_sip_contact_wrapper *wrapper = object;
773 struct ast_str **buf = arg;
774
775 ast_str_append(buf, 0, "%s,", wrapper->contact_id);
776
777 return 0;
778}
779
780static int sip_aor_to_ami(const struct ast_sip_aor *aor, struct ast_str **buf)
781{
782 struct ast_variable *objset;
783 struct ast_variable *i;
784
787 if (!objset) {
788 return -1;
789 }
790
791 ast_str_append(buf, 0, "ObjectType: %s\r\n",
793 ast_str_append(buf, 0, "ObjectName: %s\r\n",
795
796 for (i = objset; i; i = i->next) {
797 char *camel = ast_to_camel_case(i->name);
798
799 if (strcmp(camel, "Contact") == 0) {
800 ast_free(camel);
801 camel = NULL;
802 }
803 ast_str_append(buf, 0, "%s: %s\r\n", S_OR(camel, "Contacts"), i->value);
804 ast_free(camel);
805 }
806
807 ast_variables_destroy(objset);
808 return 0;
809}
810
811static int contacts_to_str(const void *obj, const intptr_t *args, char **buf)
812{
813 const struct ast_sip_aor *aor = obj;
814 struct ast_str *str;
815
817 if (!str) {
818 *buf = NULL;
819 return -1;
820 }
821
824
826 ast_free(str);
827
828 return *buf ? 0 : -1;
829}
830
831static int format_ami_aor_handler(void *obj, void *arg, int flags)
832{
833 struct ast_sip_aor *aor = obj;
834 struct ast_sip_ami *ami = arg;
835 const struct ast_sip_endpoint *endpoint = ami->arg;
836 struct ast_str *buf;
837 struct ao2_container *contacts;
838 int total_contacts;
839 int num_permanent;
840
841 buf = ast_sip_create_ami_event("AorDetail", ami);
842 if (!buf) {
843 return -1;
844 }
846 if (!contacts) {
847 ast_free(buf);
848 return -1;
849 }
850
851 sip_aor_to_ami(aor, &buf);
852 total_contacts = ao2_container_count(contacts);
853 num_permanent = aor->permanent_contacts ?
855
856 ast_str_append(&buf, 0, "TotalContacts: %d\r\n", total_contacts);
857 ast_str_append(&buf, 0, "ContactsRegistered: %d\r\n",
858 total_contacts - num_permanent);
859 ast_str_append(&buf, 0, "EndpointName: %s\r\n",
860 ast_sorcery_object_get_id(endpoint));
861
862 astman_append(ami->s, "%s\r\n", ast_str_buffer(buf));
863 ami->count++;
864
865 ast_free(buf);
866 ao2_ref(contacts, -1);
867 return 0;
868}
869
870static int format_ami_endpoint_aor(const struct ast_sip_endpoint *endpoint,
871 struct ast_sip_ami *ami)
872{
873 ami->arg = (void *)endpoint;
874 return ast_sip_for_each_aor(endpoint->aors,
876}
877
880};
881
882static struct ao2_container *cli_aor_get_container(const char *regex)
883{
884 struct ao2_container *container;
885 struct ao2_container *s_container;
886
888 if (!container) {
889 return NULL;
890 }
891
892 /* Create a sorted container of aors. */
895 if (s_container
896 && ao2_container_dup(s_container, container, 0)) {
897 ao2_ref(s_container, -1);
898 s_container = NULL;
899 }
900 ao2_ref(container, -1);
901
902 return s_container;
903}
904
905static int cli_contact_populate_container(void *obj, void *arg, int flags)
906{
907 ao2_link(arg, obj);
908
909 return 0;
910}
911
912static int cli_aor_gather_contacts(void *obj, void *arg, int flags)
913{
914 struct ast_sip_aor *aor = obj;
915
917}
918
919static const char *cli_contact_get_id(const void *obj)
920{
921 const struct ast_sip_contact_wrapper *wrapper = obj;
922 return wrapper->contact_id;
923}
924
925static int cli_contact_sort(const void *obj, const void *arg, int flags)
926{
927 const struct ast_sip_contact_wrapper *left_wrapper = obj;
928 const struct ast_sip_contact_wrapper *right_wrapper = arg;
929 const char *right_key = arg;
930 int cmp = 0;
931
932 switch (flags & OBJ_SEARCH_MASK) {
934 right_key = right_wrapper->contact_id;
935 /* Fall through */
936 case OBJ_SEARCH_KEY:
937 cmp = strcmp(left_wrapper->contact_id, right_key);
938 break;
940 cmp = strncmp(left_wrapper->contact_id, right_key, strlen(right_key));
941 break;
942 default:
943 cmp = 0;
944 break;
945 }
946
947 return cmp;
948}
949
950static int cli_contact_compare(void *obj, void *arg, int flags)
951{
952 const struct ast_sip_contact_wrapper *left_wrapper = obj;
953 const struct ast_sip_contact_wrapper *right_wrapper = arg;
954 const char *right_key = arg;
955 int cmp = 0;
956
957 switch (flags & OBJ_SEARCH_MASK) {
959 right_key = right_wrapper->contact_id;
960 /* Fall through */
961 case OBJ_SEARCH_KEY:
962 if (strcmp(left_wrapper->contact_id, right_key) == 0) {;
963 cmp = CMP_MATCH | CMP_STOP;
964 }
965 break;
967 if (strncmp(left_wrapper->contact_id, right_key, strlen(right_key)) == 0) {
968 cmp = CMP_MATCH;
969 }
970 break;
971 default:
972 cmp = 0;
973 break;
974 }
975
976 return cmp;
977}
978
979static int cli_contact_iterate(void *container, ao2_callback_fn callback, void *args)
980{
981 return ast_sip_for_each_contact(container, callback, args);
982}
983
984static int cli_filter_contacts(void *obj, void *arg, int flags)
985{
986 struct ast_sip_contact_wrapper *wrapper = obj;
987 regex_t *regexbuf = arg;
988
989 if (!regexec(regexbuf, wrapper->contact_id, 0, NULL, 0)) {
990 return 0;
991 }
992
993 return CMP_MATCH;
994}
995
996static int cli_gather_contact(void *obj, void *arg, int flags)
997{
998 struct ast_sip_contact *contact = obj;
1000
1001 if (strcmp(contact->reg_server, ast_config_AST_SYSTEM_NAME ?: "")) {
1002 return 0;
1003 }
1004
1005 wrapper = ao2_alloc_options(sizeof(struct ast_sip_contact_wrapper),
1007 if (!wrapper) {
1008 return -1;
1009 }
1010
1011 wrapper->contact_id = ast_malloc(strlen(contact->aor) + strlen(contact->uri) + 2);
1012 if (!wrapper->contact_id) {
1013 return -1;
1014 }
1015 sprintf(wrapper->contact_id, "%s/%s", contact->aor, contact->uri);
1016
1017 wrapper->aor_id = ast_strdup(contact->aor);
1018 if (!wrapper->aor_id) {
1019 return -1;
1020 }
1021
1022 wrapper->contact = ao2_bump(contact);
1023
1024 ao2_link(arg, wrapper);
1025
1026 return 0;
1027}
1028
1030{
1031 RAII_VAR(struct ao2_container *, aors, NULL, ao2_cleanup);
1032 RAII_VAR(struct ao2_container *, contacts, NULL, ao2_cleanup);
1033 RAII_VAR(struct ast_variable *, var_aor, NULL, ast_variables_destroy);
1034 struct ao2_container *contacts_container;
1035 regex_t regexbuf;
1036
1037 if (!(var_aor = ast_variable_new("contact !=", "", ""))) {
1038 return NULL;
1039 }
1040
1041 /* Retrieving all the contacts may result in finding the same contact multiple
1042 * times. So that they don't get displayed multiple times we only allow a
1043 * single one to be placed into the container.
1044 */
1047 if (!contacts_container) {
1048 return NULL;
1049 }
1050
1052 if (!contacts) {
1053 ao2_ref(contacts_container, -1);
1054 return NULL;
1055 }
1056 ao2_callback(contacts, OBJ_NODATA, cli_gather_contact, contacts_container);
1057
1059 "aor", AST_RETRIEVE_FLAG_MULTIPLE, var_aor);
1060 if (!aors) {
1061 ao2_ref(contacts_container, -1);
1062 return NULL;
1063 }
1064
1065 ao2_callback(aors, OBJ_NODATA, cli_aor_gather_contacts, contacts_container);
1066
1067 if (!ast_strlen_zero(regex)) {
1068 if (regcomp(&regexbuf, regex, REG_EXTENDED | REG_NOSUB)) {
1069 ao2_ref(contacts_container, -1);
1070 return NULL;
1071 }
1072 ao2_callback(contacts_container, OBJ_UNLINK | OBJ_MULTIPLE | OBJ_NODATA, cli_filter_contacts, &regexbuf);
1073 regfree(&regexbuf);
1074 }
1075
1076 return contacts_container;
1077}
1078
1079static void *cli_contact_retrieve_by_id(const char *id)
1080{
1081 struct ao2_container *container;
1082 void *obj;
1083
1085 if (!container) {
1086 return NULL;
1087 }
1088
1089 obj = ao2_find(container, id, OBJ_SEARCH_KEY);
1090 ao2_ref(container, -1);
1091 return obj;
1092}
1093
1094static int cli_contact_print_header(void *obj, void *arg, int flags)
1095{
1096 struct ast_sip_cli_context *context = arg;
1097 int indent = CLI_INDENT_TO_SPACES(context->indent_level);
1098 int filler = CLI_LAST_TABSTOP - indent - 23;
1099
1100 ast_assert(context->output_buffer != NULL);
1101
1102 ast_str_append(&context->output_buffer, 0,
1103 "%*s: <Aor/ContactUri%*.*s> <Hash....> <Status> <RTT(ms)..>\n",
1104 indent, "Contact", filler, filler, CLI_HEADER_FILLER);
1105
1106 return 0;
1107}
1108
1109static int cli_contact_print_body(void *obj, void *arg, int flags)
1110{
1111 struct ast_sip_contact_wrapper *wrapper = obj;
1112 struct ast_sip_contact *contact = wrapper->contact;
1113 struct ast_sip_cli_context *context = arg;
1114 int indent;
1115 int flexwidth;
1116 const char *contact_id = ast_sorcery_object_get_id(contact);
1117 const char *hash_start = contact_id + strlen(contact->aor) + 2;
1119
1120 ast_assert(contact->uri != NULL);
1121 ast_assert(context->output_buffer != NULL);
1122
1124
1125 indent = CLI_INDENT_TO_SPACES(context->indent_level);
1126 flexwidth = CLI_LAST_TABSTOP - indent - 9 - strlen(contact->aor) + 1;
1127
1128 ast_str_append(&context->output_buffer, 0, "%*s: %s/%-*.*s %-10.10s %-7.7s %11.3f\n",
1129 indent,
1130 "Contact",
1131 contact->aor,
1132 flexwidth, flexwidth,
1133 contact->uri,
1134 hash_start,
1136 (status && (status->status == AVAILABLE)) ? ((long long) status->rtt) / 1000.0 : NAN);
1137
1139 return 0;
1140}
1141
1142static int cli_aor_iterate(void *container, ao2_callback_fn callback, void *args)
1143{
1144 const char *aor_list = container;
1145
1146 return ast_sip_for_each_aor(aor_list, callback, args);
1147}
1148
1149static void *cli_aor_retrieve_by_id(const char *id)
1150{
1152}
1153
1154static const char *cli_aor_get_id(const void *obj)
1155{
1156 return ast_sorcery_object_get_id(obj);
1157}
1158
1159static int cli_aor_print_header(void *obj, void *arg, int flags)
1160{
1161 struct ast_sip_cli_context *context = arg;
1162 int indent = CLI_INDENT_TO_SPACES(context->indent_level);
1163 int filler = CLI_LAST_TABSTOP - indent - 7;
1164
1165 ast_assert(context->output_buffer != NULL);
1166
1167 ast_str_append(&context->output_buffer, 0,
1168 "%*s: <Aor%*.*s> <MaxContact>\n",
1169 indent, "Aor", filler, filler, CLI_HEADER_FILLER);
1170
1171 if (context->recurse) {
1172 struct ast_sip_cli_formatter_entry *formatter_entry;
1173
1174 context->indent_level++;
1175 formatter_entry = ast_sip_lookup_cli_formatter("contact");
1176 if (formatter_entry) {
1177 formatter_entry->print_header(NULL, context, 0);
1178 ao2_ref(formatter_entry, -1);
1179 }
1180 context->indent_level--;
1181 }
1182
1183 return 0;
1184}
1185
1186static int cli_aor_print_body(void *obj, void *arg, int flags)
1187{
1188 struct ast_sip_aor *aor = obj;
1189 struct ast_sip_cli_context *context = arg;
1190 int indent;
1191 int flexwidth;
1192
1193 ast_assert(context->output_buffer != NULL);
1194
1195// context->current_aor = aor;
1196
1197 indent = CLI_INDENT_TO_SPACES(context->indent_level);
1198 flexwidth = CLI_LAST_TABSTOP - indent - 12;
1199
1200 ast_str_append(&context->output_buffer, 0, "%*s: %-*.*s %12u\n",
1201 indent,
1202 "Aor",
1203 flexwidth, flexwidth,
1205
1206 if (context->recurse) {
1207 struct ast_sip_cli_formatter_entry *formatter_entry;
1208
1209 context->indent_level++;
1210
1211 formatter_entry = ast_sip_lookup_cli_formatter("contact");
1212 if (formatter_entry) {
1213 formatter_entry->iterate(aor, formatter_entry->print_body, context);
1214 ao2_ref(formatter_entry, -1);
1215 }
1216
1217 context->indent_level--;
1218
1219 if (context->indent_level == 0) {
1220 ast_str_append(&context->output_buffer, 0, "\n");
1221 }
1222 }
1223
1224 if (context->show_details || (context->show_details_only_level_0 && context->indent_level == 0)) {
1225 ast_str_append(&context->output_buffer, 0, "\n");
1227 }
1228
1229 return 0;
1230}
1231
1232static struct ao2_container *cli_get_aors(void)
1233{
1234 struct ao2_container *aors;
1235
1238
1239 return aors;
1240}
1241
1242static int format_ami_aorlist_handler(void *obj, void *arg, int flags)
1243{
1244 struct ast_sip_aor *aor = obj;
1245 struct ast_sip_ami *ami = arg;
1246 struct ast_str *buf;
1247
1248 buf = ast_sip_create_ami_event("AorList", ami);
1249 if (!buf) {
1250 return -1;
1251 }
1252
1253 sip_aor_to_ami(aor, &buf);
1254
1255 astman_append(ami->s, "%s\r\n", ast_str_buffer(buf));
1256 ami->count++;
1257
1258 ast_free(buf);
1259
1260 return 0;
1261}
1262
1263static int ami_show_aors(struct mansession *s, const struct message *m)
1264{
1265 struct ast_sip_ami ami = { .s = s, .m = m, .action_id = astman_get_header(m, "ActionID"), };
1266 struct ao2_container *aors;
1267
1268 aors = cli_get_aors();
1269 if (!aors) {
1270 astman_send_error(s, m, "Could not get AORs\n");
1271 return 0;
1272 }
1273
1274 if (!ao2_container_count(aors)) {
1275 astman_send_error(s, m, "No AORs found\n");
1276 ao2_ref(aors, -1);
1277 return 0;
1278 }
1279
1280 astman_send_listack(s, m, "A listing of AORs follows, presented as AorList events",
1281 "start");
1282
1284
1285 astman_send_list_complete_start(s, m, "AorListComplete", ami.count);
1287
1288 ao2_ref(aors, -1);
1289
1290 return 0;
1291}
1292
1293static struct ast_cli_entry cli_commands[] = {
1295 .command = "pjsip list aors",
1296 .usage = "Usage: pjsip list aors [ like <pattern> ]\n"
1297 " List the configured PJSIP Aors\n"
1298 " Optional regular expression pattern is used to filter the list.\n"),
1300 .command = "pjsip show aors",
1301 .usage = "Usage: pjsip show aors [ like <pattern> ]\n"
1302 " Show the configured PJSIP Aors\n"
1303 " Optional regular expression pattern is used to filter the list.\n"),
1305 .command = "pjsip show aor",
1306 .usage = "Usage: pjsip show aor <id>\n"
1307 " Show the configured PJSIP Aor\n"),
1308
1309 AST_CLI_DEFINE(ast_sip_cli_traverse_objects, "List PJSIP Contacts",
1310 .command = "pjsip list contacts",
1311 .usage = "Usage: pjsip list contacts [ like <pattern> ]\n"
1312 " List the configured PJSIP contacts\n"
1313 " Optional regular expression pattern is used to filter the list.\n"),
1314 AST_CLI_DEFINE(ast_sip_cli_traverse_objects, "Show PJSIP Contacts",
1315 .command = "pjsip show contacts",
1316 .usage = "Usage: pjsip show contacts [ like <pattern> ]\n"
1317 " Show the configured PJSIP contacts\n"
1318 " Optional regular expression pattern is used to filter the list.\n"),
1319 AST_CLI_DEFINE(ast_sip_cli_traverse_objects, "Show PJSIP Contact",
1320 .command = "pjsip show contact",
1321 .usage = "Usage: pjsip show contact\n"
1322 " Show the configured PJSIP contact\n"),
1323};
1324
1327
1328/*! \brief Always create a contact_status for each contact */
1329static int contact_apply_handler(const struct ast_sorcery *sorcery, void *object)
1330{
1332 struct ast_sip_contact *contact = object;
1333
1334 if (ast_strlen_zero(contact->uri)) {
1335 ast_log(LOG_ERROR, "A URI on dynamic contact '%s' is empty\n",
1336 ast_sorcery_object_get_id(contact));
1337 return -1;
1338 }
1341
1342 return status ? 0 : -1;
1343}
1344
1345static int aor_apply_outbound_proxy(void *obj, void *arg, int flags)
1346{
1347 struct ast_sip_contact *contact = obj;
1348 struct ast_sip_aor *aor = arg;
1349
1351
1352 return 0;
1353}
1354
1355static int aor_apply_handler(const struct ast_sorcery *sorcery, void *object)
1356{
1357 struct ast_sip_aor *aor = object;
1358
1360 return 0;
1361 }
1362
1364
1365 return 0;
1366}
1367
1368/*! \brief Initialize sorcery with location support */
1370{
1372 int i;
1373
1374 ast_pjproject_get_buildopt("PJ_MAX_HOSTNAME", "%d", &pj_max_hostname);
1375 /* As of pjproject 2.4.5, PJSIP_MAX_URL_SIZE isn't exposed yet but we try anyway. */
1376 ast_pjproject_get_buildopt("PJSIP_MAX_URL_SIZE", "%d", &pjsip_max_url_size);
1377
1378 ast_sorcery_apply_default(sorcery, "contact", "astdb", "registrar");
1381 ast_sorcery_apply_default(sorcery, "aor", "config", "pjsip.conf,criteria=type=aor");
1382
1385 return -1;
1386 }
1387
1389
1390 ast_sorcery_object_field_register(sorcery, "contact", "type", "", OPT_NOOP_T, 0, 0);
1392 ast_sorcery_object_field_register(sorcery, "contact", "path", "", OPT_STRINGFIELD_T, 0, STRFLDSET(struct ast_sip_contact, path));
1394 ast_sorcery_object_field_register(sorcery, "contact", "qualify_frequency", 0, OPT_UINT_T,
1395 PARSE_IN_RANGE, FLDSET(struct ast_sip_contact, qualify_frequency), 0, 86400);
1396 ast_sorcery_object_field_register(sorcery, "contact", "qualify_timeout", "3.0", OPT_DOUBLE_T, 0, FLDSET(struct ast_sip_contact, qualify_timeout));
1397 ast_sorcery_object_field_register(sorcery, "contact", "authenticate_qualify", "no", OPT_YESNO_T, 1, FLDSET(struct ast_sip_contact, authenticate_qualify));
1398 ast_sorcery_object_field_register(sorcery, "contact", "outbound_proxy", "", OPT_STRINGFIELD_T, 0, STRFLDSET(struct ast_sip_contact, outbound_proxy));
1399 ast_sorcery_object_field_register(sorcery, "contact", "user_agent", "", OPT_STRINGFIELD_T, 0, STRFLDSET(struct ast_sip_contact, user_agent));
1400 ast_sorcery_object_field_register(sorcery, "contact", "endpoint", "", OPT_STRINGFIELD_T, 0, STRFLDSET(struct ast_sip_contact, endpoint_name));
1401 ast_sorcery_object_field_register(sorcery, "contact", "reg_server", "", OPT_STRINGFIELD_T, 0, STRFLDSET(struct ast_sip_contact, reg_server));
1402 ast_sorcery_object_field_register(sorcery, "contact", "via_addr", "", OPT_STRINGFIELD_T, 0, STRFLDSET(struct ast_sip_contact, via_addr));
1403 ast_sorcery_object_field_register(sorcery, "contact", "via_port", "0", OPT_UINT_T, 0, FLDSET(struct ast_sip_contact, via_port));
1404 ast_sorcery_object_field_register(sorcery, "contact", "call_id", "", OPT_STRINGFIELD_T, 0, STRFLDSET(struct ast_sip_contact, call_id));
1405 ast_sorcery_object_field_register(sorcery, "contact", "prune_on_boot", "no", OPT_YESNO_T, 1, FLDSET(struct ast_sip_contact, prune_on_boot));
1406
1407 ast_sorcery_object_field_register(sorcery, "aor", "type", "", OPT_NOOP_T, 0, 0);
1408 ast_sorcery_object_field_register(sorcery, "aor", "minimum_expiration", "60", OPT_UINT_T, 0, FLDSET(struct ast_sip_aor, minimum_expiration));
1409 ast_sorcery_object_field_register(sorcery, "aor", "maximum_expiration", "7200", OPT_UINT_T, 0, FLDSET(struct ast_sip_aor, maximum_expiration));
1410 ast_sorcery_object_field_register(sorcery, "aor", "default_expiration", "3600", OPT_UINT_T, 0, FLDSET(struct ast_sip_aor, default_expiration));
1411 ast_sorcery_object_field_register(sorcery, "aor", "qualify_frequency", 0, OPT_UINT_T, PARSE_IN_RANGE, FLDSET(struct ast_sip_aor, qualify_frequency), 0, 86400);
1412 ast_sorcery_object_field_register(sorcery, "aor", "qualify_timeout", "3.0", OPT_DOUBLE_T, 0, FLDSET(struct ast_sip_aor, qualify_timeout));
1413 ast_sorcery_object_field_register(sorcery, "aor", "authenticate_qualify", "no", OPT_BOOL_T, 1, FLDSET(struct ast_sip_aor, authenticate_qualify));
1414 ast_sorcery_object_field_register(sorcery, "aor", "max_contacts", "0", OPT_UINT_T, 0, FLDSET(struct ast_sip_aor, max_contacts));
1415 ast_sorcery_object_field_register(sorcery, "aor", "remove_existing", "no", OPT_BOOL_T, 1, FLDSET(struct ast_sip_aor, remove_existing));
1416 ast_sorcery_object_field_register(sorcery, "aor", "remove_unavailable", "no", OPT_BOOL_T, 1, FLDSET(struct ast_sip_aor, remove_unavailable));
1420 ast_sorcery_object_field_register(sorcery, "aor", "outbound_proxy", "", OPT_STRINGFIELD_T, 0, STRFLDSET(struct ast_sip_aor, outbound_proxy));
1421 ast_sorcery_object_field_register(sorcery, "aor", "support_path", "no", OPT_BOOL_T, 1, FLDSET(struct ast_sip_aor, support_path));
1422
1424
1426 if (!contact_formatter) {
1427 ast_log(LOG_ERROR, "Unable to allocate memory for contact_formatter\n");
1428 return -1;
1429 }
1430 contact_formatter->name = "contact";
1437
1439 if (!aor_formatter) {
1440 ast_log(LOG_ERROR, "Unable to allocate memory for aor_formatter\n");
1441 return -1;
1442 }
1443 aor_formatter->name = "aor";
1450
1454
1456 return -1;
1457 }
1458
1459 /*
1460 * Reset StatsD gauges in case we didn't shut down cleanly.
1461 * Note that this must done here, as contacts will create the contact_status
1462 * object before PJSIP options handling is initialized.
1463 */
1464 for (i = 0; i <= REMOVED; i++) {
1465 ast_statsd_log_full_va("PJSIP.contacts.states.%s", AST_STATSD_GAUGE, 0, 1.0, ast_sip_get_contact_status_label(i));
1466 }
1467
1468 return 0;
1469}
1470
1472{
1477 ast_manager_unregister("PJSIPShowAors");
1478
1480
1481 return 0;
1482}
jack_status_t status
Definition: app_jack.c:146
const char * str
Definition: app_jack.c:147
enum queue_result id
Definition: app_queue.c:1638
ast_mutex_t lock
Definition: app_sla.c:331
static int copy(char *infile, char *outfile)
Utility function to copy a file.
#define var
Definition: ast_expr2f.c:605
Asterisk main include file. File version handling, generic pbx functions.
#define ast_free(a)
Definition: astmm.h:180
#define ast_strdup(str)
A wrapper for strdup()
Definition: astmm.h:241
#define ast_strdupa(s)
duplicate a string in memory from the stack
Definition: astmm.h:298
#define ast_asprintf(ret, fmt,...)
A wrapper for asprintf()
Definition: astmm.h:267
#define ast_malloc(len)
A wrapper for malloc()
Definition: astmm.h:191
#define ast_log
Definition: astobj2.c:42
int ao2_container_dup(struct ao2_container *dest, struct ao2_container *src, enum search_flags flags)
Copy all object references in the src container into the dest container.
#define ao2_iterator_next(iter)
Definition: astobj2.h:1911
#define ao2_link(container, obj)
Add an object to a container.
Definition: astobj2.h:1532
@ CMP_MATCH
Definition: astobj2.h:1027
@ CMP_STOP
Definition: astobj2.h:1028
@ AO2_ALLOC_OPT_LOCK_NOLOCK
Definition: astobj2.h:367
#define ao2_callback(c, flags, cb_fn, arg)
ao2_callback() is a generic function that applies cb_fn() to all objects in a container,...
Definition: astobj2.h:1693
int ao2_container_count(struct ao2_container *c)
Returns the number of elements in a container.
#define ao2_cleanup(obj)
Definition: astobj2.h:1934
int() ao2_callback_fn(void *obj, void *arg, int flags)
Type of a generic callback function.
Definition: astobj2.h:1226
#define ao2_find(container, arg, flags)
Definition: astobj2.h:1736
struct ao2_iterator ao2_iterator_init(struct ao2_container *c, int flags) attribute_warn_unused_result
Create an iterator for a container.
#define ao2_unlock(a)
Definition: astobj2.h:729
#define ao2_lock(a)
Definition: astobj2.h:717
#define ao2_ref(o, delta)
Reference/unreference an object and return the old refcount.
Definition: astobj2.h:459
#define ao2_alloc_options(data_size, destructor_fn, options)
Definition: astobj2.h:404
#define ao2_bump(obj)
Bump refcount on an AO2 object by one, returning the object.
Definition: astobj2.h:480
void ao2_iterator_destroy(struct ao2_iterator *iter)
Destroy a container iterator.
@ OBJ_SEARCH_PARTIAL_KEY
The arg parameter is a partial search key similar to OBJ_SEARCH_KEY.
Definition: astobj2.h:1116
@ OBJ_SEARCH_OBJECT
The arg parameter is an object of the same type.
Definition: astobj2.h:1087
@ OBJ_NODATA
Definition: astobj2.h:1044
@ OBJ_SEARCH_MASK
Search option field mask.
Definition: astobj2.h:1072
@ OBJ_MULTIPLE
Definition: astobj2.h:1049
@ OBJ_UNLINK
Definition: astobj2.h:1039
@ OBJ_SEARCH_KEY
The arg parameter is a search key, but is not an object.
Definition: astobj2.h:1101
#define ao2_container_alloc_list(ao2_options, container_options, sort_fn, cmp_fn)
Allocate and initialize a list container.
Definition: astobj2.h:1327
#define ao2_alloc(data_size, destructor_fn)
Definition: astobj2.h:409
@ AO2_CONTAINER_ALLOC_OPT_DUPS_REJECT
Reject objects with duplicate keys in container.
Definition: astobj2.h:1188
int ast_cli_unregister_multiple(struct ast_cli_entry *e, int len)
Unregister multiple commands.
Definition: clicompat.c:30
#define AST_CLI_DEFINE(fn, txt,...)
Definition: cli.h:197
#define ast_cli_register_multiple(e, len)
Register multiple commands.
Definition: cli.h:265
#define STRFLDSET(type,...)
Convert a struct and a list of stringfield fields to an argument list of field offsets.
#define FLDSET(type,...)
Convert a struct and list of fields to an argument list of field offsets.
@ OPT_UINT_T
Type for default option handler for unsigned integers.
@ OPT_NOOP_T
Type for a default handler that should do nothing.
@ OPT_BOOL_T
Type for default option handler for bools (ast_true/ast_false)
@ OPT_YESNO_T
Type for default option handler for bools (ast_true/ast_false)
@ OPT_DOUBLE_T
Type for default option handler for doubles.
@ OPT_STRINGFIELD_T
Type for default option handler for stringfields.
char buf[BUFSIZE]
Definition: eagi_proxy.c:66
static const char name[]
Definition: format_mp3.c:68
static int regex(struct ast_channel *chan, const char *cmd, char *parse, char *buf, size_t len)
void astman_send_listack(struct mansession *s, const struct message *m, char *msg, char *listflag)
Send ack in manager transaction to begin a list.
Definition: manager.c:3423
void astman_send_error(struct mansession *s, const struct message *m, char *error)
Send error in manager transaction.
Definition: manager.c:3381
void astman_send_list_complete_start(struct mansession *s, const struct message *m, const char *event_name, int count)
Start the list complete event.
Definition: manager.c:3459
const char * astman_get_header(const struct message *m, char *var)
Get header from manager transaction.
Definition: manager.c:3042
void astman_send_list_complete_end(struct mansession *s)
End the list complete event.
Definition: manager.c:3467
void astman_append(struct mansession *s, const char *fmt,...)
Definition: manager.c:3302
int ast_manager_unregister(const char *action)
Unregister a registered manager command.
Definition: manager.c:8041
#define ast_named_lock_get(lock_type, keyspace, key)
Geta named lock handle.
Definition: named_locks.h:83
@ AST_NAMED_LOCK_TYPE_MUTEX
Definition: named_locks.h:59
static char prefix[MAX_PREFIX]
Definition: http.c:144
#define NAN
char * strsep(char **str, const char *delims)
#define ast_variable_new(name, value, filename)
#define ast_variable_list_append(head, new_var)
void ast_variables_destroy(struct ast_variable *var)
Free variable list.
Definition: extconf.c:1262
Support for logging to various files, console and syslog Configuration in file logger....
#define LOG_ERROR
#define ast_verb(level,...)
#define LOG_WARNING
static int contact_apply_handler(const struct ast_sorcery *sorcery, void *object)
Always create a contact_status for each contact.
Definition: location.c:1329
int ast_sip_validate_uri_length(const char *contact_uri)
Definition: location.c:528
static int expiration_str2struct(const struct aco_option *opt, struct ast_variable *var, void *obj)
Custom handler for translating from a string timeval to actual structure.
Definition: location.c:482
static struct ast_cli_entry cli_commands[]
Definition: location.c:1293
static void * contact_alloc(const char *name)
Allocator for contact.
Definition: location.c:120
struct ast_sip_contact * ast_sip_location_retrieve_contact_from_aor_list(const char *aor_list)
Retrieve the first bound contact from a list of AORs.
Definition: location.c:304
int ast_sip_location_add_contact(struct ast_sip_aor *aor, const char *uri, struct timeval expiration_time, const char *path_info, const char *user_agent, const char *via_addr, int via_port, const char *call_id, struct ast_sip_endpoint *endpoint)
Add a new contact to an AOR.
Definition: location.c:429
void ast_sip_location_retrieve_contact_and_aor_from_list(const char *aor_list, struct ast_sip_aor **aor, struct ast_sip_contact **contact)
Retrieve the first bound contact AND the AOR chosen from a list of AORs.
Definition: location.c:266
static int cli_aor_print_body(void *obj, void *arg, int flags)
Definition: location.c:1186
static const struct ast_sorcery_observer aor_observer
Observer for contacts so state can be updated on respective endpoints.
Definition: location.c:105
static int contacts_to_var_list(const void *obj, struct ast_variable **fields)
Definition: location.c:660
struct ast_sip_aor * ast_sip_location_retrieve_aor(const char *aor_name)
Retrieve a named AOR.
Definition: location.c:147
static void contact_wrapper_destroy(void *obj)
Definition: location.c:713
struct ao2_container * ast_sip_location_retrieve_aor_contacts_nolock_filtered(const struct ast_sip_aor *aor, unsigned int flags)
Retrieve all contacts currently available for an AOR without locking the AOR and filter based on flag...
Definition: location.c:219
static int aor_apply_outbound_proxy(void *obj, void *arg, int flags)
Definition: location.c:1345
static int contact_to_var_list(void *object, void *arg, int flags)
Definition: location.c:650
static int format_ami_aorlist_handler(void *obj, void *arg, int flags)
Definition: location.c:1242
int ast_sip_for_each_contact(const struct ast_sip_aor *aor, ao2_callback_fn on_contact, void *arg)
For every contact on an AOR call the given 'on_contact' handler.
Definition: location.c:722
int ast_sip_for_each_aor(const char *aors, ao2_callback_fn on_aor, void *arg)
For every aor in the comma separated aors string call the given 'on_aor' handler.
Definition: location.c:687
struct ast_sip_contact * ast_sip_location_retrieve_first_aor_contact_filtered(const struct ast_sip_aor *aor, unsigned int flags)
Retrieve the first bound contact for an AOR and filter based on flags.
Definition: location.c:199
static struct ao2_container * cli_get_aors(void)
Definition: location.c:1232
static int format_ami_aor_handler(void *obj, void *arg, int flags)
Definition: location.c:831
static int pjsip_max_url_size
Definition: location.c:37
static int format_ami_endpoint_aor(const struct ast_sip_endpoint *endpoint, struct ast_sip_ami *ami)
Definition: location.c:870
static int cli_contact_iterate(void *container, ao2_callback_fn callback, void *args)
Definition: location.c:979
static int cli_filter_contacts(void *obj, void *arg, int flags)
Definition: location.c:984
static int voicemail_extension_to_str(const void *obj, const intptr_t *args, char **buf)
Definition: location.c:678
struct ast_sip_cli_formatter_entry * contact_formatter
Definition: location.c:1325
static int expiration_struct2str(const void *obj, const intptr_t *args, char **buf)
Custom handler for translating from an actual structure timeval to string.
Definition: location.c:489
static int contact_link_static(void *obj, void *arg, int flags)
Internal callback function which links static contacts into another container.
Definition: location.c:168
struct ast_sip_cli_formatter_entry * aor_formatter
Definition: location.c:1326
static int cli_gather_contact(void *obj, void *arg, int flags)
Definition: location.c:996
static int prune_boot_contacts_cb(void *obj, void *arg, int flags)
Definition: location.c:455
static int cli_contact_compare(void *obj, void *arg, int flags)
Definition: location.c:950
static void contact_destroy(void *obj)
Destructor for contact.
Definition: location.c:111
static const char * cli_contact_get_id(const void *obj)
Definition: location.c:919
static void * aor_alloc(const char *name)
Allocator for AOR.
Definition: location.c:50
static int permanent_uri_handler(const struct aco_option *opt, struct ast_variable *var, void *obj)
Custom handler for permanent URIs.
Definition: location.c:592
static int permanent_uri_sort_fn(const void *obj_left, const void *obj_right, int flags)
Definition: location.c:498
static int voicemail_extension_handler(const struct aco_option *opt, struct ast_variable *var, void *obj)
Definition: location.c:669
static void * cli_contact_retrieve_by_id(const char *id)
Definition: location.c:1079
static int sip_aor_to_ami(const struct ast_sip_aor *aor, struct ast_str **buf)
Definition: location.c:780
struct ao2_container * ast_sip_location_retrieve_aor_contacts_nolock(const struct ast_sip_aor *aor)
Retrieve all contacts currently available for an AOR without locking the AOR.
Definition: location.c:214
static int contacts_to_str(const void *obj, const intptr_t *args, char **buf)
Definition: location.c:811
static int pj_max_hostname
Definition: location.c:36
static int gather_contacts_for_aor(void *obj, void *arg, int flags)
Definition: location.c:319
struct ast_sip_contact * ast_sip_location_retrieve_contact(const char *contact_name)
Retrieve a named contact.
Definition: location.c:350
static int contact_remove_unreachable(void *obj, void *arg, int flags)
Internal callback function which removes any contact which is unreachable.
Definition: location.c:177
static int contact_expire(void *obj, void *arg, int flags)
Internal callback function which deletes and unlinks any expired contacts.
Definition: location.c:153
static int cli_aor_print_header(void *obj, void *arg, int flags)
Definition: location.c:1159
struct ao2_container * ast_sip_location_retrieve_contacts_from_aor_list(const char *aor_list)
Retrieve all contacts from a list of AORs.
Definition: location.c:335
static struct ao2_container * cli_contact_get_container(const char *regex)
Definition: location.c:1029
static const char * cli_aor_get_id(const void *obj)
Definition: location.c:1154
int ast_sip_initialize_sorcery_location(void)
Initialize sorcery with location support.
Definition: location.c:1369
static void aor_destroy(void *obj)
Destructor for AOR.
Definition: location.c:40
static struct ao2_container * cli_aor_get_container(const char *regex)
Definition: location.c:882
void ast_sip_location_retrieve_contact_and_aor_from_list_filtered(const char *aor_list, unsigned int flags, struct ast_sip_aor **aor, struct ast_sip_contact **contact)
Retrieve the first bound contact AND the AOR chosen from a list of AORs and filter based on flags.
Definition: location.c:272
struct ast_sip_endpoint_formatter endpoint_aor_formatter
Definition: location.c:878
int ast_sip_destroy_sorcery_location(void)
Definition: location.c:1471
struct ast_sip_contact * ast_sip_location_create_contact(struct ast_sip_aor *aor, const char *uri, struct timeval expiration_time, const char *path_info, const char *user_agent, const char *via_addr, int via_port, const char *call_id, int prune_on_boot, struct ast_sip_endpoint *endpoint)
Create a new contact for an AOR without locking the AOR.
Definition: location.c:355
static void * cli_aor_retrieve_by_id(const char *id)
Definition: location.c:1149
static int cli_contact_print_header(void *obj, void *arg, int flags)
Definition: location.c:1094
static void aor_deleted_observer(const void *object)
Definition: location.c:81
int ast_sip_location_update_contact(struct ast_sip_contact *contact)
Update a contact.
Definition: location.c:445
static int cli_contact_populate_container(void *obj, void *arg, int flags)
Definition: location.c:905
static int aor_apply_handler(const struct ast_sorcery *sorcery, void *object)
Definition: location.c:1355
static int cli_contact_sort(const void *obj, const void *arg, int flags)
Definition: location.c:925
static int cli_contact_print_body(void *obj, void *arg, int flags)
Definition: location.c:1109
int ast_sip_contact_to_str(void *object, void *arg, int flags)
Handler used to convert a contact to a string.
Definition: location.c:770
struct ast_sip_contact * ast_sip_location_retrieve_first_aor_contact(const struct ast_sip_aor *aor)
Retrieve the first bound contact for an AOR.
Definition: location.c:194
static int cli_aor_iterate(void *container, ao2_callback_fn callback, void *args)
Definition: location.c:1142
void ast_sip_location_prune_boot_contacts(void)
Prune the prune_on_boot contacts.
Definition: location.c:469
struct ao2_container * ast_sip_location_retrieve_aor_contacts(const struct ast_sip_aor *aor)
Retrieve all contacts currently available for an AOR.
Definition: location.c:247
static int destroy_contact(void *obj, void *arg, int flags)
Internal callback function which destroys the specified contact.
Definition: location.c:72
struct ao2_container * ast_sip_location_retrieve_aor_contacts_filtered(const struct ast_sip_aor *aor, unsigned int flags)
Retrieve all contacts currently available for an AOR and filter based on flags.
Definition: location.c:252
static int cli_aor_gather_contacts(void *obj, void *arg, int flags)
Definition: location.c:912
int ast_sip_location_delete_contact(struct ast_sip_contact *contact)
Delete a contact.
Definition: location.c:450
static int ami_show_aors(struct mansession *s, const struct message *m)
Definition: location.c:1263
int ast_sip_location_add_contact_nolock(struct ast_sip_aor *aor, const char *uri, struct timeval expiration_time, const char *path_info, const char *user_agent, const char *via_addr, int via_port, const char *call_id, struct ast_sip_endpoint *endpoint)
Add a new contact to an AOR without locking the AOR.
Definition: location.c:416
#define EVENT_FLAG_SYSTEM
Definition: manager.h:75
#define ast_manager_register_xml(action, authority, func)
Register a manager callback using XML documentation to describe the manager.
Definition: manager.h:191
Named Locks.
Asterisk file paths, configured in asterisk.conf.
const char * ast_config_AST_SYSTEM_NAME
Definition: options.c:170
static int default_expiration
Definition: pbx_dundi.c:199
static struct stasis_rest_handlers mailboxes
REST handler for /api-docs/mailboxes.json.
struct ao2_container * container
Definition: res_fax.c:501
int ast_pjproject_get_buildopt(char *option, char *format_string,...)
Retrieve a pjproject build option.
const char * ast_sip_get_contact_short_status_label(const enum ast_sip_contact_status_type status)
@ AST_SIP_CONTACT_FILTER_REACHABLE
Return only reachable or unknown contacts.
Definition: res_pjsip.h:1306
@ AST_SIP_CONTACT_FILTER_DEFAULT
Default filter flags.
Definition: res_pjsip.h:1303
void ast_sip_register_endpoint_formatter(struct ast_sip_endpoint_formatter *obj)
Register an endpoint formatter.
Definition: res_pjsip.c:481
void ast_sip_unregister_endpoint_formatter(struct ast_sip_endpoint_formatter *obj)
Unregister an endpoint formatter.
Definition: res_pjsip.c:487
struct ast_str * ast_sip_create_ami_event(const char *event, struct ast_sip_ami *ami)
Creates a string to store AMI event data in.
struct ast_sorcery * ast_sip_get_sorcery(void)
Get a pointer to the SIP sorcery structure.
struct ast_sip_contact_status * ast_sip_get_contact_status(const struct ast_sip_contact *contact)
Retrieve the current status for a contact.
const char * ast_sip_get_contact_status_label(const enum ast_sip_contact_status_type status)
translate ast_sip_contact_status_type to character string.
@ AVAILABLE
Definition: res_pjsip.h:438
@ UNAVAILABLE
Definition: res_pjsip.h:436
@ REMOVED
Definition: res_pjsip.h:443
@ UNKNOWN
Definition: res_pjsip.h:440
int ast_sip_unregister_cli_formatter(struct ast_sip_cli_formatter_entry *formatter)
Unregisters a CLI formatter.
Definition: pjsip_cli.c:326
#define CLI_HEADER_FILLER
Definition: res_pjsip_cli.h:24
int ast_sip_cli_print_sorcery_objectset(void *obj, void *arg, int flags)
Prints a sorcery object's ast_variable list.
Definition: pjsip_cli.c:36
struct ast_sip_cli_formatter_entry * ast_sip_lookup_cli_formatter(const char *name)
Looks up a CLI formatter by type.
Definition: pjsip_cli.c:305
#define CLI_LAST_TABSTOP
Definition: res_pjsip_cli.h:27
char * ast_sip_cli_traverse_objects(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
Definition: pjsip_cli.c:109
#define CLI_INDENT_TO_SPACES(x)
Definition: res_pjsip_cli.h:29
int ast_sip_register_cli_formatter(struct ast_sip_cli_formatter_entry *formatter)
Registers a CLI formatter.
Definition: pjsip_cli.c:310
static struct ast_sorcery * sorcery
struct ast_sip_contact_status * ast_res_pjsip_find_or_create_contact_status(const struct ast_sip_contact *contact)
#define NULL
Definition: resample.c:96
Sorcery Data Access Layer API.
const char * ast_sorcery_object_get_id(const void *object)
Get the unique identifier of a sorcery object.
Definition: sorcery.c:2312
void ast_sorcery_observer_remove(const struct ast_sorcery *sorcery, const char *type, const struct ast_sorcery_observer *callbacks)
Remove an observer from a specific object type.
Definition: sorcery.c:2418
@ AST_RETRIEVE_FLAG_MULTIPLE
Return all matching objects.
Definition: sorcery.h:120
@ AST_RETRIEVE_FLAG_ALL
Perform no matching, return all objects.
Definition: sorcery.h:123
const char * ast_sorcery_object_get_type(const void *object)
Get the type of a sorcery object.
Definition: sorcery.c:2324
int ast_sorcery_create(const struct ast_sorcery *sorcery, void *object)
Create and potentially persist an object using an available wizard.
Definition: sorcery.c:2057
void * ast_sorcery_retrieve_by_id(const struct ast_sorcery *sorcery, const char *type, const char *id)
Retrieve an object using its unique identifier.
Definition: sorcery.c:1853
#define ast_sorcery_object_register(sorcery, type, alloc, transform, apply)
Register an object type.
Definition: sorcery.h:837
struct ao2_container * ast_sorcery_retrieve_by_regex(const struct ast_sorcery *sorcery, const char *type, const char *regex)
Retrieve multiple objects using a regular expression on their id.
Definition: sorcery.c:1949
int ast_sorcery_observer_add(const struct ast_sorcery *sorcery, const char *type, const struct ast_sorcery_observer *callbacks)
Add an observer to a specific object type.
Definition: sorcery.c:2386
#define ast_sorcery_object_field_register_custom(sorcery, type, name, default_val, config_handler, sorcery_handler, multiple_handler, flags,...)
Register a field within an object with custom handlers.
Definition: sorcery.h:1005
void * ast_sorcery_generic_alloc(size_t size, ao2_destructor_fn destructor)
Allocate a generic sorcery capable object.
Definition: sorcery.c:1728
int ast_sorcery_object_id_compare(void *obj, void *arg, int flags)
ao2 object comparator based on sorcery id.
Definition: sorcery.c:2459
#define ast_sorcery_object_field_register(sorcery, type, name, default_val, opt_type, flags,...)
Register a field within an object.
Definition: sorcery.h:955
void * ast_sorcery_alloc(const struct ast_sorcery *sorcery, const char *type, const char *id)
Allocate an object.
Definition: sorcery.c:1744
int ast_sorcery_object_id_sort(const void *obj, const void *arg, int flags)
ao2 object sorter based on sorcery id.
Definition: sorcery.c:2435
void * ast_sorcery_lockable_alloc(size_t size, ao2_destructor_fn destructor, void *lockobj)
Allocate a generic sorcery capable object with locking.
Definition: sorcery.c:1712
int ast_sorcery_update(const struct ast_sorcery *sorcery, void *object)
Update an object.
Definition: sorcery.c:2145
@ AST_HANDLER_ONLY_STRING
Use string handler only.
Definition: sorcery.h:137
#define MAX_OBJECT_FIELD
Maximum length of an object field name.
Definition: sorcery.h:110
#define ast_sorcery_apply_default(sorcery, type, name, data)
Definition: sorcery.h:476
struct ast_variable * ast_sorcery_objectset_create2(const struct ast_sorcery *sorcery, const void *object, enum ast_sorcery_field_handler_flags flags)
Create an object set (KVP list) for an object.
Definition: sorcery.c:1511
void * ast_sorcery_retrieve_by_fields(const struct ast_sorcery *sorcery, const char *type, unsigned int flags, struct ast_variable *fields)
Retrieve an object or multiple objects using specific fields.
Definition: sorcery.c:1897
int ast_sorcery_object_set_congestion_levels(struct ast_sorcery *sorcery, const char *type, long low_water, long high_water)
Set the high and low alert water marks of the sorcery object type.
Definition: sorcery.c:1114
int ast_sorcery_delete(const struct ast_sorcery *sorcery, void *object)
Delete an object.
Definition: sorcery.c:2233
struct ao2_container * ast_sorcery_retrieve_by_prefix(const struct ast_sorcery *sorcery, const char *type, const char *prefix, const size_t prefix_len)
Retrieve multiple objects whose id begins with the specified prefix.
Definition: sorcery.c:1984
#define AST_STATSD_GAUGE
Support for publishing to a statsd server.
Definition: statsd.h:32
void ast_statsd_log_full_va(const char *metric_name, const char *metric_type, intmax_t value, double sample_rate,...)
Send a stat to the configured statsd server.
Definition: res_statsd.c:209
#define ast_string_field_set(x, field, data)
Set a field to a simple string value.
Definition: stringfields.h:521
#define ast_string_field_init(x, size)
Initialize a field pool and fields.
Definition: stringfields.h:359
#define ast_string_field_free_memory(x)
free all memory - to be called before destroying the object
Definition: stringfields.h:374
char * ast_str_truncate(struct ast_str *buf, ssize_t len)
Truncates the enclosed string to the given length.
Definition: strings.h:786
int ast_str_append(struct ast_str **buf, ssize_t max_len, const char *fmt,...)
Append to a thread local dynamic string.
Definition: strings.h:1139
char * ast_str_buffer(const struct ast_str *buf)
Returns the string buffer within the ast_str buf.
Definition: strings.h:761
#define S_OR(a, b)
returns the equivalent of logic or for strings: first one if not empty, otherwise second one.
Definition: strings.h:80
static force_inline int attribute_pure ast_strlen_zero(const char *s)
Definition: strings.h:65
char * ast_strip_quoted(char *s, const char *beg_quotes, const char *end_quotes)
Strip leading/trailing whitespace and quotes from a string.
Definition: utils.c:1818
#define ast_str_create(init_len)
Create a malloc'ed dynamic length string.
Definition: strings.h:659
char * ast_strip(char *s)
Strip leading/trailing whitespace from a string.
Definition: strings.h:223
#define ast_to_camel_case(s)
Attempts to convert the given string to camel case using an underscore as the specified delimiter.
Definition: strings.h:546
int ast_get_timeval(const char *src, struct timeval *tv, struct timeval _default, int *consumed)
Parse a time (float) string.
Definition: utils.c:2419
Generic container type.
When we need to walk through a container, we use an ao2_iterator to keep track of the current positio...
Definition: astobj2.h:1821
descriptor for a cli entry.
Definition: cli.h:171
char * command
Definition: cli.h:186
AMI variable container.
Definition: res_pjsip.h:3047
struct mansession * s
Definition: res_pjsip.h:3049
void * arg
Definition: res_pjsip.h:3055
const struct message * m
Definition: res_pjsip.h:3051
A SIP address of record.
Definition: res_pjsip.h:478
char * voicemail_extension
Definition: res_pjsip.h:508
unsigned int max_contacts
Definition: res_pjsip.h:498
struct ao2_container * permanent_contacts
Definition: res_pjsip.h:502
const ast_string_field outbound_proxy
Definition: res_pjsip.h:486
CLI Formatter Context passed to all formatters.
Definition: res_pjsip_cli.h:34
CLI Formatter Registry Entry.
Definition: res_pjsip_cli.h:52
int(* iterate)(void *container, ao2_callback_fn callback, void *args)
Definition: res_pjsip_cli.h:66
ao2_callback_fn * print_header
Definition: res_pjsip_cli.h:60
void *(* retrieve_by_id)(const char *id)
Definition: res_pjsip_cli.h:68
const char *(* get_id)(const void *obj)
Definition: res_pjsip_cli.h:70
const char * name
Definition: res_pjsip_cli.h:58
ao2_callback_fn * print_body
Definition: res_pjsip_cli.h:62
struct ao2_container *(* get_container)(const char *regex)
Definition: res_pjsip_cli.h:64
A contact's status.
Definition: res_pjsip.h:451
const ast_string_field uri
Definition: res_pjsip.h:457
const ast_string_field aor
Definition: res_pjsip.h:457
A wrapper for contact that adds the aor_id and a consistent contact id. Used by ast_sip_for_each_cont...
Definition: res_pjsip.h:517
struct ast_sip_contact * contact
Definition: res_pjsip.h:523
Contact associated with an address of record.
Definition: res_pjsip.h:392
const ast_string_field uri
Definition: res_pjsip.h:414
double qualify_timeout
Definition: res_pjsip.h:422
struct ast_sip_endpoint * endpoint
Definition: res_pjsip.h:424
const ast_string_field via_addr
Definition: res_pjsip.h:414
const ast_string_field call_id
Definition: res_pjsip.h:414
const ast_string_field aor
Definition: res_pjsip.h:414
const ast_string_field outbound_proxy
Definition: res_pjsip.h:414
struct timeval expiration_time
Definition: res_pjsip.h:416
const ast_string_field path
Definition: res_pjsip.h:414
const ast_string_field endpoint_name
Definition: res_pjsip.h:414
int authenticate_qualify
Definition: res_pjsip.h:420
const ast_string_field reg_server
Definition: res_pjsip.h:414
const ast_string_field user_agent
Definition: res_pjsip.h:414
unsigned int qualify_frequency
Definition: res_pjsip.h:418
An entity responsible formatting endpoint information.
Definition: res_pjsip.h:3073
int(* format_ami)(const struct ast_sip_endpoint *endpoint, struct ast_sip_ami *ami)
Callback used to format endpoint information over AMI.
Definition: res_pjsip.h:3077
An entity with which Asterisk communicates.
Definition: res_pjsip.h:963
const ast_string_field aors
Definition: res_pjsip.h:992
Interface for a sorcery object type observer.
Definition: sorcery.h:332
void(* deleted)(const void *object)
Callback for when an object is deleted.
Definition: sorcery.h:340
Full structure for sorcery.
Definition: sorcery.c:230
Support for dynamic strings.
Definition: strings.h:623
Structure for variables, used for configurations and for channel variables.
struct ast_variable * next
In case you didn't read that giant block of text above the mansession_session struct,...
Definition: manager.c:1777
An API for managing task processing threads that can be shared across modules.
#define AST_TASKPROCESSOR_HIGH_WATER_LEVEL
Definition: taskprocessor.h:64
const char * args
int ast_time_t_to_string(time_t time, char *buf, size_t length)
Converts to a string representation of a time_t as decimal seconds since the epoch....
Definition: time.c:152
#define AST_TIME_T_LEN
Definition: time.h:45
int64_t ast_tvdiff_ms(struct timeval end, struct timeval start)
Computes the difference (in milliseconds) between two struct timeval instances.
Definition: time.h:107
struct timeval ast_tvnow(void)
Returns current timeval. Meant to replace calls to gettimeofday().
Definition: time.h:159
struct timeval ast_tv(ast_time_t sec, ast_suseconds_t usec)
Returns a timeval from sec, usec.
Definition: time.h:235
char * usage
Definition: utils/frame.c:37
#define RAII_VAR(vartype, varname, initval, dtor)
Declare a variable that will call a destructor function when it goes out of scope.
Definition: utils.h:941
#define ast_assert(a)
Definition: utils.h:739
#define ARRAY_LEN(a)
Definition: utils.h:666
void ast_md5_hash(char *output, const char *input)
Produces MD5 hash based on input string.
Definition: utils.c:250