Asterisk - The Open Source Telephony Project  GIT-master-a24979a
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"
28 #include "asterisk/taskprocessor.h"
30 #include "asterisk/res_pjsip_cli.h"
31 #include "asterisk/statsd.h"
32 #include "asterisk/named_locks.h"
33 
34 #include "asterisk/res_pjproject.h"
35 
36 static int pj_max_hostname = PJ_MAX_HOSTNAME;
37 static int pjsip_max_url_size = PJSIP_MAX_URL_SIZE;
38 
39 /*! \brief Destructor for AOR */
40 static void aor_destroy(void *obj)
41 {
42  struct ast_sip_aor *aor = obj;
43 
47 }
48 
49 /*! \brief Allocator for AOR */
50 static 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 */
72 static 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 
81 static 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 */
105 static const struct ast_sorcery_observer aor_observer = {
107 };
108 
109 
110 /*! \brief Destructor for contact */
111 static 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 */
120 static void *contact_alloc(const char *name)
121 {
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)) {
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 
143 
144  return contact;
145 }
146 
147 struct 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 */
153 static 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 */
168 static 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 */
177 static 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 
240  if (flags & AST_SIP_CONTACT_FILTER_REACHABLE) {
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 
266 void ast_sip_location_retrieve_contact_and_aor_from_list(const char *aor_list, struct ast_sip_aor **aor,
267  struct ast_sip_contact **contact)
268 {
270 }
271 
272 void 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 
311  ao2_cleanup(aor);
312 
313  return contact;
314 }
315 
316 static int permanent_uri_sort_fn(const void *obj_left, const void *obj_right, int flags);
317 static int cli_contact_populate_container(void *obj, void *arg, int flags);
318 
319 static 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 
345  ast_sip_for_each_aor(aor_list, gather_contacts_for_aor, contacts);
346 
347  return contacts;
348 }
349 
350 struct 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 
368  if (!contact) {
369  return NULL;
370  }
371 
373  contact->expiration_time = expiration_time;
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 
385  if (!ast_strlen_zero(user_agent)) {
387  }
388 
391  }
392 
393  if (!ast_strlen_zero(via_addr)) {
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 
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,
419  struct ast_sip_endpoint *endpoint)
420 {
421  struct ast_sip_contact *contact;
422 
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,
432  struct ast_sip_endpoint *endpoint)
433 {
434  int res;
435 
436  ao2_lock(aor);
439  endpoint);
440  ao2_unlock(aor);
441 
442  return res;
443 }
444 
446 {
448 }
449 
451 {
453 }
454 
455 static 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 
473  contacts = ast_sorcery_retrieve_by_fields(ast_sip_get_sorcery(), "contact",
475  if (contacts) {
477  ao2_ref(contacts, -1);
478  }
479 }
480 
481 /*! \brief Custom handler for translating from a string timeval to actual structure */
482 static 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 */
489 static 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 
498 static 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) {
506  case OBJ_SEARCH_OBJECT:
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 
528 int 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 */
592 static 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 
650 static 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 
660 static 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 
669 static 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 
678 static 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 
687 int 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 
713 static 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 
722 int ast_sip_for_each_contact(const struct ast_sip_aor *aor,
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);
738  RAII_VAR(struct ast_sip_contact_wrapper *, wrapper, NULL, 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 
770 int 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 
780 static 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 
811 static 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 
823  ast_str_truncate(str, -1);
824 
826  ast_free(str);
827 
828  return *buf ? 0 : -1;
829 }
830 
831 static 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 
870 static 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 
882 static 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 
905 static int cli_contact_populate_container(void *obj, void *arg, int flags)
906 {
907  ao2_link(arg, obj);
908 
909  return 0;
910 }
911 
912 static int cli_aor_gather_contacts(void *obj, void *arg, int flags)
913 {
914  struct ast_sip_aor *aor = obj;
915 
917 }
918 
919 static 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 
925 static 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) {
933  case OBJ_SEARCH_OBJECT:
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 
950 static 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) {
958  case OBJ_SEARCH_OBJECT:
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 
979 static 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 
984 static 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 
996 static int cli_gather_contact(void *obj, void *arg, int flags)
997 {
998  struct ast_sip_contact *contact = obj;
999  RAII_VAR(struct ast_sip_contact_wrapper *, wrapper, NULL, ao2_cleanup);
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 
1029 static struct ao2_container *cli_contact_get_container(const char *regex)
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 
1051  contacts = ast_sorcery_retrieve_by_regex(ast_sip_get_sorcery(), "contact", regex);
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 
1079 static 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 
1094 static 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 
1109 static 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 
1142 static 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 
1149 static void *cli_aor_retrieve_by_id(const char *id)
1150 {
1151  return ast_sorcery_retrieve_by_id(ast_sip_get_sorcery(), "aor", id);
1152 }
1153 
1154 static const char *cli_aor_get_id(const void *obj)
1155 {
1156  return ast_sorcery_object_get_id(obj);
1157 }
1158 
1159 static 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 
1186 static 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 
1232 static struct ao2_container *cli_get_aors(void)
1233 {
1234  struct ao2_container *aors;
1235 
1238 
1239  return aors;
1240 }
1241 
1242 static 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 
1263 static 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 
1293 static struct ast_cli_entry cli_commands[] = {
1294  AST_CLI_DEFINE(ast_sip_cli_traverse_objects, "List PJSIP Aors",
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"),
1299  AST_CLI_DEFINE(ast_sip_cli_traverse_objects, "Show PJSIP Aors",
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"),
1304  AST_CLI_DEFINE(ast_sip_cli_traverse_objects, "Show PJSIP Aor",
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 */
1329 static 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",
1337  return -1;
1338  }
1341 
1342  return status ? 0 : -1;
1343 }
1344 
1345 static 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 
1355 static int aor_apply_handler(const struct ast_sorcery *sorcery, void *object)
1356 {
1357  struct ast_sip_aor *aor = object;
1358 
1359  if (!aor->permanent_contacts || ast_strlen_zero(aor->outbound_proxy)) {
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);
1391  ast_sorcery_object_field_register(sorcery, "contact", "uri", "", OPT_STRINGFIELD_T, 0, STRFLDSET(struct ast_sip_contact, uri));
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 
1455  if (ast_manager_register_xml("PJSIPShowAors", EVENT_FLAG_SYSTEM, ami_show_aors)) {
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
ast_mutex_t lock
Definition: app_meetme.c:1093
enum queue_result id
Definition: app_queue.c:1640
static int copy(char *infile, char *outfile)
Utility function to copy a file.
#define var
Definition: ast_expr2f.c:614
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
static char context[AST_MAX_CONTEXT]
Definition: chan_alsa.c:120
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:3208
void astman_send_error(struct mansession *s, const struct message *m, char *error)
Send error in manager transaction.
Definition: manager.c:3166
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:3244
void astman_send_list_complete_end(struct mansession *s)
End the list complete event.
Definition: manager.c:3252
void astman_append(struct mansession *s, const char *fmt,...)
Definition: manager.c:3087
const char * astman_get_header(const struct message *m, char *var)
Get header from manager transaction.
Definition: manager.c:2827
int ast_manager_unregister(const char *action)
Unregister a registered manager command.
Definition: manager.c:7268
#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
char * strsep(char **str, const char *delims)
#define NAN
#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
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
static struct ao2_container * cli_get_aors(void)
Definition: location.c:1232
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 ao2_container * cli_aor_get_container(const char *regex)
Definition: location.c:882
static struct ast_cli_entry cli_commands[]
Definition: location.c:1293
static void * aor_alloc(const char *name)
Allocator for AOR.
Definition: location.c:50
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
static void contact_wrapper_destroy(void *obj)
Definition: location.c:713
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
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 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
struct ast_sip_aor * ast_sip_location_retrieve_aor(const char *aor_name)
Retrieve a named AOR.
Definition: location.c:147
struct ast_sip_contact * ast_sip_location_retrieve_contact(const char *contact_name)
Retrieve a named contact.
Definition: location.c:350
static void * contact_alloc(const char *name)
Allocator for contact.
Definition: location.c:120
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
static int format_ami_aor_handler(void *obj, void *arg, int flags)
Definition: location.c:831
static struct ao2_container * cli_contact_get_container(const char *regex)
Definition: location.c:1029
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
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 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_aor_get_id(const void *obj)
Definition: location.c:1154
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 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 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_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
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 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
static void * cli_contact_retrieve_by_id(const char *id)
Definition: location.c:1079
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
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
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
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
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
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
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 const char * cli_contact_get_id(const void *obj)
Definition: location.c:919
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
static void * cli_aor_retrieve_by_id(const char *id)
Definition: location.c:1149
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
static int destroy_contact(void *obj, void *arg, int flags)
Internal callback function which destroys the specified contact.
Definition: location.c:72
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.
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_short_status_label(const enum ast_sip_contact_status_type status)
struct ast_sorcery * ast_sip_get_sorcery(void)
Get a pointer to the SIP sorcery structure.
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.
@ AST_SIP_CONTACT_FILTER_REACHABLE
Return only reachable or unknown contacts.
Definition: res_pjsip.h:1089
@ AST_SIP_CONTACT_FILTER_DEFAULT
Default filter flags.
Definition: res_pjsip.h:1086
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.
void ast_sip_register_endpoint_formatter(struct ast_sip_endpoint_formatter *obj)
Register an endpoint formatter.
Definition: res_pjsip.c:474
void ast_sip_unregister_endpoint_formatter(struct ast_sip_endpoint_formatter *obj)
Unregister an endpoint formatter.
Definition: res_pjsip.c:480
@ AVAILABLE
Definition: res_pjsip.h:343
@ UNAVAILABLE
Definition: res_pjsip.h:341
@ REMOVED
Definition: res_pjsip.h:348
@ UNKNOWN
Definition: res_pjsip.h:345
int ast_sip_unregister_cli_formatter(struct ast_sip_cli_formatter_entry *formatter)
Unregisters a CLI formatter.
Definition: pjsip_cli.c:326
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_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
#define CLI_LAST_TABSTOP
Definition: res_pjsip_cli.h:27
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_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.
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
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
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
void * ast_sorcery_generic_alloc(size_t size, ao2_destructor_fn destructor)
Allocate a generic sorcery capable object.
Definition: sorcery.c:1728
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_create(const struct ast_sorcery *sorcery, void *object)
Create and potentially persist an object using an available wizard.
Definition: sorcery.c:2057
#define ast_sorcery_object_register(sorcery, type, alloc, transform, apply)
Register an object type.
Definition: sorcery.h:837
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
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
int ast_sorcery_object_id_compare(void *obj, void *arg, int flags)
ao2 object comparator based on sorcery id.
Definition: sorcery.c:2459
const char * ast_sorcery_object_get_id(const void *object)
Get the unique identifier of a sorcery object.
Definition: sorcery.c:2312
#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_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_id_sort(const void *obj, const void *arg, int flags)
ao2 object sorter based on sorcery id.
Definition: sorcery.c:2435
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
const char * ast_sorcery_object_get_type(const void *object)
Get the type of a sorcery object.
Definition: sorcery.c:2324
#define MAX_OBJECT_FIELD
Maximum length of an object field name.
Definition: sorcery.h:110
void * ast_sorcery_alloc(const struct ast_sorcery *sorcery, const char *type, const char *id)
Allocate an object.
Definition: sorcery.c:1744
#define ast_sorcery_apply_default(sorcery, type, name, data)
Definition: sorcery.h:476
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 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
#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:764
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:1117
char * ast_str_buffer(const struct ast_str *buf)
Returns the string buffer within the ast_str buf.
Definition: strings.h:739
#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
#define ast_str_create(init_len)
Create a malloc'ed dynamic length string.
Definition: strings.h:640
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:527
char * ast_strip_quoted(char *s, const char *beg_quotes, const char *end_quotes)
Strip leading/trailing whitespace and quotes from a string.
Definition: main/utils.c:1785
int ast_get_timeval(const char *src, struct timeval *tv, struct timeval _default, int *consumed)
Parse a time (float) string.
Definition: main/utils.c:2317
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:2819
struct mansession * s
Definition: res_pjsip.h:2821
void * arg
Definition: res_pjsip.h:2827
const struct message * m
Definition: res_pjsip.h:2823
A SIP address of record.
Definition: res_pjsip.h:376
char * voicemail_extension
Definition: res_pjsip.h:406
unsigned int max_contacts
Definition: res_pjsip.h:396
struct ao2_container * permanent_contacts
Definition: res_pjsip.h:400
const ast_string_field outbound_proxy
Definition: res_pjsip.h:384
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
const char *(* get_id)(const void *obj)
Definition: res_pjsip_cli.h:70
struct ao2_container *(* get_container)(const char *regex)
Definition: res_pjsip_cli.h:64
void *(* retrieve_by_id)(const char *id)
Definition: res_pjsip_cli.h:68
const char * name
Definition: res_pjsip_cli.h:58
ao2_callback_fn * print_body
Definition: res_pjsip_cli.h:62
A contact's status.
Definition: res_pjsip.h:356
const ast_string_field uri
Definition: res_pjsip.h:362
const ast_string_field aor
Definition: res_pjsip.h:362
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:415
struct ast_sip_contact * contact
Definition: res_pjsip.h:421
Contact associated with an address of record.
Definition: res_pjsip.h:297
const ast_string_field uri
Definition: res_pjsip.h:319
struct ast_sip_endpoint * endpoint
Definition: res_pjsip.h:329
const ast_string_field via_addr
Definition: res_pjsip.h:319
const ast_string_field call_id
Definition: res_pjsip.h:319
const ast_string_field aor
Definition: res_pjsip.h:319
const ast_string_field outbound_proxy
Definition: res_pjsip.h:319
struct timeval expiration_time
Definition: res_pjsip.h:321
const ast_string_field path
Definition: res_pjsip.h:319
const ast_string_field endpoint_name
Definition: res_pjsip.h:319
const ast_string_field reg_server
Definition: res_pjsip.h:319
const ast_string_field user_agent
Definition: res_pjsip.h:319
An entity responsible formatting endpoint information.
Definition: res_pjsip.h:2845
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:2849
An entity with which Asterisk communicates.
Definition: res_pjsip.h:854
const ast_string_field aors
Definition: res_pjsip.h:883
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:604
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:1632
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:43
int64_t ast_tvdiff_ms(struct timeval end, struct timeval start)
Computes the difference (in milliseconds) between two struct timeval instances.
Definition: time.h:105
struct timeval ast_tvnow(void)
Returns current timeval. Meant to replace calls to gettimeofday().
Definition: time.h:157
struct timeval ast_tv(ast_time_t sec, ast_suseconds_t usec)
Returns a timeval from sec, usec.
Definition: time.h:233
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:936
#define ast_assert(a)
Definition: utils.h:734
#define ARRAY_LEN(a)
Definition: utils.h:661
void ast_md5_hash(char *output, const char *input)
Produces MD5 hash based on input string.
Definition: main/utils.c:250