Asterisk - The Open Source Telephony Project  18.5.0
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 <[email protected]>
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 
55  lock = ast_named_lock_get(AST_NAMED_LOCK_TYPE_MUTEX, "aor", name);
56  if (!lock) {
57  return NULL;
58  }
59 
60  aor = ast_sorcery_lockable_alloc(sizeof(struct ast_sip_aor), aor_destroy, lock);
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)) {
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 
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 
183  status = ast_sip_get_contact_status(contact);
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 
309  ast_sip_location_retrieve_contact_and_aor_from_list(aor_list, &aor, &contact);
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 
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);
373  contact->expiration_time = expiration_time;
374  contact->qualify_frequency = aor->qualify_frequency;
375  contact->qualify_timeout = aor->qualify_timeout;
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)) {
383  }
384 
385  if (!ast_strlen_zero(user_agent)) {
386  ast_string_field_set(contact, user_agent, user_agent);
387  }
388 
391  }
392 
393  if (!ast_strlen_zero(via_addr)) {
394  ast_string_field_set(contact, via_addr, via_addr);
395  }
396  contact->via_port = via_port;
397 
398  if (!ast_strlen_zero(call_id)) {
399  ast_string_field_set(contact, call_id, call_id);
400  }
401 
402  contact->endpoint = ao2_bump(endpoint);
403  if (endpoint) {
405  }
406 
407  contact->prune_on_boot = prune_on_boot;
408 
409  if (ast_sorcery_create(ast_sip_get_sorcery(), contact)) {
410  ao2_ref(contact, -1);
411  return NULL;
412  }
413  return contact;
414 }
415 
417  struct timeval expiration_time, const char *path_info, const char *user_agent,
418  const char *via_addr, int via_port, const char *call_id,
419  struct ast_sip_endpoint *endpoint)
420 {
421  struct ast_sip_contact *contact;
422 
423  contact = ast_sip_location_create_contact(aor, uri, expiration_time, path_info,
424  user_agent, via_addr, via_port, call_id, 0, endpoint);
425  ao2_cleanup(contact);
426  return contact ? 0 : -1;
427 }
428 
430  struct timeval expiration_time, const char *path_info, const char *user_agent,
431  const char *via_addr, int via_port, const char *call_id,
432  struct ast_sip_endpoint *endpoint)
433 {
434  int res;
435 
436  ao2_lock(aor);
437  res = ast_sip_location_add_contact_nolock(aor, uri, expiration_time, path_info, user_agent,
438  via_addr, via_port, call_id,
439  endpoint);
440  ao2_unlock(aor);
441 
442  return res;
443 }
444 
446 {
447  return ast_sorcery_update(ast_sip_get_sorcery(), contact);
448 }
449 
451 {
452  return ast_sorcery_delete(ast_sip_get_sorcery(), contact);
453 }
454 
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  return (ast_asprintf(buf, "%ld", contact->expiration_time.tv_sec) < 0) ? -1 : 0;
493 }
494 
495 static int permanent_uri_sort_fn(const void *obj_left, const void *obj_right, int flags)
496 {
497  const struct ast_sip_contact *object_left = obj_left;
498  const struct ast_sip_contact *object_right = obj_right;
499  const char *right_key = obj_right;
500  int cmp;
501 
502  switch (flags & OBJ_SEARCH_MASK) {
503  case OBJ_SEARCH_OBJECT:
504  right_key = ast_sorcery_object_get_id(object_right);
505  /* Fall through */
506  case OBJ_SEARCH_KEY:
507  cmp = strcmp(ast_sorcery_object_get_id(object_left), right_key);
508  break;
510  /*
511  * We could also use a partial key struct containing a length
512  * so strlen() does not get called for every comparison instead.
513  */
514  cmp = strncmp(ast_sorcery_object_get_id(object_left), right_key, strlen(right_key));
515  break;
516  default:
517  /* Sort can only work on something with a full or partial key. */
518  ast_assert(0);
519  cmp = 0;
520  break;
521  }
522  return cmp;
523 }
524 
525 int ast_sip_validate_uri_length(const char *contact_uri)
526 {
527  int max_length = pj_max_hostname - 1;
528  char *contact = ast_strdupa(contact_uri);
529  char *host;
530  char *at;
531  int theres_a_port = 0;
532 
533  if (strlen(contact_uri) > pjsip_max_url_size - 1) {
534  return -1;
535  }
536 
537  contact = ast_strip_quoted(contact, "<", ">");
538 
539  if (!strncasecmp(contact, "sip:", 4)) {
540  host = contact + 4;
541  } else if (!strncasecmp(contact, "sips:", 5)) {
542  host = contact + 5;
543  } else {
544  /* Not a SIP URI */
545  return -1;
546  }
547 
548  at = strchr(contact, '@');
549  if (at) {
550  /* sip[s]:user@host */
551  host = at + 1;
552  }
553 
554  if (host[0] == '[') {
555  /* Host is an IPv6 address. Just get up to the matching bracket */
556  char *close_bracket;
557 
558  close_bracket = strchr(host, ']');
559  if (!close_bracket) {
560  return -1;
561  }
562  close_bracket++;
563  if (*close_bracket == ':') {
564  theres_a_port = 1;
565  }
566  *close_bracket = '\0';
567  } else {
568  /* uri parameters could contain ';' so trim them off first */
569  host = strsep(&host, ";?");
570  /* Host is FQDN or IPv4 address. Need to find closing delimiter */
571  if (strchr(host, ':')) {
572  theres_a_port = 1;
573  host = strsep(&host, ":");
574  }
575  }
576 
577  if (!theres_a_port) {
578  max_length -= strlen("_sips.tcp.");
579  }
580 
581  if (strlen(host) > max_length) {
582  return -1;
583  }
584 
585  return 0;
586 }
587 
588 /*! \brief Custom handler for permanent URIs */
589 static int permanent_uri_handler(const struct aco_option *opt, struct ast_variable *var, void *obj)
590 {
591  struct ast_sip_aor *aor = obj;
592  const char *aor_id = ast_sorcery_object_get_id(aor);
593  char *contacts;
594  char *contact_uri;
595 
596  if (ast_strlen_zero(var->value)) {
597  return 0;
598  }
599 
600  contacts = ast_strdupa(var->value);
601  while ((contact_uri = ast_strip(strsep(&contacts, ",")))) {
602  struct ast_sip_contact *contact;
604  char hash[33];
605  char contact_id[strlen(aor_id) + sizeof(hash) + 2];
606 
607  if (ast_strlen_zero(contact_uri)) {
608  continue;
609  }
610 
611  if (ast_sip_validate_uri_length(contact_uri)) {
612  ast_log(LOG_ERROR, "Contact uri or hostname length exceeds pjproject limit or is not a sip(s) uri: %s\n", contact_uri);
613  return -1;
614  }
615 
616  if (!aor->permanent_contacts) {
619  if (!aor->permanent_contacts) {
620  return -1;
621  }
622  }
623 
624  ast_md5_hash(hash, contact_uri);
625  snprintf(contact_id, sizeof(contact_id), "%s@@%s", aor_id, hash);
626  contact = ast_sorcery_alloc(ast_sip_get_sorcery(), "contact", contact_id);
627  if (!contact) {
628  return -1;
629  }
630 
631  ast_string_field_set(contact, uri, contact_uri);
632 
634  if (!status) {
635  ao2_ref(contact, -1);
636  return -1;
637  }
638  ao2_ref(status, -1);
639 
640  ao2_link(aor->permanent_contacts, contact);
641  ao2_ref(contact, -1);
642  }
643 
644  return 0;
645 }
646 
647 static int contact_to_var_list(void *object, void *arg, int flags)
648 {
649  struct ast_sip_contact_wrapper *wrapper = object;
650  struct ast_variable **var = arg;
651 
652  ast_variable_list_append(&*var, ast_variable_new("contact", wrapper->contact->uri, ""));
653 
654  return 0;
655 }
656 
657 static int contacts_to_var_list(const void *obj, struct ast_variable **fields)
658 {
659  const struct ast_sip_aor *aor = obj;
660 
662 
663  return 0;
664 }
665 
666 static int voicemail_extension_handler(const struct aco_option *opt, struct ast_variable *var, void *obj)
667 {
668  struct ast_sip_aor *aor = obj;
669 
670  aor->voicemail_extension = ast_strdup(var->value);
671 
672  return aor->voicemail_extension ? 0 : -1;
673 }
674 
675 static int voicemail_extension_to_str(const void *obj, const intptr_t *args, char **buf)
676 {
677  const struct ast_sip_aor *aor = obj;
678 
679  *buf = ast_strdup(aor->voicemail_extension);
680 
681  return 0;
682 }
683 
684 int ast_sip_for_each_aor(const char *aors, ao2_callback_fn on_aor, void *arg)
685 {
686  char *copy;
687  char *name;
688  int res;
689 
690  if (!on_aor || ast_strlen_zero(aors)) {
691  return 0;
692  }
693 
694  copy = ast_strdupa(aors);
695  while ((name = ast_strip(strsep(&copy, ",")))) {
696  struct ast_sip_aor *aor;
697 
698  aor = ast_sip_location_retrieve_aor(name);
699  if (aor) {
700  res = on_aor(aor, arg, 0);
701  ao2_ref(aor, -1);
702  if (res) {
703  return -1;
704  }
705  }
706  }
707  return 0;
708 }
709 
710 static void contact_wrapper_destroy(void *obj)
711 {
712  struct ast_sip_contact_wrapper *wrapper = obj;
713 
714  ast_free(wrapper->aor_id);
715  ast_free(wrapper->contact_id);
716  ao2_cleanup(wrapper->contact);
717 }
718 
719 int ast_sip_for_each_contact(const struct ast_sip_aor *aor,
720  ao2_callback_fn on_contact, void *arg)
721 {
722  struct ao2_container *contacts;
723  struct ao2_iterator i;
724  int res = 0;
725  void *object = NULL;
726 
727  if (!on_contact ||
728  !(contacts = ast_sip_location_retrieve_aor_contacts(aor))) {
729  return 0;
730  }
731 
732  i = ao2_iterator_init(contacts, 0);
733  while ((object = ao2_iterator_next(&i))) {
734  RAII_VAR(struct ast_sip_contact *, contact, object, ao2_cleanup);
735  RAII_VAR(struct ast_sip_contact_wrapper *, wrapper, NULL, ao2_cleanup);
736  const char *aor_id = ast_sorcery_object_get_id(aor);
737 
738  wrapper = ao2_alloc_options(sizeof(struct ast_sip_contact_wrapper),
740  if (!wrapper) {
741  res = -1;
742  break;
743  }
744  wrapper->contact_id = ast_malloc(strlen(aor_id) + strlen(contact->uri) + 2);
745  if (!wrapper->contact_id) {
746  res = -1;
747  break;
748  }
749  sprintf(wrapper->contact_id, "%s/%s", aor_id, contact->uri);
750  wrapper->aor_id = ast_strdup(aor_id);
751  if (!wrapper->aor_id) {
752  res = -1;
753  break;
754  }
755  wrapper->contact = contact;
756  ao2_bump(wrapper->contact);
757 
758  if ((res = on_contact(wrapper, arg, 0))) {
759  break;
760  }
761  }
763  ao2_ref(contacts, -1);
764  return res;
765 }
766 
767 int ast_sip_contact_to_str(void *object, void *arg, int flags)
768 {
769  struct ast_sip_contact_wrapper *wrapper = object;
770  struct ast_str **buf = arg;
771 
772  ast_str_append(buf, 0, "%s,", wrapper->contact_id);
773 
774  return 0;
775 }
776 
777 static int sip_aor_to_ami(const struct ast_sip_aor *aor, struct ast_str **buf)
778 {
779  struct ast_variable *objset;
780  struct ast_variable *i;
781 
784  if (!objset) {
785  return -1;
786  }
787 
788  ast_str_append(buf, 0, "ObjectType: %s\r\n",
790  ast_str_append(buf, 0, "ObjectName: %s\r\n",
792 
793  for (i = objset; i; i = i->next) {
794  char *camel = ast_to_camel_case(i->name);
795 
796  if (strcmp(camel, "Contact") == 0) {
797  ast_free(camel);
798  camel = NULL;
799  }
800  ast_str_append(buf, 0, "%s: %s\r\n", S_OR(camel, "Contacts"), i->value);
801  ast_free(camel);
802  }
803 
804  ast_variables_destroy(objset);
805  return 0;
806 }
807 
808 static int contacts_to_str(const void *obj, const intptr_t *args, char **buf)
809 {
810  const struct ast_sip_aor *aor = obj;
811  struct ast_str *str;
812 
814  if (!str) {
815  *buf = NULL;
816  return -1;
817  }
818 
820  ast_str_truncate(str, -1);
821 
822  *buf = ast_strdup(ast_str_buffer(str));
823  ast_free(str);
824 
825  return *buf ? 0 : -1;
826 }
827 
828 static int format_ami_aor_handler(void *obj, void *arg, int flags)
829 {
830  struct ast_sip_aor *aor = obj;
831  struct ast_sip_ami *ami = arg;
832  const struct ast_sip_endpoint *endpoint = ami->arg;
833  struct ast_str *buf;
834  struct ao2_container *contacts;
835  int total_contacts;
836  int num_permanent;
837 
838  buf = ast_sip_create_ami_event("AorDetail", ami);
839  if (!buf) {
840  return -1;
841  }
843  if (!contacts) {
844  ast_free(buf);
845  return -1;
846  }
847 
848  sip_aor_to_ami(aor, &buf);
849  total_contacts = ao2_container_count(contacts);
850  num_permanent = aor->permanent_contacts ?
852 
853  ast_str_append(&buf, 0, "TotalContacts: %d\r\n", total_contacts);
854  ast_str_append(&buf, 0, "ContactsRegistered: %d\r\n",
855  total_contacts - num_permanent);
856  ast_str_append(&buf, 0, "EndpointName: %s\r\n",
857  ast_sorcery_object_get_id(endpoint));
858 
859  astman_append(ami->s, "%s\r\n", ast_str_buffer(buf));
860  ami->count++;
861 
862  ast_free(buf);
863  ao2_ref(contacts, -1);
864  return 0;
865 }
866 
867 static int format_ami_endpoint_aor(const struct ast_sip_endpoint *endpoint,
868  struct ast_sip_ami *ami)
869 {
870  ami->arg = (void *)endpoint;
871  return ast_sip_for_each_aor(endpoint->aors,
873 }
874 
877 };
878 
879 static struct ao2_container *cli_aor_get_container(const char *regex)
880 {
881  struct ao2_container *container;
882  struct ao2_container *s_container;
883 
884  container = ast_sorcery_retrieve_by_regex(ast_sip_get_sorcery(), "aor", regex);
885  if (!container) {
886  return NULL;
887  }
888 
889  /* Create a sorted container of aors. */
892  if (s_container
893  && ao2_container_dup(s_container, container, 0)) {
894  ao2_ref(s_container, -1);
895  s_container = NULL;
896  }
897  ao2_ref(container, -1);
898 
899  return s_container;
900 }
901 
902 static int cli_contact_populate_container(void *obj, void *arg, int flags)
903 {
904  ao2_link(arg, obj);
905 
906  return 0;
907 }
908 
909 static int cli_aor_gather_contacts(void *obj, void *arg, int flags)
910 {
911  struct ast_sip_aor *aor = obj;
912 
914 }
915 
916 static const char *cli_contact_get_id(const void *obj)
917 {
918  const struct ast_sip_contact_wrapper *wrapper = obj;
919  return wrapper->contact_id;
920 }
921 
922 static int cli_contact_sort(const void *obj, const void *arg, int flags)
923 {
924  const struct ast_sip_contact_wrapper *left_wrapper = obj;
925  const struct ast_sip_contact_wrapper *right_wrapper = arg;
926  const char *right_key = arg;
927  int cmp = 0;
928 
929  switch (flags & OBJ_SEARCH_MASK) {
930  case OBJ_SEARCH_OBJECT:
931  right_key = right_wrapper->contact_id;
932  /* Fall through */
933  case OBJ_SEARCH_KEY:
934  cmp = strcmp(left_wrapper->contact_id, right_key);
935  break;
937  cmp = strncmp(left_wrapper->contact_id, right_key, strlen(right_key));
938  break;
939  default:
940  cmp = 0;
941  break;
942  }
943 
944  return cmp;
945 }
946 
947 static int cli_contact_compare(void *obj, void *arg, int flags)
948 {
949  const struct ast_sip_contact_wrapper *left_wrapper = obj;
950  const struct ast_sip_contact_wrapper *right_wrapper = arg;
951  const char *right_key = arg;
952  int cmp = 0;
953 
954  switch (flags & OBJ_SEARCH_MASK) {
955  case OBJ_SEARCH_OBJECT:
956  right_key = right_wrapper->contact_id;
957  /* Fall through */
958  case OBJ_SEARCH_KEY:
959  if (strcmp(left_wrapper->contact_id, right_key) == 0) {;
960  cmp = CMP_MATCH | CMP_STOP;
961  }
962  break;
964  if (strncmp(left_wrapper->contact_id, right_key, strlen(right_key)) == 0) {
965  cmp = CMP_MATCH;
966  }
967  break;
968  default:
969  cmp = 0;
970  break;
971  }
972 
973  return cmp;
974 }
975 
976 static int cli_contact_iterate(void *container, ao2_callback_fn callback, void *args)
977 {
978  return ast_sip_for_each_contact(container, callback, args);
979 }
980 
981 static int cli_filter_contacts(void *obj, void *arg, int flags)
982 {
983  struct ast_sip_contact_wrapper *wrapper = obj;
984  regex_t *regexbuf = arg;
985 
986  if (!regexec(regexbuf, wrapper->contact_id, 0, NULL, 0)) {
987  return 0;
988  }
989 
990  return CMP_MATCH;
991 }
992 
993 static int cli_gather_contact(void *obj, void *arg, int flags)
994 {
995  struct ast_sip_contact *contact = obj;
996  RAII_VAR(struct ast_sip_contact_wrapper *, wrapper, NULL, ao2_cleanup);
997 
998  if (strcmp(contact->reg_server, ast_config_AST_SYSTEM_NAME ?: "")) {
999  return 0;
1000  }
1001 
1002  wrapper = ao2_alloc_options(sizeof(struct ast_sip_contact_wrapper),
1004  if (!wrapper) {
1005  return -1;
1006  }
1007 
1008  wrapper->contact_id = ast_malloc(strlen(contact->aor) + strlen(contact->uri) + 2);
1009  if (!wrapper->contact_id) {
1010  return -1;
1011  }
1012  sprintf(wrapper->contact_id, "%s/%s", contact->aor, contact->uri);
1013 
1014  wrapper->aor_id = ast_strdup(contact->aor);
1015  if (!wrapper->aor_id) {
1016  return -1;
1017  }
1018 
1019  wrapper->contact = ao2_bump(contact);
1020 
1021  ao2_link(arg, wrapper);
1022 
1023  return 0;
1024 }
1025 
1026 static struct ao2_container *cli_contact_get_container(const char *regex)
1027 {
1028  RAII_VAR(struct ao2_container *, aors, NULL, ao2_cleanup);
1029  RAII_VAR(struct ao2_container *, contacts, NULL, ao2_cleanup);
1030  RAII_VAR(struct ast_variable *, var_aor, NULL, ast_variables_destroy);
1031  struct ao2_container *contacts_container;
1032  regex_t regexbuf;
1033 
1034  if (!(var_aor = ast_variable_new("contact !=", "", ""))) {
1035  return NULL;
1036  }
1037 
1038  /* Retrieving all the contacts may result in finding the same contact multiple
1039  * times. So that they don't get displayed multiple times we only allow a
1040  * single one to be placed into the container.
1041  */
1044  if (!contacts_container) {
1045  return NULL;
1046  }
1047 
1048  contacts = ast_sorcery_retrieve_by_regex(ast_sip_get_sorcery(), "contact", regex);
1049  if (!contacts) {
1050  ao2_ref(contacts_container, -1);
1051  return NULL;
1052  }
1053  ao2_callback(contacts, OBJ_NODATA, cli_gather_contact, contacts_container);
1054 
1056  "aor", AST_RETRIEVE_FLAG_MULTIPLE, var_aor);
1057  if (!aors) {
1058  ao2_ref(contacts_container, -1);
1059  return NULL;
1060  }
1061 
1062  ao2_callback(aors, OBJ_NODATA, cli_aor_gather_contacts, contacts_container);
1063 
1064  if (!ast_strlen_zero(regex)) {
1065  if (regcomp(&regexbuf, regex, REG_EXTENDED | REG_NOSUB)) {
1066  ao2_ref(contacts_container, -1);
1067  return NULL;
1068  }
1069  ao2_callback(contacts_container, OBJ_UNLINK | OBJ_MULTIPLE | OBJ_NODATA, cli_filter_contacts, &regexbuf);
1070  regfree(&regexbuf);
1071  }
1072 
1073  return contacts_container;
1074 }
1075 
1076 static void *cli_contact_retrieve_by_id(const char *id)
1077 {
1078  struct ao2_container *container;
1079  void *obj;
1080 
1081  container = cli_contact_get_container("");
1082  if (!container) {
1083  return NULL;
1084  }
1085 
1086  obj = ao2_find(container, id, OBJ_SEARCH_KEY);
1087  ao2_ref(container, -1);
1088  return obj;
1089 }
1090 
1091 static int cli_contact_print_header(void *obj, void *arg, int flags)
1092 {
1093  struct ast_sip_cli_context *context = arg;
1094  int indent = CLI_INDENT_TO_SPACES(context->indent_level);
1095  int filler = CLI_LAST_TABSTOP - indent - 23;
1096 
1097  ast_assert(context->output_buffer != NULL);
1098 
1099  ast_str_append(&context->output_buffer, 0,
1100  "%*s: <Aor/ContactUri%*.*s> <Hash....> <Status> <RTT(ms)..>\n",
1101  indent, "Contact", filler, filler, CLI_HEADER_FILLER);
1102 
1103  return 0;
1104 }
1105 
1106 static int cli_contact_print_body(void *obj, void *arg, int flags)
1107 {
1108  struct ast_sip_contact_wrapper *wrapper = obj;
1109  struct ast_sip_contact *contact = wrapper->contact;
1110  struct ast_sip_cli_context *context = arg;
1111  int indent;
1112  int flexwidth;
1113  const char *contact_id = ast_sorcery_object_get_id(contact);
1114  const char *hash_start = contact_id + strlen(contact->aor) + 2;
1116 
1117  ast_assert(contact->uri != NULL);
1118  ast_assert(context->output_buffer != NULL);
1119 
1120  status = ast_sip_get_contact_status(contact);
1121 
1122  indent = CLI_INDENT_TO_SPACES(context->indent_level);
1123  flexwidth = CLI_LAST_TABSTOP - indent - 9 - strlen(contact->aor) + 1;
1124 
1125  ast_str_append(&context->output_buffer, 0, "%*s: %s/%-*.*s %-10.10s %-7.7s %11.3f\n",
1126  indent,
1127  "Contact",
1128  contact->aor,
1129  flexwidth, flexwidth,
1130  contact->uri,
1131  hash_start,
1133  (status && (status->status == AVAILABLE)) ? ((long long) status->rtt) / 1000.0 : NAN);
1134 
1135  ao2_cleanup(status);
1136  return 0;
1137 }
1138 
1139 static int cli_aor_iterate(void *container, ao2_callback_fn callback, void *args)
1140 {
1141  const char *aor_list = container;
1142 
1143  return ast_sip_for_each_aor(aor_list, callback, args);
1144 }
1145 
1146 static void *cli_aor_retrieve_by_id(const char *id)
1147 {
1148  return ast_sorcery_retrieve_by_id(ast_sip_get_sorcery(), "aor", id);
1149 }
1150 
1151 static const char *cli_aor_get_id(const void *obj)
1152 {
1153  return ast_sorcery_object_get_id(obj);
1154 }
1155 
1156 static int cli_aor_print_header(void *obj, void *arg, int flags)
1157 {
1158  struct ast_sip_cli_context *context = arg;
1159  int indent = CLI_INDENT_TO_SPACES(context->indent_level);
1160  int filler = CLI_LAST_TABSTOP - indent - 7;
1161 
1162  ast_assert(context->output_buffer != NULL);
1163 
1164  ast_str_append(&context->output_buffer, 0,
1165  "%*s: <Aor%*.*s> <MaxContact>\n",
1166  indent, "Aor", filler, filler, CLI_HEADER_FILLER);
1167 
1168  if (context->recurse) {
1169  struct ast_sip_cli_formatter_entry *formatter_entry;
1170 
1171  context->indent_level++;
1172  formatter_entry = ast_sip_lookup_cli_formatter("contact");
1173  if (formatter_entry) {
1174  formatter_entry->print_header(NULL, context, 0);
1175  ao2_ref(formatter_entry, -1);
1176  }
1177  context->indent_level--;
1178  }
1179 
1180  return 0;
1181 }
1182 
1183 static int cli_aor_print_body(void *obj, void *arg, int flags)
1184 {
1185  struct ast_sip_aor *aor = obj;
1186  struct ast_sip_cli_context *context = arg;
1187  int indent;
1188  int flexwidth;
1189 
1190  ast_assert(context->output_buffer != NULL);
1191 
1192 // context->current_aor = aor;
1193 
1194  indent = CLI_INDENT_TO_SPACES(context->indent_level);
1195  flexwidth = CLI_LAST_TABSTOP - indent - 12;
1196 
1197  ast_str_append(&context->output_buffer, 0, "%*s: %-*.*s %12u\n",
1198  indent,
1199  "Aor",
1200  flexwidth, flexwidth,
1202 
1203  if (context->recurse) {
1204  struct ast_sip_cli_formatter_entry *formatter_entry;
1205 
1206  context->indent_level++;
1207 
1208  formatter_entry = ast_sip_lookup_cli_formatter("contact");
1209  if (formatter_entry) {
1210  formatter_entry->iterate(aor, formatter_entry->print_body, context);
1211  ao2_ref(formatter_entry, -1);
1212  }
1213 
1214  context->indent_level--;
1215 
1216  if (context->indent_level == 0) {
1217  ast_str_append(&context->output_buffer, 0, "\n");
1218  }
1219  }
1220 
1221  if (context->show_details || (context->show_details_only_level_0 && context->indent_level == 0)) {
1222  ast_str_append(&context->output_buffer, 0, "\n");
1223  ast_sip_cli_print_sorcery_objectset(aor, context, 0);
1224  }
1225 
1226  return 0;
1227 }
1228 
1229 static struct ao2_container *cli_get_aors(void)
1230 {
1231  struct ao2_container *aors;
1232 
1235 
1236  return aors;
1237 }
1238 
1239 static int format_ami_aorlist_handler(void *obj, void *arg, int flags)
1240 {
1241  struct ast_sip_aor *aor = obj;
1242  struct ast_sip_ami *ami = arg;
1243  struct ast_str *buf;
1244 
1245  buf = ast_sip_create_ami_event("AorList", ami);
1246  if (!buf) {
1247  return -1;
1248  }
1249 
1250  sip_aor_to_ami(aor, &buf);
1251 
1252  astman_append(ami->s, "%s\r\n", ast_str_buffer(buf));
1253  ami->count++;
1254 
1255  ast_free(buf);
1256 
1257  return 0;
1258 }
1259 
1260 static int ami_show_aors(struct mansession *s, const struct message *m)
1261 {
1262  struct ast_sip_ami ami = { .s = s, .m = m, .action_id = astman_get_header(m, "ActionID"), };
1263  struct ao2_container *aors;
1264 
1265  aors = cli_get_aors();
1266  if (!aors) {
1267  astman_send_error(s, m, "Could not get AORs\n");
1268  return 0;
1269  }
1270 
1271  if (!ao2_container_count(aors)) {
1272  astman_send_error(s, m, "No AORs found\n");
1273  ao2_ref(aors, -1);
1274  return 0;
1275  }
1276 
1277  astman_send_listack(s, m, "A listing of AORs follows, presented as AorList events",
1278  "start");
1279 
1281 
1282  astman_send_list_complete_start(s, m, "AorListComplete", ami.count);
1284 
1285  ao2_ref(aors, -1);
1286 
1287  return 0;
1288 }
1289 
1290 static struct ast_cli_entry cli_commands[] = {
1291  AST_CLI_DEFINE(ast_sip_cli_traverse_objects, "List PJSIP Aors",
1292  .command = "pjsip list aors",
1293  .usage = "Usage: pjsip list aors [ like <pattern> ]\n"
1294  " List the configured PJSIP Aors\n"
1295  " Optional regular expression pattern is used to filter the list.\n"),
1296  AST_CLI_DEFINE(ast_sip_cli_traverse_objects, "Show PJSIP Aors",
1297  .command = "pjsip show aors",
1298  .usage = "Usage: pjsip show aors [ like <pattern> ]\n"
1299  " Show the configured PJSIP Aors\n"
1300  " Optional regular expression pattern is used to filter the list.\n"),
1301  AST_CLI_DEFINE(ast_sip_cli_traverse_objects, "Show PJSIP Aor",
1302  .command = "pjsip show aor",
1303  .usage = "Usage: pjsip show aor <id>\n"
1304  " Show the configured PJSIP Aor\n"),
1305 
1306  AST_CLI_DEFINE(ast_sip_cli_traverse_objects, "List PJSIP Contacts",
1307  .command = "pjsip list contacts",
1308  .usage = "Usage: pjsip list contacts [ like <pattern> ]\n"
1309  " List the configured PJSIP contacts\n"
1310  " Optional regular expression pattern is used to filter the list.\n"),
1311  AST_CLI_DEFINE(ast_sip_cli_traverse_objects, "Show PJSIP Contacts",
1312  .command = "pjsip show contacts",
1313  .usage = "Usage: pjsip show contacts [ like <pattern> ]\n"
1314  " Show the configured PJSIP contacts\n"
1315  " Optional regular expression pattern is used to filter the list.\n"),
1316  AST_CLI_DEFINE(ast_sip_cli_traverse_objects, "Show PJSIP Contact",
1317  .command = "pjsip show contact",
1318  .usage = "Usage: pjsip show contact\n"
1319  " Show the configured PJSIP contact\n"),
1320 };
1321 
1324 
1325 /*! \brief Always create a contact_status for each contact */
1326 static int contact_apply_handler(const struct ast_sorcery *sorcery, void *object)
1327 {
1329  struct ast_sip_contact *contact = object;
1330 
1331  if (ast_strlen_zero(contact->uri)) {
1332  ast_log(LOG_ERROR, "A URI on dynamic contact '%s' is empty\n",
1333  ast_sorcery_object_get_id(contact));
1334  return -1;
1335  }
1337  ao2_cleanup(status);
1338 
1339  return status ? 0 : -1;
1340 }
1341 
1342 static int aor_apply_outbound_proxy(void *obj, void *arg, int flags)
1343 {
1344  struct ast_sip_contact *contact = obj;
1345  struct ast_sip_aor *aor = arg;
1346 
1348 
1349  return 0;
1350 }
1351 
1352 static int aor_apply_handler(const struct ast_sorcery *sorcery, void *object)
1353 {
1354  struct ast_sip_aor *aor = object;
1355 
1356  if (!aor->permanent_contacts || ast_strlen_zero(aor->outbound_proxy)) {
1357  return 0;
1358  }
1359 
1361 
1362  return 0;
1363 }
1364 
1365 /*! \brief Initialize sorcery with location support */
1367 {
1369  int i;
1370 
1371  ast_pjproject_get_buildopt("PJ_MAX_HOSTNAME", "%d", &pj_max_hostname);
1372  /* As of pjproject 2.4.5, PJSIP_MAX_URL_SIZE isn't exposed yet but we try anyway. */
1373  ast_pjproject_get_buildopt("PJSIP_MAX_URL_SIZE", "%d", &pjsip_max_url_size);
1374 
1375  ast_sorcery_apply_default(sorcery, "contact", "astdb", "registrar");
1376  ast_sorcery_object_set_congestion_levels(sorcery, "contact", -1,
1378  ast_sorcery_apply_default(sorcery, "aor", "config", "pjsip.conf,criteria=type=aor");
1379 
1382  return -1;
1383  }
1384 
1385  ast_sorcery_observer_add(sorcery, "aor", &aor_observer);
1386 
1387  ast_sorcery_object_field_register(sorcery, "contact", "type", "", OPT_NOOP_T, 0, 0);
1388  ast_sorcery_object_field_register(sorcery, "contact", "uri", "", OPT_STRINGFIELD_T, 0, STRFLDSET(struct ast_sip_contact, uri));
1389  ast_sorcery_object_field_register(sorcery, "contact", "path", "", OPT_STRINGFIELD_T, 0, STRFLDSET(struct ast_sip_contact, path));
1390  ast_sorcery_object_field_register_custom(sorcery, "contact", "expiration_time", "", expiration_str2struct, expiration_struct2str, NULL, 0, 0);
1391  ast_sorcery_object_field_register(sorcery, "contact", "qualify_frequency", 0, OPT_UINT_T,
1392  PARSE_IN_RANGE, FLDSET(struct ast_sip_contact, qualify_frequency), 0, 86400);
1393  ast_sorcery_object_field_register(sorcery, "contact", "qualify_timeout", "3.0", OPT_DOUBLE_T, 0, FLDSET(struct ast_sip_contact, qualify_timeout));
1394  ast_sorcery_object_field_register(sorcery, "contact", "authenticate_qualify", "no", OPT_YESNO_T, 1, FLDSET(struct ast_sip_contact, authenticate_qualify));
1395  ast_sorcery_object_field_register(sorcery, "contact", "outbound_proxy", "", OPT_STRINGFIELD_T, 0, STRFLDSET(struct ast_sip_contact, outbound_proxy));
1396  ast_sorcery_object_field_register(sorcery, "contact", "user_agent", "", OPT_STRINGFIELD_T, 0, STRFLDSET(struct ast_sip_contact, user_agent));
1397  ast_sorcery_object_field_register(sorcery, "contact", "endpoint", "", OPT_STRINGFIELD_T, 0, STRFLDSET(struct ast_sip_contact, endpoint_name));
1398  ast_sorcery_object_field_register(sorcery, "contact", "reg_server", "", OPT_STRINGFIELD_T, 0, STRFLDSET(struct ast_sip_contact, reg_server));
1399  ast_sorcery_object_field_register(sorcery, "contact", "via_addr", "", OPT_STRINGFIELD_T, 0, STRFLDSET(struct ast_sip_contact, via_addr));
1400  ast_sorcery_object_field_register(sorcery, "contact", "via_port", "0", OPT_UINT_T, 0, FLDSET(struct ast_sip_contact, via_port));
1401  ast_sorcery_object_field_register(sorcery, "contact", "call_id", "", OPT_STRINGFIELD_T, 0, STRFLDSET(struct ast_sip_contact, call_id));
1402  ast_sorcery_object_field_register(sorcery, "contact", "prune_on_boot", "no", OPT_YESNO_T, 1, FLDSET(struct ast_sip_contact, prune_on_boot));
1403 
1404  ast_sorcery_object_field_register(sorcery, "aor", "type", "", OPT_NOOP_T, 0, 0);
1405  ast_sorcery_object_field_register(sorcery, "aor", "minimum_expiration", "60", OPT_UINT_T, 0, FLDSET(struct ast_sip_aor, minimum_expiration));
1406  ast_sorcery_object_field_register(sorcery, "aor", "maximum_expiration", "7200", OPT_UINT_T, 0, FLDSET(struct ast_sip_aor, maximum_expiration));
1407  ast_sorcery_object_field_register(sorcery, "aor", "default_expiration", "3600", OPT_UINT_T, 0, FLDSET(struct ast_sip_aor, default_expiration));
1408  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);
1409  ast_sorcery_object_field_register(sorcery, "aor", "qualify_timeout", "3.0", OPT_DOUBLE_T, 0, FLDSET(struct ast_sip_aor, qualify_timeout));
1410  ast_sorcery_object_field_register(sorcery, "aor", "authenticate_qualify", "no", OPT_BOOL_T, 1, FLDSET(struct ast_sip_aor, authenticate_qualify));
1411  ast_sorcery_object_field_register(sorcery, "aor", "max_contacts", "0", OPT_UINT_T, 0, FLDSET(struct ast_sip_aor, max_contacts));
1412  ast_sorcery_object_field_register(sorcery, "aor", "remove_existing", "no", OPT_BOOL_T, 1, FLDSET(struct ast_sip_aor, remove_existing));
1414  ast_sorcery_object_field_register(sorcery, "aor", "mailboxes", "", OPT_STRINGFIELD_T, 0, STRFLDSET(struct ast_sip_aor, mailboxes));
1416  ast_sorcery_object_field_register(sorcery, "aor", "outbound_proxy", "", OPT_STRINGFIELD_T, 0, STRFLDSET(struct ast_sip_aor, outbound_proxy));
1417  ast_sorcery_object_field_register(sorcery, "aor", "support_path", "no", OPT_BOOL_T, 1, FLDSET(struct ast_sip_aor, support_path));
1418 
1419  ast_sip_register_endpoint_formatter(&endpoint_aor_formatter);
1420 
1421  contact_formatter = ao2_alloc(sizeof(struct ast_sip_cli_formatter_entry), NULL);
1422  if (!contact_formatter) {
1423  ast_log(LOG_ERROR, "Unable to allocate memory for contact_formatter\n");
1424  return -1;
1425  }
1426  contact_formatter->name = "contact";
1427  contact_formatter->print_header = cli_contact_print_header;
1428  contact_formatter->print_body = cli_contact_print_body;
1429  contact_formatter->get_container = cli_contact_get_container;
1430  contact_formatter->iterate = cli_contact_iterate;
1431  contact_formatter->get_id = cli_contact_get_id;
1432  contact_formatter->retrieve_by_id = cli_contact_retrieve_by_id;
1433 
1434  aor_formatter = ao2_alloc(sizeof(struct ast_sip_cli_formatter_entry), NULL);
1435  if (!aor_formatter) {
1436  ast_log(LOG_ERROR, "Unable to allocate memory for aor_formatter\n");
1437  return -1;
1438  }
1439  aor_formatter->name = "aor";
1440  aor_formatter->print_header = cli_aor_print_header;
1441  aor_formatter->print_body = cli_aor_print_body;
1442  aor_formatter->get_container = cli_aor_get_container;
1443  aor_formatter->iterate = cli_aor_iterate;
1444  aor_formatter->get_id = cli_aor_get_id;
1445  aor_formatter->retrieve_by_id = cli_aor_retrieve_by_id;
1446 
1447  ast_sip_register_cli_formatter(contact_formatter);
1448  ast_sip_register_cli_formatter(aor_formatter);
1449  ast_cli_register_multiple(cli_commands, ARRAY_LEN(cli_commands));
1450 
1451  if (ast_manager_register_xml("PJSIPShowAors", EVENT_FLAG_SYSTEM, ami_show_aors)) {
1452  return -1;
1453  }
1454 
1455  /*
1456  * Reset StatsD gauges in case we didn't shut down cleanly.
1457  * Note that this must done here, as contacts will create the contact_status
1458  * object before PJSIP options handling is initialized.
1459  */
1460  for (i = 0; i <= REMOVED; i++) {
1461  ast_statsd_log_full_va("PJSIP.contacts.states.%s", AST_STATSD_GAUGE, 0, 1.0, ast_sip_get_contact_status_label(i));
1462  }
1463 
1464  return 0;
1465 }
1466 
1468 {
1469  ast_sorcery_observer_remove(ast_sip_get_sorcery(), "aor", &aor_observer);
1470  ast_cli_unregister_multiple(cli_commands, ARRAY_LEN(cli_commands));
1471  ast_sip_unregister_cli_formatter(contact_formatter);
1472  ast_sip_unregister_cli_formatter(aor_formatter);
1473  ast_manager_unregister("PJSIPShowAors");
1474 
1475  ast_sip_unregister_endpoint_formatter(&endpoint_aor_formatter);
1476 
1477  return 0;
1478 }
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
double qualify_timeout
Definition: res_pjsip.h:387
struct ast_str * output_buffer
Definition: res_pjsip_cli.h:36
static int sip_aor_to_ami(const struct ast_sip_aor *aor, struct ast_str **buf)
Definition: location.c:777
struct ast_variable * next
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
struct ao2_container *(* get_container)(const char *regex)
Definition: res_pjsip_cli.h:64
int authenticate_qualify
Definition: res_pjsip.h:309
#define AST_CLI_DEFINE(fn, txt,...)
Definition: cli.h:197
int ast_sip_contact_to_str(void *object, void *arg, int flags)
Handler used to convert a contact to a string.
Definition: location.c:767
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:199
A contact&#39;s status.
Definition: res_pjsip.h:341
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 astman_append(struct mansession *s, const char *fmt,...)
Definition: manager.c:3080
Asterisk main include file. File version handling, generic pbx functions.
A SIP address of record.
Definition: res_pjsip.h:361
int ao2_container_count(struct ao2_container *c)
Returns the number of elements in a container.
#define ARRAY_LEN(a)
Definition: isdn_lib.c:42
An entity responsible formatting endpoint information.
Definition: res_pjsip.h:2763
Definition: res_pjsip_cli.h:52
void(* deleted)(const void *object)
Callback for when an object is deleted.
Definition: sorcery.h:340
const ast_string_field outbound_proxy
Definition: res_pjsip.h:303
struct ast_sip_contact_status * ast_sip_get_contact_status(const struct ast_sip_contact *contact)
Retrieve the current status for a contact.
#define CLI_LAST_TABSTOP
Definition: res_pjsip_cli.h:27
#define NAN
struct ast_sip_cli_formatter_entry * aor_formatter
Definition: location.c:1323
void ast_variables_destroy(struct ast_variable *var)
Free variable list.
Definition: extconf.c:1263
const ast_string_field call_id
Definition: res_pjsip.h:303
static int ami_show_aors(struct mansession *s, const struct message *m)
Definition: location.c:1260
const ast_string_field user_agent
Definition: res_pjsip.h:303
int ast_cli_unregister_multiple(struct ast_cli_entry *e, int len)
Unregister multiple commands.
Definition: clicompat.c:30
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 &#39;on_aor&#39; handler. ...
Definition: location.c:684
The arg parameter is a search key, but is not an object.
Definition: astobj2.h:1105
const ast_string_field path
Definition: res_pjsip.h:303
static struct ao2_container * cli_get_aors(void)
Definition: location.c:1229
const struct message * m
Definition: res_pjsip.h:2741
char buf[BUFSIZE]
Definition: eagi_proxy.c:66
Default filter flags.
Definition: res_pjsip.h:1006
static int contact_expire(void *obj, void *arg, int flags)
Internal callback function which deletes and unlinks any expired contacts.
Definition: location.c:153
unsigned int max_contacts
Definition: res_pjsip.h:379
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:3237
descriptor for a cli entry.
Definition: cli.h:171
#define LOG_WARNING
Definition: logger.h:274
const ast_string_field via_addr
Definition: res_pjsip.h:303
char * ast_str_buffer(const struct ast_str *buf)
Returns the string buffer within the ast_str buf.
Definition: strings.h:714
#define AST_TASKPROCESSOR_HIGH_WATER_LEVEL
Definition: taskprocessor.h:63
#define ao2_callback(c, flags, cb_fn, arg)
Definition: astobj2.h:1716
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 void * aor_alloc(const char *name)
Allocator for AOR.
Definition: location.c:50
static struct stasis_rest_handlers mailboxes
REST handler for /api-docs/mailboxes.json.
static int prune_boot_contacts_cb(void *obj, void *arg, int flags)
Definition: location.c:455
static int cli_contact_iterate(void *container, ao2_callback_fn callback, void *args)
Definition: location.c:976
void * arg
Definition: res_pjsip.h:2745
AMI variable container.
Definition: res_pjsip.h:2737
#define ao2_container_alloc_list(ao2_options, container_options, sort_fn, cmp_fn)
Definition: astobj2.h:1335
static int cli_filter_contacts(void *obj, void *arg, int flags)
Definition: location.c:981
Structure for variables, used for configurations and for channel variables.
static int cli_aor_print_body(void *obj, void *arg, int flags)
Definition: location.c:1183
#define var
Definition: ast_expr2f.c:614
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
struct ast_sip_aor * ast_sip_location_retrieve_aor(const char *aor_name)
Retrieve a named AOR.
Definition: location.c:147
Perform no matching, return all objects.
Definition: sorcery.h:123
int ast_sorcery_object_id_compare(void *obj, void *arg, int flags)
ao2 object comparator based on sorcery id.
Definition: sorcery.c:2459
static int format_ami_aorlist_handler(void *obj, void *arg, int flags)
Definition: location.c:1239
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
Full structure for sorcery.
Definition: sorcery.c:230
int(* iterate)(void *container, ao2_callback_fn callback, void *args)
Definition: res_pjsip_cli.h:66
Type for a default handler that should do nothing.
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
static void * contact_alloc(const char *name)
Allocator for contact.
Definition: location.c:120
const char * ast_sip_get_contact_short_status_label(const enum ast_sip_contact_status_type status)
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:1091
#define ast_cli_register_multiple(e, len)
Register multiple commands.
Definition: cli.h:265
unsigned int qualify_frequency
Definition: res_pjsip.h:307
void ao2_iterator_destroy(struct ao2_iterator *iter)
Destroy a container iterator.
static int copy(char *infile, char *outfile)
Utility function to copy a file.
struct timeval ast_tvnow(void)
Returns current timeval. Meant to replace calls to gettimeofday().
Definition: time.h:150
Return all matching objects.
Definition: sorcery.h:120
#define ao2_alloc_options(data_size, destructor_fn, options)
Definition: astobj2.h:406
#define ast_assert(a)
Definition: utils.h:695
#define ao2_unlock(a)
Definition: astobj2.h:730
int ast_pjproject_get_buildopt(char *option, char *format_string,...)
Retrieve a pjproject build option.
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.
int64_t ast_tvdiff_ms(struct timeval end, struct timeval start)
Computes the difference (in milliseconds) between two struct timeval instances.
Definition: time.h:98
#define ast_strdup(str)
A wrapper for strdup()
Definition: astmm.h:243
static void contact_destroy(void *obj)
Destructor for contact.
Definition: location.c:111
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
const char * str
Definition: app_jack.c:147
void ast_sip_unregister_endpoint_formatter(struct ast_sip_endpoint_formatter *obj)
Unregister an endpoint formatter.
Definition: res_pjsip.c:3685
static int contacts_to_var_list(const void *obj, struct ast_variable **fields)
Definition: location.c:657
const ast_string_field outbound_proxy
Definition: res_pjsip.h:367
const char * args
const ast_string_field reg_server
Definition: res_pjsip.h:303
#define NULL
Definition: resample.c:96
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 ast_sip_endpoint_formatter endpoint_aor_formatter
Definition: location.c:875
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
int ast_get_timeval(const char *src, struct timeval *tv, struct timeval _default, int *consumed)
get values from config variables.
Definition: main/utils.c:2171
#define ast_to_camel_case(s)
Definition: strings.h:509
const ast_string_field uri
Definition: res_pjsip.h:347
static void aor_deleted_observer(const void *object)
Definition: location.c:81
#define ast_verb(level,...)
Definition: logger.h:463
static void * cli_aor_retrieve_by_id(const char *id)
Definition: location.c:1146
char * ast_sip_cli_traverse_objects(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
Definition: pjsip_cli.c:109
static int gather_contacts_for_aor(void *obj, void *arg, int flags)
Definition: location.c:319
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
char * voicemail_extension
Definition: res_pjsip.h:389
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
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
#define ast_asprintf(ret, fmt,...)
A wrapper for asprintf()
Definition: astmm.h:269
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
const char * ast_sorcery_object_get_type(const void *object)
Get the type of a sorcery object.
Definition: sorcery.c:2324
char * ast_str_truncate(struct ast_str *buf, ssize_t len)
Truncates the enclosed string to the given length.
Definition: strings.h:738
const char * astman_get_header(const struct message *m, char *var)
Get header from mananger transaction.
Definition: manager.c:2820
#define ast_strlen_zero(foo)
Definition: strings.h:52
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
int ast_sip_register_cli_formatter(struct ast_sip_cli_formatter_entry *formatter)
Registers a CLI formatter.
Definition: pjsip_cli.c:310
static int cli_aor_iterate(void *container, ao2_callback_fn callback, void *args)
Definition: location.c:1139
const char * ast_config_AST_SYSTEM_NAME
Definition: options.c:170
struct ast_sip_endpoint * endpoint
Definition: res_pjsip.h:313
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
#define ao2_bump(obj)
Definition: astobj2.h:491
static int cli_contact_print_body(void *obj, void *arg, int flags)
Definition: location.c:1106
Type for default option handler for bools (ast_true/ast_false)
unsigned int qualify_frequency
Definition: res_pjsip.h:375
void ast_sip_register_endpoint_formatter(struct ast_sip_endpoint_formatter *obj)
Register an endpoint formatter.
Definition: res_pjsip.c:3679
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:1639
#define EVENT_FLAG_SYSTEM
Definition: manager.h:71
int() ao2_callback_fn(void *obj, void *arg, int flags)
Type of a generic callback function.
Definition: astobj2.h:1230
#define ast_log
Definition: astobj2.c:42
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
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_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
The arg parameter is a partial search key similar to OBJ_SEARCH_KEY.
Definition: astobj2.h:1120
#define FLDSET(type,...)
Convert a struct and list of fields to an argument list of field offsets.
const ast_string_field endpoint_name
Definition: res_pjsip.h:303
static char host[256]
Definition: muted.c:77
static int format_ami_endpoint_aor(const struct ast_sip_endpoint *endpoint, struct ast_sip_ami *ami)
Definition: location.c:867
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:396
static int contact_to_var_list(void *object, void *arg, int flags)
Definition: location.c:647
Asterisk file paths, configured in asterisk.conf.
void astman_send_list_complete_end(struct mansession *s)
End the list complete event.
Definition: manager.c:3245
#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:911
Type for default option handler for unsigned integers.
static int permanent_uri_sort_fn(const void *obj_left, const void *obj_right, int flags)
Definition: location.c:495
static void aor_destroy(void *obj)
Destructor for AOR.
Definition: location.c:40
static int aor_apply_outbound_proxy(void *obj, void *arg, int flags)
Definition: location.c:1342
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 &#39;on_contact&#39; handler.
Definition: location.c:719
#define ast_string_field_init(x, size)
Initialize a field pool and fields.
Definition: stringfields.h:353
#define CLI_INDENT_TO_SPACES(x)
Definition: res_pjsip_cli.h:29
ast_mutex_t lock
Definition: app_meetme.c:1091
char * ast_strip(char *s)
Strip leading/trailing whitespace from a string.
Definition: strings.h:219
static const struct ast_sorcery_observer aor_observer
Observer for contacts so state can be updated on respective endpoints.
Definition: location.c:105
#define ao2_ref(o, delta)
Definition: astobj2.h:464
Use string handler only.
Definition: sorcery.h:137
In case you didn&#39;t read that giant block of text above the mansession_session struct, the struct mansession is named this solely to keep the API the same in Asterisk. This structure really represents data that is different from Manager action to Manager action. The mansession_session pointer contained within points to session-specific data.
Definition: manager.c:1625
#define ao2_lock(a)
Definition: astobj2.h:718
#define ast_strdupa(s)
duplicate a string in memory from the stack
Definition: astmm.h:300
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
const char * ast_sorcery_object_get_id(const void *object)
Get the unique identifier of a sorcery object.
Definition: sorcery.c:2312
void *(* retrieve_by_id)(const char *id)
Definition: res_pjsip_cli.h:68
struct mansession * s
Definition: res_pjsip.h:2739
#define ast_malloc(len)
A wrapper for malloc()
Definition: astmm.h:193
struct ao2_container * container
Definition: res_fax.c:502
double qualify_timeout
Definition: res_pjsip.h:311
static int cli_contact_print_header(void *obj, void *arg, int flags)
Definition: location.c:1091
int ast_sip_validate_uri_length(const char *contact_uri)
Definition: location.c:525
static int default_expiration
Definition: pbx_dundi.c:199
#define ast_variable_new(name, value, filename)
int ast_sip_unregister_cli_formatter(struct ast_sip_cli_formatter_entry *formatter)
Unregisters a CLI formatter.
Definition: pjsip_cli.c:326
An entity with which Asterisk communicates.
Definition: res_pjsip.h:812
unsigned int support_path
Definition: res_pjsip.h:385
Named Locks.
#define ast_sorcery_object_register(sorcery, type, alloc, transform, apply)
Register an object type.
Definition: sorcery.h:838
#define MAX_OBJECT_FIELD
Maximum length of an object field name.
Definition: sorcery.h:110
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 struct ao2_container * cli_contact_get_container(const char *regex)
Definition: location.c:1026
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
enum ast_sip_contact_status_type status
Definition: res_pjsip.h:351
struct ast_sip_contact * contact
Definition: res_pjsip.h:402
int ast_sip_initialize_sorcery_location(void)
Initialize sorcery with location support.
Definition: location.c:1366
int ast_manager_unregister(const char *action)
Unregister a registered manager command.
Definition: manager.c:7258
#define CLI_HEADER_FILLER
Definition: res_pjsip_cli.h:24
void ast_sip_location_prune_boot_contacts(void)
Prune the prune_on_boot contacts.
Definition: location.c:469
static const char * cli_aor_get_id(const void *obj)
Definition: location.c:1151
int ast_sorcery_delete(const struct ast_sorcery *sorcery, void *object)
Delete an object.
Definition: sorcery.c:2233
static int cli_gather_contact(void *obj, void *arg, int flags)
Definition: location.c:993
#define LOG_ERROR
Definition: logger.h:285
The descriptor of a dynamic string XXX storage will be optimized later if needed We use the ts field ...
Definition: strings.h:584
char * usage
Definition: utils/frame.c:37
static int permanent_uri_handler(const struct aco_option *opt, struct ast_variable *var, void *obj)
Custom handler for permanent URIs.
Definition: location.c:589
int ast_sip_location_delete_contact(struct ast_sip_contact *contact)
Delete a contact.
Definition: location.c:450
static void contact_wrapper_destroy(void *obj)
Definition: location.c:710
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.
static int voicemail_extension_handler(const struct aco_option *opt, struct ast_variable *var, void *obj)
Definition: location.c:666
static int cli_aor_gather_contacts(void *obj, void *arg, int flags)
Definition: location.c:909
Interface for a sorcery object type observer.
Definition: sorcery.h:332
Type for default option handler for bools (ast_true/ast_false)
int ast_sip_destroy_sorcery_location(void)
Definition: location.c:1467
#define ast_sorcery_apply_default(sorcery, type, name, data)
Definition: sorcery.h:477
Contact associated with an address of record.
Definition: res_pjsip.h:281
static int format_ami_aor_handler(void *obj, void *arg, int flags)
Definition: location.c:828
static int destroy_contact(void *obj, void *arg, int flags)
Internal callback function which destroys the specified contact.
Definition: location.c:72
#define ao2_iterator_next(iter)
Definition: astobj2.h:1933
#define ao2_alloc(data_size, destructor_fn)
Definition: astobj2.h:411
void * ast_sorcery_alloc(const struct ast_sorcery *sorcery, const char *type, const char *id)
Allocate an object.
Definition: sorcery.c:1744
static int contacts_to_str(const void *obj, const intptr_t *args, char **buf)
Definition: location.c:808
static int contact_apply_handler(const struct ast_sorcery *sorcery, void *object)
Always create a contact_status for each contact.
Definition: location.c:1326
static int aor_apply_handler(const struct ast_sorcery *sorcery, void *object)
Definition: location.c:1352
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
struct timeval expiration_time
Definition: res_pjsip.h:305
static const char name[]
Definition: cdr_mysql.c:74
#define ast_free(a)
Definition: astmm.h:182
char * command
Definition: cli.h:186
static int cli_aor_print_header(void *obj, void *arg, int flags)
Definition: location.c:1156
static int regex(struct ast_channel *chan, const char *cmd, char *parse, char *buf, size_t len)
Definition: func_strings.c:948
int ast_sip_location_update_contact(struct ast_sip_contact *contact)
Update a contact.
Definition: location.c:445
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
Type for default option handler for doubles.
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:2767
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 * permanent_contacts
Definition: res_pjsip.h:383
#define STRFLDSET(type,...)
Convert a struct and a list of stringfield fields to an argument list of field offsets.
static struct ast_cli_entry cli_commands[]
Definition: location.c:1290
#define ao2_find(container, arg, flags)
Definition: astobj2.h:1756
An API for managing task processing threads that can be shared across modules.
const char *(* get_id)(const void *obj)
Definition: res_pjsip_cli.h:70
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.
static int cli_contact_compare(void *obj, void *arg, int flags)
Definition: location.c:947
Support for logging to various files, console and syslog Configuration in file logger.conf.
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
static struct ao2_container * cli_aor_get_container(const char *regex)
Definition: location.c:879
#define ast_sorcery_object_field_register(sorcery, type, name, default_val, opt_type, flags,...)
Register a field within an object.
Definition: sorcery.h:955
static int cli_contact_populate_container(void *obj, void *arg, int flags)
Definition: location.c:902
#define AST_STATSD_GAUGE
Support for publishing to a statsd server.
Definition: statsd.h:32
const ast_string_field aor
Definition: res_pjsip.h:303
The arg parameter is an object of the same type.
Definition: astobj2.h:1091
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
char * strsep(char **str, const char *delims)
static struct ast_sorcery * sorcery
struct ast_sorcery * ast_sip_get_sorcery(void)
Get a pointer to the SIP sorcery structure.
When we need to walk through a container, we use an ao2_iterator to keep track of the current positio...
Definition: astobj2.h:1841
#define ao2_cleanup(obj)
Definition: astobj2.h:1958
#define S_OR(a, b)
returns the equivalent of logic or for strings: first one if not empty, otherwise second one...
Definition: strings.h:79
struct timeval ast_tv(ast_time_t sec, ast_suseconds_t usec)
Returns a timeval from sec, usec.
Definition: time.h:226
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
int authenticate_qualify
Definition: res_pjsip.h:377
Type for default option handler for stringfields.
ao2_callback_fn * print_header
Definition: res_pjsip_cli.h:60
enum queue_result id
Definition: app_queue.c:1507
Reject objects with duplicate keys in container.
Definition: astobj2.h:1192
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
Return only reachable or unknown contacts.
Definition: res_pjsip.h:1009
struct ast_sip_cli_formatter_entry * contact_formatter
Definition: location.c:1322
Generic container type.
Search option field mask.
Definition: astobj2.h:1076
static char context[AST_MAX_CONTEXT]
Definition: chan_alsa.c:116
void * ast_sorcery_generic_alloc(size_t size, ao2_destructor_fn destructor)
Allocate a generic sorcery capable object.
Definition: sorcery.c:1728
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
static int pjsip_max_url_size
Definition: location.c:37
struct ast_sip_contact * ast_sip_location_retrieve_contact(const char *contact_name)
Retrieve a named contact.
Definition: location.c:350
const ast_string_field aors
Definition: res_pjsip.h:821
static void * cli_contact_retrieve_by_id(const char *id)
Definition: location.c:1076
#define ast_manager_register_xml(action, authority, func)
Register a manager callback using XML documentation to describe the manager.
Definition: manager.h:186
ao2_callback_fn * print_body
Definition: res_pjsip_cli.h:62
static const char * cli_contact_get_id(const void *obj)
Definition: location.c:916
void ast_md5_hash(char *output, const char *input)
Produces MD5 hash based on input string.
Definition: main/utils.c:248
const ast_string_field uri
Definition: res_pjsip.h:303
void astman_send_error(struct mansession *s, const struct message *m, char *error)
Send error in manager transaction.
Definition: manager.c:3159
int ast_sip_cli_print_sorcery_objectset(void *obj, void *arg, int flags)
Prints a sorcery object&#39;s ast_variable list.
Definition: pjsip_cli.c:36
const char * name
Definition: res_pjsip_cli.h:58
#define ast_string_field_free_memory(x)
free all memory - to be called before destroying the object
Definition: stringfields.h:368
struct ao2_iterator ao2_iterator_init(struct ao2_container *c, int flags) attribute_warn_unused_result
Create an iterator for a container.
static int cli_contact_sort(const void *obj, const void *arg, int flags)
Definition: location.c:922
#define ast_variable_list_append(head, new_var)
#define ast_named_lock_get(lock_type, keyspace, key)
Geta named lock handle.
Definition: named_locks.h:83
jack_status_t status
Definition: app_jack.c:146
#define ast_str_create(init_len)
Create a malloc&#39;ed dynamic length string.
Definition: strings.h:620
static int voicemail_extension_to_str(const void *obj, const intptr_t *args, char **buf)
Definition: location.c:675
Sorcery Data Access Layer API.
int ast_sorcery_update(const struct ast_sorcery *sorcery, void *object)
Update an object.
Definition: sorcery.c:2145
static char prefix[MAX_PREFIX]
Definition: http.c:141
#define ast_string_field_set(x, field, data)
Set a field to a simple string value.
Definition: stringfields.h:514
static int pj_max_hostname
Definition: location.c:36
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:3201
unsigned show_details_only_level_0
Definition: res_pjsip_cli.h:46
struct ast_sip_contact_status * ast_res_pjsip_find_or_create_contact_status(const struct ast_sip_contact *contact)
#define ao2_link(container, obj)
Definition: astobj2.h:1549