Asterisk - The Open Source Telephony Project GIT-master-3dee037
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->qualify_2xx_only = aor->qualify_2xx_only;
377 contact->authenticate_qualify = aor->authenticate_qualify;
378 if (path_info && aor->support_path) {
379 ast_string_field_set(contact, path, path_info);
380 }
381
382 if (!ast_strlen_zero(aor->outbound_proxy)) {
383 ast_string_field_set(contact, outbound_proxy, aor->outbound_proxy);
384 }
385
388 }
389
392 }
393
396 }
397 contact->via_port = via_port;
398
399 if (!ast_strlen_zero(call_id)) {
401 }
402
403 contact->endpoint = ao2_bump(endpoint);
404 if (endpoint) {
406 }
407
408 contact->prune_on_boot = prune_on_boot;
409
410 if (ast_sorcery_create(ast_sip_get_sorcery(), contact)) {
411 ao2_ref(contact, -1);
412 return NULL;
413 }
414 return contact;
415}
416
418 struct timeval expiration_time, const char *path_info, const char *user_agent,
419 const char *via_addr, int via_port, const char *call_id,
421{
422 struct ast_sip_contact *contact;
423
426 ao2_cleanup(contact);
427 return contact ? 0 : -1;
428}
429
431 struct timeval expiration_time, const char *path_info, const char *user_agent,
432 const char *via_addr, int via_port, const char *call_id,
434{
435 int res;
436
437 ao2_lock(aor);
440 endpoint);
442
443 return res;
444}
445
447{
448 return ast_sorcery_update(ast_sip_get_sorcery(), contact);
449}
450
452{
453 return ast_sorcery_delete(ast_sip_get_sorcery(), contact);
454}
455
456static int prune_boot_contacts_cb(void *obj, void *arg, int flags)
457{
458 struct ast_sip_contact *contact = obj;
459
460 if (contact->prune_on_boot
461 && !strcmp(contact->reg_server, ast_config_AST_SYSTEM_NAME ?: "")) {
462 ast_verb(3, "Removed contact '%s' from AOR '%s' due to system boot\n",
463 contact->uri, contact->aor);
465 }
466
467 return 0;
468}
469
471{
472 struct ao2_container *contacts;
473
476 if (contacts) {
478 ao2_ref(contacts, -1);
479 }
480}
481
482/*! \brief Custom handler for translating from a string timeval to actual structure */
483static int expiration_str2struct(const struct aco_option *opt, struct ast_variable *var, void *obj)
484{
485 struct ast_sip_contact *contact = obj;
486 return ast_get_timeval(var->value, &contact->expiration_time, ast_tv(0, 0), NULL);
487}
488
489/*! \brief Custom handler for translating from an actual structure timeval to string */
490static int expiration_struct2str(const void *obj, const intptr_t *args, char **buf)
491{
492 const struct ast_sip_contact *contact = obj;
493 char secs[AST_TIME_T_LEN];
494
495 ast_time_t_to_string(contact->expiration_time.tv_sec, secs, sizeof(secs));
496 return (ast_asprintf(buf, "%s", secs) < 0) ? -1 : 0;
497}
498
499static int permanent_uri_sort_fn(const void *obj_left, const void *obj_right, int flags)
500{
501 const struct ast_sip_contact *object_left = obj_left;
502 const struct ast_sip_contact *object_right = obj_right;
503 const char *right_key = obj_right;
504 int cmp;
505
506 switch (flags & OBJ_SEARCH_MASK) {
508 right_key = ast_sorcery_object_get_id(object_right);
509 /* Fall through */
510 case OBJ_SEARCH_KEY:
511 cmp = strcmp(ast_sorcery_object_get_id(object_left), right_key);
512 break;
514 /*
515 * We could also use a partial key struct containing a length
516 * so strlen() does not get called for every comparison instead.
517 */
518 cmp = strncmp(ast_sorcery_object_get_id(object_left), right_key, strlen(right_key));
519 break;
520 default:
521 /* Sort can only work on something with a full or partial key. */
522 ast_assert(0);
523 cmp = 0;
524 break;
525 }
526 return cmp;
527}
528
529int ast_sip_validate_uri_length(const char *contact_uri)
530{
531 int max_length = pj_max_hostname - 1;
532 char *contact = ast_strdupa(contact_uri);
533 char *host;
534 char *at;
535 int theres_a_port = 0;
536
537 if (strlen(contact_uri) > pjsip_max_url_size - 1) {
538 return -1;
539 }
540
541 contact = ast_strip_quoted(contact, "<", ">");
542
543 if (!strncasecmp(contact, "sip:", 4)) {
544 host = contact + 4;
545 } else if (!strncasecmp(contact, "sips:", 5)) {
546 host = contact + 5;
547 } else {
548 /* Not a SIP URI */
549 return -1;
550 }
551
552 at = strchr(contact, '@');
553 if (at) {
554 /* sip[s]:user@host */
555 host = at + 1;
556 }
557
558 if (host[0] == '[') {
559 /* Host is an IPv6 address. Just get up to the matching bracket */
560 char *close_bracket;
561
562 close_bracket = strchr(host, ']');
563 if (!close_bracket) {
564 return -1;
565 }
566 close_bracket++;
567 if (*close_bracket == ':') {
568 theres_a_port = 1;
569 }
570 *close_bracket = '\0';
571 } else {
572 /* uri parameters could contain ';' so trim them off first */
573 host = strsep(&host, ";?");
574 /* Host is FQDN or IPv4 address. Need to find closing delimiter */
575 if (strchr(host, ':')) {
576 theres_a_port = 1;
577 host = strsep(&host, ":");
578 }
579 }
580
581 if (!theres_a_port) {
582 max_length -= strlen("_sips.tcp.");
583 }
584
585 if (strlen(host) > max_length) {
586 return -1;
587 }
588
589 return 0;
590}
591
592/*! \brief Custom handler for permanent URIs */
593static int permanent_uri_handler(const struct aco_option *opt, struct ast_variable *var, void *obj)
594{
595 struct ast_sip_aor *aor = obj;
596 const char *aor_id = ast_sorcery_object_get_id(aor);
597 char *contacts;
598 char *contact_uri;
599
600 if (ast_strlen_zero(var->value)) {
601 return 0;
602 }
603
604 contacts = ast_strdupa(var->value);
605 while ((contact_uri = ast_strip(strsep(&contacts, ",")))) {
606 struct ast_sip_contact *contact;
608 char hash[33];
609 char contact_id[strlen(aor_id) + sizeof(hash) + 2];
610
611 if (ast_strlen_zero(contact_uri)) {
612 continue;
613 }
614
615 if (ast_sip_validate_uri_length(contact_uri)) {
616 ast_log(LOG_ERROR, "Contact uri or hostname length exceeds pjproject limit or is not a sip(s) uri: %s\n", contact_uri);
617 return -1;
618 }
619
620 if (!aor->permanent_contacts) {
623 if (!aor->permanent_contacts) {
624 return -1;
625 }
626 }
627
628 ast_md5_hash(hash, contact_uri);
629 snprintf(contact_id, sizeof(contact_id), "%s@@%s", aor_id, hash);
630 contact = ast_sorcery_alloc(ast_sip_get_sorcery(), "contact", contact_id);
631 if (!contact) {
632 return -1;
633 }
634
635 ast_string_field_set(contact, uri, contact_uri);
636
638 if (!status) {
639 ao2_ref(contact, -1);
640 return -1;
641 }
642 ao2_ref(status, -1);
643
644 ao2_link(aor->permanent_contacts, contact);
645 ao2_ref(contact, -1);
646 }
647
648 return 0;
649}
650
651static int contact_to_var_list(void *object, void *arg, int flags)
652{
653 struct ast_sip_contact_wrapper *wrapper = object;
654 struct ast_variable **var = arg;
655
656 ast_variable_list_append(&*var, ast_variable_new("contact", wrapper->contact->uri, ""));
657
658 return 0;
659}
660
661static int contacts_to_var_list(const void *obj, struct ast_variable **fields)
662{
663 const struct ast_sip_aor *aor = obj;
664
666
667 return 0;
668}
669
670static int voicemail_extension_handler(const struct aco_option *opt, struct ast_variable *var, void *obj)
671{
672 struct ast_sip_aor *aor = obj;
673
674 aor->voicemail_extension = ast_strdup(var->value);
675
676 return aor->voicemail_extension ? 0 : -1;
677}
678
679static int voicemail_extension_to_str(const void *obj, const intptr_t *args, char **buf)
680{
681 const struct ast_sip_aor *aor = obj;
682
684
685 return 0;
686}
687
688int ast_sip_for_each_aor(const char *aors, ao2_callback_fn on_aor, void *arg)
689{
690 char *copy;
691 char *name;
692 int res;
693
694 if (!on_aor || ast_strlen_zero(aors)) {
695 return 0;
696 }
697
698 copy = ast_strdupa(aors);
699 while ((name = ast_strip(strsep(&copy, ",")))) {
700 struct ast_sip_aor *aor;
701
703 if (aor) {
704 res = on_aor(aor, arg, 0);
705 ao2_ref(aor, -1);
706 if (res) {
707 return -1;
708 }
709 }
710 }
711 return 0;
712}
713
714static void contact_wrapper_destroy(void *obj)
715{
716 struct ast_sip_contact_wrapper *wrapper = obj;
717
718 ast_free(wrapper->aor_id);
719 ast_free(wrapper->contact_id);
720 ao2_cleanup(wrapper->contact);
721}
722
724 ao2_callback_fn on_contact, void *arg)
725{
726 struct ao2_container *contacts;
727 struct ao2_iterator i;
728 int res = 0;
729 void *object = NULL;
730
731 if (!on_contact ||
732 !(contacts = ast_sip_location_retrieve_aor_contacts(aor))) {
733 return 0;
734 }
735
736 i = ao2_iterator_init(contacts, 0);
737 while ((object = ao2_iterator_next(&i))) {
738 RAII_VAR(struct ast_sip_contact *, contact, object, ao2_cleanup);
740 const char *aor_id = ast_sorcery_object_get_id(aor);
741
742 wrapper = ao2_alloc_options(sizeof(struct ast_sip_contact_wrapper),
744 if (!wrapper) {
745 res = -1;
746 break;
747 }
748 wrapper->contact_id = ast_malloc(strlen(aor_id) + strlen(contact->uri) + 2);
749 if (!wrapper->contact_id) {
750 res = -1;
751 break;
752 }
753 sprintf(wrapper->contact_id, "%s/%s", aor_id, contact->uri);
754 wrapper->aor_id = ast_strdup(aor_id);
755 if (!wrapper->aor_id) {
756 res = -1;
757 break;
758 }
759 wrapper->contact = contact;
760 ao2_bump(wrapper->contact);
761
762 if ((res = on_contact(wrapper, arg, 0))) {
763 break;
764 }
765 }
767 ao2_ref(contacts, -1);
768 return res;
769}
770
771int ast_sip_contact_to_str(void *object, void *arg, int flags)
772{
773 struct ast_sip_contact_wrapper *wrapper = object;
774 struct ast_str **buf = arg;
775
776 ast_str_append(buf, 0, "%s,", wrapper->contact_id);
777
778 return 0;
779}
780
781static int sip_aor_to_ami(const struct ast_sip_aor *aor, struct ast_str **buf)
782{
783 struct ast_variable *objset;
784 struct ast_variable *i;
785
788 if (!objset) {
789 return -1;
790 }
791
792 ast_str_append(buf, 0, "ObjectType: %s\r\n",
794 ast_str_append(buf, 0, "ObjectName: %s\r\n",
796
797 for (i = objset; i; i = i->next) {
798 char *camel = ast_to_camel_case(i->name);
799
800 if (strcmp(camel, "Contact") == 0) {
801 ast_free(camel);
802 camel = NULL;
803 }
804 ast_str_append(buf, 0, "%s: %s\r\n", S_OR(camel, "Contacts"), i->value);
805 ast_free(camel);
806 }
807
808 ast_variables_destroy(objset);
809 return 0;
810}
811
812static int contacts_to_str(const void *obj, const intptr_t *args, char **buf)
813{
814 const struct ast_sip_aor *aor = obj;
815 struct ast_str *str;
816
818 if (!str) {
819 *buf = NULL;
820 return -1;
821 }
822
825
827 ast_free(str);
828
829 return *buf ? 0 : -1;
830}
831
832static int format_ami_aor_handler(void *obj, void *arg, int flags)
833{
834 struct ast_sip_aor *aor = obj;
835 struct ast_sip_ami *ami = arg;
836 const struct ast_sip_endpoint *endpoint = ami->arg;
837 struct ast_str *buf;
838 struct ao2_container *contacts;
839 int total_contacts;
840 int num_permanent;
841
842 buf = ast_sip_create_ami_event("AorDetail", ami);
843 if (!buf) {
844 return -1;
845 }
847 if (!contacts) {
848 ast_free(buf);
849 return -1;
850 }
851
852 sip_aor_to_ami(aor, &buf);
853 total_contacts = ao2_container_count(contacts);
854 num_permanent = aor->permanent_contacts ?
856
857 ast_str_append(&buf, 0, "TotalContacts: %d\r\n", total_contacts);
858 ast_str_append(&buf, 0, "ContactsRegistered: %d\r\n",
859 total_contacts - num_permanent);
860 ast_str_append(&buf, 0, "EndpointName: %s\r\n",
861 ast_sorcery_object_get_id(endpoint));
862
863 astman_append(ami->s, "%s\r\n", ast_str_buffer(buf));
864 ami->count++;
865
866 ast_free(buf);
867 ao2_ref(contacts, -1);
868 return 0;
869}
870
871static int format_ami_endpoint_aor(const struct ast_sip_endpoint *endpoint,
872 struct ast_sip_ami *ami)
873{
874 ami->arg = (void *)endpoint;
875 return ast_sip_for_each_aor(endpoint->aors,
877}
878
881};
882
883static struct ao2_container *cli_aor_get_container(const char *regex)
884{
885 struct ao2_container *container;
886 struct ao2_container *s_container;
887
889 if (!container) {
890 return NULL;
891 }
892
893 /* Create a sorted container of aors. */
896 if (s_container
897 && ao2_container_dup(s_container, container, 0)) {
898 ao2_ref(s_container, -1);
899 s_container = NULL;
900 }
901 ao2_ref(container, -1);
902
903 return s_container;
904}
905
906static int cli_contact_populate_container(void *obj, void *arg, int flags)
907{
908 ao2_link(arg, obj);
909
910 return 0;
911}
912
913static int cli_aor_gather_contacts(void *obj, void *arg, int flags)
914{
915 struct ast_sip_aor *aor = obj;
916
918}
919
920static const char *cli_contact_get_id(const void *obj)
921{
922 const struct ast_sip_contact_wrapper *wrapper = obj;
923 return wrapper->contact_id;
924}
925
926static int cli_contact_sort(const void *obj, const void *arg, int flags)
927{
928 const struct ast_sip_contact_wrapper *left_wrapper = obj;
929 const struct ast_sip_contact_wrapper *right_wrapper = arg;
930 const char *right_key = arg;
931 int cmp = 0;
932
933 switch (flags & OBJ_SEARCH_MASK) {
935 right_key = right_wrapper->contact_id;
936 /* Fall through */
937 case OBJ_SEARCH_KEY:
938 cmp = strcmp(left_wrapper->contact_id, right_key);
939 break;
941 cmp = strncmp(left_wrapper->contact_id, right_key, strlen(right_key));
942 break;
943 default:
944 cmp = 0;
945 break;
946 }
947
948 return cmp;
949}
950
951static int cli_contact_compare(void *obj, void *arg, int flags)
952{
953 const struct ast_sip_contact_wrapper *left_wrapper = obj;
954 const struct ast_sip_contact_wrapper *right_wrapper = arg;
955 const char *right_key = arg;
956 int cmp = 0;
957
958 switch (flags & OBJ_SEARCH_MASK) {
960 right_key = right_wrapper->contact_id;
961 /* Fall through */
962 case OBJ_SEARCH_KEY:
963 if (strcmp(left_wrapper->contact_id, right_key) == 0) {;
964 cmp = CMP_MATCH | CMP_STOP;
965 }
966 break;
968 if (strncmp(left_wrapper->contact_id, right_key, strlen(right_key)) == 0) {
969 cmp = CMP_MATCH;
970 }
971 break;
972 default:
973 cmp = 0;
974 break;
975 }
976
977 return cmp;
978}
979
980static int cli_contact_iterate(void *container, ao2_callback_fn callback, void *args)
981{
982 return ast_sip_for_each_contact(container, callback, args);
983}
984
985static int cli_filter_contacts(void *obj, void *arg, int flags)
986{
987 struct ast_sip_contact_wrapper *wrapper = obj;
988 regex_t *regexbuf = arg;
989
990 if (!regexec(regexbuf, wrapper->contact_id, 0, NULL, 0)) {
991 return 0;
992 }
993
994 return CMP_MATCH;
995}
996
997static int cli_gather_contact(void *obj, void *arg, int flags)
998{
999 struct ast_sip_contact *contact = obj;
1000 RAII_VAR(struct ast_sip_contact_wrapper *, wrapper, NULL, ao2_cleanup);
1001
1002 if (strcmp(contact->reg_server, ast_config_AST_SYSTEM_NAME ?: "")) {
1003 return 0;
1004 }
1005
1006 wrapper = ao2_alloc_options(sizeof(struct ast_sip_contact_wrapper),
1008 if (!wrapper) {
1009 return -1;
1010 }
1011
1012 wrapper->contact_id = ast_malloc(strlen(contact->aor) + strlen(contact->uri) + 2);
1013 if (!wrapper->contact_id) {
1014 return -1;
1015 }
1016 sprintf(wrapper->contact_id, "%s/%s", contact->aor, contact->uri);
1017
1018 wrapper->aor_id = ast_strdup(contact->aor);
1019 if (!wrapper->aor_id) {
1020 return -1;
1021 }
1022
1023 wrapper->contact = ao2_bump(contact);
1024
1025 ao2_link(arg, wrapper);
1026
1027 return 0;
1028}
1029
1031{
1032 RAII_VAR(struct ao2_container *, aors, NULL, ao2_cleanup);
1033 RAII_VAR(struct ao2_container *, contacts, NULL, ao2_cleanup);
1034 RAII_VAR(struct ast_variable *, var_aor, NULL, ast_variables_destroy);
1035 struct ao2_container *contacts_container;
1036 regex_t regexbuf;
1037
1038 if (!(var_aor = ast_variable_new("contact !=", "", ""))) {
1039 return NULL;
1040 }
1041
1042 /* Retrieving all the contacts may result in finding the same contact multiple
1043 * times. So that they don't get displayed multiple times we only allow a
1044 * single one to be placed into the container.
1045 */
1048 if (!contacts_container) {
1049 return NULL;
1050 }
1051
1053 if (!contacts) {
1054 ao2_ref(contacts_container, -1);
1055 return NULL;
1056 }
1057 ao2_callback(contacts, OBJ_NODATA, cli_gather_contact, contacts_container);
1058
1060 "aor", AST_RETRIEVE_FLAG_MULTIPLE, var_aor);
1061 if (!aors) {
1062 ao2_ref(contacts_container, -1);
1063 return NULL;
1064 }
1065
1066 ao2_callback(aors, OBJ_NODATA, cli_aor_gather_contacts, contacts_container);
1067
1068 if (!ast_strlen_zero(regex)) {
1069 if (regcomp(&regexbuf, regex, REG_EXTENDED | REG_NOSUB)) {
1070 ao2_ref(contacts_container, -1);
1071 return NULL;
1072 }
1073 ao2_callback(contacts_container, OBJ_UNLINK | OBJ_MULTIPLE | OBJ_NODATA, cli_filter_contacts, &regexbuf);
1074 regfree(&regexbuf);
1075 }
1076
1077 return contacts_container;
1078}
1079
1080static void *cli_contact_retrieve_by_id(const char *id)
1081{
1082 struct ao2_container *container;
1083 void *obj;
1084
1086 if (!container) {
1087 return NULL;
1088 }
1089
1090 obj = ao2_find(container, id, OBJ_SEARCH_KEY);
1091 ao2_ref(container, -1);
1092 return obj;
1093}
1094
1095static int cli_contact_print_header(void *obj, void *arg, int flags)
1096{
1097 struct ast_sip_cli_context *context = arg;
1098 int indent = CLI_INDENT_TO_SPACES(context->indent_level);
1099 int filler = CLI_LAST_TABSTOP - indent - 23;
1100
1101 ast_assert(context->output_buffer != NULL);
1102
1103 ast_str_append(&context->output_buffer, 0,
1104 "%*s: <Aor/ContactUri%*.*s> <Hash....> <Status> <RTT(ms)..>\n",
1105 indent, "Contact", filler, filler, CLI_HEADER_FILLER);
1106
1107 return 0;
1108}
1109
1110static int cli_contact_print_body(void *obj, void *arg, int flags)
1111{
1112 struct ast_sip_contact_wrapper *wrapper = obj;
1113 struct ast_sip_contact *contact = wrapper->contact;
1114 struct ast_sip_cli_context *context = arg;
1115 int indent;
1116 int flexwidth;
1117 const char *contact_id = ast_sorcery_object_get_id(contact);
1118 const char *hash_start = contact_id + strlen(contact->aor) + 2;
1120
1121 ast_assert(contact->uri != NULL);
1122 ast_assert(context->output_buffer != NULL);
1123
1125
1126 indent = CLI_INDENT_TO_SPACES(context->indent_level);
1127 flexwidth = CLI_LAST_TABSTOP - indent - 9 - strlen(contact->aor) + 1;
1128
1129 ast_str_append(&context->output_buffer, 0, "%*s: %s/%-*.*s %-10.10s %-7.7s %11.3f\n",
1130 indent,
1131 "Contact",
1132 contact->aor,
1133 flexwidth, flexwidth,
1134 contact->uri,
1135 hash_start,
1137 (status && (status->status == AVAILABLE)) ? ((long long) status->rtt) / 1000.0 : NAN);
1138
1140 return 0;
1141}
1142
1143static int cli_aor_iterate(void *container, ao2_callback_fn callback, void *args)
1144{
1145 const char *aor_list = container;
1146
1147 return ast_sip_for_each_aor(aor_list, callback, args);
1148}
1149
1150static void *cli_aor_retrieve_by_id(const char *id)
1151{
1153}
1154
1155static const char *cli_aor_get_id(const void *obj)
1156{
1157 return ast_sorcery_object_get_id(obj);
1158}
1159
1160static int cli_aor_print_header(void *obj, void *arg, int flags)
1161{
1162 struct ast_sip_cli_context *context = arg;
1163 int indent = CLI_INDENT_TO_SPACES(context->indent_level);
1164 int filler = CLI_LAST_TABSTOP - indent - 7;
1165
1166 ast_assert(context->output_buffer != NULL);
1167
1168 ast_str_append(&context->output_buffer, 0,
1169 "%*s: <Aor%*.*s> <MaxContact>\n",
1170 indent, "Aor", filler, filler, CLI_HEADER_FILLER);
1171
1172 if (context->recurse) {
1173 struct ast_sip_cli_formatter_entry *formatter_entry;
1174
1175 context->indent_level++;
1176 formatter_entry = ast_sip_lookup_cli_formatter("contact");
1177 if (formatter_entry) {
1178 formatter_entry->print_header(NULL, context, 0);
1179 ao2_ref(formatter_entry, -1);
1180 }
1181 context->indent_level--;
1182 }
1183
1184 return 0;
1185}
1186
1187static int cli_aor_print_body(void *obj, void *arg, int flags)
1188{
1189 struct ast_sip_aor *aor = obj;
1190 struct ast_sip_cli_context *context = arg;
1191 int indent;
1192 int flexwidth;
1193
1194 ast_assert(context->output_buffer != NULL);
1195
1196// context->current_aor = aor;
1197
1198 indent = CLI_INDENT_TO_SPACES(context->indent_level);
1199 flexwidth = CLI_LAST_TABSTOP - indent - 12;
1200
1201 ast_str_append(&context->output_buffer, 0, "%*s: %-*.*s %12u\n",
1202 indent,
1203 "Aor",
1204 flexwidth, flexwidth,
1206
1207 if (context->recurse) {
1208 struct ast_sip_cli_formatter_entry *formatter_entry;
1209
1210 context->indent_level++;
1211
1212 formatter_entry = ast_sip_lookup_cli_formatter("contact");
1213 if (formatter_entry) {
1214 formatter_entry->iterate(aor, formatter_entry->print_body, context);
1215 ao2_ref(formatter_entry, -1);
1216 }
1217
1218 context->indent_level--;
1219
1220 if (context->indent_level == 0) {
1221 ast_str_append(&context->output_buffer, 0, "\n");
1222 }
1223 }
1224
1225 if (context->show_details || (context->show_details_only_level_0 && context->indent_level == 0)) {
1226 ast_str_append(&context->output_buffer, 0, "\n");
1228 }
1229
1230 return 0;
1231}
1232
1233static struct ao2_container *cli_get_aors(void)
1234{
1235 struct ao2_container *aors;
1236
1239
1240 return aors;
1241}
1242
1243static int format_ami_aorlist_handler(void *obj, void *arg, int flags)
1244{
1245 struct ast_sip_aor *aor = obj;
1246 struct ast_sip_ami *ami = arg;
1247 struct ast_str *buf;
1248
1249 buf = ast_sip_create_ami_event("AorList", ami);
1250 if (!buf) {
1251 return -1;
1252 }
1253
1254 sip_aor_to_ami(aor, &buf);
1255
1256 astman_append(ami->s, "%s\r\n", ast_str_buffer(buf));
1257 ami->count++;
1258
1259 ast_free(buf);
1260
1261 return 0;
1262}
1263
1264static int ami_show_aors(struct mansession *s, const struct message *m)
1265{
1266 struct ast_sip_ami ami = { .s = s, .m = m, .action_id = astman_get_header(m, "ActionID"), };
1267 struct ao2_container *aors;
1268
1269 aors = cli_get_aors();
1270 if (!aors) {
1271 astman_send_error(s, m, "Could not get AORs\n");
1272 return 0;
1273 }
1274
1275 if (!ao2_container_count(aors)) {
1276 astman_send_error(s, m, "No AORs found\n");
1277 ao2_ref(aors, -1);
1278 return 0;
1279 }
1280
1281 astman_send_listack(s, m, "A listing of AORs follows, presented as AorList events",
1282 "start");
1283
1285
1286 astman_send_list_complete_start(s, m, "AorListComplete", ami.count);
1288
1289 ao2_ref(aors, -1);
1290
1291 return 0;
1292}
1293
1294static struct ast_cli_entry cli_commands[] = {
1296 .command = "pjsip list aors",
1297 .usage = "Usage: pjsip list aors [ like <pattern> ]\n"
1298 " List the configured PJSIP Aors\n"
1299 " Optional regular expression pattern is used to filter the list.\n"),
1301 .command = "pjsip show aors",
1302 .usage = "Usage: pjsip show aors [ like <pattern> ]\n"
1303 " Show the configured PJSIP Aors\n"
1304 " Optional regular expression pattern is used to filter the list.\n"),
1306 .command = "pjsip show aor",
1307 .usage = "Usage: pjsip show aor <id>\n"
1308 " Show the configured PJSIP Aor\n"),
1309
1310 AST_CLI_DEFINE(ast_sip_cli_traverse_objects, "List PJSIP Contacts",
1311 .command = "pjsip list contacts",
1312 .usage = "Usage: pjsip list contacts [ like <pattern> ]\n"
1313 " List the configured PJSIP contacts\n"
1314 " Optional regular expression pattern is used to filter the list.\n"),
1315 AST_CLI_DEFINE(ast_sip_cli_traverse_objects, "Show PJSIP Contacts",
1316 .command = "pjsip show contacts",
1317 .usage = "Usage: pjsip show contacts [ like <pattern> ]\n"
1318 " Show the configured PJSIP contacts\n"
1319 " Optional regular expression pattern is used to filter the list.\n"),
1320 AST_CLI_DEFINE(ast_sip_cli_traverse_objects, "Show PJSIP Contact",
1321 .command = "pjsip show contact",
1322 .usage = "Usage: pjsip show contact\n"
1323 " Show the configured PJSIP contact\n"),
1324};
1325
1328
1329/*! \brief Always create a contact_status for each contact */
1330static int contact_apply_handler(const struct ast_sorcery *sorcery, void *object)
1331{
1333 struct ast_sip_contact *contact = object;
1334
1335 if (ast_strlen_zero(contact->uri)) {
1336 ast_log(LOG_ERROR, "A URI on dynamic contact '%s' is empty\n",
1337 ast_sorcery_object_get_id(contact));
1338 return -1;
1339 }
1342
1343 return status ? 0 : -1;
1344}
1345
1346static int aor_apply_outbound_proxy(void *obj, void *arg, int flags)
1347{
1348 struct ast_sip_contact *contact = obj;
1349 struct ast_sip_aor *aor = arg;
1350
1352
1353 return 0;
1354}
1355
1356static int aor_apply_handler(const struct ast_sorcery *sorcery, void *object)
1357{
1358 struct ast_sip_aor *aor = object;
1359
1361 return 0;
1362 }
1363
1365
1366 return 0;
1367}
1368
1369/*! \brief Initialize sorcery with location support */
1371{
1373 int i;
1374
1375 ast_pjproject_get_buildopt("PJ_MAX_HOSTNAME", "%d", &pj_max_hostname);
1376 /* As of pjproject 2.4.5, PJSIP_MAX_URL_SIZE isn't exposed yet but we try anyway. */
1377 ast_pjproject_get_buildopt("PJSIP_MAX_URL_SIZE", "%d", &pjsip_max_url_size);
1378
1379 ast_sorcery_apply_default(sorcery, "contact", "astdb", "registrar");
1382 ast_sorcery_apply_default(sorcery, "aor", "config", "pjsip.conf,criteria=type=aor");
1383
1386 return -1;
1387 }
1388
1390
1391 ast_sorcery_object_field_register(sorcery, "contact", "type", "", OPT_NOOP_T, 0, 0);
1393 ast_sorcery_object_field_register(sorcery, "contact", "path", "", OPT_STRINGFIELD_T, 0, STRFLDSET(struct ast_sip_contact, path));
1395 ast_sorcery_object_field_register(sorcery, "contact", "qualify_frequency", 0, OPT_UINT_T,
1396 PARSE_IN_RANGE, FLDSET(struct ast_sip_contact, qualify_frequency), 0, 86400);
1397 ast_sorcery_object_field_register(sorcery, "contact", "qualify_timeout", "3.0", OPT_DOUBLE_T, 0, FLDSET(struct ast_sip_contact, qualify_timeout));
1398 ast_sorcery_object_field_register(sorcery, "contact", "qualify_2xx_only", "no", OPT_BOOL_T, 1, FLDSET(struct ast_sip_contact, qualify_2xx_only));
1399 ast_sorcery_object_field_register(sorcery, "contact", "authenticate_qualify", "no", OPT_YESNO_T, 1, FLDSET(struct ast_sip_contact, authenticate_qualify));
1400 ast_sorcery_object_field_register(sorcery, "contact", "outbound_proxy", "", OPT_STRINGFIELD_T, 0, STRFLDSET(struct ast_sip_contact, outbound_proxy));
1401 ast_sorcery_object_field_register(sorcery, "contact", "user_agent", "", OPT_STRINGFIELD_T, 0, STRFLDSET(struct ast_sip_contact, user_agent));
1402 ast_sorcery_object_field_register(sorcery, "contact", "endpoint", "", OPT_STRINGFIELD_T, 0, STRFLDSET(struct ast_sip_contact, endpoint_name));
1403 ast_sorcery_object_field_register(sorcery, "contact", "reg_server", "", OPT_STRINGFIELD_T, 0, STRFLDSET(struct ast_sip_contact, reg_server));
1404 ast_sorcery_object_field_register(sorcery, "contact", "via_addr", "", OPT_STRINGFIELD_T, 0, STRFLDSET(struct ast_sip_contact, via_addr));
1405 ast_sorcery_object_field_register(sorcery, "contact", "via_port", "0", OPT_UINT_T, 0, FLDSET(struct ast_sip_contact, via_port));
1406 ast_sorcery_object_field_register(sorcery, "contact", "call_id", "", OPT_STRINGFIELD_T, 0, STRFLDSET(struct ast_sip_contact, call_id));
1407 ast_sorcery_object_field_register(sorcery, "contact", "prune_on_boot", "no", OPT_YESNO_T, 1, FLDSET(struct ast_sip_contact, prune_on_boot));
1408
1409 ast_sorcery_object_field_register(sorcery, "aor", "type", "", OPT_NOOP_T, 0, 0);
1410 ast_sorcery_object_field_register(sorcery, "aor", "minimum_expiration", "60", OPT_UINT_T, 0, FLDSET(struct ast_sip_aor, minimum_expiration));
1411 ast_sorcery_object_field_register(sorcery, "aor", "maximum_expiration", "7200", OPT_UINT_T, 0, FLDSET(struct ast_sip_aor, maximum_expiration));
1412 ast_sorcery_object_field_register(sorcery, "aor", "default_expiration", "3600", OPT_UINT_T, 0, FLDSET(struct ast_sip_aor, default_expiration));
1413 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);
1414 ast_sorcery_object_field_register(sorcery, "aor", "qualify_timeout", "3.0", OPT_DOUBLE_T, 0, FLDSET(struct ast_sip_aor, qualify_timeout));
1415 ast_sorcery_object_field_register(sorcery, "aor", "qualify_2xx_only", "no", OPT_BOOL_T, 1, FLDSET(struct ast_sip_aor, qualify_2xx_only));
1416 ast_sorcery_object_field_register(sorcery, "aor", "authenticate_qualify", "no", OPT_BOOL_T, 1, FLDSET(struct ast_sip_aor, authenticate_qualify));
1417 ast_sorcery_object_field_register(sorcery, "aor", "max_contacts", "0", OPT_UINT_T, 0, FLDSET(struct ast_sip_aor, max_contacts));
1418 ast_sorcery_object_field_register(sorcery, "aor", "remove_existing", "no", OPT_BOOL_T, 1, FLDSET(struct ast_sip_aor, remove_existing));
1419 ast_sorcery_object_field_register(sorcery, "aor", "remove_unavailable", "no", OPT_BOOL_T, 1, FLDSET(struct ast_sip_aor, remove_unavailable));
1423 ast_sorcery_object_field_register(sorcery, "aor", "outbound_proxy", "", OPT_STRINGFIELD_T, 0, STRFLDSET(struct ast_sip_aor, outbound_proxy));
1424 ast_sorcery_object_field_register(sorcery, "aor", "support_path", "no", OPT_BOOL_T, 1, FLDSET(struct ast_sip_aor, support_path));
1425
1427
1429 if (!contact_formatter) {
1430 ast_log(LOG_ERROR, "Unable to allocate memory for contact_formatter\n");
1431 return -1;
1432 }
1433 contact_formatter->name = "contact";
1440
1442 if (!aor_formatter) {
1443 ast_log(LOG_ERROR, "Unable to allocate memory for aor_formatter\n");
1444 return -1;
1445 }
1446 aor_formatter->name = "aor";
1453
1457
1459 return -1;
1460 }
1461
1462 /*
1463 * Reset StatsD gauges in case we didn't shut down cleanly.
1464 * Note that this must done here, as contacts will create the contact_status
1465 * object before PJSIP options handling is initialized.
1466 */
1467 for (i = 0; i <= REMOVED; i++) {
1468 ast_statsd_log_full_va("PJSIP.contacts.states.%s", AST_STATSD_GAUGE, 0, 1.0, ast_sip_get_contact_status_label(i));
1469 }
1470
1471 return 0;
1472}
1473
1475{
1480 ast_manager_unregister("PJSIPShowAors");
1481
1483
1484 return 0;
1485}
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:1667
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:2011
void astman_send_error(struct mansession *s, const struct message *m, char *error)
Send error in manager transaction.
Definition: manager.c:1969
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:2047
const char * astman_get_header(const struct message *m, char *var)
Get header from manager transaction.
Definition: manager.c:1630
void astman_send_list_complete_end(struct mansession *s)
End the list complete event.
Definition: manager.c:2055
void astman_append(struct mansession *s, const char *fmt,...)
Definition: manager.c:1890
int ast_manager_unregister(const char *action)
Unregister a registered manager command.
Definition: manager.c:7608
#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:1330
int ast_sip_validate_uri_length(const char *contact_uri)
Definition: location.c:529
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:483
static struct ast_cli_entry cli_commands[]
Definition: location.c:1294
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:430
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:1187
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:661
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:714
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:1346
static int contact_to_var_list(void *object, void *arg, int flags)
Definition: location.c:651
static int format_ami_aorlist_handler(void *obj, void *arg, int flags)
Definition: location.c:1243
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:723
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:688
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:1233
static int format_ami_aor_handler(void *obj, void *arg, int flags)
Definition: location.c:832
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:871
static int cli_contact_iterate(void *container, ao2_callback_fn callback, void *args)
Definition: location.c:980
static int cli_filter_contacts(void *obj, void *arg, int flags)
Definition: location.c:985
static int voicemail_extension_to_str(const void *obj, const intptr_t *args, char **buf)
Definition: location.c:679
struct ast_sip_cli_formatter_entry * contact_formatter
Definition: location.c:1326
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:490
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:1327
static int cli_gather_contact(void *obj, void *arg, int flags)
Definition: location.c:997
static int prune_boot_contacts_cb(void *obj, void *arg, int flags)
Definition: location.c:456
static int cli_contact_compare(void *obj, void *arg, int flags)
Definition: location.c:951
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:920
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:593
static int permanent_uri_sort_fn(const void *obj_left, const void *obj_right, int flags)
Definition: location.c:499
static int voicemail_extension_handler(const struct aco_option *opt, struct ast_variable *var, void *obj)
Definition: location.c:670
static void * cli_contact_retrieve_by_id(const char *id)
Definition: location.c:1080
static int sip_aor_to_ami(const struct ast_sip_aor *aor, struct ast_str **buf)
Definition: location.c:781
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:812
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:1160
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:1030
static const char * cli_aor_get_id(const void *obj)
Definition: location.c:1155
int ast_sip_initialize_sorcery_location(void)
Initialize sorcery with location support.
Definition: location.c:1370
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:883
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:879
int ast_sip_destroy_sorcery_location(void)
Definition: location.c:1474
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:1150
static int cli_contact_print_header(void *obj, void *arg, int flags)
Definition: location.c:1095
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:446
static int cli_contact_populate_container(void *obj, void *arg, int flags)
Definition: location.c:906
static int aor_apply_handler(const struct ast_sorcery *sorcery, void *object)
Definition: location.c:1356
static int cli_contact_sort(const void *obj, const void *arg, int flags)
Definition: location.c:926
static int cli_contact_print_body(void *obj, void *arg, int flags)
Definition: location.c:1110
int ast_sip_contact_to_str(void *object, void *arg, int flags)
Handler used to convert a contact to a string.
Definition: location.c:771
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:1143
void ast_sip_location_prune_boot_contacts(void)
Prune the prune_on_boot contacts.
Definition: location.c:470
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:913
int ast_sip_location_delete_contact(struct ast_sip_contact *contact)
Delete a contact.
Definition: location.c:451
static int ami_show_aors(struct mansession *s, const struct message *m)
Definition: location.c:1264
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:417
#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:1309
@ AST_SIP_CONTACT_FILTER_DEFAULT
Default filter flags.
Definition: res_pjsip.h:1306
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:437
@ UNAVAILABLE
Definition: res_pjsip.h:435
@ REMOVED
Definition: res_pjsip.h:442
@ UNKNOWN
Definition: res_pjsip.h:439
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:2317
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:2423
@ 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:2329
int ast_sorcery_create(const struct ast_sorcery *sorcery, void *object)
Create and potentially persist an object using an available wizard.
Definition: sorcery.c:2062
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:1954
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:2391
#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:2464
#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:2440
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:2150
@ 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:2238
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:1989
#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:3050
struct mansession * s
Definition: res_pjsip.h:3052
void * arg
Definition: res_pjsip.h:3058
const struct message * m
Definition: res_pjsip.h:3054
A SIP address of record.
Definition: res_pjsip.h:477
char * voicemail_extension
Definition: res_pjsip.h:507
unsigned int max_contacts
Definition: res_pjsip.h:497
struct ao2_container * permanent_contacts
Definition: res_pjsip.h:501
const ast_string_field outbound_proxy
Definition: res_pjsip.h:485
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:450
const ast_string_field uri
Definition: res_pjsip.h:456
const ast_string_field aor
Definition: res_pjsip.h:456
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:518
struct ast_sip_contact * contact
Definition: res_pjsip.h:524
Contact associated with an address of record.
Definition: res_pjsip.h:389
const ast_string_field uri
Definition: res_pjsip.h:411
double qualify_timeout
Definition: res_pjsip.h:419
struct ast_sip_endpoint * endpoint
Definition: res_pjsip.h:421
const ast_string_field via_addr
Definition: res_pjsip.h:411
int qualify_2xx_only
Definition: res_pjsip.h:427
const ast_string_field call_id
Definition: res_pjsip.h:411
const ast_string_field aor
Definition: res_pjsip.h:411
const ast_string_field outbound_proxy
Definition: res_pjsip.h:411
struct timeval expiration_time
Definition: res_pjsip.h:413
const ast_string_field path
Definition: res_pjsip.h:411
const ast_string_field endpoint_name
Definition: res_pjsip.h:411
int authenticate_qualify
Definition: res_pjsip.h:417
const ast_string_field reg_server
Definition: res_pjsip.h:411
const ast_string_field user_agent
Definition: res_pjsip.h:411
unsigned int qualify_frequency
Definition: res_pjsip.h:415
An entity responsible formatting endpoint information.
Definition: res_pjsip.h:3076
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:3080
An entity with which Asterisk communicates.
Definition: res_pjsip.h:962
const ast_string_field aors
Definition: res_pjsip.h:991
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:326
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