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