VECTOR: Passing parameters with side effects to macros is dangerous.
[asterisk/asterisk.git] / res / res_pjsip / pjsip_options.c
1 /*
2  * Asterisk -- An open source telephony toolkit.
3  *
4  * Copyright (C) 2018, Digium, Inc.
5  *
6  * Joshua Colp <jcolp@digium.com>
7  * Richard Mudgett <rmudgett@digium.com>
8  *
9  * See http://www.asterisk.org for more information about
10  * the Asterisk project. Please do not directly contact
11  * any of the maintainers of this project for assistance;
12  * the project provides a web site, mailing lists and IRC
13  * channels for your use.
14  *
15  * This program is free software, distributed under the terms of
16  * the GNU General Public License Version 2. See the LICENSE file
17  * at the top of the source tree.
18  */
19
20 #include "asterisk.h"
21
22 #include <pjsip.h>
23 #include <pjsip_ua.h>
24 #include <pjlib.h>
25
26 #include "asterisk/res_pjsip.h"
27 #include "asterisk/channel.h"
28 #include "asterisk/pbx.h"
29 #include "asterisk/astobj2.h"
30 #include "asterisk/cli.h"
31 #include "asterisk/time.h"
32 #include "asterisk/test.h"
33 #include "asterisk/statsd.h"
34 #include "include/res_pjsip_private.h"
35 #include "asterisk/taskprocessor.h"
36 #include "asterisk/threadpool.h"
37
38 /*
39  * This implementation for OPTIONS support is based around the idea
40  * that realistically an AOR generally has very few contacts and is
41  * referenced by only a few endpoints. While it is perfectly fine for
42  * use in opposite scenarios it works best in the above case. It is
43  * also not shy to keeping state but it is reactive to outside changes
44  * so it can be updated.
45  *
46  * The lowest level object in here is a contact and its associated
47  * contact status. The result of an OPTIONS request to a contact is
48  * reflected in the contact status. The scheduling of these OPTIONS
49  * request is driven by the AOR. The AOR periodicially (according to
50  * configuration) sends OPTIONS requests out to any contacts
51  * associated with it. Contacts themselves are not individually
52  * scheduled. Contacts can be added or deleted as appropriate with no
53  * requirement to reschedule.
54  *
55  * The next level object up is the AOR itself. The result of a contact
56  * status change is fed into it and the result composited with all
57  * other contacts. This may result in the AOR itself changing state
58  * (it can be either AVAILABLE or UNAVAILABLE).
59  *
60  * The highest level object up is the endpoint state compositor (ESC).
61  * The result of AOR state changes is fed into it and the result
62  * composited with all other referenced AORs. This may result in the
63  * endpoint itself changing state (it can be either ONLINE or
64  * OFFLINE).  If this occurs the permanent endpoint is updated to
65  * reflect it.
66  *
67  * The threading model errs on the side of a world where things are
68  * not constantly changing. That is: A world where AORs and endpoints
69  * are not being constantly added/removed. This more closely mirrors
70  * the usage of the vast majority of people. This scenario can still
71  * be done but it may not be applied immediately.
72  *
73  * Manipulation of which AORs, endpoint state compositors, and
74  * contacts exist is done within a single serializer. This ensures
75  * that no matter the source threads order is preserved and you won't
76  * get into a weird situation where things are referencing other
77  * things that should have already been destroyed.
78  *
79  * Operations which impact the state of an AOR are done within a
80  * serializer that is specific to the AOR. This includes the result of
81  * a contact status change. This change is queued and executed on the
82  * AOR serializer afterwards.
83  *
84  * Operations which impact an endpoint state compositor are protected
85  * by a lock. This is done as the endpoint state compositor usage is
86  * minimal and the overhead of using a serializer and queueing things
87  * is not warranted.
88  *
89  * AORs which do not have a qualify frequency are also kept in here
90  * but do not require the same criteria as qualified AORs to be
91  * considered available. In their case as long as at least 1 contact
92  * is configured on the AOR (or added to it by registration) it is
93  * considered available.
94  */
95
96 #define DEFAULT_LANGUAGE "en"
97 #define DEFAULT_ENCODING "text/plain"
98
99 /*! \brief These are the number of buckets to store AORs in */
100 #ifdef LOW_MEMORY
101 #define AOR_BUCKETS 61
102 #else
103 #define AOR_BUCKETS 1567
104 #endif
105
106 /*! \brief These are the number of contact status buckets */
107 #ifdef LOW_MEMORY
108 #define CONTACT_STATUS_BUCKETS 61
109 #else
110 #define CONTACT_STATUS_BUCKETS 1567
111 #endif
112
113 /*! \brief These are the number of buckets (per AOR) to use to store contacts */
114 #define CONTACT_BUCKETS 13
115
116 /*! \brief These are the number of buckets to store endpoint state compositors */
117 #define ENDPOINT_STATE_COMPOSITOR_BUCKETS 13
118
119 /*! \brief The initial vector size for the endpoint state compositors on an AOR */
120 #define ENDPOINT_STATE_COMPOSITOR_INITIAL_SIZE 1
121
122 /*! \brief These are the number of buckets (per endpoint state compositor) to use to store AOR statuses */
123 #define AOR_STATUS_BUCKETS 3
124
125 /*! \brief Maximum wait time to join the below shutdown group */
126 #define MAX_UNLOAD_TIMEOUT_TIME         10      /* Seconds */
127
128 /*! \brief Shutdown group for options serializers */
129 static struct ast_serializer_shutdown_group *shutdown_group;
130
131 /*!
132  * \brief Structure which contains status information for an AOR feeding an endpoint state compositor
133  */
134 struct sip_options_endpoint_aor_status {
135         /*! \brief The last contributed available status of the named AOR (1 if available, 0 if not available) */
136         char available;
137         /*! \brief The name of the AOR */
138         char name[0];
139 };
140
141 /*!
142  * \brief Structure which contains composites information for endpoint state
143  */
144 struct sip_options_endpoint_state_compositor {
145         /*! \brief The last contributed available status of the AORs feeding this compositor */
146         struct ao2_container *aor_statuses;
147         /*!
148          * \brief Non-zero if the compositor is in normal operation. i.e. Not being setup/reconfigured.
149          *
150          * \details
151          * The aor layer can only update its aor_statuses record when not active.
152          * When active the aor layer can update its aor_statuses record, calculate the new
153          * number of available aors, determine if the endpoint compositor changed state,
154          * and report it.
155          */
156         char active;
157         /*! \brief The name of the endpoint */
158         char name[0];
159 };
160
161 /*!
162  * \brief Structure which contains an AOR and contacts for qualifying purposes
163  */
164 struct sip_options_aor {
165         /*! \brief The scheduler task for this AOR */
166         struct ast_sip_sched_task *sched_task;
167         /*! \brief The serializer for this AOR */
168         struct ast_taskprocessor *serializer;
169         /*! \brief All contacts associated with this AOR */
170         struct ao2_container *contacts;
171         /*!
172          * \brief Only dynamic contacts associated with this AOR
173          * \note Used to speed up applying AOR configuration by
174          * minimizing wild card sorcery access.
175          */
176         struct ao2_container *dynamic_contacts;
177         /*! \brief The endpoint state compositors we are feeding, a reference is held to each */
178         AST_VECTOR(, struct sip_options_endpoint_state_compositor *) compositors;
179         /*! \brief The number of available contacts on this AOR */
180         unsigned int available;
181         /*! \brief Frequency to send OPTIONS requests to AOR contacts. 0 is disabled. */
182         unsigned int qualify_frequency;
183         /*! If true authenticate the qualify challenge response if needed */
184         int authenticate_qualify;
185         /*! \brief Qualify timeout. 0 is diabled. */
186         double qualify_timeout;
187         /*! \brief The name of the AOR */
188         char name[0];
189 };
190
191 /*!
192  * \internal
193  * \brief Container of active SIP AORs for qualifying
194  */
195 static struct ao2_container *sip_options_aors;
196
197 /*!
198  * \internal
199  * \brief Container of contact statuses
200  */
201 static struct ao2_container *sip_options_contact_statuses;
202
203 /*!
204  * \internal
205  * \brief Container of endpoint state compositors
206  */
207 static struct ao2_container *sip_options_endpoint_state_compositors;
208
209 /*!
210  * \internal
211  * \brief Serializer for AOR, endpoint state compositor, and contact existence management
212  */
213 static struct ast_taskprocessor *management_serializer;
214
215 static pj_status_t send_options_response(pjsip_rx_data *rdata, int code)
216 {
217         pjsip_endpoint *endpt = ast_sip_get_pjsip_endpoint();
218         pjsip_dialog *dlg = pjsip_rdata_get_dlg(rdata);
219         pjsip_transaction *trans = pjsip_rdata_get_tsx(rdata);
220         pjsip_tx_data *tdata;
221         const pjsip_hdr *hdr;
222         pj_status_t status;
223
224         /* Make the response object */
225         status = ast_sip_create_response(rdata, code, NULL, &tdata);
226         if (status != PJ_SUCCESS) {
227                 ast_log(LOG_ERROR, "Unable to create response (%d)\n", status);
228                 return status;
229         }
230
231         /* Add appropriate headers */
232         if ((hdr = pjsip_endpt_get_capability(endpt, PJSIP_H_ACCEPT, NULL))) {
233                 pjsip_msg_add_hdr(tdata->msg, (pjsip_hdr*)pjsip_hdr_clone(tdata->pool, hdr));
234         }
235         if ((hdr = pjsip_endpt_get_capability(endpt, PJSIP_H_ALLOW, NULL))) {
236                 pjsip_msg_add_hdr(tdata->msg, (pjsip_hdr*)pjsip_hdr_clone(tdata->pool, hdr));
237         }
238         if ((hdr = pjsip_endpt_get_capability(endpt, PJSIP_H_SUPPORTED, NULL))) {
239                 pjsip_msg_add_hdr(tdata->msg, (pjsip_hdr*)pjsip_hdr_clone(tdata->pool, hdr));
240         }
241
242         /*
243          * XXX TODO: pjsip doesn't care a lot about either of these headers -
244          * while it provides specific methods to create them, they are defined
245          * to be the standard string header creation. We never did add them
246          * in chan_sip, although RFC 3261 says they SHOULD. Hard coded here.
247          */
248         ast_sip_add_header(tdata, "Accept-Encoding", DEFAULT_ENCODING);
249         ast_sip_add_header(tdata, "Accept-Language", DEFAULT_LANGUAGE);
250
251         if (dlg && trans) {
252                 status = pjsip_dlg_send_response(dlg, trans, tdata);
253         } else {
254                 struct ast_sip_endpoint *endpoint;
255
256                 endpoint = ast_pjsip_rdata_get_endpoint(rdata);
257                 status = ast_sip_send_stateful_response(rdata, tdata, endpoint);
258                 ao2_cleanup(endpoint);
259         }
260
261         if (status != PJ_SUCCESS) {
262                 ast_log(LOG_ERROR, "Unable to send response (%d)\n", status);
263         }
264
265         return status;
266 }
267
268 static pj_bool_t options_on_rx_request(pjsip_rx_data *rdata)
269 {
270         RAII_VAR(struct ast_sip_endpoint *, endpoint, NULL, ao2_cleanup);
271         pjsip_uri *ruri;
272         pjsip_sip_uri *sip_ruri;
273         char exten[AST_MAX_EXTENSION];
274
275         if (pjsip_method_cmp(&rdata->msg_info.msg->line.req.method, &pjsip_options_method)) {
276                 return PJ_FALSE;
277         }
278
279         if (!(endpoint = ast_pjsip_rdata_get_endpoint(rdata))) {
280                 return PJ_FALSE;
281         }
282
283         ruri = rdata->msg_info.msg->line.req.uri;
284         if (!PJSIP_URI_SCHEME_IS_SIP(ruri) && !PJSIP_URI_SCHEME_IS_SIPS(ruri)) {
285                 send_options_response(rdata, 416);
286                 return PJ_TRUE;
287         }
288
289         sip_ruri = pjsip_uri_get_uri(ruri);
290         ast_copy_pj_str(exten, &sip_ruri->user, sizeof(exten));
291
292         /*
293          * We may want to match in the dialplan without any user
294          * options getting in the way.
295          */
296         AST_SIP_USER_OPTIONS_TRUNCATE_CHECK(exten);
297
298         if (ast_shutting_down()) {
299                 /*
300                  * Not taking any new calls at this time.
301                  * Likely a server availability OPTIONS poll.
302                  */
303                 send_options_response(rdata, 503);
304         } else if (!ast_strlen_zero(exten)
305                 && !ast_exists_extension(NULL, endpoint->context, exten, 1, NULL)) {
306                 send_options_response(rdata, 404);
307         } else {
308                 send_options_response(rdata, 200);
309         }
310         return PJ_TRUE;
311 }
312
313 static pjsip_module options_module = {
314         .name = {"Options Module", 14},
315         .id = -1,
316         .priority = PJSIP_MOD_PRIORITY_APPLICATION,
317         .on_rx_request = options_on_rx_request,
318 };
319
320 static const char *status_map[] = {
321         [UNAVAILABLE] = "Unreachable",
322         [AVAILABLE] = "Reachable",
323         [UNKNOWN] = "Unknown",
324         [CREATED] = "NonQualified",
325         [REMOVED] = "Removed",
326 };
327
328 static const char *short_status_map[] = {
329         [UNAVAILABLE] = "Unavail",
330         [AVAILABLE] = "Avail",
331         [UNKNOWN] = "Unknown",
332         [CREATED] = "NonQual",
333         [REMOVED] = "Removed",
334 };
335
336 const char *ast_sip_get_contact_status_label(const enum ast_sip_contact_status_type status)
337 {
338         ast_assert(0 <= status && status < ARRAY_LEN(status_map));
339         return status_map[status];
340 }
341
342 const char *ast_sip_get_contact_short_status_label(const enum ast_sip_contact_status_type status)
343 {
344         ast_assert(0 <= status && status < ARRAY_LEN(short_status_map));
345         return short_status_map[status];
346 }
347
348 /*! \brief Destructor for contact statuses */
349 static void sip_contact_status_dtor(void *obj)
350 {
351         struct ast_sip_contact_status *contact_status = obj;
352
353         ast_string_field_free_memory(contact_status);
354 }
355
356 static struct ast_sip_contact_status *sip_contact_status_alloc(const char *name)
357 {
358         struct ast_sip_contact_status *contact_status;
359         size_t size = sizeof(*contact_status) + strlen(name) + 1;
360
361         contact_status = ao2_alloc_options(size, sip_contact_status_dtor,
362                 AO2_ALLOC_OPT_LOCK_NOLOCK);
363         if (!contact_status) {
364                 return NULL;
365         }
366         if (ast_string_field_init(contact_status, 256)) {
367                 ao2_ref(contact_status, -1);
368                 return NULL;
369         }
370         strcpy(contact_status->name, name); /* SAFE */
371         return contact_status;
372 }
373
374 static struct ast_sip_contact_status *sip_contact_status_copy(const struct ast_sip_contact_status *src)
375 {
376         struct ast_sip_contact_status *dst;
377
378         dst = sip_contact_status_alloc(src->name);
379         if (!dst) {
380                 return NULL;
381         }
382
383         if (ast_string_fields_copy(dst, src)) {
384                 ao2_ref(dst, -1);
385                 return NULL;
386         }
387         dst->rtt = src->rtt;
388         dst->status = src->status;
389         dst->last_status = src->last_status;
390         return dst;
391 }
392
393 /*! \brief Hashing function for contact statuses */
394 AO2_STRING_FIELD_HASH_FN(ast_sip_contact_status, name);
395
396 /*! \brief Sort function for contact statuses */
397 AO2_STRING_FIELD_SORT_FN(ast_sip_contact_status, name);
398
399 /*! \brief Comparator function for contact statuses */
400 AO2_STRING_FIELD_CMP_FN(ast_sip_contact_status, name);
401
402 /*! \brief Helper function to allocate a contact statuses container */
403 static struct ao2_container *sip_options_contact_statuses_alloc(void)
404 {
405         /*
406          * Replace duplicate objects so we can update the immutable
407          * contact status objects by simply linking in a new object.
408          */
409         return ao2_container_alloc_hash(AO2_ALLOC_OPT_LOCK_MUTEX,
410                 AO2_CONTAINER_ALLOC_OPT_DUPS_REPLACE, CONTACT_STATUS_BUCKETS,
411                 ast_sip_contact_status_hash_fn, ast_sip_contact_status_sort_fn,
412                 ast_sip_contact_status_cmp_fn);
413 }
414
415 /*! \brief Function which publishes a contact status update to all interested endpoints */
416 static void sip_options_publish_contact_state(const struct sip_options_aor *aor_options,
417         const struct ast_sip_contact_status *contact_status)
418 {
419         int i;
420
421         for (i = 0; i < AST_VECTOR_SIZE(&aor_options->compositors); ++i) {
422                 const struct sip_options_endpoint_state_compositor *endpoint_state_compositor;
423
424                 endpoint_state_compositor = AST_VECTOR_GET(&aor_options->compositors, i);
425                 ast_sip_persistent_endpoint_publish_contact_state(endpoint_state_compositor->name,
426                         contact_status);
427         }
428 }
429
430 /*!
431  * \brief Task to notify endpoints of a contact status change
432  * \note Run by management_serializer
433  */
434 static int contact_status_publish_update_task(void *obj)
435 {
436         struct ast_sip_contact_status *contact_status = obj;
437         struct sip_options_aor *aor_options;
438
439         aor_options = ao2_find(sip_options_aors, contact_status->aor, OBJ_SEARCH_KEY);
440         if (aor_options) {
441                 sip_options_publish_contact_state(aor_options, contact_status);
442                 ao2_ref(aor_options, -1);
443         }
444         ao2_ref(contact_status, -1);
445
446         return 0;
447 }
448
449 static void sip_options_contact_status_update(struct ast_sip_contact_status *contact_status)
450 {
451         struct ast_taskprocessor *mgmt_serializer = management_serializer;
452
453         if (mgmt_serializer) {
454                 ao2_ref(contact_status, +1);
455                 if (ast_sip_push_task(mgmt_serializer, contact_status_publish_update_task,
456                         contact_status)) {
457                         ao2_ref(contact_status, -1);
458                 }
459         }
460 }
461
462 struct ast_sip_contact_status *ast_res_pjsip_find_or_create_contact_status(const struct ast_sip_contact *contact)
463 {
464         struct ast_sip_contact_status *contact_status;
465         int res;
466
467         /*
468          * At startup a contact status can be retrieved when static contacts
469          * are themselves being setup.  This happens before we are fully setup.
470          * Since we don't actually trigger qualify or anything as a result it
471          * is safe to do so.  They'll just get back a contact status that will
472          * be updated later.  At this time they only care that the contact
473          * status gets created for the static contact anyway.
474          */
475         if (!sip_options_contact_statuses) {
476                 /*
477                  * We haven't been pre-initialized or we are shutting down.
478                  * Neither situation should happen.
479                  */
480                 ast_assert(0);
481                 return NULL;
482         }
483
484         ao2_lock(sip_options_contact_statuses);
485
486         /* If contact status for this contact already exists just return it */
487         contact_status = ao2_find(sip_options_contact_statuses,
488                 ast_sorcery_object_get_id(contact), OBJ_SEARCH_KEY | OBJ_NOLOCK);
489         if (contact_status) {
490                 ao2_unlock(sip_options_contact_statuses);
491                 return contact_status;
492         }
493
494         /* Otherwise we have to create and store a new contact status */
495         contact_status = sip_contact_status_alloc(ast_sorcery_object_get_id(contact));
496         if (!contact_status) {
497                 ao2_unlock(sip_options_contact_statuses);
498                 return NULL;
499         }
500
501         contact_status->rtt = 0;
502         contact_status->status = CREATED;
503         contact_status->last_status = CREATED;
504         res = ast_string_field_set(contact_status, uri, contact->uri);
505         res |= ast_string_field_set(contact_status, aor, contact->aor);
506         if (res) {
507                 ao2_unlock(sip_options_contact_statuses);
508                 ao2_ref(contact_status, -1);
509                 return NULL;
510         }
511
512         ao2_link_flags(sip_options_contact_statuses, contact_status, OBJ_NOLOCK);
513         ao2_unlock(sip_options_contact_statuses);
514
515         ast_statsd_log_string_va("PJSIP.contacts.states.%s", AST_STATSD_GAUGE,
516                 "+1", 1.0, ast_sip_get_contact_status_label(contact_status->status));
517
518         sip_options_contact_status_update(contact_status);
519
520         return contact_status;
521 }
522
523 struct ast_sip_contact_status *ast_sip_get_contact_status(const struct ast_sip_contact *contact)
524 {
525         return ao2_find(sip_options_contact_statuses, ast_sorcery_object_get_id(contact),
526                 OBJ_SEARCH_KEY);
527 }
528
529 /*! \brief Hashing function for OPTIONS AORs */
530 AO2_STRING_FIELD_HASH_FN(sip_options_aor, name);
531
532 /*! \brief Comparator function for SIP OPTIONS AORs */
533 AO2_STRING_FIELD_CMP_FN(sip_options_aor, name);
534
535 /*! \brief Hashing function for endpoint state compositors */
536 AO2_STRING_FIELD_HASH_FN(sip_options_endpoint_state_compositor, name);
537
538 /*! \brief Comparator function for endpoint state compositors */
539 AO2_STRING_FIELD_CMP_FN(sip_options_endpoint_state_compositor, name);
540
541 /*! \brief Structure used to contain information for an OPTIONS callback */
542 struct sip_options_contact_callback_data {
543         /*! \brief The contact we qualified */
544         struct ast_sip_contact *contact;
545         /*! \brief The AOR options */
546         struct sip_options_aor *aor_options;
547         /*! \brief The time at which this OPTIONS attempt was started */
548         struct timeval rtt_start;
549         /*! \brief The new status of the contact */
550         enum ast_sip_contact_status_type status;
551 };
552
553 /*!
554  * \brief Return the current state of an endpoint state compositor
555  * \pre The endpoint_state_compositor lock must be held.
556  */
557 static enum ast_endpoint_state sip_options_get_endpoint_state_compositor_state(
558         const struct sip_options_endpoint_state_compositor *endpoint_state_compositor)
559 {
560         struct ao2_iterator it_aor_statuses;
561         struct sip_options_endpoint_aor_status *aor_status;
562         enum ast_endpoint_state state = AST_ENDPOINT_OFFLINE;
563
564         it_aor_statuses = ao2_iterator_init(endpoint_state_compositor->aor_statuses, 0);
565         for (; (aor_status = ao2_iterator_next(&it_aor_statuses)); ao2_ref(aor_status, -1)) {
566                 if (aor_status->available) {
567                         state = AST_ENDPOINT_ONLINE;
568                         break;
569                 }
570         }
571         ao2_iterator_destroy(&it_aor_statuses);
572
573         return state;
574 }
575
576 /*!
577  * \brief Update the AOR status on an endpoint state compositor
578  * \pre The endpoint_state_compositor lock must be held.
579  */
580 static void sip_options_update_endpoint_state_compositor_aor(struct sip_options_endpoint_state_compositor *endpoint_state_compositor,
581         const char *name, enum ast_sip_contact_status_type status)
582 {
583         struct sip_options_endpoint_aor_status *aor_status;
584         enum ast_endpoint_state endpoint_state;
585
586         aor_status = ao2_find(endpoint_state_compositor->aor_statuses, name,
587                 OBJ_SEARCH_KEY | OBJ_NOLOCK);
588         if (!aor_status) {
589                 /* The AOR status doesn't exist already so we don't need to go any further */
590                 if (status == REMOVED) {
591                         return;
592                 }
593
594                 aor_status = ao2_alloc_options(sizeof(*aor_status) + strlen(name) + 1, NULL,
595                         AO2_ALLOC_OPT_LOCK_NOLOCK);
596                 if (!aor_status) {
597                         return;
598                 }
599
600                 strcpy(aor_status->name, name); /* SAFE */
601                 ao2_link(endpoint_state_compositor->aor_statuses, aor_status);
602         }
603
604         if (status == REMOVED) {
605                 /*
606                  * If the AOR is being removed then remove its AOR status
607                  * from the endpoint compositor.
608                  */
609                 ao2_unlink(endpoint_state_compositor->aor_statuses, aor_status);
610         } else {
611                 aor_status->available = (status == AVAILABLE ? 1 : 0);
612         }
613         ao2_ref(aor_status, -1);
614
615         if (!endpoint_state_compositor->active) {
616                 return;
617         }
618
619         /* If this AOR is available then the endpoint itself has to be online */
620         if (status == AVAILABLE) {
621                 ast_debug(3, "Endpoint state compositor '%s' is online as AOR '%s' is available\n",
622                         endpoint_state_compositor->name, name);
623                 endpoint_state = AST_ENDPOINT_ONLINE;
624         } else {
625                 endpoint_state =
626                         sip_options_get_endpoint_state_compositor_state(endpoint_state_compositor);
627         }
628
629         ast_sip_persistent_endpoint_update_state(endpoint_state_compositor->name,
630                 endpoint_state);
631 }
632
633 /*! \brief Function which notifies endpoint state compositors of a state change of an AOR */
634 static void sip_options_notify_endpoint_state_compositors(struct sip_options_aor *aor_options,
635         enum ast_sip_contact_status_type status)
636 {
637         int i;
638
639         /* Iterate through the associated endpoint state compositors updating them */
640         for (i = 0; i < AST_VECTOR_SIZE(&aor_options->compositors); ++i) {
641                 struct sip_options_endpoint_state_compositor *endpoint_state_compositor;
642
643                 endpoint_state_compositor = AST_VECTOR_GET(&aor_options->compositors, i);
644
645                 ao2_lock(endpoint_state_compositor);
646                 sip_options_update_endpoint_state_compositor_aor(endpoint_state_compositor,
647                         aor_options->name, status);
648                 ao2_unlock(endpoint_state_compositor);
649         }
650
651         if (status == REMOVED) {
652                 AST_VECTOR_RESET(&aor_options->compositors, ao2_cleanup);
653         }
654 }
655
656 /*!
657  * \brief Task to notify an AOR of a contact status change
658  * \note Run by aor_options->serializer
659  */
660 static int sip_options_contact_status_notify_task(void *obj)
661 {
662         struct sip_options_contact_callback_data *contact_callback_data = obj;
663         struct ast_sip_contact *contact;
664         struct ast_sip_contact_status *cs_old;
665         struct ast_sip_contact_status *cs_new;
666
667         /*
668          * Determine if this is a late arriving notification, as it is
669          * possible that we get a callback from PJSIP giving us contact
670          * status but in the mean time said contact has been removed
671          * from the controlling AOR.
672          */
673
674         if (!contact_callback_data->aor_options->qualify_frequency) {
675                 /* Contact qualify response is late */
676                 ao2_ref(contact_callback_data, -1);
677                 return 0;
678         }
679
680         contact = ao2_find(contact_callback_data->aor_options->contacts,
681                 contact_callback_data->contact, OBJ_SEARCH_OBJECT);
682         if (!contact) {
683                 /* Contact qualify response is late */
684                 ao2_ref(contact_callback_data, -1);
685                 return 0;
686         }
687         ao2_ref(contact, -1);
688
689         cs_old = ao2_find(sip_options_contact_statuses,
690                 ast_sorcery_object_get_id(contact_callback_data->contact), OBJ_SEARCH_KEY);
691         if (!cs_old) {
692                 /* Contact qualify response is late */
693                 ao2_ref(contact_callback_data, -1);
694                 return 0;
695         }
696
697         /* Update the contact specific status information */
698         cs_new = sip_contact_status_copy(cs_old);
699         ao2_ref(cs_old, -1);
700         if (!cs_new) {
701                 ao2_ref(contact_callback_data, -1);
702                 return 0;
703         }
704         cs_new->last_status = cs_new->status;
705         cs_new->status = contact_callback_data->status;
706         cs_new->rtt =
707                 cs_new->status == AVAILABLE
708                         ? ast_tvdiff_us(ast_tvnow(), contact_callback_data->rtt_start)
709                         : 0;
710         ao2_link(sip_options_contact_statuses, cs_new);
711
712         /*
713          * If the status has changed then notify the endpoint state compositors
714          * and publish our events.
715          */
716         if (cs_new->last_status != cs_new->status) {
717                 if (cs_new->status == AVAILABLE) {
718                         /* If this is the first available contact then the AOR has become available */
719                         ++contact_callback_data->aor_options->available;
720                         if (contact_callback_data->aor_options->available == 1) {
721                                 sip_options_notify_endpoint_state_compositors(
722                                         contact_callback_data->aor_options, AVAILABLE);
723                         }
724                 } else if (cs_new->last_status == AVAILABLE) {
725                         ast_assert(cs_new->status == UNAVAILABLE);
726
727                         /* If there are no more available contacts then this AOR is unavailable */
728                         --contact_callback_data->aor_options->available;
729                         if (!contact_callback_data->aor_options->available) {
730                                 sip_options_notify_endpoint_state_compositors(
731                                         contact_callback_data->aor_options, UNAVAILABLE);
732                         }
733                 }
734
735                 ast_verb(3, "Contact %s/%s is now %s.  RTT: %.3f msec\n",
736                         cs_new->aor,
737                         cs_new->uri,
738                         ast_sip_get_contact_status_label(cs_new->status),
739                         cs_new->rtt / 1000.0);
740
741                 ast_statsd_log_string_va("PJSIP.contacts.states.%s", AST_STATSD_GAUGE,
742                         "-1", 1.0, ast_sip_get_contact_status_label(cs_new->last_status));
743                 ast_statsd_log_string_va("PJSIP.contacts.states.%s", AST_STATSD_GAUGE,
744                         "+1", 1.0, ast_sip_get_contact_status_label(cs_new->status));
745
746                 sip_options_contact_status_update(cs_new);
747
748                 ast_test_suite_event_notify("AOR_CONTACT_UPDATE",
749                         "Contact: %s\r\n"
750                         "Status: %s",
751                         cs_new->name,
752                         ast_sip_get_contact_status_label(cs_new->status));
753         } else {
754                 ast_debug(3, "Contact %s/%s status didn't change: %s, RTT: %.3f msec\n",
755                         cs_new->aor,
756                         cs_new->uri,
757                         ast_sip_get_contact_status_label(cs_new->status),
758                         cs_new->rtt / 1000.0);
759         }
760
761         ast_statsd_log_full_va("PJSIP.contacts.%s.rtt", AST_STATSD_TIMER,
762                 cs_new->status != AVAILABLE ? -1 : cs_new->rtt / 1000,
763                 1.0,
764                 cs_new->name);
765
766         ast_test_suite_event_notify("AOR_CONTACT_QUALIFY_RESULT",
767                 "Contact: %s\r\n"
768                 "Status: %s\r\n"
769                 "RTT: %" PRId64,
770                 cs_new->name,
771                 ast_sip_get_contact_status_label(cs_new->status),
772                 cs_new->rtt);
773
774         ast_debug(3, "AOR '%s' now has %d available contacts\n",
775                 contact_callback_data->aor_options->name,
776                 contact_callback_data->aor_options->available);
777
778         ao2_ref(cs_new, -1);
779         ao2_ref(contact_callback_data, -1);
780
781         return 0;
782 }
783
784 /*! \brief Callback for when we get a result from a SIP OPTIONS request (a response or a timeout) */
785 static void qualify_contact_cb(void *token, pjsip_event *e)
786 {
787         struct sip_options_contact_callback_data *contact_callback_data = token;
788         enum ast_sip_contact_status_type status;
789
790         switch(e->body.tsx_state.type) {
791         default:
792                 ast_log(LOG_ERROR, "Unexpected PJSIP event %u\n", e->body.tsx_state.type);
793                 /* Fall through */
794         case PJSIP_EVENT_TRANSPORT_ERROR:
795         case PJSIP_EVENT_TIMER:
796                 status = UNAVAILABLE;
797                 break;
798         case PJSIP_EVENT_RX_MSG:
799                 status = AVAILABLE;
800                 break;
801         }
802
803         /* Update the callback data with the new status, this will get handled in the AOR serializer */
804         contact_callback_data->status = status;
805
806         if (ast_sip_push_task(contact_callback_data->aor_options->serializer,
807                 sip_options_contact_status_notify_task, contact_callback_data)) {
808                 ast_log(LOG_NOTICE, "Unable to queue contact status update for '%s' on AOR '%s', state will be incorrect\n",
809                         ast_sorcery_object_get_id(contact_callback_data->contact),
810                         contact_callback_data->aor_options->name);
811                 ao2_ref(contact_callback_data, -1);
812         }
813
814         /* The task inherited our reference so we don't unreference here */
815 }
816
817 /*! \brief Destructor for contact callback data */
818 static void sip_options_contact_callback_data_dtor(void *obj)
819 {
820         struct sip_options_contact_callback_data *contact_callback_data = obj;
821
822         ao2_cleanup(contact_callback_data->contact);
823         ao2_cleanup(contact_callback_data->aor_options);
824 }
825
826 /*! \brief Contact callback data allocator */
827 static struct sip_options_contact_callback_data *sip_options_contact_callback_data_alloc(
828         struct ast_sip_contact *contact, struct sip_options_aor *aor_options)
829 {
830         struct sip_options_contact_callback_data *contact_callback_data;
831
832         contact_callback_data = ao2_alloc_options(sizeof(*contact_callback_data),
833                 sip_options_contact_callback_data_dtor, AO2_ALLOC_OPT_LOCK_NOLOCK);
834         if (!contact_callback_data) {
835                 return NULL;
836         }
837
838         contact_callback_data->contact = ao2_bump(contact);
839         contact_callback_data->aor_options = ao2_bump(aor_options);
840         contact_callback_data->rtt_start = ast_tvnow();
841
842         return contact_callback_data;
843 }
844
845 /*! \brief Send a SIP OPTIONS request for a contact */
846 static int sip_options_qualify_contact(void *obj, void *arg, int flags)
847 {
848         struct ast_sip_contact *contact = obj;
849         struct sip_options_aor *aor_options = arg;
850         RAII_VAR(struct ast_sip_endpoint *, endpoint, NULL, ao2_cleanup);
851         pjsip_tx_data *tdata;
852         struct ast_sip_contact_status *contact_status;
853         struct sip_options_contact_callback_data *contact_callback_data;
854
855         ast_debug(3, "Qualifying contact '%s' on AOR '%s'\n",
856                 ast_sorcery_object_get_id(contact), aor_options->name);
857
858         if (!ast_strlen_zero(contact->endpoint_name)) {
859                 endpoint = ast_sorcery_retrieve_by_id(ast_sip_get_sorcery(), "endpoint",
860                         contact->endpoint_name);
861         }
862         if (!endpoint && AST_VECTOR_SIZE(&aor_options->compositors)) {
863                 struct sip_options_endpoint_state_compositor *endpoint_state_compositor;
864
865                 endpoint_state_compositor = AST_VECTOR_GET(&aor_options->compositors, 0);
866                 endpoint = ast_sorcery_retrieve_by_id(ast_sip_get_sorcery(), "endpoint",
867                         endpoint_state_compositor->name);
868         }
869         if (!endpoint) {
870                 ast_debug(3, "Could not find an endpoint to qualify contact '%s' on AOR '%s'\n",
871                         ast_sorcery_object_get_id(contact), aor_options->name);
872                 return 0;
873         }
874
875         if (ast_sip_create_request("OPTIONS", NULL, endpoint, NULL, contact, &tdata)) {
876                 ast_log(LOG_ERROR, "Unable to create request to qualify contact %s on AOR %s\n",
877                         contact->uri, aor_options->name);
878                 return 0;
879         }
880
881         /* If an outbound proxy is specified set it on this request */
882         if (!ast_strlen_zero(contact->outbound_proxy) &&
883                 ast_sip_set_outbound_proxy(tdata, contact->outbound_proxy)) {
884                 ast_log(LOG_ERROR, "Unable to apply outbound proxy on request to qualify contact %s\n",
885                         contact->uri);
886                 pjsip_tx_data_dec_ref(tdata);
887                 return 0;
888         }
889
890         contact_status = ast_res_pjsip_find_or_create_contact_status(contact);
891         if (!contact_status) {
892                 ast_log(LOG_ERROR, "Unable to retrieve contact status information for contact %s on AOR %s\n",
893                         contact->uri, aor_options->name);
894                 pjsip_tx_data_dec_ref(tdata);
895                 return 0;
896         }
897         ao2_ref(contact_status, -1);
898
899         contact_callback_data = sip_options_contact_callback_data_alloc(contact, aor_options);
900         if (!contact_callback_data) {
901                 ast_log(LOG_ERROR, "Unable to create object to contain callback data for contact %s on AOR %s\n",
902                         contact->uri, aor_options->name);
903                 pjsip_tx_data_dec_ref(tdata);
904                 return 0;
905         }
906
907         if (ast_sip_send_out_of_dialog_request(tdata, endpoint,
908                 (int)(aor_options->qualify_timeout * 1000), contact_callback_data,
909                 qualify_contact_cb)) {
910                 ast_log(LOG_ERROR, "Unable to send request to qualify contact %s on AOR %s\n",
911                         contact->uri, aor_options->name);
912                 ao2_ref(contact_callback_data, -1);
913         }
914
915         return 0;
916 }
917
918 /*!
919  * \brief Task to qualify contacts of an AOR
920  * \note Run by aor_options->serializer
921  */
922 static int sip_options_qualify_aor(void *obj)
923 {
924         struct sip_options_aor *aor_options = obj;
925
926         ast_debug(3, "Qualifying all contacts on AOR '%s'\n", aor_options->name);
927
928         /* Attempt to send an OPTIONS request to every contact on this AOR */
929         ao2_callback(aor_options->contacts, OBJ_NODATA, sip_options_qualify_contact,
930                 (struct sip_options_aor *) aor_options);
931
932         /* Always reschedule to the frequency we should go */
933         return aor_options->qualify_frequency * 1000;
934 }
935
936 /*! \brief Forward declaration of this helpful function */
937 static int sip_options_remove_contact(void *obj, void *arg, int flags);
938
939 /*! \brief Destructor function for SIP OPTIONS AORs */
940 static void sip_options_aor_dtor(void *obj)
941 {
942         struct sip_options_aor *aor_options = obj;
943
944         /*
945          * Any contacts are unreachable since the AOR is being destroyed
946          * so remove their contact status
947          */
948         if (aor_options->contacts) {
949                 ao2_callback(aor_options->contacts, OBJ_NODATA | OBJ_UNLINK,
950                         sip_options_remove_contact, aor_options);
951                 ao2_ref(aor_options->contacts, -1);
952         }
953         ao2_cleanup(aor_options->dynamic_contacts);
954
955         ast_taskprocessor_unreference(aor_options->serializer);
956
957         ast_assert(AST_VECTOR_SIZE(&aor_options->compositors) == 0);
958         AST_VECTOR_FREE(&aor_options->compositors);
959 }
960
961 /*! \brief Allocator for AOR OPTIONS */
962 static struct sip_options_aor *sip_options_aor_alloc(struct ast_sip_aor *aor)
963 {
964         struct sip_options_aor *aor_options;
965         char tps_name[AST_TASKPROCESSOR_MAX_NAME + 1];
966
967         aor_options = ao2_alloc_options(sizeof(*aor_options) + strlen(ast_sorcery_object_get_id(aor)) + 1,
968                 sip_options_aor_dtor, AO2_ALLOC_OPT_LOCK_NOLOCK);
969         if (!aor_options) {
970                 return NULL;
971         }
972
973         strcpy(aor_options->name, ast_sorcery_object_get_id(aor)); /* SAFE */
974
975         ast_taskprocessor_build_name(tps_name, sizeof(tps_name), "pjsip/options/%s",
976                 ast_sorcery_object_get_id(aor));
977         aor_options->serializer = ast_sip_create_serializer_group(tps_name,
978                 shutdown_group);
979         if (!aor_options->serializer) {
980                 ao2_ref(aor_options, -1);
981                 return NULL;
982         }
983
984         if (AST_VECTOR_INIT(&aor_options->compositors, ENDPOINT_STATE_COMPOSITOR_INITIAL_SIZE)) {
985                 ao2_ref(aor_options, -1);
986                 return NULL;
987         }
988
989         aor_options->contacts = ao2_container_alloc_hash(AO2_ALLOC_OPT_LOCK_NOLOCK,
990                 AO2_CONTAINER_ALLOC_OPT_DUPS_REJECT, CONTACT_BUCKETS, ast_sorcery_object_id_hash,
991                 ast_sorcery_object_id_sort, ast_sorcery_object_id_compare);
992         if (!aor_options->contacts) {
993                 ao2_ref(aor_options, -1);
994                 return NULL;
995         }
996
997         aor_options->dynamic_contacts = ao2_container_alloc_hash(AO2_ALLOC_OPT_LOCK_NOLOCK,
998                 AO2_CONTAINER_ALLOC_OPT_DUPS_REJECT, CONTACT_BUCKETS, ast_sorcery_object_id_hash,
999                 ast_sorcery_object_id_sort, ast_sorcery_object_id_compare);
1000         if (!aor_options->dynamic_contacts) {
1001                 ao2_ref(aor_options, -1);
1002                 return NULL;
1003         }
1004
1005         return aor_options;
1006 }
1007
1008 /*! \brief Remove contact status for a hint */
1009 static void sip_options_remove_contact_status(struct sip_options_aor *aor_options,
1010         struct ast_sip_contact *contact)
1011 {
1012         struct ast_sip_contact_status *cs_new;
1013         struct ast_sip_contact_status *cs_old;
1014
1015         cs_old = ao2_find(sip_options_contact_statuses, ast_sorcery_object_get_id(contact),
1016                 OBJ_SEARCH_KEY | OBJ_UNLINK);
1017         if (!cs_old) {
1018                 ast_debug(3, "Attempted to remove contact status for '%s' but it does not exist\n",
1019                         ast_sorcery_object_get_id(contact));
1020                 return;
1021         }
1022
1023         ast_verb(2, "Contact %s/%s has been deleted\n", contact->aor, contact->uri);
1024
1025         /* Update the contact status to reflect its new state */
1026         cs_new = sip_contact_status_copy(cs_old);
1027         if (!cs_new) {
1028                 /*
1029                  * We'll have to violate the immutable property because we
1030                  * couldn't create a new one to modify and we are deleting
1031                  * the contact status anyway.
1032                  */
1033                 cs_new = cs_old;
1034         } else {
1035                 ao2_ref(cs_old, -1);
1036         }
1037         cs_new->last_status = cs_new->status;
1038         cs_new->status = REMOVED;
1039         cs_new->rtt = 0;
1040
1041         ast_statsd_log_string_va("PJSIP.contacts.states.%s", AST_STATSD_GAUGE,
1042                 "-1", 1.0, ast_sip_get_contact_status_label(cs_new->last_status));
1043         ast_statsd_log_string_va("PJSIP.contacts.states.%s", AST_STATSD_GAUGE,
1044                 "+1", 1.0, ast_sip_get_contact_status_label(cs_new->status));
1045
1046         sip_options_contact_status_update(cs_new);
1047
1048         /*
1049          * The only time we need to update the AOR is if this contact was
1050          * available and qualify is in use, otherwise we can just stop
1051          * early.
1052          */
1053         if (!aor_options->qualify_frequency || cs_new->last_status != AVAILABLE) {
1054                 ao2_ref(cs_new, -1);
1055                 return;
1056         }
1057
1058         --aor_options->available;
1059         if (!aor_options->available) {
1060                 sip_options_notify_endpoint_state_compositors(aor_options, UNAVAILABLE);
1061         }
1062
1063         ast_debug(3, "AOR '%s' now has %d available contacts\n", aor_options->name,
1064                 aor_options->available);
1065
1066         ao2_ref(cs_new, -1);
1067 }
1068
1069 /*! \brief Task data for AOR creation or updating */
1070 struct sip_options_synchronize_aor_task_data {
1071         /*! \brief The AOR options for this AOR */
1072         struct sip_options_aor *aor_options;
1073         /*! \brief The AOR which contains the new configuraton */
1074         struct ast_sip_aor *aor;
1075         /*! \brief Optional container of existing AOR s*/
1076         struct ao2_container *existing;
1077         /*! \brief Whether this AOR is being added */
1078         int added;
1079 };
1080
1081 /*! \brief Callback function to remove a contact and its contact status from an AOR */
1082 static int sip_options_remove_contact(void *obj, void *arg, int flags)
1083 {
1084         struct ast_sip_contact *contact = obj;
1085         struct sip_options_aor *aor_options = arg;
1086
1087         sip_options_remove_contact_status(aor_options, contact);
1088
1089         return CMP_MATCH;
1090 }
1091
1092 /*! \brief Determine an initial time for scheduling AOR qualifying */
1093 static int sip_options_determine_initial_qualify_time(int qualify_frequency)
1094 {
1095         int initial_interval;
1096         int max_time = ast_sip_get_max_initial_qualify_time();
1097
1098         if (max_time && max_time < qualify_frequency) {
1099                 initial_interval = max_time;
1100         } else {
1101                 initial_interval = qualify_frequency;
1102         }
1103
1104         initial_interval = (int)((initial_interval * 1000) * ast_random_double());
1105         return 0 < initial_interval ? initial_interval : 1;
1106 }
1107
1108 /*! \brief Set the contact status for a contact */
1109 static void sip_options_set_contact_status(struct ast_sip_contact_status *contact_status,
1110         enum ast_sip_contact_status_type status)
1111 {
1112         struct ast_sip_contact_status *cs_new;
1113
1114         /* Update the contact specific status information */
1115         cs_new = sip_contact_status_copy(contact_status);
1116         if (!cs_new) {
1117                 return;
1118         }
1119         cs_new->last_status = cs_new->status;
1120         cs_new->status = status;
1121
1122         /*
1123          * We need to always set the RTT to zero because we haven't completed
1124          * an OPTIONS ping so RTT is unknown.  If the OPTIONS ping were still
1125          * running it will be refreshed on the next go round anyway.
1126          */
1127         cs_new->rtt = 0;
1128
1129         ao2_link(sip_options_contact_statuses, cs_new);
1130
1131         if (cs_new->status != cs_new->last_status) {
1132                 ast_verb(3, "Contact %s/%s is now %s.\n",
1133                         cs_new->aor, cs_new->uri,
1134                         ast_sip_get_contact_status_label(cs_new->status));
1135
1136                 ast_statsd_log_string_va("PJSIP.contacts.states.%s", AST_STATSD_GAUGE,
1137                         "-1", 1.0, ast_sip_get_contact_status_label(cs_new->last_status));
1138                 ast_statsd_log_string_va("PJSIP.contacts.states.%s", AST_STATSD_GAUGE,
1139                         "+1", 1.0, ast_sip_get_contact_status_label(cs_new->status));
1140
1141                 sip_options_contact_status_update(cs_new);
1142
1143                 ast_test_suite_event_notify("AOR_CONTACT_UPDATE",
1144                         "Contact: %s\r\n"
1145                         "Status: %s",
1146                         cs_new->name,
1147                         ast_sip_get_contact_status_label(cs_new->status));
1148         }
1149         ao2_ref(cs_new, -1);
1150 }
1151
1152 /*! \brief Transition the contact status to unqualified mode */
1153 static int sip_options_set_contact_status_unqualified(void *obj, void *arg, int flags)
1154 {
1155         struct ast_sip_contact *contact = obj;
1156         struct ast_sip_contact_status *contact_status;
1157
1158         contact_status = ast_res_pjsip_find_or_create_contact_status(contact);
1159         if (!contact_status) {
1160                 return 0;
1161         }
1162
1163         switch (contact_status->status) {
1164         case AVAILABLE:
1165         case UNAVAILABLE:
1166         case UNKNOWN:
1167                 sip_options_set_contact_status(contact_status, CREATED);
1168                 break;
1169         case CREATED:
1170         case REMOVED:
1171                 break;
1172         }
1173
1174         ao2_ref(contact_status, -1);
1175
1176         return 0;
1177 }
1178
1179 /*! \brief Transition the contact status to qualified mode */
1180 static int sip_options_set_contact_status_qualified(void *obj, void *arg, int flags)
1181 {
1182         struct ast_sip_contact *contact = obj;
1183         struct ast_sip_contact_status *contact_status;
1184
1185         contact_status = ast_res_pjsip_find_or_create_contact_status(contact);
1186         if (!contact_status) {
1187                 return 0;
1188         }
1189
1190         switch (contact_status->status) {
1191         case AVAILABLE:
1192                 sip_options_set_contact_status(contact_status, UNAVAILABLE);
1193                 break;
1194         case UNAVAILABLE:
1195         case UNKNOWN:
1196         case CREATED:
1197         case REMOVED:
1198                 break;
1199         }
1200
1201         ao2_ref(contact_status, -1);
1202
1203         return 0;
1204 }
1205
1206 /*! \brief Count AVAILABLE qualified contacts. */
1207 static int sip_options_contact_status_available_count(void *obj, void *arg, int flags)
1208 {
1209         struct ast_sip_contact *contact = obj;
1210         unsigned int *available = arg;
1211         struct ast_sip_contact_status *contact_status;
1212
1213         contact_status = ast_res_pjsip_find_or_create_contact_status(contact);
1214         if (!contact_status) {
1215                 return 0;
1216         }
1217
1218         /* Count qualified available contacts. */
1219         switch (contact_status->status) {
1220         case AVAILABLE:
1221                 ++*available;
1222                 break;
1223         case UNAVAILABLE:
1224         case UNKNOWN:
1225         case CREATED:
1226         case REMOVED:
1227                 break;
1228         }
1229
1230         ao2_ref(contact_status, -1);
1231
1232         return 0;
1233 }
1234
1235 /*!
1236  * \brief Function which applies configuration to an AOR options structure
1237  * \note Run by aor_options->serializer (or management_serializer on aor_options creation)
1238  */
1239 static void sip_options_apply_aor_configuration(struct sip_options_aor *aor_options,
1240         struct ast_sip_aor *aor, int is_new)
1241 {
1242         struct ao2_container *existing_contacts;
1243         struct ast_sip_contact *contact;
1244         struct ao2_iterator iter;
1245
1246         ast_debug(3, "Configuring AOR '%s' with current state of configuration and world\n",
1247                 aor_options->name);
1248
1249         /*
1250          * Permanent contacts, since we receive no notification that they
1251          * are gone, follow the same approach as AORs.  We create a copy
1252          * of the existing container and any reused contacts are removed
1253          * from it.  Any contacts remaining in the container after
1254          * processing no longer exist so we need to remove their state.
1255          */
1256         existing_contacts = ao2_container_clone(aor_options->contacts, 0);
1257         if (!existing_contacts) {
1258                 ast_log(LOG_WARNING, "Synchronization of AOR '%s' failed for qualify, retaining existing state\n",
1259                         aor_options->name);
1260                 return;
1261         }
1262
1263         ao2_callback(aor_options->contacts, OBJ_NODATA | OBJ_UNLINK | OBJ_MULTIPLE,
1264                 NULL, NULL);
1265
1266         /* Process permanent contacts */
1267         if (aor->permanent_contacts) {
1268                 iter = ao2_iterator_init(aor->permanent_contacts, 0);
1269                 for (; (contact = ao2_iterator_next(&iter)); ao2_ref(contact, -1)) {
1270                         ao2_find(existing_contacts, ast_sorcery_object_get_id(contact),
1271                                 OBJ_NODATA | OBJ_UNLINK | OBJ_SEARCH_KEY);
1272                         ao2_link(aor_options->contacts, contact);
1273                 }
1274                 ao2_iterator_destroy(&iter);
1275         }
1276
1277         /*
1278          * If this is newly added we need to see if there are any
1279          * existing dynamic contacts to add.  Ones that are added
1280          * after creation will occur as a result of the contact
1281          * observer creation callback.
1282          */
1283         if (is_new) {
1284                 size_t prefix_len = strlen(ast_sorcery_object_get_id(aor)) + sizeof(";@") - 1;
1285                 char prefix[prefix_len + 1];
1286                 struct ao2_container *contacts;
1287
1288                 sprintf(prefix, "%s;@", ast_sorcery_object_get_id(aor)); /* Safe */
1289                 contacts = ast_sorcery_retrieve_by_prefix(ast_sip_get_sorcery(), "contact",
1290                         prefix, prefix_len);
1291                 if (contacts) {
1292                         ao2_container_dup(aor_options->dynamic_contacts, contacts, 0);
1293                         ao2_ref(contacts, -1);
1294                 }
1295         }
1296
1297         /* Process dynamic contacts */
1298         iter = ao2_iterator_init(aor_options->dynamic_contacts, 0);
1299         for (; (contact = ao2_iterator_next(&iter)); ao2_ref(contact, -1)) {
1300                 ao2_find(existing_contacts, ast_sorcery_object_get_id(contact),
1301                         OBJ_NODATA | OBJ_UNLINK | OBJ_SEARCH_KEY);
1302                 ao2_link(aor_options->contacts, contact);
1303         }
1304         ao2_iterator_destroy(&iter);
1305
1306         /* Any contacts left no longer exist, so raise events and make them disappear */
1307         ao2_callback(existing_contacts, OBJ_NODATA | OBJ_UNLINK,
1308                 sip_options_remove_contact, aor_options);
1309         ao2_ref(existing_contacts, -1);
1310
1311         /*
1312          * Update the available count if we transition between qualified
1313          * and unqualified.  In the qualified case we need to start with
1314          * 0 available as the qualify process will take care of it.  In
1315          * the unqualified case it is based on the number of contacts
1316          * present.
1317          */
1318         if (!aor->qualify_frequency) {
1319                 ao2_callback(aor_options->contacts, OBJ_NODATA,
1320                         sip_options_set_contact_status_unqualified, NULL);
1321                 aor_options->available = ao2_container_count(aor_options->contacts);
1322                 ast_debug(3, "AOR '%s' is unqualified, number of available contacts is therefore '%d'\n",
1323                         aor_options->name, aor_options->available);
1324         } else if (!aor_options->qualify_frequency) {
1325                 ao2_callback(aor_options->contacts, OBJ_NODATA,
1326                         sip_options_set_contact_status_qualified, NULL);
1327                 aor_options->available = 0;
1328                 ast_debug(3, "AOR '%s' has transitioned from unqualified to qualified, reset available contacts to 0\n",
1329                         aor_options->name);
1330         } else {
1331                 /*
1332                 * Count the number of AVAILABLE qualified contacts to ensure
1333                 * the count is in sync with reality.
1334                 */
1335                 aor_options->available = 0;
1336                 ao2_callback(aor_options->contacts, OBJ_NODATA,
1337                         sip_options_contact_status_available_count, &aor_options->available);
1338         }
1339
1340         aor_options->authenticate_qualify = aor->authenticate_qualify;
1341         aor_options->qualify_timeout = aor->qualify_timeout;
1342
1343         /*
1344          * If we need to stop or start the scheduled callback then do so.
1345          * This occurs due to the following:
1346          * 1. The qualify frequency has changed
1347          * 2. Contacts were added when previously there were none
1348          * 3. There are no contacts but previously there were some
1349          */
1350         if (aor_options->qualify_frequency != aor->qualify_frequency
1351                 || (!aor_options->sched_task && ao2_container_count(aor_options->contacts))
1352                 || (aor_options->sched_task && !ao2_container_count(aor_options->contacts))) {
1353                 if (aor_options->sched_task) {
1354                         ast_sip_sched_task_cancel(aor_options->sched_task);
1355                         ao2_ref(aor_options->sched_task, -1);
1356                         aor_options->sched_task = NULL;
1357                 }
1358
1359                 /* If there is still a qualify frequency then schedule this */
1360                 aor_options->qualify_frequency = aor->qualify_frequency;
1361                 if (aor_options->qualify_frequency
1362                         && ao2_container_count(aor_options->contacts)) {
1363                         aor_options->sched_task = ast_sip_schedule_task(aor_options->serializer,
1364                                 sip_options_determine_initial_qualify_time(aor_options->qualify_frequency),
1365                                 sip_options_qualify_aor, ast_taskprocessor_name(aor_options->serializer),
1366                                 aor_options, AST_SIP_SCHED_TASK_VARIABLE | AST_SIP_SCHED_TASK_DATA_AO2);
1367                         if (!aor_options->sched_task) {
1368                                 ast_log(LOG_ERROR, "Unable to schedule qualify for contacts of AOR '%s'\n",
1369                                         aor_options->name);
1370                         }
1371                 }
1372         }
1373
1374         ast_debug(3, "AOR '%s' now has %d available contacts\n", aor_options->name,
1375                 aor_options->available);
1376 }
1377
1378 /*!
1379  * \brief Task to synchronize an AOR with our local state
1380  * \note Run by aor_options->serializer (or management_serializer on aor_options creation)
1381  */
1382 static int sip_options_synchronize_aor_task(void *obj)
1383 {
1384         struct sip_options_synchronize_aor_task_data *task_data = obj;
1385         int i;
1386
1387         ast_debug(3, "Synchronizing AOR '%s' with current state of configuration and world\n",
1388                 task_data->aor_options->name);
1389
1390         sip_options_apply_aor_configuration(task_data->aor_options, task_data->aor,
1391                 task_data->added);
1392
1393         /*
1394          * Endpoint state compositors are removed in this operation but not
1395          * added.  To reduce the amount of work done they are done later.  In
1396          * the mean time things can still qualify and once an endpoint state
1397          * compositor is added to the AOR it will be updated with the current
1398          * state.
1399          */
1400         for (i = 0; i < AST_VECTOR_SIZE(&task_data->aor_options->compositors); ++i) {
1401                 struct sip_options_endpoint_state_compositor *endpoint_state_compositor;
1402
1403                 endpoint_state_compositor = AST_VECTOR_GET(&task_data->aor_options->compositors, i);
1404
1405                 ao2_lock(endpoint_state_compositor);
1406                 endpoint_state_compositor->active = 0;
1407                 sip_options_update_endpoint_state_compositor_aor(endpoint_state_compositor,
1408                         task_data->aor_options->name, REMOVED);
1409                 ao2_unlock(endpoint_state_compositor);
1410         }
1411         AST_VECTOR_RESET(&task_data->aor_options->compositors, ao2_cleanup);
1412
1413         return 0;
1414 }
1415
1416 /*!
1417  * \brief Synchronize an AOR with our local state
1418  * \note Run by management_serializer
1419  */
1420 static int sip_options_synchronize_aor(void *obj, void *arg, int flags)
1421 {
1422         struct sip_options_synchronize_aor_task_data task_data = {
1423                 .aor = obj,
1424                 .existing = arg,
1425         };
1426
1427         task_data.aor_options = ao2_find(sip_options_aors,
1428                 ast_sorcery_object_get_id(task_data.aor), OBJ_SEARCH_KEY);
1429         if (!task_data.aor_options) {
1430                 task_data.aor_options = sip_options_aor_alloc(task_data.aor);
1431                 if (!task_data.aor_options) {
1432                         return 0;
1433                 }
1434
1435                 task_data.added = 1;
1436
1437                 /* Nothing is aware of this AOR yet so we can just update it in this thread */
1438                 sip_options_synchronize_aor_task(&task_data);
1439                 ao2_link(sip_options_aors, task_data.aor_options);
1440         } else {
1441                 /* This AOR already exists so we have to do manipulation in its serializer */
1442                 ast_sip_push_task_wait_serializer(task_data.aor_options->serializer,
1443                         sip_options_synchronize_aor_task, &task_data);
1444         }
1445
1446         ao2_ref(task_data.aor_options, -1);
1447
1448         if (task_data.existing) {
1449                 ao2_find(task_data.existing, ast_sorcery_object_get_id(task_data.aor),
1450                         OBJ_SEARCH_KEY | OBJ_UNLINK | OBJ_NODATA);
1451         }
1452
1453         return 0;
1454 }
1455
1456 /*! \brief Destructor for endpoint state compositors */
1457 static void sip_options_endpoint_state_compositor_dtor(void *obj)
1458 {
1459         struct sip_options_endpoint_state_compositor *endpoint_state_compositor = obj;
1460
1461         ao2_cleanup(endpoint_state_compositor->aor_statuses);
1462 }
1463
1464 /*! \brief Hashing function for endpoint AOR status */
1465 AO2_STRING_FIELD_HASH_FN(sip_options_endpoint_aor_status, name);
1466
1467 /*! \brief Comparator function for endpoint AOR status */
1468 AO2_STRING_FIELD_CMP_FN(sip_options_endpoint_aor_status, name);
1469
1470 /*! \brief Find (or create) an endpoint state compositor */
1471 static struct sip_options_endpoint_state_compositor *sip_options_endpoint_state_compositor_find_or_alloc(const struct ast_sip_endpoint *endpoint)
1472 {
1473         struct sip_options_endpoint_state_compositor *endpoint_state_compositor;
1474
1475         ao2_lock(sip_options_endpoint_state_compositors);
1476         endpoint_state_compositor = ao2_find(sip_options_endpoint_state_compositors,
1477                 ast_sorcery_object_get_id(endpoint), OBJ_SEARCH_KEY | OBJ_NOLOCK);
1478         if (endpoint_state_compositor) {
1479                 ao2_unlock(sip_options_endpoint_state_compositors);
1480                 return endpoint_state_compositor;
1481         }
1482
1483         endpoint_state_compositor = ao2_alloc(sizeof(*endpoint_state_compositor)
1484                 + strlen(ast_sorcery_object_get_id(endpoint)) + 1,
1485                 sip_options_endpoint_state_compositor_dtor);
1486         if (!endpoint_state_compositor) {
1487                 ao2_unlock(sip_options_endpoint_state_compositors);
1488                 return NULL;
1489         }
1490
1491         /*
1492          * NOTE: The endpoint_state_compositor->aor_statuses container is
1493          * externally protected by the endpoint_state_compositor lock.
1494          */
1495         endpoint_state_compositor->aor_statuses = ao2_container_alloc_hash(
1496                 AO2_ALLOC_OPT_LOCK_NOLOCK, 0, AOR_STATUS_BUCKETS,
1497                 sip_options_endpoint_aor_status_hash_fn, NULL,
1498                 sip_options_endpoint_aor_status_cmp_fn);
1499         if (!endpoint_state_compositor->aor_statuses) {
1500                 ao2_unlock(sip_options_endpoint_state_compositors);
1501                 ao2_ref(endpoint_state_compositor, -1);
1502                 return NULL;
1503         }
1504
1505         strcpy(endpoint_state_compositor->name, ast_sorcery_object_get_id(endpoint)); /* SAFE */
1506
1507         ao2_link_flags(sip_options_endpoint_state_compositors, endpoint_state_compositor,
1508                 OBJ_NOLOCK);
1509         ao2_unlock(sip_options_endpoint_state_compositors);
1510
1511         return endpoint_state_compositor;
1512 }
1513
1514 /*! \brief Task details for adding an AOR to an endpoint state compositor */
1515 struct sip_options_endpoint_compositor_task_data {
1516         /*! \brief The AOR options that the endpoint state compositor should be added to */
1517         struct sip_options_aor *aor_options;
1518         /*! \brief The endpoint state compositor */
1519         struct sip_options_endpoint_state_compositor *endpoint_state_compositor;
1520 };
1521
1522 /*!
1523  * \brief Task which adds an AOR to an endpoint state compositor
1524  * \note Run by aor_options->serializer
1525  */
1526 static int sip_options_endpoint_compositor_add_task(void *obj)
1527 {
1528         struct sip_options_endpoint_compositor_task_data *task_data = obj;
1529
1530         ast_debug(3, "Adding endpoint compositor '%s' to AOR '%s'\n",
1531                 task_data->endpoint_state_compositor->name, task_data->aor_options->name);
1532
1533         ao2_ref(task_data->endpoint_state_compositor, +1);
1534         if (AST_VECTOR_APPEND(&task_data->aor_options->compositors,
1535                 task_data->endpoint_state_compositor)) {
1536                 /* Failed to add so no need to update the endpoint status.  Nothing changed. */
1537                 ao2_ref(task_data->endpoint_state_compositor, -1);
1538                 return 0;
1539         }
1540
1541         ao2_lock(task_data->endpoint_state_compositor);
1542         sip_options_update_endpoint_state_compositor_aor(task_data->endpoint_state_compositor,
1543                 task_data->aor_options->name,
1544                 task_data->aor_options->available ? AVAILABLE : UNAVAILABLE);
1545         ao2_unlock(task_data->endpoint_state_compositor);
1546
1547         return 0;
1548 }
1549
1550 /*!
1551  * \brief Task which adds removes an AOR from an endpoint state compositor
1552  * \note Run by aor_options->serializer
1553  */
1554 static int sip_options_endpoint_compositor_remove_task(void *obj)
1555 {
1556         struct sip_options_endpoint_compositor_task_data *task_data = obj;
1557         int i;
1558
1559         ast_debug(3, "Removing endpoint compositor '%s' from AOR '%s'\n",
1560                 task_data->endpoint_state_compositor->name,
1561                 task_data->aor_options->name);
1562
1563         for (i = 0; i < AST_VECTOR_SIZE(&task_data->aor_options->compositors); ++i) {
1564                 struct sip_options_endpoint_state_compositor *endpoint_state_compositor;
1565
1566                 endpoint_state_compositor = AST_VECTOR_GET(&task_data->aor_options->compositors, i);
1567                 if (endpoint_state_compositor != task_data->endpoint_state_compositor) {
1568                         continue;
1569                 }
1570
1571                 AST_VECTOR_REMOVE(&task_data->aor_options->compositors, i, 0);
1572                 ao2_ref(endpoint_state_compositor, -1);
1573                 break;
1574         }
1575
1576         return 0;
1577 }
1578
1579 /*!
1580  * \brief Synchronize an endpoint with our local state
1581  * \note Run by management_serializer
1582  */
1583 static int sip_options_synchronize_endpoint(void *obj, void *arg, int flags)
1584 {
1585         struct ast_sip_endpoint *endpoint = obj;
1586         struct ast_sip_aor *aor = arg;
1587         char *aors;
1588         char *aor_name;
1589         struct sip_options_endpoint_compositor_task_data task_data = { NULL, };
1590
1591         if (ast_strlen_zero(endpoint->aors)) {
1592                 /* There are no AORs, so really... who the heck knows */
1593                 ast_debug(3, "Endpoint '%s' is not interested in any AORs so not creating endpoint state compositor\n",
1594                         ast_sorcery_object_get_id(endpoint));
1595                 return 0;
1596         }
1597
1598         ast_debug(3, "Synchronizing endpoint '%s' with AORs '%s'\n",
1599                 ast_sorcery_object_get_id(endpoint), endpoint->aors);
1600
1601         aors = ast_strdupa(endpoint->aors);
1602         while ((aor_name = ast_strip(strsep(&aors, ",")))) {
1603                 if (ast_strlen_zero(aor_name)) {
1604                         continue;
1605                 }
1606                 if (aor && strcasecmp(ast_sorcery_object_get_id(aor), aor_name)) {
1607                         ast_debug(3, "Filtered AOR '%s' on endpoint '%s' as we are looking for '%s'\n",
1608                                 aor_name, ast_sorcery_object_get_id(endpoint),
1609                                 ast_sorcery_object_get_id(aor));
1610                         continue;
1611                 }
1612
1613                 task_data.aor_options = ao2_find(sip_options_aors, aor_name, OBJ_SEARCH_KEY);
1614                 if (!task_data.aor_options) {
1615                         /*
1616                          * They have referenced an invalid AOR. If that's all they've
1617                          * done we will set them to offline at the end.
1618                          */
1619                         ast_debug(3, "Endpoint '%s' referenced invalid AOR '%s'\n",
1620                                 ast_sorcery_object_get_id(endpoint), aor_name);
1621                         continue;
1622                 }
1623
1624                 if (!task_data.endpoint_state_compositor) {
1625                         /*
1626                          * We create an endpoint state compositor only after we know
1627                          * for sure we need it.
1628                          */
1629                         task_data.endpoint_state_compositor =
1630                                 sip_options_endpoint_state_compositor_find_or_alloc(endpoint);
1631                         if (!task_data.endpoint_state_compositor) {
1632                                 ast_log(LOG_WARNING,
1633                                         "Could not create endpoint state compositor for '%s', endpoint state will be incorrect\n",
1634                                         ast_sorcery_object_get_id(endpoint));
1635                                 ao2_ref(task_data.aor_options, -1);
1636                                 ast_sip_persistent_endpoint_update_state(ast_sorcery_object_get_id(endpoint),
1637                                         AST_ENDPOINT_OFFLINE);
1638                                 return 0;
1639                         }
1640                 }
1641
1642                 /* We use a synchronous task so that we don't flood the system */
1643                 ast_sip_push_task_wait_serializer(task_data.aor_options->serializer,
1644                         sip_options_endpoint_compositor_add_task, &task_data);
1645
1646                 ao2_ref(task_data.aor_options, -1);
1647
1648                 /*
1649                  * If we filtered on a specific AOR name then the endpoint can
1650                  * only reference it once so break early.
1651                  */
1652                 if (aor) {
1653                         break;
1654                 }
1655         }
1656
1657         if (task_data.endpoint_state_compositor) {
1658                 /*
1659                  * If an endpoint state compositor is present determine the current state
1660                  * of the endpoint and update it.
1661                  */
1662                 ao2_lock(task_data.endpoint_state_compositor);
1663                 task_data.endpoint_state_compositor->active = 1;
1664                 ast_sip_persistent_endpoint_update_state(ast_sorcery_object_get_id(endpoint),
1665                         sip_options_get_endpoint_state_compositor_state(task_data.endpoint_state_compositor));
1666                 ao2_unlock(task_data.endpoint_state_compositor);
1667
1668                 ao2_ref(task_data.endpoint_state_compositor, -1);
1669         } else {
1670                 /* If there is none then they may have referenced an invalid AOR or none at all */
1671                 ast_debug(3, "Endpoint '%s' has no AORs feeding it, setting it to offline state as default\n",
1672                         ast_sorcery_object_get_id(endpoint));
1673                 ast_sip_persistent_endpoint_update_state(ast_sorcery_object_get_id(endpoint),
1674                         AST_ENDPOINT_OFFLINE);
1675         }
1676
1677         return 0;
1678 }
1679
1680 /*!
1681  * \brief Task which removes an AOR from all of the ESCs it is reporting to
1682  * \note Run by aor_options->serializer
1683  */
1684 static int sip_options_aor_remove_task(void *obj)
1685 {
1686         struct sip_options_aor *aor_options = obj;
1687
1688         sip_options_notify_endpoint_state_compositors(aor_options, REMOVED);
1689
1690         if (aor_options->sched_task) {
1691                 ast_sip_sched_task_cancel(aor_options->sched_task);
1692                 ao2_ref(aor_options->sched_task, -1);
1693                 aor_options->sched_task = NULL;
1694         }
1695
1696         return 0;
1697 }
1698
1699 /*!
1700  * \brief Callback which removes any unused AORs that remained after reloading
1701  * \note Run by management_serializer
1702  */
1703 static int sip_options_unused_aor(void *obj, void *arg, int flags)
1704 {
1705         struct sip_options_aor *aor_options = obj;
1706
1707         ast_debug(3, "AOR '%s' is no longer configured, removing it\n", aor_options->name);
1708
1709         ast_sip_push_task_wait_serializer(aor_options->serializer, sip_options_aor_remove_task,
1710                 aor_options);
1711         ao2_unlink(sip_options_aors, aor_options);
1712
1713         return CMP_MATCH;
1714 }
1715
1716 /*!
1717  * \brief Callback function used to unlink and remove event state compositors that have no AORs feeding them
1718  * \note Run by management_serializer
1719  */
1720 static int sip_options_unused_endpoint_state_compositor(void *obj, void *arg, int flags)
1721 {
1722         struct sip_options_endpoint_state_compositor *endpoint_state_compositor = obj;
1723
1724         if (ao2_container_count(endpoint_state_compositor->aor_statuses)) {
1725                 return 0;
1726         }
1727
1728         /* No AORs are feeding this endpoint state compositor */
1729         ast_sip_persistent_endpoint_update_state(endpoint_state_compositor->name,
1730                 AST_ENDPOINT_OFFLINE);
1731
1732         return CMP_MATCH;
1733 }
1734
1735 /*! \brief Structure which contains information required to synchronize */
1736 struct sip_options_synchronize_task_data {
1737         /*! \brief Whether this is a reload or not */
1738         int reload;
1739 };
1740
1741 /*!
1742  * \brief Task to synchronize our local container of AORs and endpoint state compositors with the current configuration
1743  * \note Run by management_serializer
1744  */
1745 static int sip_options_synchronize_task(void *obj)
1746 {
1747         struct sip_options_synchronize_task_data *task_data = obj;
1748         struct ao2_container *existing = NULL;
1749         struct ao2_container *objects;
1750
1751         /*
1752          * When reloading we keep track of the existing AORs so we can
1753          * terminate old ones that are no longer referenced or used.
1754          */
1755         if (task_data->reload) {
1756                 existing = ao2_container_clone(sip_options_aors, 0);
1757                 if (!existing) {
1758                         return 0;
1759                 }
1760         }
1761
1762         objects = ast_sorcery_retrieve_by_fields(ast_sip_get_sorcery(), "aor",
1763                 AST_RETRIEVE_FLAG_MULTIPLE | AST_RETRIEVE_FLAG_ALL, NULL);
1764         if (objects) {
1765                 /* Go through the returned AORs and synchronize with our local state */
1766                 ao2_callback(objects, OBJ_NODATA, sip_options_synchronize_aor, existing);
1767                 ao2_ref(objects, -1);
1768         }
1769
1770         /*
1771          * Any AORs remaining in existing are no longer referenced by
1772          * the current container of AORs we retrieved, so remove them.
1773          */
1774         if (existing) {
1775                 ao2_callback(existing, OBJ_NODATA | OBJ_MULTIPLE | OBJ_UNLINK,
1776                         sip_options_unused_aor, NULL);
1777                 ao2_ref(existing, -1);
1778         }
1779
1780         objects = ast_sorcery_retrieve_by_fields(ast_sip_get_sorcery(), "endpoint",
1781                 AST_RETRIEVE_FLAG_MULTIPLE | AST_RETRIEVE_FLAG_ALL, NULL);
1782         if (objects) {
1783                 /* Go through the provided endpoints and update AORs */
1784                 ao2_callback(objects, OBJ_NODATA, sip_options_synchronize_endpoint, NULL);
1785                 ao2_ref(objects, -1);
1786         }
1787
1788         /*
1789          * All endpoint state compositors that don't have any AORs
1790          * feeding them information can be removed.  If they end
1791          * up getting needed later they'll just be recreated.
1792          */
1793         ao2_callback(sip_options_endpoint_state_compositors,
1794                 OBJ_NODATA | OBJ_MULTIPLE | OBJ_UNLINK,
1795                 sip_options_unused_endpoint_state_compositor, NULL);
1796
1797         return 0;
1798 }
1799
1800 /*! \brief Synchronize our local container of AORs and endpoint state compositors with the current configuration */
1801 static void sip_options_synchronize(int reload)
1802 {
1803         struct sip_options_synchronize_task_data task_data = {
1804                 .reload = reload,
1805         };
1806
1807         ast_sip_push_task_wait_serializer(management_serializer, sip_options_synchronize_task,
1808                 &task_data);
1809 }
1810
1811 /*!
1812  * \brief Unlink AORs feeding the endpoint status compositor
1813  * \note Run by management_serializer
1814  */
1815 static void sip_options_endpoint_unlink_aor_feeders(struct ast_sip_endpoint *endpoint,
1816         struct sip_options_endpoint_state_compositor *endpoint_state_compositor)
1817 {
1818         struct ao2_iterator it_aor_statuses;
1819         struct sip_options_endpoint_aor_status *aor_status;
1820         struct sip_options_endpoint_compositor_task_data task_data = {
1821                 .endpoint_state_compositor = endpoint_state_compositor,
1822         };
1823
1824         ao2_lock(endpoint_state_compositor);
1825         endpoint_state_compositor->active = 0;
1826
1827         /* Unlink AOR feeders pointing to endpoint */
1828         it_aor_statuses = ao2_iterator_init(endpoint_state_compositor->aor_statuses, 0);
1829         for (; (aor_status = ao2_iterator_next(&it_aor_statuses)); ao2_ref(aor_status, -1)) {
1830                 task_data.aor_options = ao2_find(sip_options_aors, aor_status->name,
1831                         OBJ_SEARCH_KEY);
1832                 if (!task_data.aor_options) {
1833                         continue;
1834                 }
1835
1836                 ast_debug(3, "Removing endpoint state compositor '%s' from AOR '%s'\n",
1837                         ast_sorcery_object_get_id(endpoint), aor_status->name);
1838                 ao2_unlock(endpoint_state_compositor);
1839                 ast_sip_push_task_wait_serializer(task_data.aor_options->serializer,
1840                         sip_options_endpoint_compositor_remove_task, &task_data);
1841                 ao2_lock(endpoint_state_compositor);
1842                 ao2_ref(task_data.aor_options, -1);
1843         }
1844         ao2_iterator_destroy(&it_aor_statuses);
1845
1846         /*
1847          * We do not need to remove the AOR feeder status memory from the
1848          * aor_statuses container.  The endpoint_state_compositor is about
1849          * to die and do it for us.
1850          */
1851
1852         ao2_unlock(endpoint_state_compositor);
1853 }
1854
1855 /*!
1856  * \brief Task to delete an endpoint from the known universe
1857  * \note Run by management_serializer
1858  */
1859 static int sip_options_endpoint_observer_deleted_task(void *obj)
1860 {
1861         struct ast_sip_endpoint *endpoint = obj;
1862         struct sip_options_endpoint_state_compositor *endpoint_state_compositor;
1863
1864         endpoint_state_compositor = ao2_find(sip_options_endpoint_state_compositors,
1865                 ast_sorcery_object_get_id(endpoint), OBJ_SEARCH_KEY | OBJ_UNLINK);
1866         if (!endpoint_state_compositor) {
1867                 return 0;
1868         }
1869
1870         ast_debug(3, "Endpoint '%s' has been deleted, removing endpoint state compositor from AORs\n",
1871                 ast_sorcery_object_get_id(endpoint));
1872         sip_options_endpoint_unlink_aor_feeders(endpoint, endpoint_state_compositor);
1873         ao2_ref(endpoint_state_compositor, -1);
1874
1875         return 0;
1876 }
1877
1878 /*! \brief Observer callback invoked on endpoint deletion */
1879 static void endpoint_observer_deleted(const void *obj)
1880 {
1881         ast_sip_push_task_wait_serializer(management_serializer,
1882                 sip_options_endpoint_observer_deleted_task, (void *) obj);
1883 }
1884
1885 /*!
1886  * \brief Task to synchronize the endpoint
1887  * \note Run by management_serializer
1888  */
1889 static int sip_options_endpoint_observer_modified_task(void *obj)
1890 {
1891         struct ast_sip_endpoint *endpoint = obj;
1892         struct sip_options_endpoint_state_compositor *endpoint_state_compositor;
1893
1894         ast_debug(3, "Endpoint '%s' has been created or modified, updating state\n",
1895                 ast_sorcery_object_get_id(endpoint));
1896
1897         endpoint_state_compositor = ao2_find(sip_options_endpoint_state_compositors,
1898                 ast_sorcery_object_get_id(endpoint), OBJ_SEARCH_KEY | OBJ_UNLINK);
1899         if (endpoint_state_compositor) {
1900                 /* Unlink the AORs currently feeding the endpoint. */
1901                 sip_options_endpoint_unlink_aor_feeders(endpoint, endpoint_state_compositor);
1902                 ao2_ref(endpoint_state_compositor, -1);
1903         }
1904
1905         /* Connect the AORs that now feed the endpoint. */
1906         sip_options_synchronize_endpoint(endpoint, NULL, 0);
1907         return 0;
1908 }
1909
1910 /*! \brief Observer callback invoked on endpoint creation or modification */
1911 static void endpoint_observer_modified(const void *obj)
1912 {
1913         ast_sip_push_task_wait_serializer(management_serializer,
1914                 sip_options_endpoint_observer_modified_task, (void *)obj);
1915 }
1916
1917 /*! \brief Observer callbacks for endpoints */
1918 static const struct ast_sorcery_observer endpoint_observer_callbacks = {
1919         .created = endpoint_observer_modified,
1920         .updated = endpoint_observer_modified,
1921         .deleted = endpoint_observer_deleted,
1922 };
1923
1924 /*!
1925  * \brief Task to synchronize an AOR with our local state
1926  * \note Run by aor_options->serializer
1927  */
1928 static int sip_options_update_aor_task(void *obj)
1929 {
1930         struct sip_options_synchronize_aor_task_data *task_data = obj;
1931         int available = task_data->aor_options->available;
1932
1933         ast_debug(3, "Individually updating AOR '%s' with current state of configuration and world\n",
1934                 task_data->aor_options->name);
1935
1936         sip_options_apply_aor_configuration(task_data->aor_options, task_data->aor,
1937                 task_data->added);
1938
1939         if (!available && task_data->aor_options->available) {
1940                 ast_debug(3, "After modifying AOR '%s' it has now become available\n",
1941                         task_data->aor_options->name);
1942                 sip_options_notify_endpoint_state_compositors(task_data->aor_options, AVAILABLE);
1943         } else if (available && !task_data->aor_options->available) {
1944                 ast_debug(3, "After modifying AOR '%s' it has become unavailable\n",
1945                         task_data->aor_options->name);
1946                 sip_options_notify_endpoint_state_compositors(task_data->aor_options, UNAVAILABLE);
1947         }
1948
1949         return 0;
1950 }
1951
1952 /*!
1953  * \brief Task to synchronize the AOR
1954  * \note Run by management_serializer
1955  */
1956 static int sip_options_aor_observer_modified_task(void *obj)
1957 {
1958         struct ast_sip_aor *aor = obj;
1959         struct sip_options_aor *aor_options;
1960
1961         aor_options = ao2_find(sip_options_aors, ast_sorcery_object_get_id(aor),
1962                 OBJ_SEARCH_KEY);
1963         if (!aor_options) {
1964                 struct ao2_container *endpoints;
1965
1966                 aor_options = sip_options_aor_alloc(aor);
1967                 if (!aor_options) {
1968                         return 0;
1969                 }
1970
1971                 /*
1972                  * This is a newly added AOR and we need to establish any
1973                  * endpoint state compositors that may reference only the
1974                  * AOR.  If these need to be updated later then they'll
1975                  * be done by modifying the endpoint or issuing a reload.
1976                  */
1977                 sip_options_apply_aor_configuration(aor_options, aor, 1);
1978                 ao2_link(sip_options_aors, aor_options);
1979
1980                 /*
1981                  * Using LIKE doesn't seem to work very well with non-realtime so we
1982                  * fetch everything right now and do a filter on our side.
1983                  */
1984                 endpoints = ast_sorcery_retrieve_by_fields(ast_sip_get_sorcery(),
1985                         "endpoint", AST_RETRIEVE_FLAG_MULTIPLE | AST_RETRIEVE_FLAG_ALL, NULL);
1986                 if (endpoints) {
1987                         ao2_callback(endpoints, OBJ_NODATA, sip_options_synchronize_endpoint, aor);
1988                         ao2_ref(endpoints, -1);
1989                 }
1990         } else {
1991                 struct sip_options_synchronize_aor_task_data task_data = {
1992                         .aor_options = aor_options,
1993                         .aor = aor,
1994                 };
1995
1996                 /*
1997                  * If this AOR was modified we have to do our work in its serializer
1998                  * instead of this thread to ensure that things aren't modified by
1999                  * multiple threads.
2000                  */
2001                 ast_sip_push_task_wait_serializer(aor_options->serializer,
2002                         sip_options_update_aor_task, &task_data);
2003         }
2004
2005         ao2_ref(aor_options, -1);
2006
2007         return 0;
2008 }
2009
2010 /*! \brief Observer callback invoked on AOR creation or modification */
2011 static void aor_observer_modified(const void *obj)
2012 {
2013         ast_sip_push_task_wait_serializer(management_serializer,
2014                 sip_options_aor_observer_modified_task, (void *) obj);
2015 }
2016
2017 /*!
2018  * \brief Task to delete an AOR from the known universe
2019  * \note Run by management_serializer
2020  */
2021 static int sip_options_aor_observer_deleted_task(void *obj)
2022 {
2023         struct ast_sip_aor *aor = obj;
2024         struct sip_options_aor *aor_options;
2025
2026         aor_options = ao2_find(sip_options_aors, ast_sorcery_object_get_id(aor),
2027                 OBJ_SEARCH_KEY | OBJ_UNLINK);
2028         if (!aor_options) {
2029                 return 0;
2030         }
2031
2032         ast_debug(3, "AOR '%s' has been deleted, removing it\n", aor_options->name);
2033
2034         ast_sip_push_task_wait_serializer(aor_options->serializer, sip_options_aor_remove_task,
2035                 aor_options);
2036         ao2_ref(aor_options, -1);
2037
2038         return 0;
2039 }
2040
2041 /*! \brief Observer callback invoked on AOR deletion */
2042 static void aor_observer_deleted(const void *obj)
2043 {
2044         ast_sip_push_task_wait_serializer(management_serializer,
2045                 sip_options_aor_observer_deleted_task, (void *) obj);
2046 }
2047
2048 /*! \brief Observer callbacks for AORs */
2049 static const struct ast_sorcery_observer aor_observer_callbacks = {
2050         .created = aor_observer_modified,
2051         .updated = aor_observer_modified,
2052         .deleted = aor_observer_deleted,
2053 };
2054
2055 /*! \brief Task details for adding an AOR to an endpoint state compositor */
2056 struct sip_options_contact_observer_task_data {
2057         /*! \brief The AOR options that the contact is referring to */
2058         struct sip_options_aor *aor_options;
2059         /*! \brief The contact itself */
2060         struct ast_sip_contact *contact;
2061 };
2062
2063
2064 /*!
2065  * \brief Check if the contact qualify options are different than local aor qualify options
2066  */
2067 static int has_qualify_changed (struct ast_sip_contact *contact, struct sip_options_aor *aor_options)
2068 {
2069         if (!contact) {
2070             return 0;
2071         }
2072
2073         if (!aor_options) {
2074                 if (contact->qualify_frequency) {
2075                         return 1;
2076                 }
2077         } else if (contact->qualify_frequency != aor_options->qualify_frequency
2078                 || contact->authenticate_qualify != aor_options->authenticate_qualify
2079                 || ((int)(contact->qualify_timeout * 1000)) != ((int)(aor_options->qualify_timeout * 1000))) {
2080                 return 1;
2081         }
2082
2083         return 0;
2084 }
2085
2086 /*!
2087  * \brief Task which adds a dynamic contact to an AOR
2088  * \note Run by aor_options->serializer
2089  */
2090 static int sip_options_contact_add_task(void *obj)
2091 {
2092         struct sip_options_contact_observer_task_data *task_data = obj;
2093         struct ast_sip_contact_status *contact_status;
2094
2095         ao2_link(task_data->aor_options->dynamic_contacts, task_data->contact);
2096         ao2_link(task_data->aor_options->contacts, task_data->contact);
2097
2098         contact_status = ast_res_pjsip_find_or_create_contact_status(task_data->contact);
2099         ao2_cleanup(contact_status);
2100
2101         if (task_data->aor_options->qualify_frequency) {
2102                 /* If this is the first contact we need to schedule up qualification */
2103                 if (ao2_container_count(task_data->aor_options->contacts) == 1) {
2104                         ast_debug(3, "Starting scheduled callback on AOR '%s' for qualifying as there is now a contact on it\n",
2105                                 task_data->aor_options->name);
2106                         /*
2107                          * We immediately schedule the initial qualify so that we get
2108                          * reachable/unreachable as soon as possible.  Realistically
2109                          * since they pretty much just registered they should be
2110                          * reachable.
2111                          */
2112                         if (task_data->aor_options->sched_task) {
2113                                 ast_sip_sched_task_cancel(task_data->aor_options->sched_task);
2114                                 ao2_ref(task_data->aor_options->sched_task, -1);
2115                                 task_data->aor_options->sched_task = NULL;
2116                         }
2117                         task_data->aor_options->sched_task = ast_sip_schedule_task(
2118                                 task_data->aor_options->serializer, 1, sip_options_qualify_aor,
2119                                 ast_taskprocessor_name(task_data->aor_options->serializer),
2120                                 task_data->aor_options,
2121                                 AST_SIP_SCHED_TASK_VARIABLE | AST_SIP_SCHED_TASK_DATA_AO2);
2122                         if (!task_data->aor_options->sched_task) {
2123                                 ast_log(LOG_ERROR, "Unable to schedule qualify for contacts of AOR '%s'\n",
2124                                         task_data->aor_options->name);
2125                         }
2126                 }
2127         } else {
2128                 /*
2129                  * If this was the first contact added to a non-qualified AOR then
2130                  * it should become available.
2131                  */
2132                 task_data->aor_options->available =
2133                         ao2_container_count(task_data->aor_options->contacts);
2134                 if (task_data->aor_options->available == 1) {
2135                         ast_debug(3, "An unqualified contact has been added to AOR '%s' so it is now available\n",
2136                                 task_data->aor_options->name);
2137                         sip_options_notify_endpoint_state_compositors(task_data->aor_options,
2138                                 AVAILABLE);
2139                 }
2140         }
2141
2142         return 0;
2143 }
2144
2145 /*!
2146  * \brief Task to add a dynamic contact to an AOR in its serializer
2147  * \note Run by management_serializer
2148  */
2149 static int sip_options_contact_add_management_task(void *obj)
2150 {
2151         struct sip_options_contact_observer_task_data task_data;
2152
2153         task_data.contact = obj;
2154         task_data.aor_options = ao2_find(sip_options_aors, task_data.contact->aor,
2155                 OBJ_SEARCH_KEY);
2156
2157         if (has_qualify_changed(task_data.contact, task_data.aor_options)) {
2158                 struct ast_sip_aor *aor;
2159
2160                 aor = ast_sorcery_retrieve_by_id(ast_sip_get_sorcery(), "aor",
2161                         task_data.contact->aor);
2162                 if (aor) {
2163                         ast_debug(3, "AOR '%s' qualify options have been modified. Synchronize an AOR local state\n",
2164                                 task_data.contact->aor);
2165                         sip_options_aor_observer_modified_task(aor);
2166                         ao2_ref(aor, -1);
2167                 }
2168         }
2169
2170         if (!task_data.aor_options) {
2171                 return 0;
2172         }
2173
2174         ast_sip_push_task_wait_serializer(task_data.aor_options->serializer,
2175                 sip_options_contact_add_task, &task_data);
2176         ao2_ref(task_data.aor_options, -1);
2177
2178         return 0;
2179 }
2180
2181 /*! \brief Observer callback invoked on contact creation */
2182 static void contact_observer_created(const void *obj)
2183 {
2184         ast_sip_push_task_wait_serializer(management_serializer,
2185                 sip_options_contact_add_management_task, (void *) obj);
2186 }
2187
2188 /*!
2189  * \brief Task which updates a dynamic contact to an AOR
2190  * \note Run by aor_options->serializer
2191  */
2192 static int sip_options_contact_update_task(void *obj)
2193 {
2194         struct sip_options_contact_observer_task_data *task_data = obj;
2195         struct ast_sip_contact_status *contact_status;
2196
2197         contact_status = ast_sip_get_contact_status(task_data->contact);
2198         if (contact_status) {
2199                 switch (contact_status->status) {
2200                 case CREATED:
2201                 case UNAVAILABLE:
2202                 case AVAILABLE:
2203                 case UNKNOWN:
2204                         /* Refresh the ContactStatus AMI events. */
2205                         sip_options_contact_status_update(contact_status);
2206                         break;
2207                 case REMOVED:
2208                         break;
2209                 }
2210                 ao2_ref(contact_status, -1);
2211         }
2212
2213         ao2_ref(task_data->contact, -1);
2214         ao2_ref(task_data->aor_options, -1);
2215         ast_free(task_data);
2216         return 0;
2217 }
2218
2219 /*! \brief Observer callback invoked on contact update */
2220 static void contact_observer_updated(const void *obj)
2221 {
2222         struct sip_options_contact_observer_task_data *task_data;
2223
2224         task_data = ast_malloc(sizeof(*task_data));
2225         if (!task_data) {
2226                 return;
2227         }
2228
2229         task_data->contact = (struct ast_sip_contact *) obj;
2230         task_data->aor_options = ao2_find(sip_options_aors, task_data->contact->aor,
2231                 OBJ_SEARCH_KEY);
2232
2233         if (has_qualify_changed(task_data->contact, task_data->aor_options)) {
2234                 struct ast_sip_aor *aor;
2235
2236                 aor = ast_sorcery_retrieve_by_id(ast_sip_get_sorcery(), "aor",
2237                         task_data->contact->aor);
2238                 if (aor) {
2239                         ast_debug(3, "AOR '%s' qualify options have been modified. Synchronize an AOR local state\n",
2240                                 task_data->contact->aor);
2241                         ast_sip_push_task_wait_serializer(management_serializer,
2242                                 sip_options_aor_observer_modified_task, aor);
2243                         ao2_ref(aor, -1);
2244                 }
2245         }
2246
2247         if (!task_data->aor_options) {
2248                 ast_free(task_data);
2249                 return;
2250         }
2251
2252         ao2_ref(task_data->contact, +1);
2253         if (ast_sip_push_task(task_data->aor_options->serializer,
2254                 sip_options_contact_update_task, task_data)) {
2255                 ao2_ref(task_data->contact, -1);
2256                 ao2_ref(task_data->aor_options, -1);
2257                 ast_free(task_data);
2258         }
2259 }
2260
2261 /*!
2262  * \brief Task which deletes a dynamic contact from an AOR
2263  * \note Run by aor_options->serializer
2264  */
2265 static int sip_options_contact_delete_task(void *obj)
2266 {
2267         struct sip_options_contact_observer_task_data *task_data = obj;
2268
2269         ao2_find(task_data->aor_options->dynamic_contacts, task_data->contact,
2270                 OBJ_NODATA | OBJ_UNLINK | OBJ_SEARCH_OBJECT);
2271         ao2_find(task_data->aor_options->contacts, task_data->contact,
2272                 OBJ_NODATA | OBJ_UNLINK | OBJ_SEARCH_OBJECT);
2273
2274         sip_options_remove_contact_status(task_data->aor_options, task_data->contact);
2275
2276         if (task_data->aor_options->qualify_frequency) {
2277                 /* If this is the last contact then we need to stop the scheduled callback */
2278                 if (!ao2_container_count(task_data->aor_options->contacts)) {
2279                         ast_debug(3, "Terminating scheduled callback on AOR '%s' as there are no contacts to qualify\n",
2280                                 task_data->aor_options->name);
2281                         if (task_data->aor_options->sched_task) {
2282                                 ast_sip_sched_task_cancel(task_data->aor_options->sched_task);
2283                                 ao2_ref(task_data->aor_options->sched_task, -1);
2284                                 task_data->aor_options->sched_task = NULL;
2285                         }
2286                 }
2287         } else {
2288                 task_data->aor_options->available =
2289                         ao2_container_count(task_data->aor_options->contacts);
2290                 if (!task_data->aor_options->available) {
2291                         ast_debug(3, "An unqualified contact has been removed from AOR '%s' leaving no remaining contacts\n",
2292                                 task_data->aor_options->name);
2293                         sip_options_notify_endpoint_state_compositors(task_data->aor_options,
2294                                 UNAVAILABLE);
2295                 }
2296         }
2297
2298         return 0;
2299 }
2300
2301 /*!
2302  * \brief Task to delete a contact from an AOR in its serializer
2303  * \note Run by management_serializer
2304  */
2305 static int sip_options_contact_delete_management_task(void *obj)
2306 {
2307         struct sip_options_contact_observer_task_data task_data;
2308
2309         task_data.contact = obj;
2310         task_data.aor_options = ao2_find(sip_options_aors, task_data.contact->aor,
2311                 OBJ_SEARCH_KEY);
2312         if (!task_data.aor_options) {
2313                 /* For contacts that are deleted we don't really care if there is no AOR locally */
2314                 return 0;
2315         }
2316
2317         ast_sip_push_task_wait_serializer(task_data.aor_options->serializer,
2318                 sip_options_contact_delete_task, &task_data);
2319         ao2_ref(task_data.aor_options, -1);
2320
2321         return 0;
2322 }
2323
2324 /*! \brief Observer callback invoked on contact deletion */
2325 static void contact_observer_deleted(const void *obj)
2326 {
2327         ast_sip_push_task_wait_serializer(management_serializer,
2328                 sip_options_contact_delete_management_task, (void *) obj);
2329 }
2330
2331 /*! \brief Observer callbacks for contacts */
2332 static const struct ast_sorcery_observer contact_observer_callbacks = {
2333         .created = contact_observer_created,
2334         .updated = contact_observer_updated,
2335         .deleted = contact_observer_deleted,
2336 };
2337
2338 static char *cli_qualify(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
2339 {
2340         RAII_VAR(struct ast_sip_endpoint *, endpoint, NULL, ao2_cleanup);
2341         const char *endpoint_name;
2342         char *aors;
2343         char *aor_name;
2344
2345         switch (cmd) {
2346         case CLI_INIT:
2347                 e->command = "pjsip qualify";
2348                 e->usage =
2349                         "Usage: pjsip qualify <endpoint>\n"
2350                         "       Send a SIP OPTIONS request to all contacts on the endpoint.\n";
2351                 return NULL;
2352         case CLI_GENERATE:
2353                 return NULL;
2354         }
2355
2356         if (a->argc != 3) {
2357                 return CLI_SHOWUSAGE;
2358         }
2359
2360         endpoint_name = a->argv[2];
2361
2362         endpoint = ast_sorcery_retrieve_by_id(ast_sip_get_sorcery(), "endpoint",
2363                 endpoint_name);
2364         if (!endpoint) {
2365                 ast_cli(a->fd, "Unable to retrieve endpoint %s\n", endpoint_name);
2366                 return CLI_FAILURE;
2367         }
2368
2369         if (ast_strlen_zero(endpoint->aors)) {
2370                 ast_cli(a->fd, "No AORs configured for endpoint '%s'\n", endpoint_name);
2371                 return CLI_FAILURE;
2372         }
2373
2374         aors = ast_strdupa(endpoint->aors);
2375         while ((aor_name = ast_strip(strsep(&aors, ",")))) {
2376                 struct sip_options_aor *aor_options;
2377
2378                 aor_options = ao2_find(sip_options_aors, aor_name, OBJ_SEARCH_KEY);
2379                 if (!aor_options) {
2380                         continue;
2381                 }
2382
2383                 ast_cli(a->fd, "Qualifying AOR '%s' on endpoint '%s'\n", aor_name, endpoint_name);
2384                 ast_sip_push_task_wait_serializer(aor_options->serializer, sip_options_qualify_aor,
2385                         aor_options);
2386                 ao2_ref(aor_options, -1);
2387         }
2388
2389         return CLI_SUCCESS;
2390 }
2391
2392 static struct ao2_container *get_all_contacts(void)
2393 {
2394         struct ao2_container *contacts;
2395
2396         contacts = ast_sorcery_retrieve_by_fields(ast_sip_get_sorcery(), "contact",
2397                         AST_RETRIEVE_FLAG_MULTIPLE | AST_RETRIEVE_FLAG_ALL, NULL);
2398
2399         return contacts;
2400 }
2401
2402 static int sip_contact_to_ami(const struct ast_sip_contact *contact,
2403                            struct ast_str **buf)
2404 {
2405         return ast_sip_sorcery_object_to_ami(contact, buf);
2406 }
2407
2408 static int format_ami_contactlist_handler(void *obj, void *arg, int flags)
2409 {
2410         struct ast_sip_contact *contact = obj;
2411         struct ast_sip_ami *ami = arg;
2412         struct ast_str *buf;
2413         struct ast_sip_contact_status *status;
2414
2415         buf = ast_sip_create_ami_event("ContactList", ami);
2416         if (!buf) {
2417                 return CMP_STOP;
2418         }
2419
2420         if (sip_contact_to_ami(contact, &buf)) {
2421                 ast_free(buf);
2422                 return CMP_STOP;
2423         }
2424
2425         /* Add extra info */
2426         status = ast_sip_get_contact_status(contact);
2427         ast_str_append(&buf, 0, "Status: %s\r\n",
2428                 ast_sip_get_contact_status_label(status ? status->status : UNKNOWN));
2429         if (!status || status->status != AVAILABLE) {
2430                 ast_str_append(&buf, 0, "RoundtripUsec: N/A\r\n");
2431         } else {
2432                 ast_str_append(&buf, 0, "RoundtripUsec: %" PRId64 "\r\n", status->rtt);
2433         }
2434         ao2_cleanup(status);
2435
2436         astman_append(ami->s, "%s\r\n", ast_str_buffer(buf));
2437
2438         ami->count++;
2439
2440         ast_free(buf);
2441
2442         return 0;
2443 }
2444
2445 static int ami_show_contacts(struct mansession *s, const struct message *m)
2446 {
2447         struct ast_sip_ami ami = { .s = s, .m = m, .action_id = astman_get_header(m, "ActionID"), };
2448         struct ao2_container *contacts;
2449
2450         contacts = get_all_contacts();
2451         if (!contacts) {
2452                 astman_send_error(s, m, "Could not get Contacts\n");
2453                 return 0;
2454         }
2455
2456         if (!ao2_container_count(contacts)) {
2457                 astman_send_error(s, m, "No Contacts found\n");
2458                 ao2_ref(contacts, -1);
2459                 return 0;
2460         }
2461
2462         astman_send_listack(s, m, "A listing of Contacts follows, presented as ContactList events",
2463                         "start");
2464
2465         ao2_callback(contacts, OBJ_NODATA, format_ami_contactlist_handler, &ami);
2466
2467         astman_send_list_complete_start(s, m, "ContactListComplete", ami.count);
2468         astman_send_list_complete_end(s);
2469
2470         ao2_ref(contacts, -1);
2471
2472         return 0;
2473 }
2474
2475 static char *cli_show_qualify_endpoint(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
2476 {
2477         RAII_VAR(struct ast_sip_endpoint *, endpoint, NULL, ao2_cleanup);
2478         const char *endpoint_name;
2479         char *aors;
2480         char *aor_name;
2481
2482         switch (cmd) {
2483         case CLI_INIT:
2484                 e->command = "pjsip show qualify endpoint";
2485                 e->usage =
2486                         "Usage: pjsip show qualify endpoint <id>\n"
2487                         "       Show the current qualify options for all Aors on the PJSIP endpoint.\n";
2488                 return NULL;
2489         case CLI_GENERATE:
2490                 return NULL;
2491         }
2492
2493         if (a->argc != 5) {
2494                 return CLI_SHOWUSAGE;
2495         }
2496
2497         endpoint_name = a->argv[4];
2498
2499         endpoint = ast_sorcery_retrieve_by_id(ast_sip_get_sorcery(), "endpoint",
2500                 endpoint_name);
2501         if (!endpoint) {
2502                 ast_cli(a->fd, "Unable to retrieve endpoint %s\n", endpoint_name);
2503                 return CLI_FAILURE;
2504         }
2505
2506         if (ast_strlen_zero(endpoint->aors)) {
2507                 ast_cli(a->fd, "No AORs configured for endpoint '%s'\n", endpoint_name);
2508                 return CLI_FAILURE;
2509         }
2510
2511         aors = ast_strdupa(endpoint->aors);
2512         while ((aor_name = ast_strip(strsep(&aors, ",")))) {
2513                 struct sip_options_aor *aor_options;
2514
2515                 aor_options = ao2_find(sip_options_aors, aor_name, OBJ_SEARCH_KEY);
2516                 if (!aor_options) {
2517                         continue;
2518                 }
2519
2520                 ast_cli(a->fd, " * AOR '%s' on endpoint '%s'\n", aor_name, endpoint_name);
2521                 ast_cli(a->fd, "  Qualify frequency    : %d sec\n", aor_options->qualify_frequency);
2522                 ast_cli(a->fd, "  Qualify timeout      : %d ms\n", (int)(aor_options->qualify_timeout / 1000));
2523                 ast_cli(a->fd, "  Authenticate qualify : %s\n", aor_options->authenticate_qualify?"yes":"no");
2524                 ast_cli(a->fd, "\n");
2525                 ao2_ref(aor_options, -1);
2526         }
2527
2528         return CLI_SUCCESS;
2529 }
2530
2531 static char *cli_show_qualify_aor(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
2532 {
2533         struct sip_options_aor *aor_options;
2534         const char *aor_name;
2535
2536         switch (cmd) {
2537         case CLI_INIT:
2538                 e->command = "pjsip show qualify aor";
2539                 e->usage =
2540                         "Usage: pjsip show qualify aor <id>\n"
2541                         "       Show the PJSIP Aor current qualify options.\n";
2542                 return NULL;
2543         case CLI_GENERATE:
2544                 return NULL;
2545         }
2546
2547         if (a->argc != 5) {
2548                 return CLI_SHOWUSAGE;
2549         }
2550
2551         aor_name = a->argv[4];
2552
2553         aor_options = ao2_find(sip_options_aors, aor_name, OBJ_SEARCH_KEY);
2554         if (!aor_options) {
2555                 ast_cli(a->fd, "Unable to retrieve aor '%s' qualify options\n", aor_name);
2556                 return CLI_FAILURE;
2557         }
2558
2559         ast_cli(a->fd, " * AOR '%s'\n", aor_name);
2560         ast_cli(a->fd, "  Qualify frequency    : %d sec\n", aor_options->qualify_frequency);
2561         ast_cli(a->fd, "  Qualify timeout      : %d ms\n", (int)(aor_options->qualify_timeout / 1000));
2562         ast_cli(a->fd, "  Authenticate qualify : %s\n", aor_options->authenticate_qualify?"yes":"no");
2563         ao2_ref(aor_options, -1);
2564
2565         return CLI_SUCCESS;
2566 }
2567
2568 static char *cli_reload_qualify_endpoint(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
2569 {
2570         RAII_VAR(struct ast_sip_endpoint *, endpoint, NULL, ao2_cleanup);
2571         const char *endpoint_name;
2572         char *aors;
2573         char *aor_name;
2574
2575         switch (cmd) {
2576         case CLI_INIT:
2577                 e->command = "pjsip reload qualify endpoint";
2578                 e->usage =
2579                         "Usage: pjsip reload qualify endpoint <id>\n"
2580                         "       Synchronize the qualify options for all Aors on the PJSIP endpoint.\n";
2581                 return NULL;
2582         case CLI_GENERATE:
2583                 return NULL;
2584         }
2585
2586         if (a->argc != 5) {
2587                 return CLI_SHOWUSAGE;
2588         }
2589
2590         endpoint_name = a->argv[4];
2591
2592         endpoint = ast_sorcery_retrieve_by_id(ast_sip_get_sorcery(), "endpoint",
2593                 endpoint_name);
2594         if (!endpoint) {
2595                 ast_cli(a->fd, "Unable to retrieve endpoint %s\n", endpoint_name);
2596                 return CLI_FAILURE;
2597         }
2598
2599         if (ast_strlen_zero(endpoint->aors)) {
2600                 ast_cli(a->fd, "No AORs configured for endpoint '%s'\n", endpoint_name);
2601                 return CLI_FAILURE;
2602         }
2603
2604         aors = ast_strdupa(endpoint->aors);
2605         while ((aor_name = ast_strip(strsep(&aors, ",")))) {
2606                 struct ast_sip_aor *aor;
2607
2608                 aor = ast_sorcery_retrieve_by_id(ast_sip_get_sorcery(), "aor", aor_name);
2609                 if (!aor) {
2610                         continue;
2611                 }
2612
2613                 ast_cli(a->fd, "Synchronizing AOR '%s' on endpoint '%s'\n", aor_name, endpoint_name);
2614                 ast_sip_push_task_wait_serializer(management_serializer,
2615                         sip_options_aor_observer_modified_task, aor);
2616                 ao2_ref(aor, -1);
2617         }
2618
2619         return CLI_SUCCESS;
2620 }
2621
2622 static char *cli_reload_qualify_aor(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
2623 {
2624         struct ast_sip_aor *aor;
2625         const char *aor_name;
2626
2627         switch (cmd) {
2628         case CLI_INIT:
2629                 e->command = "pjsip reload qualify aor";
2630                 e->usage =
2631                         "Usage: pjsip reload qualify aor <id>\n"
2632                         "       Synchronize the PJSIP Aor qualify options.\n";
2633                 return NULL;
2634         case CLI_GENERATE:
2635                 return NULL;
2636         }
2637
2638         if (a->argc != 5) {
2639                 return CLI_SHOWUSAGE;
2640         }
2641
2642         aor_name = a->argv[4];
2643
2644         aor = ast_sorcery_retrieve_by_id(ast_sip_get_sorcery(), "aor", aor_name);
2645         if (!aor) {
2646                 ast_cli(a->fd, "Unable to retrieve aor '%s'\n", aor_name);
2647                 return CLI_FAILURE;
2648         }
2649
2650         ast_cli(a->fd, "Synchronizing AOR '%s'\n", aor_name);
2651         ast_sip_push_task_wait_serializer(management_serializer,
2652                 sip_options_aor_observer_modified_task, aor);
2653         ao2_ref(aor, -1);
2654
2655         return CLI_SUCCESS;
2656 }
2657
2658 static int ami_sip_qualify(struct mansession *s, const struct message *m)
2659 {
2660         const char *endpoint_name = astman_get_header(m, "Endpoint");
2661         RAII_VAR(struct ast_sip_endpoint *, endpoint, NULL, ao2_cleanup);
2662         char *aors;
2663         char *aor_name;
2664
2665         if (ast_strlen_zero(endpoint_name)) {
2666                 astman_send_error(s, m, "Endpoint parameter missing.");
2667                 return 0;
2668         }
2669
2670         endpoint = ast_sorcery_retrieve_by_id(ast_sip_get_sorcery(), "endpoint",
2671                 endpoint_name);
2672         if (!endpoint) {
2673                 astman_send_error(s, m, "Unable to retrieve endpoint\n");
2674                 return 0;
2675         }
2676
2677         /* send a qualify for all contacts registered with the endpoint */
2678         if (ast_strlen_zero(endpoint->aors)) {
2679                 astman_send_error(s, m, "No AoRs configured for endpoint\n");
2680                 return 0;
2681         }
2682
2683         aors = ast_strdupa(endpoint->aors);
2684         while ((aor_name = ast_strip(strsep(&aors, ",")))) {
2685                 struct sip_options_aor *aor_options;
2686
2687                 aor_options = ao2_find(sip_options_aors, aor_name, OBJ_SEARCH_KEY);
2688                 if (!aor_options) {
2689                         continue;
2690                 }
2691
2692                 ast_sip_push_task_wait_serializer(aor_options->serializer, sip_options_qualify_aor,
2693                         aor_options);
2694                 ao2_ref(aor_options, -1);
2695         }
2696
2697         astman_send_ack(s, m, "Endpoint found, will qualify");
2698         return 0;
2699 }
2700
2701 static struct ast_cli_entry cli_options[] = {
2702         AST_CLI_DEFINE(cli_qualify, "Send an OPTIONS request to a PJSIP endpoint"),
2703         AST_CLI_DEFINE(cli_show_qualify_endpoint, "Show the current qualify options for all Aors on the PJSIP endpoint"),
2704         AST_CLI_DEFINE(cli_show_qualify_aor, "Show the PJSIP Aor current qualify options"),
2705         AST_CLI_DEFINE(cli_reload_qualify_endpoint, "Synchronize the qualify options for all Aors on the PJSIP endpoint"),
2706         AST_CLI_DEFINE(cli_reload_qualify_aor, "Synchronize the PJSIP Aor qualify options"),
2707 };
2708
2709 int ast_sip_format_contact_ami(void *obj, void *arg, int flags)
2710 {
2711         struct ast_sip_contact_wrapper *wrapper = obj;
2712         struct ast_sip_contact *contact = wrapper->contact;
2713         struct ast_sip_ami *ami = arg;
2714         struct ast_sip_contact_status *status;
2715         struct ast_str *buf;
2716         const struct ast_sip_endpoint *endpoint = ami->arg;
2717
2718         buf = ast_sip_create_ami_event("ContactStatusDetail", ami);
2719         if (!buf) {
2720                 return -1;
2721         }
2722
2723         status = ast_sip_get_contact_status(contact);
2724
2725         ast_str_append(&buf, 0, "AOR: %s\r\n", wrapper->aor_id);
2726         ast_str_append(&buf, 0, "URI: %s\r\n", contact->uri);
2727         ast_str_append(&buf, 0, "UserAgent: %s\r\n", contact->user_agent);
2728         ast_str_append(&buf, 0, "RegExpire: %ld\r\n", contact->expiration_time.tv_sec);
2729         if (!ast_strlen_zero(contact->via_addr)) {
2730                 ast_str_append(&buf, 0, "ViaAddress: %s", contact->via_addr);
2731                 if (contact->via_port) {
2732                         ast_str_append(&buf, 0, ":%d", contact->via_port);
2733                 }
2734                 ast_str_append(&buf, 0, "\r\n");
2735         }
2736         if (!ast_strlen_zero(contact->call_id)) {
2737                 ast_str_append(&buf, 0, "CallID: %s\r\n", contact->call_id);
2738         }
2739         ast_str_append(&buf, 0, "Status: %s\r\n",
2740                 ast_sip_get_contact_status_label(status ? status->status : UNKNOWN));
2741         if (!status || status->status != AVAILABLE) {
2742                 ast_str_append(&buf, 0, "RoundtripUsec: N/A\r\n");
2743         } else {
2744                 ast_str_append(&buf, 0, "RoundtripUsec: %" PRId64 "\r\n", status->rtt);
2745         }
2746         ast_str_append(&buf, 0, "EndpointName: %s\r\n",
2747                 endpoint ? ast_sorcery_object_get_id(endpoint) : S_OR(contact->endpoint_name, ""));
2748
2749         ast_str_append(&buf, 0, "ID: %s\r\n", ast_sorcery_object_get_id(contact));
2750         ast_str_append(&buf, 0, "AuthenticateQualify: %d\r\n", contact->authenticate_qualify);
2751         ast_str_append(&buf, 0, "OutboundProxy: %s\r\n", contact->outbound_proxy);
2752         ast_str_append(&buf, 0, "Path: %s\r\n", contact->path);
2753         ast_str_append(&buf, 0, "QualifyFrequency: %u\r\n", contact->qualify_frequency);
2754         ast_str_append(&buf, 0, "QualifyTimeout: %.3f\r\n", contact->qualify_timeout);
2755
2756         astman_append(ami->s, "%s\r\n", ast_str_buffer(buf));
2757         ami->count++;
2758
2759         ast_free(buf);
2760         ao2_cleanup(status);
2761         return 0;
2762 }
2763
2764 static int format_contact_status_for_aor(void *obj, void *arg, int flags)
2765 {
2766         struct ast_sip_aor *aor = obj;
2767
2768         return ast_sip_for_each_contact(aor, ast_sip_format_contact_ami, arg);
2769 }
2770
2771 static int format_ami_contact_status(const struct ast_sip_endpoint *endpoint,
2772                 struct ast_sip_ami *ami)
2773 {
2774         ami->arg = (void *)endpoint;
2775         return ast_sip_for_each_aor(endpoint->aors, format_contact_status_for_aor, ami);
2776 }
2777
2778 static struct ast_sip_endpoint_formatter contact_status_formatter = {
2779         .format_ami = format_ami_contact_status
2780 };
2781
2782 /*!
2783  * \brief Management task to clean up an AOR
2784  * \note Run by aor_options->serializer
2785  */
2786 static int sip_options_cleanup_aor_task(void *obj)
2787 {
2788         struct sip_options_aor *aor_options = obj;
2789
2790         ast_debug(2, "Cleaning up AOR '%s' for shutdown\n", aor_options->name);
2791
2792         aor_options->qualify_frequency = 0;
2793         if (aor_options->sched_task) {
2794                 ast_sip_sched_task_cancel(aor_options->sched_task);
2795                 ao2_ref(aor_options->sched_task, -1);
2796                 aor_options->sched_task = NULL;
2797         }
2798         AST_VECTOR_RESET(&aor_options->compositors, ao2_cleanup);
2799
2800         return 0;
2801 }
2802
2803 /*!
2804  * \brief Management task to clean up the environment
2805  * \note Run by management_serializer
2806  */
2807 static int sip_options_cleanup_task(void *obj)
2808 {
2809         struct ao2_iterator it_aor;
2810         struct sip_options_aor *aor_options;
2811
2812         if (!sip_options_aors) {
2813                 /* Nothing to do */
2814                 return 0;
2815         }
2816
2817         it_aor = ao2_iterator_init(sip_options_aors, AO2_ITERATOR_UNLINK);
2818         for (; (aor_options = ao2_iterator_next(&it_aor)); ao2_ref(aor_options, -1)) {
2819                 ast_sip_push_task_wait_serializer(aor_options->serializer,
2820                         sip_options_cleanup_aor_task, aor_options);
2821         }
2822         ao2_iterator_destroy(&it_aor);
2823
2824         return 0;
2825 }
2826
2827 void ast_res_pjsip_cleanup_options_handling(void)
2828 {
2829         int remaining;
2830         struct ast_taskprocessor *mgmt_serializer;
2831
2832         ast_cli_unregister_multiple(cli_options, ARRAY_LEN(cli_options));
2833         ast_manager_unregister("PJSIPQualify");
2834         ast_manager_unregister("PJSIPShowContacts");
2835         ast_sip_unregister_endpoint_formatter(&contact_status_formatter);
2836
2837         ast_sorcery_observer_remove(ast_sip_get_sorcery(), "contact",
2838                 &contact_observer_callbacks);
2839         ast_sorcery_observer_remove(ast_sip_get_sorcery(), "aor",
2840                 &aor_observer_callbacks);
2841         ast_sorcery_observer_remove(ast_sip_get_sorcery(), "endpoint",
2842                 &endpoint_observer_callbacks);
2843
2844         mgmt_serializer = management_serializer;
2845         management_serializer = NULL;
2846         if (mgmt_serializer) {
2847                 ast_sip_push_task_wait_serializer(mgmt_serializer, sip_options_cleanup_task, NULL);
2848         }
2849
2850         remaining = ast_serializer_shutdown_group_join(shutdown_group,
2851                 MAX_UNLOAD_TIMEOUT_TIME);
2852         if (remaining) {
2853                 ast_log(LOG_WARNING, "Cleanup incomplete. Could not stop %d AORs.\n",
2854                         remaining);
2855         }
2856         ao2_cleanup(shutdown_group);
2857         shutdown_group = NULL;
2858
2859         if (mgmt_serializer) {
2860                 ast_taskprocessor_unreference(mgmt_serializer);
2861         }
2862
2863         ao2_cleanup(sip_options_aors);
2864         sip_options_aors = NULL;
2865         ao2_cleanup(sip_options_contact_statuses);
2866         sip_options_contact_statuses = NULL;
2867         ao2_cleanup(sip_options_endpoint_state_compositors);
2868         sip_options_endpoint_state_compositors = NULL;
2869
2870         pjsip_endpt_unregister_module(ast_sip_get_pjsip_endpoint(), &options_module);
2871 }
2872
2873 /*!
2874  * \brief Management task to finish setting up the environment.
2875  * \note Run by management_serializer
2876  */
2877 static int sip_options_init_task(void *mgmt_serializer)
2878 {
2879         management_serializer = mgmt_serializer;
2880
2881         shutdown_group = ast_serializer_shutdown_group_alloc();
2882         if (!shutdown_group) {
2883                 return -1;
2884         }
2885
2886         if (ast_sorcery_observer_add(ast_sip_get_sorcery(), "endpoint",
2887                 &endpoint_observer_callbacks)) {
2888                 return -1;
2889         }
2890         if (ast_sorcery_observer_add(ast_sip_get_sorcery(), "aor",
2891                 &aor_observer_callbacks)) {
2892                 return -1;
2893         }
2894         if (ast_sorcery_observer_add(ast_sip_get_sorcery(), "contact",
2895                 &contact_observer_callbacks)) {
2896                 return -1;
2897         }
2898
2899         sip_options_synchronize(0);
2900
2901         return 0;
2902 }
2903
2904 int ast_res_pjsip_preinit_options_handling(void)
2905 {
2906         sip_options_contact_statuses = sip_options_contact_statuses_alloc();
2907         return sip_options_contact_statuses ? 0 : -1;
2908 }
2909
2910 int ast_res_pjsip_init_options_handling(int reload)
2911 {
2912         struct ast_taskprocessor *mgmt_serializer;
2913
2914         static const pj_str_t STR_OPTIONS = { "OPTIONS", 7 };
2915
2916         if (reload) {
2917                 sip_options_synchronize(1);
2918                 return 0;
2919         }
2920
2921         if (pjsip_endpt_register_module(ast_sip_get_pjsip_endpoint(), &options_module)
2922                 != PJ_SUCCESS) {
2923                 return -1;
2924         }
2925
2926         if (pjsip_endpt_add_capability(ast_sip_get_pjsip_endpoint(), NULL, PJSIP_H_ALLOW,
2927                 NULL, 1, &STR_OPTIONS) != PJ_SUCCESS) {
2928                 ast_res_pjsip_cleanup_options_handling();
2929                 return -1;
2930         }
2931
2932         sip_options_aors = ao2_container_alloc_hash(AO2_ALLOC_OPT_LOCK_RWLOCK, 0, AOR_BUCKETS,
2933                 sip_options_aor_hash_fn, NULL, sip_options_aor_cmp_fn);
2934         if (!sip_options_aors) {
2935                 ast_res_pjsip_cleanup_options_handling();
2936                 return -1;
2937         }
2938         sip_options_endpoint_state_compositors =
2939                 ao2_container_alloc_hash(AO2_ALLOC_OPT_LOCK_RWLOCK, 0,
2940                         ENDPOINT_STATE_COMPOSITOR_BUCKETS,
2941                         sip_options_endpoint_state_compositor_hash_fn, NULL,
2942                         sip_options_endpoint_state_compositor_cmp_fn);
2943         if (!sip_options_endpoint_state_compositors) {
2944                 ast_res_pjsip_cleanup_options_handling();
2945                 return -1;
2946         }
2947
2948         mgmt_serializer = ast_sip_create_serializer("pjsip/options/manage");
2949         if (!mgmt_serializer) {
2950                 ast_res_pjsip_cleanup_options_handling();
2951                 return -1;
2952         }
2953
2954         /*
2955          * Set the water mark levels high because we can get a flood of
2956          * contact status updates from sip_options_synchronize() that
2957          * quickly clears on initial load or reload.
2958          */
2959         ast_taskprocessor_alert_set_levels(mgmt_serializer, -1,
2960                 10 * AST_TASKPROCESSOR_HIGH_WATER_LEVEL);
2961
2962         /*
2963          * We make sure that the environment is completely setup before we allow
2964          * any other threads to post contact_status updates to the
2965          * management_serializer.
2966          */
2967         if (ast_sip_push_task_wait_serializer(mgmt_serializer, sip_options_init_task,
2968                 mgmt_serializer)) {
2969                 /* Set management_serializer in case pushing the task actually failed. */
2970                 management_serializer = mgmt_serializer;
2971                 ast_res_pjsip_cleanup_options_handling();
2972                 return -1;
2973         }
2974
2975         ast_sip_register_endpoint_formatter(&contact_status_formatter);
2976         ast_manager_register_xml("PJSIPQualify", EVENT_FLAG_SYSTEM | EVENT_FLAG_REPORTING,
2977                 ami_sip_qualify);
2978         ast_manager_register_xml("PJSIPShowContacts", EVENT_FLAG_SYSTEM, ami_show_contacts);
2979         ast_cli_register_multiple(cli_options, ARRAY_LEN(cli_options));
2980
2981         return 0;
2982 }