db4f9ac0995b51ba08a272549852ccabdec542f5
[asterisk/asterisk.git] / res / res_pjsip / location.c
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/sorcery.h"
27 #include "include/res_pjsip_private.h"
28 #include "asterisk/res_pjsip_cli.h"
29 #include "asterisk/statsd.h"
30 #include "asterisk/named_locks.h"
31
32 #include "asterisk/res_pjproject.h"
33
34 static int pj_max_hostname = PJ_MAX_HOSTNAME;
35 static int pjsip_max_url_size = PJSIP_MAX_URL_SIZE;
36
37 /*! \brief Destructor for AOR */
38 static void aor_destroy(void *obj)
39 {
40         struct ast_sip_aor *aor = obj;
41
42         ao2_cleanup(aor->permanent_contacts);
43         ast_string_field_free_memory(aor);
44         ast_free(aor->voicemail_extension);
45 }
46
47 /*! \brief Allocator for AOR */
48 static void *aor_alloc(const char *name)
49 {
50         struct ast_sip_aor *aor = ast_sorcery_generic_alloc(sizeof(struct ast_sip_aor), aor_destroy);
51         if (!aor) {
52                 return NULL;
53         }
54         ast_string_field_init(aor, 128);
55         return aor;
56 }
57
58 /*! \brief Internal callback function which destroys the specified contact */
59 static int destroy_contact(void *obj, void *arg, int flags)
60 {
61         struct ast_sip_contact *contact = obj;
62
63         ast_sip_location_delete_contact(contact);
64
65         return CMP_MATCH;
66 }
67
68 static void aor_deleted_observer(const void *object)
69 {
70         const struct ast_sip_aor *aor = object;
71         const char *aor_id = ast_sorcery_object_get_id(object);
72         /* Give enough space for ^ at the beginning and ;@ at the end, since that is our object naming scheme */
73         char regex[strlen(aor_id) + 4];
74         struct ao2_container *contacts;
75
76         if (aor->permanent_contacts) {
77                 ao2_callback(aor->permanent_contacts, OBJ_NODATA | OBJ_MULTIPLE | OBJ_UNLINK, destroy_contact, NULL);
78         }
79
80         snprintf(regex, sizeof(regex), "^%s;@", aor_id);
81         if (!(contacts = ast_sorcery_retrieve_by_regex(ast_sip_get_sorcery(), "contact", regex))) {
82                 return;
83         }
84         /* Destroy any contacts that may still exist that were made for this AoR */
85         ao2_callback(contacts, OBJ_NODATA | OBJ_MULTIPLE | OBJ_UNLINK, destroy_contact, NULL);
86
87         ao2_ref(contacts, -1);
88 }
89
90 /*! \brief Observer for contacts so state can be updated on respective endpoints */
91 static const struct ast_sorcery_observer aor_observer = {
92         .deleted = aor_deleted_observer,
93 };
94
95
96 /*! \brief Destructor for contact */
97 static void contact_destroy(void *obj)
98 {
99         struct ast_sip_contact *contact = obj;
100
101         ast_string_field_free_memory(contact);
102         ao2_cleanup(contact->endpoint);
103 }
104
105 /*! \brief Allocator for contact */
106 static void *contact_alloc(const char *name)
107 {
108         struct ast_sip_contact *contact = ast_sorcery_generic_alloc(sizeof(*contact), contact_destroy);
109         char *id = ast_strdupa(name);
110         char *aor = id;
111         char *aor_separator = NULL;
112
113         if (!contact) {
114                 return NULL;
115         }
116
117         if (ast_string_field_init(contact, 256)) {
118                 ao2_cleanup(contact);
119                 return NULL;
120         }
121
122         /* Dynamic contacts are delimited with ";@" and static ones with "@@" */
123         if ((aor_separator = strstr(id, ";@")) || (aor_separator = strstr(id, "@@"))) {
124                 *aor_separator = '\0';
125         }
126         ast_assert(aor_separator != NULL);
127
128         ast_string_field_set(contact, aor, aor);
129
130         return contact;
131 }
132
133 struct ast_sip_aor *ast_sip_location_retrieve_aor(const char *aor_name)
134 {
135         return ast_sorcery_retrieve_by_id(ast_sip_get_sorcery(), "aor", aor_name);
136 }
137
138 /*! \brief Internal callback function which deletes and unlinks any expired contacts */
139 static int contact_expire(void *obj, void *arg, int flags)
140 {
141         struct ast_sip_contact *contact = obj;
142
143         /* If the contact has not yet expired it is valid */
144         if (ast_tvdiff_ms(contact->expiration_time, ast_tvnow()) > 0) {
145                 return 0;
146         }
147
148         ast_sip_location_delete_contact(contact);
149
150         return CMP_MATCH;
151 }
152
153 /*! \brief Internal callback function which links static contacts into another container */
154 static int contact_link_static(void *obj, void *arg, int flags)
155 {
156         struct ao2_container *dest = arg;
157
158         ao2_link(dest, obj);
159         return 0;
160 }
161
162 struct ast_sip_contact *ast_sip_location_retrieve_first_aor_contact(const struct ast_sip_aor *aor)
163 {
164         RAII_VAR(struct ao2_container *, contacts, NULL, ao2_cleanup);
165         struct ast_sip_contact *contact;
166
167         contacts = ast_sip_location_retrieve_aor_contacts(aor);
168         if (!contacts || (ao2_container_count(contacts) == 0)) {
169                 return NULL;
170         }
171
172         /* Get the first AOR contact in the container. */
173         contact = ao2_callback(contacts, 0, NULL, NULL);
174         return contact;
175 }
176
177 struct ao2_container *ast_sip_location_retrieve_aor_contacts_nolock(const struct ast_sip_aor *aor)
178 {
179         /* Give enough space for ^ at the beginning and ;@ at the end, since that is our object naming scheme */
180         char regex[strlen(ast_sorcery_object_get_id(aor)) + 4];
181         struct ao2_container *contacts;
182
183         snprintf(regex, sizeof(regex), "^%s;@", ast_sorcery_object_get_id(aor));
184
185         if (!(contacts = ast_sorcery_retrieve_by_regex(ast_sip_get_sorcery(), "contact", regex))) {
186                 return NULL;
187         }
188
189         /* Prune any expired contacts and delete them, we do this first because static contacts can never expire */
190         ao2_callback(contacts, OBJ_NODATA | OBJ_MULTIPLE | OBJ_UNLINK, contact_expire, NULL);
191
192         /* Add any permanent contacts from the AOR */
193         if (aor->permanent_contacts) {
194                 ao2_callback(aor->permanent_contacts, OBJ_NODATA, contact_link_static, contacts);
195         }
196
197         return contacts;
198 }
199
200 struct ao2_container *ast_sip_location_retrieve_aor_contacts(const struct ast_sip_aor *aor)
201 {
202         struct ao2_container *contacts;
203         struct ast_named_lock *lock;
204
205         lock = ast_named_lock_get(AST_NAMED_LOCK_TYPE_RWLOCK, "aor", ast_sorcery_object_get_id(aor));
206         if (!lock) {
207                 return NULL;
208         }
209
210         ao2_wrlock(lock);
211         contacts = ast_sip_location_retrieve_aor_contacts_nolock(aor);
212         ao2_unlock(lock);
213         ast_named_lock_put(lock);
214
215         return contacts;
216 }
217
218 void ast_sip_location_retrieve_contact_and_aor_from_list(const char *aor_list, struct ast_sip_aor **aor,
219         struct ast_sip_contact **contact)
220 {
221         char *aor_name;
222         char *rest;
223
224         /* If the location is still empty we have nowhere to go */
225         if (ast_strlen_zero(aor_list) || !(rest = ast_strdupa(aor_list))) {
226                 ast_log(LOG_WARNING, "Unable to determine contacts from empty aor list\n");
227                 return;
228         }
229
230         *aor = NULL;
231         *contact = NULL;
232
233         while ((aor_name = ast_strip(strsep(&rest, ",")))) {
234                 *aor = ast_sip_location_retrieve_aor(aor_name);
235
236                 if (!(*aor)) {
237                         continue;
238                 }
239                 *contact = ast_sip_location_retrieve_first_aor_contact(*aor);
240                 /* If a valid contact is available use its URI for dialing */
241                 if (*contact) {
242                         break;
243                 }
244
245                 ao2_ref(*aor, -1);
246                 *aor = NULL;
247         }
248 }
249
250 struct ast_sip_contact *ast_sip_location_retrieve_contact_from_aor_list(const char *aor_list)
251 {
252         struct ast_sip_aor *aor;
253         struct ast_sip_contact *contact;
254
255         ast_sip_location_retrieve_contact_and_aor_from_list(aor_list, &aor, &contact);
256
257         ao2_cleanup(aor);
258
259         return contact;
260 }
261
262 static int permanent_uri_sort_fn(const void *obj_left, const void *obj_right, int flags);
263 static int cli_contact_populate_container(void *obj, void *arg, int flags);
264
265 static int gather_contacts_for_aor(void *obj, void *arg, int flags)
266 {
267         struct ao2_container *aor_contacts;
268         struct ast_sip_aor *aor = obj;
269         struct ao2_container *container = arg;
270
271         aor_contacts = ast_sip_location_retrieve_aor_contacts(aor);
272         if (!aor_contacts) {
273                 return 0;
274         }
275         ao2_callback(aor_contacts, OBJ_MULTIPLE | OBJ_NODATA, cli_contact_populate_container,
276                 container);
277         ao2_ref(aor_contacts, -1);
278         return CMP_MATCH;
279 }
280
281 struct ao2_container *ast_sip_location_retrieve_contacts_from_aor_list(const char *aor_list)
282 {
283         struct ao2_container *contacts;
284
285         contacts = ao2_container_alloc_list(AO2_ALLOC_OPT_LOCK_NOLOCK,
286                 AO2_CONTAINER_ALLOC_OPT_DUPS_REJECT, permanent_uri_sort_fn, NULL);
287         if (!contacts) {
288                 return NULL;
289         }
290
291         ast_sip_for_each_aor(aor_list, gather_contacts_for_aor, contacts);
292
293         return contacts;
294 }
295
296 struct ast_sip_contact *ast_sip_location_retrieve_contact(const char *contact_name)
297 {
298         return ast_sorcery_retrieve_by_id(ast_sip_get_sorcery(), "contact", contact_name);
299 }
300
301 int ast_sip_location_add_contact_nolock(struct ast_sip_aor *aor, const char *uri,
302                 struct timeval expiration_time, const char *path_info, const char *user_agent,
303                 struct ast_sip_endpoint *endpoint)
304 {
305         char name[MAX_OBJECT_FIELD * 2 + 3];
306         RAII_VAR(struct ast_sip_contact *, contact, NULL, ao2_cleanup);
307         char hash[33];
308
309         ast_md5_hash(hash, uri);
310         snprintf(name, sizeof(name), "%s;@%s", ast_sorcery_object_get_id(aor), hash);
311
312         if (!(contact = ast_sorcery_alloc(ast_sip_get_sorcery(), "contact", name))) {
313                 return -1;
314         }
315
316         ast_string_field_set(contact, uri, uri);
317         contact->expiration_time = expiration_time;
318         contact->qualify_frequency = aor->qualify_frequency;
319         contact->qualify_timeout = aor->qualify_timeout;
320         contact->authenticate_qualify = aor->authenticate_qualify;
321         if (path_info && aor->support_path) {
322                 ast_string_field_set(contact, path, path_info);
323         }
324
325         if (!ast_strlen_zero(aor->outbound_proxy)) {
326                 ast_string_field_set(contact, outbound_proxy, aor->outbound_proxy);
327         }
328
329         if (!ast_strlen_zero(user_agent)) {
330                 ast_string_field_set(contact, user_agent, user_agent);
331         }
332
333         contact->endpoint = ao2_bump(endpoint);
334
335         return ast_sorcery_create(ast_sip_get_sorcery(), contact);
336 }
337
338 int ast_sip_location_add_contact(struct ast_sip_aor *aor, const char *uri,
339                 struct timeval expiration_time, const char *path_info, const char *user_agent,
340                 struct ast_sip_endpoint *endpoint)
341 {
342         int res;
343         struct ast_named_lock *lock;
344
345         lock = ast_named_lock_get(AST_NAMED_LOCK_TYPE_RWLOCK, "aor", ast_sorcery_object_get_id(aor));
346         if (!lock) {
347                 return -1;
348         }
349
350         ao2_wrlock(lock);
351         res = ast_sip_location_add_contact_nolock(aor, uri, expiration_time, path_info, user_agent,
352                 endpoint);
353         ao2_unlock(lock);
354         ast_named_lock_put(lock);
355
356         return res;
357 }
358
359 int ast_sip_location_update_contact(struct ast_sip_contact *contact)
360 {
361         return ast_sorcery_update(ast_sip_get_sorcery(), contact);
362 }
363
364 int ast_sip_location_delete_contact(struct ast_sip_contact *contact)
365 {
366         return ast_sorcery_delete(ast_sip_get_sorcery(), contact);
367 }
368
369 /*! \brief Custom handler for translating from a string timeval to actual structure */
370 static int expiration_str2struct(const struct aco_option *opt, struct ast_variable *var, void *obj)
371 {
372         struct ast_sip_contact *contact = obj;
373         return ast_get_timeval(var->value, &contact->expiration_time, ast_tv(0, 0), NULL);
374 }
375
376 /*! \brief Custom handler for translating from an actual structure timeval to string */
377 static int expiration_struct2str(const void *obj, const intptr_t *args, char **buf)
378 {
379         const struct ast_sip_contact *contact = obj;
380         return (ast_asprintf(buf, "%ld", contact->expiration_time.tv_sec) < 0) ? -1 : 0;
381 }
382
383 static int permanent_uri_sort_fn(const void *obj_left, const void *obj_right, int flags)
384 {
385         const struct ast_sip_contact *object_left = obj_left;
386         const struct ast_sip_contact *object_right = obj_right;
387         const char *right_key = obj_right;
388         int cmp;
389
390         switch (flags & OBJ_SEARCH_MASK) {
391         case OBJ_SEARCH_OBJECT:
392                 right_key = ast_sorcery_object_get_id(object_right);
393                 /* Fall through */
394         case OBJ_SEARCH_KEY:
395                 cmp = strcmp(ast_sorcery_object_get_id(object_left), right_key);
396                 break;
397         case OBJ_SEARCH_PARTIAL_KEY:
398                 /*
399                  * We could also use a partial key struct containing a length
400                  * so strlen() does not get called for every comparison instead.
401                  */
402                 cmp = strncmp(ast_sorcery_object_get_id(object_left), right_key, strlen(right_key));
403                 break;
404         default:
405                 /* Sort can only work on something with a full or partial key. */
406                 ast_assert(0);
407                 cmp = 0;
408                 break;
409         }
410         return cmp;
411 }
412
413 int ast_sip_validate_uri_length(const char *contact_uri)
414 {
415         int max_length = pj_max_hostname - 1;
416         char *contact = ast_strdupa(contact_uri);
417         char *host;
418         char *at;
419         int theres_a_port = 0;
420
421         if (strlen(contact_uri) > pjsip_max_url_size - 1) {
422                 return -1;
423         }
424
425         contact = ast_strip_quoted(contact, "<", ">");
426
427         if (!strncasecmp(contact, "sip:", 4)) {
428                 host = contact + 4;
429         } else if (!strncasecmp(contact, "sips:", 5)) {
430                 host = contact + 5;
431         } else {
432                 /* Not a SIP URI */
433                 return -1;
434         }
435
436         at = strchr(contact, '@');
437         if (at) {
438                 /* sip[s]:user@host */
439                 host = at + 1;
440         }
441
442         if (host[0] == '[') {
443                 /* Host is an IPv6 address. Just get up to the matching bracket */
444                 char *close_bracket;
445
446                 close_bracket = strchr(host, ']');
447                 if (!close_bracket) {
448                         return -1;
449                 }
450                 close_bracket++;
451                 if (*close_bracket == ':') {
452                         theres_a_port = 1;
453                 }
454                 *close_bracket = '\0';
455         } else {
456                 /* uri parameters could contain ';' so trim them off first */
457                 host = strsep(&host, ";?");
458                 /* Host is FQDN or IPv4 address. Need to find closing delimiter */
459                 if (strchr(host, ':')) {
460                         theres_a_port = 1;
461                         host = strsep(&host, ":");
462                 }
463         }
464
465         if (!theres_a_port) {
466                 max_length -= strlen("_sips.tcp.");
467         }
468
469         if (strlen(host) > max_length) {
470                 return -1;
471         }
472
473         return 0;
474 }
475
476 /*! \brief Custom handler for permanent URIs */
477 static int permanent_uri_handler(const struct aco_option *opt, struct ast_variable *var, void *obj)
478 {
479         struct ast_sip_aor *aor = obj;
480         const char *aor_id = ast_sorcery_object_get_id(aor);
481         char *contacts;
482         char *contact_uri;
483
484         if (ast_strlen_zero(var->value)) {
485                 return 0;
486         }
487
488         contacts = ast_strdupa(var->value);
489         while ((contact_uri = ast_strip(strsep(&contacts, ",")))) {
490                 struct ast_sip_contact *contact;
491                 struct ast_sip_contact_status *status;
492                 char hash[33];
493                 char contact_id[strlen(aor_id) + sizeof(hash) + 2];
494
495                 if (ast_strlen_zero(contact_uri)) {
496                         continue;
497                 }
498
499                 if (ast_sip_validate_uri_length(contact_uri)) {
500                         ast_log(LOG_ERROR, "Contact uri or hostname length exceeds pjproject limit: %s\n", contact_uri);
501                         return -1;
502                 }
503
504                 if (!aor->permanent_contacts) {
505                         aor->permanent_contacts = ao2_container_alloc_list(AO2_ALLOC_OPT_LOCK_NOLOCK,
506                                 AO2_CONTAINER_ALLOC_OPT_DUPS_REJECT, permanent_uri_sort_fn, NULL);
507                         if (!aor->permanent_contacts) {
508                                 return -1;
509                         }
510                 }
511
512                 ast_md5_hash(hash, contact_uri);
513                 snprintf(contact_id, sizeof(contact_id), "%s@@%s", aor_id, hash);
514                 contact = ast_sorcery_alloc(ast_sip_get_sorcery(), "contact", contact_id);
515                 if (!contact) {
516                         return -1;
517                 }
518
519                 ast_string_field_set(contact, uri, contact_uri);
520
521                 status = ast_res_pjsip_find_or_create_contact_status(contact);
522                 if (!status) {
523                         ao2_ref(contact, -1);
524                         return -1;
525                 }
526                 ao2_ref(status, -1);
527
528                 ao2_link(aor->permanent_contacts, contact);
529                 ao2_ref(contact, -1);
530         }
531
532         return 0;
533 }
534
535 static int contact_to_var_list(void *object, void *arg, int flags)
536 {
537         struct ast_sip_contact_wrapper *wrapper = object;
538         struct ast_variable **var = arg;
539
540         ast_variable_list_append(&*var, ast_variable_new("contact", wrapper->contact->uri, ""));
541
542         return 0;
543 }
544
545 static int contacts_to_var_list(const void *obj, struct ast_variable **fields)
546 {
547         const struct ast_sip_aor *aor = obj;
548
549         ast_sip_for_each_contact(aor, contact_to_var_list, fields);
550
551         return 0;
552 }
553
554 static int voicemail_extension_handler(const struct aco_option *opt, struct ast_variable *var, void *obj)
555 {
556         struct ast_sip_aor *aor = obj;
557
558         aor->voicemail_extension = ast_strdup(var->value);
559
560         return aor->voicemail_extension ? 0 : -1;
561 }
562
563 static int voicemail_extension_to_str(const void *obj, const intptr_t *args, char **buf)
564 {
565         const struct ast_sip_aor *aor = obj;
566
567         *buf = ast_strdup(aor->voicemail_extension);
568
569         return 0;
570 }
571
572 int ast_sip_for_each_aor(const char *aors, ao2_callback_fn on_aor, void *arg)
573 {
574         char *copy, *name;
575
576         if (!on_aor || ast_strlen_zero(aors)) {
577                 return 0;
578         }
579
580         copy = ast_strdupa(aors);
581         while ((name = ast_strip(strsep(&copy, ",")))) {
582                 RAII_VAR(struct ast_sip_aor *, aor,
583                          ast_sip_location_retrieve_aor(name), ao2_cleanup);
584
585                 if (!aor) {
586                         continue;
587                 }
588
589                 if (on_aor(aor, arg, 0)) {
590                         return -1;
591                 }
592         }
593         return 0;
594 }
595
596 static void contact_wrapper_destroy(void *obj)
597 {
598         struct ast_sip_contact_wrapper *wrapper = obj;
599         ast_free(wrapper->aor_id);
600         ast_free(wrapper->contact_id);
601         ao2_ref(wrapper->contact, -1);
602 }
603
604 int ast_sip_for_each_contact(const struct ast_sip_aor *aor,
605                 ao2_callback_fn on_contact, void *arg)
606 {
607         RAII_VAR(struct ao2_container *, contacts, NULL, ao2_cleanup);
608         struct ao2_iterator i;
609         int res = 0;
610         void *object = NULL;
611
612         if (!on_contact ||
613             !(contacts = ast_sip_location_retrieve_aor_contacts(aor))) {
614                 return 0;
615         }
616
617         i = ao2_iterator_init(contacts, 0);
618         while ((object = ao2_iterator_next(&i))) {
619                 RAII_VAR(struct ast_sip_contact *, contact, object, ao2_cleanup);
620                 RAII_VAR(struct ast_sip_contact_wrapper *, wrapper, NULL, ao2_cleanup);
621                 const char *aor_id = ast_sorcery_object_get_id(aor);
622
623                 wrapper = ao2_alloc(sizeof(struct ast_sip_contact_wrapper), contact_wrapper_destroy);
624                 if (!wrapper) {
625                         res = -1;
626                         break;
627                 }
628                 wrapper->contact_id = ast_malloc(strlen(aor_id) + strlen(contact->uri) + 2);
629                 if (!wrapper->contact_id) {
630                         res = -1;
631                         break;
632                 }
633                 sprintf(wrapper->contact_id, "%s/%s", aor_id, contact->uri);
634                 wrapper->aor_id = ast_strdup(aor_id);
635                 if (!wrapper->aor_id) {
636                         res = -1;
637                         break;
638                 }
639                 wrapper->contact = contact;
640                 ao2_bump(wrapper->contact);
641
642                 if ((res = on_contact(wrapper, arg, 0))) {
643                         break;
644                 }
645         }
646         ao2_iterator_destroy(&i);
647         return res;
648 }
649
650 int ast_sip_contact_to_str(void *object, void *arg, int flags)
651 {
652         struct ast_sip_contact_wrapper *wrapper = object;
653         struct ast_str **buf = arg;
654
655         ast_str_append(buf, 0, "%s,", wrapper->contact_id);
656
657         return 0;
658 }
659
660 static int sip_aor_to_ami(const struct ast_sip_aor *aor, struct ast_str **buf)
661 {
662         RAII_VAR(struct ast_variable *, objset, ast_sorcery_objectset_create2(
663                          ast_sip_get_sorcery(), aor, AST_HANDLER_ONLY_STRING), ast_variables_destroy);
664         struct ast_variable *i;
665
666         if (!objset) {
667                 return -1;
668         }
669
670         ast_str_append(buf, 0, "ObjectType: %s\r\n",
671                        ast_sorcery_object_get_type(aor));
672         ast_str_append(buf, 0, "ObjectName: %s\r\n",
673                        ast_sorcery_object_get_id(aor));
674
675         for (i = objset; i; i = i->next) {
676                 char *camel = ast_to_camel_case(i->name);
677                 if (strcmp(camel, "Contact") == 0) {
678                         ast_free(camel);
679                         camel = NULL;
680                 }
681                 ast_str_append(buf, 0, "%s: %s\r\n", S_OR(camel, "Contacts"), i->value);
682                 ast_free(camel);
683         }
684
685         return 0;
686 }
687
688 static int contacts_to_str(const void *obj, const intptr_t *args, char **buf)
689 {
690         const struct ast_sip_aor *aor = obj;
691         RAII_VAR(struct ast_str *, str, ast_str_create(MAX_OBJECT_FIELD), ast_free);
692
693         ast_sip_for_each_contact(aor, ast_sip_contact_to_str, &str);
694         ast_str_truncate(str, -1);
695
696         *buf = ast_strdup(ast_str_buffer(str));
697         if (!*buf) {
698                 return -1;
699         }
700
701         return 0;
702 }
703
704 static int format_ami_aor_handler(void *obj, void *arg, int flags)
705 {
706         struct ast_sip_aor *aor = obj;
707         struct ast_sip_ami *ami = arg;
708         const struct ast_sip_endpoint *endpoint = ami->arg;
709         RAII_VAR(struct ast_str *, buf,
710                  ast_sip_create_ami_event("AorDetail", ami), ast_free);
711
712         int total_contacts;
713         int num_permanent;
714         RAII_VAR(struct ao2_container *, contacts,
715                  ast_sip_location_retrieve_aor_contacts(aor), ao2_cleanup);
716
717         if (!buf) {
718                 return -1;
719         }
720
721         sip_aor_to_ami(aor, &buf);
722         total_contacts = ao2_container_count(contacts);
723         num_permanent = aor->permanent_contacts ?
724                 ao2_container_count(aor->permanent_contacts) : 0;
725
726         ast_str_append(&buf, 0, "TotalContacts: %d\r\n", total_contacts);
727         ast_str_append(&buf, 0, "ContactsRegistered: %d\r\n",
728                        total_contacts - num_permanent);
729         ast_str_append(&buf, 0, "EndpointName: %s\r\n",
730                        ast_sorcery_object_get_id(endpoint));
731
732         astman_append(ami->s, "%s\r\n", ast_str_buffer(buf));
733         ami->count++;
734
735         return 0;
736 }
737
738 static int format_ami_endpoint_aor(const struct ast_sip_endpoint *endpoint,
739                                    struct ast_sip_ami *ami)
740 {
741         ami->arg = (void *)endpoint;
742         return ast_sip_for_each_aor(endpoint->aors,
743                                     format_ami_aor_handler, ami);
744 }
745
746 struct ast_sip_endpoint_formatter endpoint_aor_formatter = {
747         .format_ami = format_ami_endpoint_aor
748 };
749
750 static struct ao2_container *cli_aor_get_container(const char *regex)
751 {
752         RAII_VAR(struct ao2_container *, container, NULL, ao2_cleanup);
753         struct ao2_container *s_container;
754
755         container = ast_sorcery_retrieve_by_regex(ast_sip_get_sorcery(), "aor", regex);
756         if (!container) {
757                 return NULL;
758         }
759
760         s_container = ao2_container_alloc_list(AO2_ALLOC_OPT_LOCK_NOLOCK, 0,
761                 ast_sorcery_object_id_sort, ast_sorcery_object_id_compare);
762         if (!s_container) {
763                 return NULL;
764         }
765
766         if (ao2_container_dup(s_container, container, 0)) {
767                 ao2_ref(s_container, -1);
768                 return NULL;
769         }
770
771         return s_container;
772 }
773
774 static int cli_contact_populate_container(void *obj, void *arg, int flags)
775 {
776         ao2_link(arg, obj);
777
778         return 0;
779 }
780
781 static int cli_aor_gather_contacts(void *obj, void *arg, int flags)
782 {
783         struct ast_sip_aor *aor = obj;
784
785         return ast_sip_for_each_contact(aor, cli_contact_populate_container, arg);
786 }
787
788 static const char *cli_contact_get_id(const void *obj)
789 {
790         const struct ast_sip_contact_wrapper *wrapper = obj;
791         return wrapper->contact_id;
792 }
793
794 static int cli_contact_sort(const void *obj, const void *arg, int flags)
795 {
796         const struct ast_sip_contact_wrapper *left_wrapper = obj;
797         const struct ast_sip_contact_wrapper *right_wrapper = arg;
798         const char *right_key = arg;
799         int cmp = 0;
800
801         switch (flags & OBJ_SEARCH_MASK) {
802         case OBJ_SEARCH_OBJECT:
803                 right_key = right_wrapper->contact_id;
804                 /* Fall through */
805         case OBJ_SEARCH_KEY:
806                 cmp = strcmp(left_wrapper->contact_id, right_key);
807                 break;
808         case OBJ_SEARCH_PARTIAL_KEY:
809                 cmp = strncmp(left_wrapper->contact_id, right_key, strlen(right_key));
810                 break;
811         default:
812                 cmp = 0;
813                 break;
814         }
815
816         return cmp;
817 }
818
819 static int cli_contact_compare(void *obj, void *arg, int flags)
820 {
821         const struct ast_sip_contact_wrapper *left_wrapper = obj;
822         const struct ast_sip_contact_wrapper *right_wrapper = arg;
823         const char *right_key = arg;
824         int cmp = 0;
825
826         switch (flags & OBJ_SEARCH_MASK) {
827         case OBJ_SEARCH_OBJECT:
828                 right_key = right_wrapper->contact_id;
829                 /* Fall through */
830         case OBJ_SEARCH_KEY:
831                 if (strcmp(left_wrapper->contact_id, right_key) == 0) {;
832                         cmp = CMP_MATCH | CMP_STOP;
833                 }
834                 break;
835         case OBJ_SEARCH_PARTIAL_KEY:
836                 if (strncmp(left_wrapper->contact_id, right_key, strlen(right_key)) == 0) {
837                         cmp = CMP_MATCH;
838                 }
839                 break;
840         default:
841                 cmp = 0;
842                 break;
843         }
844
845         return cmp;
846 }
847
848 static int cli_contact_iterate(void *container, ao2_callback_fn callback, void *args)
849 {
850         return ast_sip_for_each_contact(container, callback, args);
851 }
852
853 static int cli_filter_contacts(void *obj, void *arg, int flags)
854 {
855         struct ast_sip_contact_wrapper *wrapper = obj;
856         regex_t *regexbuf = arg;
857
858         if (!regexec(regexbuf, wrapper->contact_id, 0, NULL, 0)) {
859                 return 0;
860         }
861
862         return CMP_MATCH;
863 }
864
865 static struct ao2_container *cli_contact_get_container(const char *regex)
866 {
867         RAII_VAR(struct ao2_container *, parent_container, NULL, ao2_cleanup);
868         struct ao2_container *child_container;
869         regex_t regexbuf;
870
871         parent_container =  cli_aor_get_container("");
872         if (!parent_container) {
873                 return NULL;
874         }
875
876         child_container = ao2_container_alloc_list(AO2_ALLOC_OPT_LOCK_NOLOCK, 0,
877                 cli_contact_sort, cli_contact_compare);
878         if (!child_container) {
879                 return NULL;
880         }
881
882         ao2_callback(parent_container, OBJ_NODATA, cli_aor_gather_contacts, child_container);
883
884         if (!ast_strlen_zero(regex)) {
885                 if (regcomp(&regexbuf, regex, REG_EXTENDED | REG_NOSUB)) {
886                         ao2_ref(child_container, -1);
887                         return NULL;
888                 }
889                 ao2_callback(child_container, OBJ_UNLINK | OBJ_MULTIPLE | OBJ_NODATA, cli_filter_contacts, &regexbuf);
890                 regfree(&regexbuf);
891         }
892
893         return child_container;
894 }
895
896 static void *cli_contact_retrieve_by_id(const char *id)
897 {
898         RAII_VAR(struct ao2_container *, container, cli_contact_get_container(""), ao2_cleanup);
899
900         return ao2_find(container, id, OBJ_KEY | OBJ_NOLOCK);
901 }
902
903 static int cli_contact_print_header(void *obj, void *arg, int flags)
904 {
905         struct ast_sip_cli_context *context = arg;
906         int indent = CLI_INDENT_TO_SPACES(context->indent_level);
907         int filler = CLI_LAST_TABSTOP - indent - 23;
908
909         ast_assert(context->output_buffer != NULL);
910
911         ast_str_append(&context->output_buffer, 0,
912                 "%*s:  <Aor/ContactUri%*.*s> <Hash....> <Status> <RTT(ms)..>\n",
913                 indent, "Contact", filler, filler, CLI_HEADER_FILLER);
914
915         return 0;
916 }
917
918 static int cli_contact_print_body(void *obj, void *arg, int flags)
919 {
920         struct ast_sip_contact_wrapper *wrapper = obj;
921         struct ast_sip_contact *contact = wrapper->contact;
922         struct ast_sip_cli_context *context = arg;
923         int indent;
924         int flexwidth;
925         const char *contact_id = ast_sorcery_object_get_id(contact);
926         const char *hash_start = contact_id + strlen(contact->aor) + 2;
927
928         RAII_VAR(struct ast_sip_contact_status *, status,
929                 ast_sorcery_retrieve_by_id( ast_sip_get_sorcery(), CONTACT_STATUS, contact_id),
930                 ao2_cleanup);
931
932         ast_assert(contact->uri != NULL);
933         ast_assert(context->output_buffer != NULL);
934
935         indent = CLI_INDENT_TO_SPACES(context->indent_level);
936         flexwidth = CLI_LAST_TABSTOP - indent - 9 - strlen(contact->aor) + 1;
937
938         ast_str_append(&context->output_buffer, 0, "%*s:  %s/%-*.*s %-10.10s %-7.7s %11.3f\n",
939                 indent,
940                 "Contact",
941                 contact->aor,
942                 flexwidth, flexwidth,
943                 contact->uri,
944                 hash_start,
945                 ast_sip_get_contact_short_status_label(status ? status->status : UNKNOWN),
946                 (status && (status->status != UNKNOWN) ? ((long long) status->rtt) / 1000.0 : NAN));
947
948         return 0;
949 }
950
951 static int cli_aor_iterate(void *container, ao2_callback_fn callback, void *args)
952 {
953         const char *aor_list = container;
954
955         return ast_sip_for_each_aor(aor_list, callback, args);
956 }
957
958 static void *cli_aor_retrieve_by_id(const char *id)
959 {
960         return ast_sorcery_retrieve_by_id(ast_sip_get_sorcery(), "aor", id);
961 }
962
963 static const char *cli_aor_get_id(const void *obj)
964 {
965         return ast_sorcery_object_get_id(obj);
966 }
967
968 static int cli_aor_print_header(void *obj, void *arg, int flags)
969 {
970         struct ast_sip_cli_context *context = arg;
971         RAII_VAR(struct ast_sip_cli_formatter_entry *, formatter_entry, NULL, ao2_cleanup);
972
973         int indent = CLI_INDENT_TO_SPACES(context->indent_level);
974         int filler = CLI_LAST_TABSTOP - indent - 7;
975
976         ast_assert(context->output_buffer != NULL);
977
978         ast_str_append(&context->output_buffer, 0,
979                 "%*s:  <Aor%*.*s>  <MaxContact>\n",
980                 indent, "Aor", filler, filler, CLI_HEADER_FILLER);
981
982         if (context->recurse) {
983                 context->indent_level++;
984                 formatter_entry = ast_sip_lookup_cli_formatter("contact");
985                 if (formatter_entry) {
986                         formatter_entry->print_header(NULL, context, 0);
987                 }
988                 context->indent_level--;
989         }
990
991         return 0;
992 }
993
994 static int cli_aor_print_body(void *obj, void *arg, int flags)
995 {
996         struct ast_sip_aor *aor = obj;
997         struct ast_sip_cli_context *context = arg;
998         RAII_VAR(struct ast_sip_cli_formatter_entry *, formatter_entry, NULL, ao2_cleanup);
999         int indent;
1000         int flexwidth;
1001
1002         ast_assert(context->output_buffer != NULL);
1003
1004 //      context->current_aor = aor;
1005
1006         indent = CLI_INDENT_TO_SPACES(context->indent_level);
1007         flexwidth = CLI_LAST_TABSTOP - indent - 12;
1008
1009         ast_str_append(&context->output_buffer, 0, "%*s:  %-*.*s %12u\n",
1010                 indent,
1011                 "Aor",
1012                 flexwidth, flexwidth,
1013                 ast_sorcery_object_get_id(aor), aor->max_contacts);
1014
1015         if (context->recurse) {
1016                 context->indent_level++;
1017
1018                 formatter_entry = ast_sip_lookup_cli_formatter("contact");
1019                 if (formatter_entry) {
1020                         formatter_entry->iterate(aor, formatter_entry->print_body, context);
1021                 }
1022
1023                 context->indent_level--;
1024
1025                 if (context->indent_level == 0) {
1026                         ast_str_append(&context->output_buffer, 0, "\n");
1027                 }
1028         }
1029
1030         if (context->show_details || (context->show_details_only_level_0 && context->indent_level == 0)) {
1031                 ast_str_append(&context->output_buffer, 0, "\n");
1032                 ast_sip_cli_print_sorcery_objectset(aor, context, 0);
1033         }
1034
1035         return 0;
1036 }
1037
1038 static struct ast_cli_entry cli_commands[] = {
1039         AST_CLI_DEFINE(ast_sip_cli_traverse_objects, "List PJSIP Aors",
1040                 .command = "pjsip list aors",
1041                 .usage = "Usage: pjsip list aors [ like <pattern> ]\n"
1042                                 "       List the configured PJSIP Aors\n"
1043                                 "       Optional regular expression pattern is used to filter the list.\n"),
1044         AST_CLI_DEFINE(ast_sip_cli_traverse_objects, "Show PJSIP Aors",
1045                 .command = "pjsip show aors",
1046                 .usage = "Usage: pjsip show aors [ like <pattern> ]\n"
1047                                 "       Show the configured PJSIP Aors\n"
1048                                 "       Optional regular expression pattern is used to filter the list.\n"),
1049         AST_CLI_DEFINE(ast_sip_cli_traverse_objects, "Show PJSIP Aor",
1050                 .command = "pjsip show aor",
1051                 .usage = "Usage: pjsip show aor <id>\n"
1052                                  "       Show the configured PJSIP Aor\n"),
1053
1054         AST_CLI_DEFINE(ast_sip_cli_traverse_objects, "List PJSIP Contacts",
1055                 .command = "pjsip list contacts",
1056                 .usage = "Usage: pjsip list contacts [ like <pattern> ]\n"
1057                                 "       List the configured PJSIP contacts\n"
1058                                 "       Optional regular expression pattern is used to filter the list.\n"),
1059         AST_CLI_DEFINE(ast_sip_cli_traverse_objects, "Show PJSIP Contacts",
1060                 .command = "pjsip show contacts",
1061                 .usage = "Usage: pjsip show contacts [ like <pattern> ]\n"
1062                                 "       Show the configured PJSIP contacts\n"
1063                                 "       Optional regular expression pattern is used to filter the list.\n"),
1064         AST_CLI_DEFINE(ast_sip_cli_traverse_objects, "Show PJSIP Contact",
1065                 .command = "pjsip show contact",
1066                 .usage = "Usage: pjsip show contact\n"
1067                                  "       Show the configured PJSIP contact\n"),
1068 };
1069
1070 struct ast_sip_cli_formatter_entry *contact_formatter;
1071 struct ast_sip_cli_formatter_entry *aor_formatter;
1072
1073 /*! \brief Always create a contact_status for each contact */
1074 static int contact_apply_handler(const struct ast_sorcery *sorcery, void *object)
1075 {
1076         struct ast_sip_contact_status *status;
1077         struct ast_sip_contact *contact = object;
1078
1079         status = ast_res_pjsip_find_or_create_contact_status(contact);
1080         ao2_cleanup(status);
1081
1082         return status ? 0 : -1;
1083 }
1084
1085 /*! \brief Initialize sorcery with location support */
1086 int ast_sip_initialize_sorcery_location(void)
1087 {
1088         struct ast_sorcery *sorcery = ast_sip_get_sorcery();
1089         int i;
1090
1091         ast_pjproject_get_buildopt("PJ_MAX_HOSTNAME", "%d", &pj_max_hostname);
1092         /* As of pjproject 2.4.5, PJSIP_MAX_URL_SIZE isn't exposed yet but we try anyway. */
1093         ast_pjproject_get_buildopt("PJSIP_MAX_URL_SIZE", "%d", &pjsip_max_url_size);
1094
1095         ast_sorcery_apply_default(sorcery, "contact", "astdb", "registrar");
1096         ast_sorcery_apply_default(sorcery, "aor", "config", "pjsip.conf,criteria=type=aor");
1097
1098         if (ast_sorcery_object_register(sorcery, "contact", contact_alloc, NULL, contact_apply_handler) ||
1099                 ast_sorcery_object_register(sorcery, "aor", aor_alloc, NULL, NULL)) {
1100                 return -1;
1101         }
1102
1103         ast_sorcery_observer_add(sorcery, "aor", &aor_observer);
1104
1105         ast_sorcery_object_field_register(sorcery, "contact", "type", "", OPT_NOOP_T, 0, 0);
1106         ast_sorcery_object_field_register(sorcery, "contact", "uri", "", OPT_STRINGFIELD_T, 0, STRFLDSET(struct ast_sip_contact, uri));
1107         ast_sorcery_object_field_register(sorcery, "contact", "path", "", OPT_STRINGFIELD_T, 0, STRFLDSET(struct ast_sip_contact, path));
1108         ast_sorcery_object_field_register_custom(sorcery, "contact", "expiration_time", "", expiration_str2struct, expiration_struct2str, NULL, 0, 0);
1109         ast_sorcery_object_field_register(sorcery, "contact", "qualify_frequency", 0, OPT_UINT_T,
1110                 PARSE_IN_RANGE, FLDSET(struct ast_sip_contact, qualify_frequency), 0, 86400);
1111         ast_sorcery_object_field_register(sorcery, "contact", "qualify_timeout", "3.0", OPT_DOUBLE_T, 0, FLDSET(struct ast_sip_contact, qualify_timeout));
1112         ast_sorcery_object_field_register(sorcery, "contact", "outbound_proxy", "", OPT_STRINGFIELD_T, 0, STRFLDSET(struct ast_sip_contact, outbound_proxy));
1113         ast_sorcery_object_field_register(sorcery, "contact", "user_agent", "", OPT_STRINGFIELD_T, 0, STRFLDSET(struct ast_sip_contact, user_agent));
1114
1115         ast_sorcery_object_field_register(sorcery, "aor", "type", "", OPT_NOOP_T, 0, 0);
1116         ast_sorcery_object_field_register(sorcery, "aor", "minimum_expiration", "60", OPT_UINT_T, 0, FLDSET(struct ast_sip_aor, minimum_expiration));
1117         ast_sorcery_object_field_register(sorcery, "aor", "maximum_expiration", "7200", OPT_UINT_T, 0, FLDSET(struct ast_sip_aor, maximum_expiration));
1118         ast_sorcery_object_field_register(sorcery, "aor", "default_expiration", "3600", OPT_UINT_T, 0, FLDSET(struct ast_sip_aor, default_expiration));
1119         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);
1120         ast_sorcery_object_field_register(sorcery, "aor", "qualify_timeout", "3.0", OPT_DOUBLE_T, 0, FLDSET(struct ast_sip_aor, qualify_timeout));
1121         ast_sorcery_object_field_register(sorcery, "aor", "authenticate_qualify", "no", OPT_BOOL_T, 1, FLDSET(struct ast_sip_aor, authenticate_qualify));
1122         ast_sorcery_object_field_register(sorcery, "aor", "max_contacts", "0", OPT_UINT_T, 0, FLDSET(struct ast_sip_aor, max_contacts));
1123         ast_sorcery_object_field_register(sorcery, "aor", "remove_existing", "no", OPT_BOOL_T, 1, FLDSET(struct ast_sip_aor, remove_existing));
1124         ast_sorcery_object_field_register_custom(sorcery, "aor", "contact", "", permanent_uri_handler, contacts_to_str, contacts_to_var_list, 0, 0);
1125         ast_sorcery_object_field_register(sorcery, "aor", "mailboxes", "", OPT_STRINGFIELD_T, 0, STRFLDSET(struct ast_sip_aor, mailboxes));
1126         ast_sorcery_object_field_register_custom(sorcery, "aor", "voicemail_extension", "", voicemail_extension_handler, voicemail_extension_to_str, NULL, 0, 0);
1127         ast_sorcery_object_field_register(sorcery, "aor", "outbound_proxy", "", OPT_STRINGFIELD_T, 0, STRFLDSET(struct ast_sip_aor, outbound_proxy));
1128         ast_sorcery_object_field_register(sorcery, "aor", "support_path", "no", OPT_BOOL_T, 1, FLDSET(struct ast_sip_aor, support_path));
1129
1130         internal_sip_register_endpoint_formatter(&endpoint_aor_formatter);
1131
1132         contact_formatter = ao2_alloc(sizeof(struct ast_sip_cli_formatter_entry), NULL);
1133         if (!contact_formatter) {
1134                 ast_log(LOG_ERROR, "Unable to allocate memory for contact_formatter\n");
1135                 return -1;
1136         }
1137         contact_formatter->name = "contact";
1138         contact_formatter->print_header = cli_contact_print_header;
1139         contact_formatter->print_body = cli_contact_print_body;
1140         contact_formatter->get_container = cli_contact_get_container;
1141         contact_formatter->iterate = cli_contact_iterate;
1142         contact_formatter->get_id = cli_contact_get_id;
1143         contact_formatter->retrieve_by_id = cli_contact_retrieve_by_id;
1144
1145         aor_formatter = ao2_alloc(sizeof(struct ast_sip_cli_formatter_entry), NULL);
1146         if (!aor_formatter) {
1147                 ast_log(LOG_ERROR, "Unable to allocate memory for aor_formatter\n");
1148                 return -1;
1149         }
1150         aor_formatter->name = "aor";
1151         aor_formatter->print_header = cli_aor_print_header;
1152         aor_formatter->print_body = cli_aor_print_body;
1153         aor_formatter->get_container = cli_aor_get_container;
1154         aor_formatter->iterate = cli_aor_iterate;
1155         aor_formatter->get_id = cli_aor_get_id;
1156         aor_formatter->retrieve_by_id = cli_aor_retrieve_by_id;
1157
1158         ast_sip_register_cli_formatter(contact_formatter);
1159         ast_sip_register_cli_formatter(aor_formatter);
1160         ast_cli_register_multiple(cli_commands, ARRAY_LEN(cli_commands));
1161
1162         /*
1163          * Reset StatsD gauges in case we didn't shut down cleanly.
1164          * Note that this must done here, as contacts will create the contact_status
1165          * object before PJSIP options handling is initialized.
1166          */
1167         for (i = 0; i <= REMOVED; i++) {
1168                 ast_statsd_log_full_va("PJSIP.contacts.states.%s", AST_STATSD_GAUGE, 0, 1.0, ast_sip_get_contact_status_label(i));
1169         }
1170
1171         return 0;
1172 }
1173
1174 int ast_sip_destroy_sorcery_location(void)
1175 {
1176         ast_sorcery_observer_remove(ast_sip_get_sorcery(), "aor", &aor_observer);
1177         ast_cli_unregister_multiple(cli_commands, ARRAY_LEN(cli_commands));
1178         ast_sip_unregister_cli_formatter(contact_formatter);
1179         ast_sip_unregister_cli_formatter(aor_formatter);
1180
1181         internal_sip_unregister_endpoint_formatter(&endpoint_aor_formatter);
1182
1183         return 0;
1184 }
1185