679c8837d931865ecc85d91a768c7f7215498dbd
[asterisk/asterisk.git] / res / res_pjsip / pjsip_configuration.c
1 /*
2  * sip_cli_commands.c
3  *
4  *  Created on: Jan 25, 2013
5  *      Author: mjordan
6  */
7
8 #include "asterisk.h"
9
10 #include <pjsip.h>
11 #include <pjsip_ua.h>
12
13 #include "asterisk/res_pjsip.h"
14 #include "include/res_pjsip_private.h"
15 #include "asterisk/res_pjsip_cli.h"
16 #include "asterisk/acl.h"
17 #include "asterisk/manager.h"
18 #include "asterisk/astobj2.h"
19 #include "asterisk/utils.h"
20 #include "asterisk/sorcery.h"
21 #include "asterisk/callerid.h"
22 #include "asterisk/test.h"
23 #include "asterisk/statsd.h"
24 #include "asterisk/pbx.h"
25
26 /*! \brief Number of buckets for persistent endpoint information */
27 #define PERSISTENT_BUCKETS 53
28
29 /*! \brief Persistent endpoint information */
30 struct sip_persistent_endpoint {
31         /*! \brief Asterisk endpoint itself */
32         struct ast_endpoint *endpoint;
33         /*! \brief AORs that we should react to */
34         char *aors;
35 };
36
37 /*! \brief Container for persistent endpoint information */
38 static struct ao2_container *persistent_endpoints;
39
40 static struct ast_sorcery *sip_sorcery;
41
42 /*! \brief Hashing function for persistent endpoint information */
43 static int persistent_endpoint_hash(const void *obj, const int flags)
44 {
45         const struct sip_persistent_endpoint *persistent = obj;
46         const char *id = (flags & OBJ_KEY ? obj : ast_endpoint_get_resource(persistent->endpoint));
47
48         return ast_str_hash(id);
49 }
50
51 /*! \brief Comparison function for persistent endpoint information */
52 static int persistent_endpoint_cmp(void *obj, void *arg, int flags)
53 {
54         const struct sip_persistent_endpoint *persistent1 = obj;
55         const struct sip_persistent_endpoint *persistent2 = arg;
56         const char *id = (flags & OBJ_KEY ? arg : ast_endpoint_get_resource(persistent2->endpoint));
57
58         return !strcmp(ast_endpoint_get_resource(persistent1->endpoint), id) ? CMP_MATCH | CMP_STOP : 0;
59 }
60
61 /*! \brief Internal function for changing the state of an endpoint */
62 static void endpoint_update_state(struct ast_endpoint *endpoint, enum ast_endpoint_state state)
63 {
64         struct ast_json *blob;
65         char *regcontext;
66
67         /* If there was no state change, don't publish anything. */
68         if (ast_endpoint_get_state(endpoint) == state) {
69                 return;
70         }
71
72         regcontext = ast_sip_get_regcontext();
73
74         if (state == AST_ENDPOINT_ONLINE) {
75                 ast_endpoint_set_state(endpoint, AST_ENDPOINT_ONLINE);
76                 blob = ast_json_pack("{s: s}", "peer_status", "Reachable");
77
78                 if (!ast_strlen_zero(regcontext)) {
79                         if (!ast_exists_extension(NULL, regcontext, ast_endpoint_get_resource(endpoint), 1, NULL)) {
80                                 ast_add_extension(regcontext, 1, ast_endpoint_get_resource(endpoint), 1, NULL, NULL,
81                                         "Noop", ast_strdup(ast_endpoint_get_resource(endpoint)), ast_free_ptr, "SIP");
82                         }
83                 }
84
85                 ast_verb(2, "Endpoint %s is now Reachable\n", ast_endpoint_get_resource(endpoint));
86         } else {
87                 ast_endpoint_set_state(endpoint, AST_ENDPOINT_OFFLINE);
88                 blob = ast_json_pack("{s: s}", "peer_status", "Unreachable");
89
90                 if (!ast_strlen_zero(regcontext)) {
91                         struct pbx_find_info q = { .stacklen = 0 };
92
93                         if (pbx_find_extension(NULL, NULL, &q, regcontext, ast_endpoint_get_resource(endpoint), 1, NULL, "", E_MATCH)) {
94                                 ast_context_remove_extension(regcontext, ast_endpoint_get_resource(endpoint), 1, NULL);
95                         }
96                 }
97
98                 ast_verb(2, "Endpoint %s is now Unreachable\n", ast_endpoint_get_resource(endpoint));
99         }
100
101         ast_free(regcontext);
102
103         ast_endpoint_blob_publish(endpoint, ast_endpoint_state_type(), blob);
104         ast_json_unref(blob);
105         ast_devstate_changed(AST_DEVICE_UNKNOWN, AST_DEVSTATE_CACHABLE, "PJSIP/%s", ast_endpoint_get_resource(endpoint));
106 }
107
108 static void endpoint_publish_contact_status(struct ast_endpoint *endpoint, struct ast_sip_contact_status *contact)
109 {
110         struct ast_json *blob;
111         char rtt[32];
112
113         snprintf(rtt, sizeof(rtt), "%" PRId64, contact->rtt);
114         blob = ast_json_pack("{s: s, s: s, s: s, s: s, s: s}",
115                 "contact_status", ast_sip_get_contact_status_label(contact->status),
116                 "aor", contact->aor,
117                 "uri", contact->uri,
118                 "roundtrip_usec", rtt,
119                 "endpoint_name", ast_endpoint_get_resource(endpoint));
120         if (blob) {
121                 ast_endpoint_blob_publish(endpoint, ast_endpoint_contact_state_type(), blob);
122                 ast_json_unref(blob);
123         }
124 }
125
126 /*! \brief Callback function for publishing the status of an endpoint */
127 static int persistent_endpoint_publish_status(void *obj, void *arg, int flags)
128 {
129         struct sip_persistent_endpoint *persistent = obj;
130         struct ast_endpoint *endpoint = persistent->endpoint;
131         struct ast_sip_contact_status *status = arg;
132
133         /* If the status' aor isn't one of the endpoint's, we skip */
134         if (!strstr(persistent->aors, status->aor)) {
135                 return 0;
136         }
137
138         endpoint_publish_contact_status(endpoint, status);
139         return 0;
140 }
141
142 /*! \brief Callback function for changing the state of an endpoint */
143 static int persistent_endpoint_update_state(void *obj, void *arg, int flags)
144 {
145         struct sip_persistent_endpoint *persistent = obj;
146         struct ast_endpoint *endpoint = persistent->endpoint;
147         struct ast_sip_contact_status *status = arg;
148         struct ao2_container *contacts;
149         struct ao2_iterator iter;
150         struct ast_sip_contact *contact;
151         enum ast_endpoint_state state = AST_ENDPOINT_OFFLINE;
152
153         /* If the status' aor isn't one of the endpoint's, we skip */
154         if (!strstr(persistent->aors, status->aor)) {
155                 return 0;
156         }
157
158         endpoint_publish_contact_status(endpoint, status);
159
160         /* Find all the contacts for this endpoint.  If ANY are available,
161          * mark the endpoint as ONLINE.
162          */
163         contacts = ast_sip_location_retrieve_contacts_from_aor_list(persistent->aors);
164         if (contacts) {
165                 iter = ao2_iterator_init(contacts, 0);
166                 while (state == AST_ENDPOINT_OFFLINE && (contact = ao2_iterator_next(&iter))) {
167                         struct ast_sip_contact_status *contact_status;
168                         const char *contact_id = ast_sorcery_object_get_id(contact);
169
170                         contact_status = ast_sorcery_retrieve_by_id(ast_sip_get_sorcery(),
171                                 CONTACT_STATUS, contact_id);
172                         if (contact_status && contact_status->status != UNAVAILABLE) {
173                                 state = AST_ENDPOINT_ONLINE;
174                         }
175                         ao2_cleanup(contact_status);
176                         ao2_ref(contact, -1);
177                 }
178                 ao2_iterator_destroy(&iter);
179                 ao2_ref(contacts, -1);
180         }
181
182         endpoint_update_state(endpoint, state);
183
184         return 0;
185 }
186
187 /*! \brief Function called when a contact is created */
188 static void persistent_endpoint_contact_created_observer(const void *object)
189 {
190         const struct ast_sip_contact *contact = object;
191         struct ast_sip_contact_status *contact_status;
192
193         contact_status = ast_sorcery_alloc(ast_sip_get_sorcery(), CONTACT_STATUS,
194                 ast_sorcery_object_get_id(contact));
195         if (!contact_status) {
196                 ast_log(LOG_ERROR, "Unable to create ast_sip_contact_status for contact %s/%s\n",
197                         contact->aor, contact->uri);
198                 return;
199         }
200         ast_string_field_set(contact_status, uri, contact->uri);
201
202         contact_status->status = CREATED;
203
204         ast_verb(2, "Contact %s/%s has been created\n", contact->aor, contact->uri);
205
206         ao2_callback(persistent_endpoints, OBJ_NODATA, persistent_endpoint_update_state, contact_status);
207         ao2_cleanup(contact_status);
208 }
209
210 /*! \brief Function called when a contact is deleted */
211 static void persistent_endpoint_contact_deleted_observer(const void *object)
212 {
213         const struct ast_sip_contact *contact = object;
214         struct ast_sip_contact_status *contact_status;
215
216         contact_status = ast_sorcery_retrieve_by_id(ast_sip_get_sorcery(), CONTACT_STATUS, ast_sorcery_object_get_id(contact));
217         if (!contact_status) {
218                 ast_log(LOG_ERROR, "Unable to find ast_sip_contact_status for contact %s/%s\n",
219                         contact->aor, contact->uri);
220                 return;
221         }
222
223         ast_verb(2, "Contact %s/%s has been deleted\n", contact->aor, contact->uri);
224         ast_statsd_log_string_va("PJSIP.contacts.states.%s", AST_STATSD_GAUGE,
225                 "-1", 1.0, ast_sip_get_contact_status_label(contact_status->status));
226         ast_statsd_log_string_va("PJSIP.contacts.states.%s", AST_STATSD_GAUGE,
227                 "+1", 1.0, ast_sip_get_contact_status_label(REMOVED));
228
229         ao2_callback(persistent_endpoints, OBJ_NODATA, persistent_endpoint_update_state, contact_status);
230         ast_sorcery_delete(ast_sip_get_sorcery(), contact_status);
231         ao2_cleanup(contact_status);
232 }
233
234 /*! \brief Observer for contacts so state can be updated on respective endpoints */
235 static const struct ast_sorcery_observer state_contact_observer = {
236         .created = persistent_endpoint_contact_created_observer,
237         .deleted = persistent_endpoint_contact_deleted_observer,
238 };
239
240 /*! \brief Function called when a contact_status is updated */
241 static void persistent_endpoint_contact_status_observer(const void *object)
242 {
243         struct ast_sip_contact_status *contact_status = (struct ast_sip_contact_status *)object;
244
245         if (contact_status->refresh) {
246                 /* We are only re-publishing the contact status. */
247                 ao2_callback(persistent_endpoints, OBJ_NODATA,
248                         persistent_endpoint_publish_status, contact_status);
249                 return;
250         }
251
252         /* If rtt_start is set (this is the outgoing OPTIONS), ignore. */
253         if (contact_status->rtt_start.tv_sec > 0) {
254                 return;
255         }
256
257         if (contact_status->status != contact_status->last_status) {
258                 ast_verb(3, "Contact %s/%s is now %s.  RTT: %.3f msec\n",
259                         contact_status->aor, contact_status->uri,
260                         ast_sip_get_contact_status_label(contact_status->status),
261                         contact_status->rtt / 1000.0);
262
263                 ast_statsd_log_string_va("PJSIP.contacts.states.%s", AST_STATSD_GAUGE,
264                         "-1", 1.0, ast_sip_get_contact_status_label(contact_status->last_status));
265                 ast_statsd_log_string_va("PJSIP.contacts.states.%s", AST_STATSD_GAUGE,
266                         "+1", 1.0, ast_sip_get_contact_status_label(contact_status->status));
267
268                 ast_test_suite_event_notify("AOR_CONTACT_UPDATE",
269                         "Contact: %s\r\n"
270                         "Status: %s",
271                         ast_sorcery_object_get_id(contact_status),
272                         ast_sip_get_contact_status_label(contact_status->status));
273
274                 ao2_callback(persistent_endpoints, OBJ_NODATA, persistent_endpoint_update_state,
275                         contact_status);
276         } else {
277                 ast_debug(3, "Contact %s/%s status didn't change: %s, RTT: %.3f msec\n",
278                         contact_status->aor, contact_status->uri,
279                         ast_sip_get_contact_status_label(contact_status->status),
280                         contact_status->rtt / 1000.0);
281         }
282
283         ast_statsd_log_full_va("PJSIP.contacts.%s.rtt", AST_STATSD_TIMER,
284                 contact_status->status != AVAILABLE ? -1 : contact_status->rtt / 1000,
285                 1.0,
286                 ast_sorcery_object_get_id(contact_status));
287 }
288
289 /*! \brief Observer for contacts so state can be updated on respective endpoints */
290 static const struct ast_sorcery_observer state_contact_status_observer = {
291         .updated = persistent_endpoint_contact_status_observer,
292 };
293
294 static void endpoint_deleted_observer(const void *object)
295 {
296         const struct ast_sip_endpoint *endpoint = object;
297
298         ao2_find(persistent_endpoints, ast_endpoint_get_resource(endpoint->persistent),
299                 OBJ_SEARCH_KEY | OBJ_UNLINK | OBJ_NODATA);
300 }
301
302 static const struct ast_sorcery_observer endpoint_observers = {
303         .deleted = endpoint_deleted_observer,
304 };
305
306 static int endpoint_acl_handler(const struct aco_option *opt, struct ast_variable *var, void *obj)
307 {
308         struct ast_sip_endpoint *endpoint = obj;
309         int error = 0;
310         int ignore;
311
312         if (ast_strlen_zero(var->value)) return 0;
313
314         if (!strncmp(var->name, "contact_", 8)) {
315                 ast_append_acl(var->name + 8, var->value, &endpoint->contact_acl, &error, &ignore);
316         } else {
317                 ast_append_acl(var->name, var->value, &endpoint->acl, &error, &ignore);
318         }
319
320         return error;
321 }
322
323 static int acl_to_str(const void *obj, const intptr_t *args, char **buf)
324 {
325         const struct ast_sip_endpoint *endpoint = obj;
326         struct ast_acl_list *acl_list;
327         struct ast_acl *first_acl;
328
329         if (endpoint && !ast_acl_list_is_empty(acl_list=endpoint->acl)) {
330                 AST_LIST_LOCK(acl_list);
331                 first_acl = AST_LIST_FIRST(acl_list);
332                 if (ast_strlen_zero(first_acl->name)) {
333                         *buf = "deny/permit";
334                 } else {
335                         *buf = first_acl->name;
336                 }
337                 AST_LIST_UNLOCK(acl_list);
338         }
339
340         *buf = ast_strdup(*buf);
341         return 0;
342 }
343
344 static int contact_acl_to_str(const void *obj, const intptr_t *args, char **buf)
345 {
346         const struct ast_sip_endpoint *endpoint = obj;
347         struct ast_acl_list *acl_list;
348         struct ast_acl *first_acl;
349
350         if (endpoint && !ast_acl_list_is_empty(acl_list=endpoint->contact_acl)) {
351                 AST_LIST_LOCK(acl_list);
352                 first_acl = AST_LIST_FIRST(acl_list);
353                 if (ast_strlen_zero(first_acl->name)) {
354                         *buf = "deny/permit";
355                 } else {
356                         *buf = first_acl->name;
357                 }
358                 AST_LIST_UNLOCK(acl_list);
359         }
360
361         *buf = ast_strdup(*buf);
362         return 0;
363 }
364
365 static int dtmf_handler(const struct aco_option *opt, struct ast_variable *var, void *obj)
366 {
367         struct ast_sip_endpoint *endpoint = obj;
368
369         if (!strcasecmp(var->value, "rfc4733")) {
370                 endpoint->dtmf = AST_SIP_DTMF_RFC_4733;
371         } else if (!strcasecmp(var->value, "inband")) {
372                 endpoint->dtmf = AST_SIP_DTMF_INBAND;
373         } else if (!strcasecmp(var->value, "info")) {
374                 endpoint->dtmf = AST_SIP_DTMF_INFO;
375         } else if (!strcasecmp(var->value, "auto")) {
376                 endpoint->dtmf = AST_SIP_DTMF_AUTO;
377         } else if (!strcasecmp(var->value, "none")) {
378                 endpoint->dtmf = AST_SIP_DTMF_NONE;
379         } else {
380                 return -1;
381         }
382
383         return 0;
384 }
385
386 static int dtmf_to_str(const void *obj, const intptr_t *args, char **buf)
387 {
388         const struct ast_sip_endpoint *endpoint = obj;
389
390         switch (endpoint->dtmf) {
391         case AST_SIP_DTMF_RFC_4733 :
392                 *buf = "rfc4733"; break;
393         case AST_SIP_DTMF_INBAND :
394                 *buf = "inband"; break;
395         case AST_SIP_DTMF_INFO :
396                 *buf = "info"; break;
397        case AST_SIP_DTMF_AUTO :
398                 *buf = "auto"; break;
399         default:
400                 *buf = "none";
401         }
402
403         *buf = ast_strdup(*buf);
404         return 0;
405 }
406
407 static int prack_handler(const struct aco_option *opt, struct ast_variable *var, void *obj)
408 {
409         struct ast_sip_endpoint *endpoint = obj;
410
411         /* clear all */
412         endpoint->extensions.flags &= ~(PJSIP_INV_SUPPORT_100REL | PJSIP_INV_REQUIRE_100REL);
413
414         if (ast_true(var->value)) {
415                 endpoint->extensions.flags |= PJSIP_INV_SUPPORT_100REL;
416         } else if (!strcasecmp(var->value, "required")) {
417                 endpoint->extensions.flags |= PJSIP_INV_REQUIRE_100REL;
418         } else if (!ast_false(var->value)){
419                 return -1;
420         }
421
422         return 0;
423 }
424
425 static int prack_to_str(const void *obj, const intptr_t *args, char **buf)
426 {
427         const struct ast_sip_endpoint *endpoint = obj;
428
429         if (endpoint->extensions.flags & PJSIP_INV_REQUIRE_100REL) {
430                 *buf = "required";
431         } else if (endpoint->extensions.flags & PJSIP_INV_SUPPORT_100REL) {
432                 *buf = "yes";
433         } else {
434                 *buf = "no";
435         }
436
437         *buf = ast_strdup(*buf);
438         return 0;
439 }
440
441 static int timers_handler(const struct aco_option *opt, struct ast_variable *var, void *obj)
442 {
443         struct ast_sip_endpoint *endpoint = obj;
444
445         /* clear all */
446         endpoint->extensions.flags &= ~(PJSIP_INV_SUPPORT_TIMER | PJSIP_INV_REQUIRE_TIMER
447                                         | PJSIP_INV_ALWAYS_USE_TIMER);
448
449         /* set only the specified flag and let pjsip normalize if needed */
450         if (ast_true(var->value)) {
451                 endpoint->extensions.flags |= PJSIP_INV_SUPPORT_TIMER;
452         } else if (!strcasecmp(var->value, "required")) {
453                 endpoint->extensions.flags |= PJSIP_INV_REQUIRE_TIMER;
454         } else if (!strcasecmp(var->value, "always") || !strcasecmp(var->value, "forced")) {
455                 endpoint->extensions.flags |= PJSIP_INV_ALWAYS_USE_TIMER;
456         } else if (!ast_false(var->value)) {
457                 return -1;
458         }
459
460         return 0;
461 }
462
463 static int timers_to_str(const void *obj, const intptr_t *args, char **buf)
464 {
465         const struct ast_sip_endpoint *endpoint = obj;
466
467         if (endpoint->extensions.flags & PJSIP_INV_ALWAYS_USE_TIMER) {
468                 *buf = "always";
469         } else if (endpoint->extensions.flags & PJSIP_INV_REQUIRE_TIMER) {
470                 *buf = "required";
471         } else if (endpoint->extensions.flags & PJSIP_INV_SUPPORT_TIMER) {
472                 *buf = "yes";
473         } else {
474                 *buf = "no";
475         }
476
477         *buf = ast_strdup(*buf);
478         return 0;
479 }
480
481 void ast_sip_auth_vector_destroy(struct ast_sip_auth_vector *auths)
482 {
483         int i;
484         size_t size;
485
486         if (!auths) {
487                 return;
488         }
489
490         size = AST_VECTOR_SIZE(auths);
491
492         for (i = 0; i < size; ++i) {
493                 const char *name = AST_VECTOR_REMOVE_UNORDERED(auths, 0);
494                 ast_free((char *) name);
495         }
496         AST_VECTOR_FREE(auths);
497 }
498
499 int ast_sip_auth_vector_init(struct ast_sip_auth_vector *auths, const char *value)
500 {
501         char *auth_names = ast_strdupa(value);
502         char *val;
503
504         ast_assert(auths != NULL);
505
506         if (AST_VECTOR_SIZE(auths)) {
507                 ast_sip_auth_vector_destroy(auths);
508         }
509         if (AST_VECTOR_INIT(auths, 1)) {
510                 return -1;
511         }
512
513         while ((val = ast_strip(strsep(&auth_names, ",")))) {
514                 if (ast_strlen_zero(val)) {
515                         continue;
516                 }
517
518                 val = ast_strdup(val);
519                 if (!val) {
520                         goto failure;
521                 }
522                 if (AST_VECTOR_APPEND(auths, val)) {
523                         goto failure;
524                 }
525         }
526         return 0;
527
528 failure:
529         ast_sip_auth_vector_destroy(auths);
530         return -1;
531 }
532
533 static int inbound_auth_handler(const struct aco_option *opt, struct ast_variable *var, void *obj)
534 {
535         struct ast_sip_endpoint *endpoint = obj;
536
537         return ast_sip_auth_vector_init(&endpoint->inbound_auths, var->value);
538 }
539
540 static int outbound_auth_handler(const struct aco_option *opt, struct ast_variable *var, void *obj)
541 {
542         struct ast_sip_endpoint *endpoint = obj;
543
544         return ast_sip_auth_vector_init(&endpoint->outbound_auths, var->value);
545 }
546
547 int ast_sip_auths_to_str(const struct ast_sip_auth_vector *auths, char **buf)
548 {
549         if (!auths || !AST_VECTOR_SIZE(auths)) {
550                 return 0;
551         }
552
553         if (!(*buf = ast_calloc(MAX_OBJECT_FIELD, sizeof(char)))) {
554                 return -1;
555         }
556
557         /* I feel like accessing the vector's elem array directly is cheating...*/
558         ast_join_delim(*buf, MAX_OBJECT_FIELD, auths->elems, AST_VECTOR_SIZE(auths), ',');
559         return 0;
560 }
561
562 static int inbound_auths_to_str(const void *obj, const intptr_t *args, char **buf)
563 {
564         const struct ast_sip_endpoint *endpoint = obj;
565         return ast_sip_auths_to_str(&endpoint->inbound_auths, buf);
566 }
567
568 static int outbound_auths_to_str(const void *obj, const intptr_t *args, char **buf)
569 {
570         const struct ast_sip_endpoint *endpoint = obj;
571         return ast_sip_auths_to_str(&endpoint->outbound_auths, buf);
572 }
573
574 static int ident_handler(const struct aco_option *opt, struct ast_variable *var, void *obj)
575 {
576         struct ast_sip_endpoint *endpoint = obj;
577         char *idents = ast_strdupa(var->value);
578         char *val;
579         enum ast_sip_endpoint_identifier_type method;
580
581         /*
582          * If there's already something in the vector when we get here,
583          * it's the default value so we need to clean it out.
584          */
585         if (AST_VECTOR_SIZE(&endpoint->ident_method_order)) {
586                 AST_VECTOR_RESET(&endpoint->ident_method_order, AST_VECTOR_ELEM_CLEANUP_NOOP);
587                 endpoint->ident_method = 0;
588         }
589
590         while ((val = ast_strip(strsep(&idents, ",")))) {
591                 if (ast_strlen_zero(val)) {
592                         continue;
593                 }
594
595                 if (!strcasecmp(val, "username")) {
596                         method = AST_SIP_ENDPOINT_IDENTIFY_BY_USERNAME;
597                 } else  if (!strcasecmp(val, "auth_username")) {
598                         method = AST_SIP_ENDPOINT_IDENTIFY_BY_AUTH_USERNAME;
599                 } else {
600                         ast_log(LOG_ERROR, "Unrecognized identification method %s specified for endpoint %s\n",
601                                         val, ast_sorcery_object_get_id(endpoint));
602                         AST_VECTOR_RESET(&endpoint->ident_method_order, AST_VECTOR_ELEM_CLEANUP_NOOP);
603                         endpoint->ident_method = 0;
604                         return -1;
605                 }
606                 if (endpoint->ident_method & method) {
607                         /* We are already indentifying by this method.  No need to do it again. */
608                         continue;
609                 }
610
611                 endpoint->ident_method |= method;
612                 AST_VECTOR_APPEND(&endpoint->ident_method_order, method);
613         }
614
615         return 0;
616 }
617
618 static int ident_to_str(const void *obj, const intptr_t *args, char **buf)
619 {
620         const struct ast_sip_endpoint *endpoint = obj;
621         int methods;
622         char *method;
623         int i;
624         int j = 0;
625
626         methods = AST_VECTOR_SIZE(&endpoint->ident_method_order);
627         if (!methods) {
628                 return 0;
629         }
630
631         if (!(*buf = ast_calloc(MAX_OBJECT_FIELD, sizeof(char)))) {
632                 return -1;
633         }
634
635         for (i = 0; i < methods; i++) {
636                 switch (AST_VECTOR_GET(&endpoint->ident_method_order, i)) {
637                 case AST_SIP_ENDPOINT_IDENTIFY_BY_USERNAME :
638                         method = "username";
639                         break;
640                 case AST_SIP_ENDPOINT_IDENTIFY_BY_AUTH_USERNAME :
641                         method = "auth_username";
642                         break;
643                 default:
644                         continue;
645                 }
646                 j = sprintf(*buf + j, "%s%s", method, i < methods - 1 ? "," : "");
647         }
648
649         return 0;
650 }
651
652 static int redirect_handler(const struct aco_option *opt, struct ast_variable *var, void *obj)
653 {
654         struct ast_sip_endpoint *endpoint = obj;
655
656         if (!strcasecmp(var->value, "user")) {
657                 endpoint->redirect_method = AST_SIP_REDIRECT_USER;
658         } else if (!strcasecmp(var->value, "uri_core")) {
659                 endpoint->redirect_method = AST_SIP_REDIRECT_URI_CORE;
660         } else if (!strcasecmp(var->value, "uri_pjsip")) {
661                 endpoint->redirect_method = AST_SIP_REDIRECT_URI_PJSIP;
662         } else {
663                 ast_log(LOG_ERROR, "Unrecognized redirect method %s specified for endpoint %s\n",
664                         var->value, ast_sorcery_object_get_id(endpoint));
665                 return -1;
666         }
667
668         return 0;
669 }
670
671 static int direct_media_method_handler(const struct aco_option *opt, struct ast_variable *var, void *obj)
672 {
673         struct ast_sip_endpoint *endpoint = obj;
674
675         if (!strcasecmp(var->value, "invite") || !strcasecmp(var->value, "reinvite")) {
676                 endpoint->media.direct_media.method = AST_SIP_SESSION_REFRESH_METHOD_INVITE;
677         } else if (!strcasecmp(var->value, "update")) {
678                 endpoint->media.direct_media.method = AST_SIP_SESSION_REFRESH_METHOD_UPDATE;
679         } else {
680                 ast_log(LOG_NOTICE, "Unrecognized option value %s for %s on endpoint %s\n",
681                                 var->value, var->name, ast_sorcery_object_get_id(endpoint));
682                 return -1;
683         }
684         return 0;
685 }
686
687 static const char *id_configuration_refresh_methods[] = {
688         [AST_SIP_SESSION_REFRESH_METHOD_INVITE] = "invite",
689         [AST_SIP_SESSION_REFRESH_METHOD_UPDATE] = "update"
690 };
691
692 static int direct_media_method_to_str(const void *obj, const intptr_t *args, char **buf)
693 {
694         const struct ast_sip_endpoint *endpoint = obj;
695         if (ARRAY_IN_BOUNDS(endpoint->id.refresh_method, id_configuration_refresh_methods)) {
696                 *buf = ast_strdup(id_configuration_refresh_methods[endpoint->id.refresh_method]);
697         }
698         return 0;
699 }
700
701 static int connected_line_method_handler(const struct aco_option *opt, struct ast_variable *var, void *obj)
702 {
703         struct ast_sip_endpoint *endpoint = obj;
704
705         if (!strcasecmp(var->value, "invite") || !strcasecmp(var->value, "reinvite")) {
706                 endpoint->id.refresh_method = AST_SIP_SESSION_REFRESH_METHOD_INVITE;
707         } else if (!strcasecmp(var->value, "update")) {
708                 endpoint->id.refresh_method = AST_SIP_SESSION_REFRESH_METHOD_UPDATE;
709         } else {
710                 ast_log(LOG_NOTICE, "Unrecognized option value %s for %s on endpoint %s\n",
711                                 var->value, var->name, ast_sorcery_object_get_id(endpoint));
712                 return -1;
713         }
714         return 0;
715 }
716
717 static int connected_line_method_to_str(const void *obj, const intptr_t *args, char **buf)
718 {
719         const struct ast_sip_endpoint *endpoint = obj;
720         *buf = ast_strdup(id_configuration_refresh_methods[endpoint->id.refresh_method]);
721         return 0;
722 }
723
724 static int direct_media_glare_mitigation_handler(const struct aco_option *opt, struct ast_variable *var, void *obj)
725 {
726         struct ast_sip_endpoint *endpoint = obj;
727
728         if (!strcasecmp(var->value, "none")) {
729                 endpoint->media.direct_media.glare_mitigation = AST_SIP_DIRECT_MEDIA_GLARE_MITIGATION_NONE;
730         } else if (!strcasecmp(var->value, "outgoing")) {
731                 endpoint->media.direct_media.glare_mitigation = AST_SIP_DIRECT_MEDIA_GLARE_MITIGATION_OUTGOING;
732         } else if (!strcasecmp(var->value, "incoming")) {
733                 endpoint->media.direct_media.glare_mitigation = AST_SIP_DIRECT_MEDIA_GLARE_MITIGATION_INCOMING;
734         } else {
735                 ast_log(LOG_NOTICE, "Unrecognized option value %s for %s on endpoint %s\n",
736                                 var->value, var->name, ast_sorcery_object_get_id(endpoint));
737                 return -1;
738         }
739
740         return 0;
741 }
742
743 static const char *direct_media_glare_mitigation_map[] = {
744         [AST_SIP_DIRECT_MEDIA_GLARE_MITIGATION_NONE] = "none",
745         [AST_SIP_DIRECT_MEDIA_GLARE_MITIGATION_OUTGOING] = "outgoing",
746         [AST_SIP_DIRECT_MEDIA_GLARE_MITIGATION_INCOMING] = "incoming"
747 };
748
749 static int direct_media_glare_mitigation_to_str(const void *obj, const intptr_t *args, char **buf)
750 {
751         const struct ast_sip_endpoint *endpoint = obj;
752         if (ARRAY_IN_BOUNDS(endpoint->media.direct_media.glare_mitigation, direct_media_glare_mitigation_map)) {
753                 *buf = ast_strdup(direct_media_glare_mitigation_map[endpoint->media.direct_media.glare_mitigation]);
754         }
755
756         return 0;
757 }
758
759 static int caller_id_handler(const struct aco_option *opt, struct ast_variable *var, void *obj)
760 {
761         struct ast_sip_endpoint *endpoint = obj;
762         char cid_name[80] = { '\0' };
763         char cid_num[80] = { '\0' };
764
765         ast_callerid_split(var->value, cid_name, sizeof(cid_name), cid_num, sizeof(cid_num));
766         if (!ast_strlen_zero(cid_name)) {
767                 endpoint->id.self.name.str = ast_strdup(cid_name);
768                 if (!endpoint->id.self.name.str) {
769                         return -1;
770                 }
771                 endpoint->id.self.name.valid = 1;
772         }
773         if (!ast_strlen_zero(cid_num)) {
774                 endpoint->id.self.number.str = ast_strdup(cid_num);
775                 if (!endpoint->id.self.number.str) {
776                         return -1;
777                 }
778                 endpoint->id.self.number.valid = 1;
779         }
780         return 0;
781 }
782
783 static int caller_id_to_str(const void *obj, const intptr_t *args, char **buf)
784 {
785         const struct ast_sip_endpoint *endpoint = obj;
786         const char *name = S_COR(endpoint->id.self.name.valid,
787                                  endpoint->id.self.name.str, NULL);
788         const char *number = S_COR(endpoint->id.self.number.valid,
789                                    endpoint->id.self.number.str, NULL);
790
791         /* make sure size is at least 10 - that should cover the "<unknown>"
792            case as well as any additional formatting characters added in
793            the name and/or number case. */
794         int size = 10;
795         size += name ? strlen(name) : 0;
796         size += number ? strlen(number) : 0;
797
798         if (!(*buf = ast_calloc(size + 1, sizeof(char)))) {
799                 return -1;
800         }
801
802         ast_callerid_merge(*buf, size + 1, name, number, NULL);
803         return 0;
804 }
805
806 static int caller_id_privacy_handler(const struct aco_option *opt, struct ast_variable *var, void *obj)
807 {
808         struct ast_sip_endpoint *endpoint = obj;
809         int callingpres = ast_parse_caller_presentation(var->value);
810         if (callingpres == -1 && sscanf(var->value, "%d", &callingpres) != 1) {
811                 return -1;
812         }
813         endpoint->id.self.number.presentation = callingpres;
814         endpoint->id.self.name.presentation = callingpres;
815         return 0;
816 }
817
818 static int caller_id_privacy_to_str(const void *obj, const intptr_t *args, char **buf)
819 {
820         const struct ast_sip_endpoint *endpoint = obj;
821         const char *presentation = ast_named_caller_presentation(
822                 endpoint->id.self.name.presentation);
823
824         *buf = ast_strdup(presentation);
825         return 0;
826 }
827
828 static int caller_id_tag_handler(const struct aco_option *opt, struct ast_variable *var, void *obj)
829 {
830         struct ast_sip_endpoint *endpoint = obj;
831         endpoint->id.self.tag = ast_strdup(var->value);
832         return endpoint->id.self.tag ? 0 : -1;
833 }
834
835 static int caller_id_tag_to_str(const void *obj, const intptr_t *args, char **buf)
836 {
837         const struct ast_sip_endpoint *endpoint = obj;
838         *buf = ast_strdup(endpoint->id.self.tag);
839         return 0;
840 }
841
842 static int media_encryption_handler(const struct aco_option *opt, struct ast_variable *var, void *obj)
843 {
844         struct ast_sip_endpoint *endpoint = obj;
845
846         if (!strcasecmp("no", var->value)) {
847                 endpoint->media.rtp.encryption = AST_SIP_MEDIA_ENCRYPT_NONE;
848         } else if (!strcasecmp("sdes", var->value)) {
849                 endpoint->media.rtp.encryption = AST_SIP_MEDIA_ENCRYPT_SDES;
850         } else if (!strcasecmp("dtls", var->value)) {
851                 endpoint->media.rtp.encryption = AST_SIP_MEDIA_ENCRYPT_DTLS;
852                 return ast_rtp_dtls_cfg_parse(&endpoint->media.rtp.dtls_cfg, "dtlsenable", "yes");
853         } else {
854                 return -1;
855         }
856
857         return 0;
858 }
859
860 static const char *media_encryption_map[] = {
861         [AST_SIP_MEDIA_TRANSPORT_INVALID] = "invalid",
862         [AST_SIP_MEDIA_ENCRYPT_NONE] = "no",
863         [AST_SIP_MEDIA_ENCRYPT_SDES] = "sdes",
864         [AST_SIP_MEDIA_ENCRYPT_DTLS] = "dtls",
865 };
866
867 static int media_encryption_to_str(const void *obj, const intptr_t *args, char **buf)
868 {
869         const struct ast_sip_endpoint *endpoint = obj;
870         if (ARRAY_IN_BOUNDS(endpoint->media.rtp.encryption, media_encryption_map)) {
871                 *buf = ast_strdup(media_encryption_map[
872                                           endpoint->media.rtp.encryption]);
873         }
874         return 0;
875 }
876
877 static int group_handler(const struct aco_option *opt,
878                          struct ast_variable *var, void *obj)
879 {
880         struct ast_sip_endpoint *endpoint = obj;
881
882         if (!strncmp(var->name, "call_group", 10)) {
883                 endpoint->pickup.callgroup = ast_get_group(var->value);
884         } else if (!strncmp(var->name, "pickup_group", 12)) {
885                 endpoint->pickup.pickupgroup = ast_get_group(var->value);
886         } else {
887                 return -1;
888         }
889
890         return 0;
891 }
892
893 static int callgroup_to_str(const void *obj, const intptr_t *args, char **buf)
894 {
895         const struct ast_sip_endpoint *endpoint = obj;
896
897         if (!(*buf = ast_calloc(MAX_OBJECT_FIELD, sizeof(char)))) {
898                 return -1;
899         }
900
901         ast_print_group(*buf, MAX_OBJECT_FIELD, endpoint->pickup.callgroup);
902         return 0;
903 }
904
905 static int pickupgroup_to_str(const void *obj, const intptr_t *args, char **buf)
906 {
907         const struct ast_sip_endpoint *endpoint = obj;
908
909         if (!(*buf = ast_calloc(MAX_OBJECT_FIELD, sizeof(char)))) {
910                 return -1;
911         }
912
913         ast_print_group(*buf, MAX_OBJECT_FIELD, endpoint->pickup.pickupgroup);
914         return 0;
915 }
916
917 static int named_groups_handler(const struct aco_option *opt,
918                                 struct ast_variable *var, void *obj)
919 {
920         struct ast_sip_endpoint *endpoint = obj;
921
922         if (!strncmp(var->name, "named_call_group", 16)) {
923                 if (ast_strlen_zero(var->value)) {
924                         endpoint->pickup.named_callgroups =
925                                 ast_unref_namedgroups(endpoint->pickup.named_callgroups);
926                 } else if (!(endpoint->pickup.named_callgroups =
927                       ast_get_namedgroups(var->value))) {
928                         return -1;
929                 }
930         } else if (!strncmp(var->name, "named_pickup_group", 18)) {
931                 if (ast_strlen_zero(var->value)) {
932                         endpoint->pickup.named_pickupgroups =
933                                 ast_unref_namedgroups(endpoint->pickup.named_pickupgroups);
934                 } else if (!(endpoint->pickup.named_pickupgroups =
935                       ast_get_namedgroups(var->value))) {
936                         return -1;
937                 }
938         } else {
939                 return -1;
940         }
941
942         return 0;
943 }
944
945 static int named_callgroups_to_str(const void *obj, const intptr_t *args, char **buf)
946 {
947         const struct ast_sip_endpoint *endpoint = obj;
948         RAII_VAR(struct ast_str *, str, ast_str_create(MAX_OBJECT_FIELD), ast_free);
949
950         ast_print_namedgroups(&str, endpoint->pickup.named_callgroups);
951         *buf = ast_strdup(ast_str_buffer(str));
952         return 0;
953 }
954
955 static int named_pickupgroups_to_str(const void *obj, const intptr_t *args, char **buf)
956 {
957         const struct ast_sip_endpoint *endpoint = obj;
958         RAII_VAR(struct ast_str *, str, ast_str_create(MAX_OBJECT_FIELD), ast_free);
959
960         ast_print_namedgroups(&str, endpoint->pickup.named_pickupgroups);
961         *buf = ast_strdup(ast_str_buffer(str));
962         return 0;
963 }
964
965 static int dtls_handler(const struct aco_option *opt,
966                          struct ast_variable *var, void *obj)
967 {
968         struct ast_sip_endpoint *endpoint = obj;
969         char *name = ast_strdupa(var->name);
970         char *front = NULL;
971         char *back = NULL;
972         char *buf = name;
973
974         /* strip out underscores in the name */
975         front = strtok_r(buf, "_", &back);
976         while (front) {
977                 int size = strlen(front);
978                 ast_copy_string(buf, front, size + 1);
979                 buf += size;
980                 front = strtok_r(NULL, "_", &back);
981         }
982
983         return ast_rtp_dtls_cfg_parse(&endpoint->media.rtp.dtls_cfg, name, var->value);
984 }
985
986 static int dtlsverify_to_str(const void *obj, const intptr_t *args, char **buf)
987 {
988         const struct ast_sip_endpoint *endpoint = obj;
989         *buf = ast_strdup(AST_YESNO(endpoint->media.rtp.dtls_cfg.verify));
990         return 0;
991 }
992
993 static int dtlsrekey_to_str(const void *obj, const intptr_t *args, char **buf)
994 {
995         const struct ast_sip_endpoint *endpoint = obj;
996
997         return ast_asprintf(
998                 buf, "%u", endpoint->media.rtp.dtls_cfg.rekey) >=0 ? 0 : -1;
999 }
1000
1001 static int dtlscertfile_to_str(const void *obj, const intptr_t *args, char **buf)
1002 {
1003         const struct ast_sip_endpoint *endpoint = obj;
1004         *buf = ast_strdup(endpoint->media.rtp.dtls_cfg.certfile);
1005         return 0;
1006 }
1007
1008 static int dtlsprivatekey_to_str(const void *obj, const intptr_t *args, char **buf)
1009 {
1010         const struct ast_sip_endpoint *endpoint = obj;
1011         *buf = ast_strdup(endpoint->media.rtp.dtls_cfg.pvtfile);
1012         return 0;
1013 }
1014
1015 static int dtlscipher_to_str(const void *obj, const intptr_t *args, char **buf)
1016 {
1017         const struct ast_sip_endpoint *endpoint = obj;
1018         *buf = ast_strdup(endpoint->media.rtp.dtls_cfg.cipher);
1019         return 0;
1020 }
1021
1022 static int dtlscafile_to_str(const void *obj, const intptr_t *args, char **buf)
1023 {
1024         const struct ast_sip_endpoint *endpoint = obj;
1025         *buf = ast_strdup(endpoint->media.rtp.dtls_cfg.cafile);
1026         return 0;
1027 }
1028
1029 static int dtlscapath_to_str(const void *obj, const intptr_t *args, char **buf)
1030 {
1031         const struct ast_sip_endpoint *endpoint = obj;
1032         *buf = ast_strdup(endpoint->media.rtp.dtls_cfg.capath);
1033         return 0;
1034 }
1035
1036 static const char *ast_rtp_dtls_setup_map[] = {
1037         [AST_RTP_DTLS_SETUP_ACTIVE] = "active",
1038         [AST_RTP_DTLS_SETUP_PASSIVE] = "passive",
1039         [AST_RTP_DTLS_SETUP_ACTPASS] = "actpass",
1040         [AST_RTP_DTLS_SETUP_HOLDCONN] = "holdconn",
1041 };
1042
1043 static int dtlssetup_to_str(const void *obj, const intptr_t *args, char **buf)
1044 {
1045         const struct ast_sip_endpoint *endpoint = obj;
1046         if (ARRAY_IN_BOUNDS(endpoint->media.rtp.dtls_cfg.default_setup, ast_rtp_dtls_setup_map)) {
1047                 *buf = ast_strdup(ast_rtp_dtls_setup_map[endpoint->media.rtp.dtls_cfg.default_setup]);
1048         }
1049         return 0;
1050 }
1051
1052 static const char *ast_rtp_dtls_fingerprint_map[] = {
1053         [AST_RTP_DTLS_HASH_SHA256] = "SHA-256",
1054         [AST_RTP_DTLS_HASH_SHA1] = "SHA-1",
1055 };
1056
1057 static int dtlsfingerprint_to_str(const void *obj, const intptr_t *args, char **buf)
1058 {
1059         const struct ast_sip_endpoint *endpoint = obj;
1060         if (ARRAY_IN_BOUNDS(endpoint->media.rtp.dtls_cfg.hash, ast_rtp_dtls_fingerprint_map)) {
1061                 *buf = ast_strdup(ast_rtp_dtls_fingerprint_map[endpoint->media.rtp.dtls_cfg.hash]);
1062         }
1063         return 0;
1064 }
1065
1066 static int t38udptl_ec_handler(const struct aco_option *opt,
1067         struct ast_variable *var, void *obj)
1068 {
1069         struct ast_sip_endpoint *endpoint = obj;
1070
1071         if (!strcmp(var->value, "none")) {
1072                 endpoint->media.t38.error_correction = UDPTL_ERROR_CORRECTION_NONE;
1073         } else if (!strcmp(var->value, "fec")) {
1074                 endpoint->media.t38.error_correction = UDPTL_ERROR_CORRECTION_FEC;
1075         } else if (!strcmp(var->value, "redundancy")) {
1076                 endpoint->media.t38.error_correction = UDPTL_ERROR_CORRECTION_REDUNDANCY;
1077         } else {
1078                 return -1;
1079         }
1080
1081         return 0;
1082 }
1083
1084 static const char *ast_t38_ec_modes_map[] = {
1085         [UDPTL_ERROR_CORRECTION_NONE] = "none",
1086         [UDPTL_ERROR_CORRECTION_FEC] = "fec",
1087         [UDPTL_ERROR_CORRECTION_REDUNDANCY] = "redundancy"
1088 };
1089
1090 static int t38udptl_ec_to_str(const void *obj, const intptr_t *args, char **buf)
1091 {
1092         const struct ast_sip_endpoint *endpoint = obj;
1093         if (ARRAY_IN_BOUNDS(endpoint->media.t38.error_correction, ast_t38_ec_modes_map)) {
1094                 *buf = ast_strdup(ast_t38_ec_modes_map[
1095                                           endpoint->media.t38.error_correction]);
1096         }
1097         return 0;
1098 }
1099
1100 static int tos_handler(const struct aco_option *opt,
1101         struct ast_variable *var, void *obj)
1102 {
1103         struct ast_sip_endpoint *endpoint = obj;
1104         unsigned int value;
1105
1106         if (ast_str2tos(var->value, &value)) {
1107                 ast_log(LOG_ERROR, "Error configuring endpoint '%s' - Could not "
1108                         "interpret '%s' value '%s'\n",
1109                         ast_sorcery_object_get_id(endpoint), var->name, var->value);
1110                 return -1;
1111         }
1112
1113         if (!strcmp(var->name, "tos_audio")) {
1114                 endpoint->media.tos_audio = value;
1115         } else if (!strcmp(var->name, "tos_video")) {
1116                 endpoint->media.tos_video = value;
1117         } else {
1118                 /* If we reach this point, someone called the tos_handler when they shouldn't have. */
1119                 ast_assert(0);
1120                 return -1;
1121         }
1122         return 0;
1123 }
1124
1125 static int tos_audio_to_str(const void *obj, const intptr_t *args, char **buf)
1126 {
1127         const struct ast_sip_endpoint *endpoint = obj;
1128
1129         if (ast_asprintf(buf, "%u", endpoint->media.tos_audio) == -1) {
1130                 return -1;
1131         }
1132         return 0;
1133 }
1134
1135 static int tos_video_to_str(const void *obj, const intptr_t *args, char **buf)
1136 {
1137         const struct ast_sip_endpoint *endpoint = obj;
1138
1139         if (ast_asprintf(buf, "%u", endpoint->media.tos_video) == -1) {
1140                 return -1;
1141         }
1142         return 0;
1143 }
1144
1145 static int set_var_handler(const struct aco_option *opt,
1146         struct ast_variable *var, void *obj)
1147 {
1148         struct ast_sip_endpoint *endpoint = obj;
1149         struct ast_variable *new_var;
1150         char *name;
1151         char *val;
1152
1153         if (ast_strlen_zero(var->value)) {
1154                 return 0;
1155         }
1156
1157         name = ast_strdupa(var->value);
1158         val = strchr(name, '=');
1159
1160         if (!val) {
1161                 return -1;
1162         }
1163
1164         *val++ = '\0';
1165
1166         if (!(new_var = ast_variable_new(name, val, ""))) {
1167                 return -1;
1168         }
1169
1170         ast_variable_list_append(&endpoint->channel_vars, new_var);
1171
1172         return 0;
1173 }
1174
1175 static int set_var_to_str(const void *obj, const intptr_t *args, char **buf)
1176 {
1177         struct ast_str *str = ast_str_create(MAX_OBJECT_FIELD);
1178         const struct ast_sip_endpoint *endpoint = obj;
1179         struct ast_variable *var;
1180
1181         for (var = endpoint->channel_vars; var; var = var->next) {
1182                 ast_str_append(&str, 0, "%s=%s,", var->name, var->value);
1183         }
1184
1185         *buf = ast_strdup(ast_str_truncate(str, -1));
1186         ast_free(str);
1187         return 0;
1188 }
1189
1190 static int set_var_to_vl(const void *obj, struct ast_variable **fields)
1191 {
1192         const struct ast_sip_endpoint *endpoint = obj;
1193         if (endpoint->channel_vars) {
1194                 *fields = ast_variables_dup(endpoint->channel_vars);
1195         }
1196         return 0;
1197 }
1198
1199 static int voicemail_extension_handler(const struct aco_option *opt, struct ast_variable *var, void *obj)
1200 {
1201         struct ast_sip_endpoint *endpoint = obj;
1202
1203         endpoint->subscription.mwi.voicemail_extension = ast_strdup(var->value);
1204
1205         return endpoint->subscription.mwi.voicemail_extension ? 0 : -1;
1206 }
1207
1208 static int voicemail_extension_to_str(const void *obj, const intptr_t *args, char **buf)
1209 {
1210         const struct ast_sip_endpoint *endpoint = obj;
1211
1212         *buf = ast_strdup(endpoint->subscription.mwi.voicemail_extension);
1213
1214         return 0;
1215 }
1216
1217 static int contact_user_handler(const struct aco_option *opt,
1218         struct ast_variable *var, void *obj)
1219 {
1220         struct ast_sip_endpoint *endpoint = obj;
1221
1222         endpoint->contact_user = ast_strdup(var->value);
1223         if (!endpoint->contact_user) {
1224                 return -1;
1225         }
1226
1227         return 0;
1228 }
1229
1230 static int contact_user_to_str(const void *obj, const intptr_t *args, char **buf)
1231 {
1232         const struct ast_sip_endpoint *endpoint = obj;
1233
1234         *buf = ast_strdup(endpoint->contact_user);
1235         if (!(*buf)) {
1236                 return -1;
1237         }
1238
1239         return 0;
1240 }
1241
1242 static void *sip_nat_hook_alloc(const char *name)
1243 {
1244         return ast_sorcery_generic_alloc(sizeof(struct ast_sip_nat_hook), NULL);
1245 }
1246
1247 /*! \brief Destructor function for persistent endpoint information */
1248 static void persistent_endpoint_destroy(void *obj)
1249 {
1250         struct sip_persistent_endpoint *persistent = obj;
1251
1252         ast_endpoint_shutdown(persistent->endpoint);
1253         ast_free(persistent->aors);
1254 }
1255
1256 int ast_sip_persistent_endpoint_update_state(const char *endpoint_name, enum ast_endpoint_state state)
1257 {
1258         struct sip_persistent_endpoint *persistent;
1259
1260         ao2_lock(persistent_endpoints);
1261         persistent = ao2_find(persistent_endpoints, endpoint_name, OBJ_SEARCH_KEY | OBJ_NOLOCK);
1262         if (persistent) {
1263                 endpoint_update_state(persistent->endpoint, state);
1264                 ao2_ref(persistent, -1);
1265         }
1266         ao2_unlock(persistent_endpoints);
1267         return persistent ? 0 : -1;
1268 }
1269
1270 /*! \brief Internal function which finds (or creates) persistent endpoint information */
1271 static struct ast_endpoint *persistent_endpoint_find_or_create(const struct ast_sip_endpoint *endpoint)
1272 {
1273         RAII_VAR(struct sip_persistent_endpoint *, persistent, NULL, ao2_cleanup);
1274         SCOPED_AO2LOCK(lock, persistent_endpoints);
1275
1276         persistent = ao2_find(persistent_endpoints, ast_sorcery_object_get_id(endpoint),
1277                 OBJ_SEARCH_KEY | OBJ_NOLOCK);
1278         if (!persistent) {
1279                 persistent = ao2_alloc_options(sizeof(*persistent), persistent_endpoint_destroy,
1280                         AO2_ALLOC_OPT_LOCK_NOLOCK);
1281                 if (!persistent) {
1282                         return NULL;
1283                 }
1284
1285                 persistent->endpoint = ast_endpoint_create("PJSIP",
1286                         ast_sorcery_object_get_id(endpoint));
1287                 if (!persistent->endpoint) {
1288                         return NULL;
1289                 }
1290
1291                 persistent->aors = ast_strdup(endpoint->aors);
1292                 if (!persistent->aors) {
1293                         return NULL;
1294                 }
1295
1296                 ast_endpoint_set_state(persistent->endpoint, AST_ENDPOINT_OFFLINE);
1297
1298                 ao2_link_flags(persistent_endpoints, persistent, OBJ_NOLOCK);
1299         }
1300
1301         ao2_ref(persistent->endpoint, +1);
1302         return persistent->endpoint;
1303 }
1304
1305 /*! \brief Callback function for when an object is finalized */
1306 static int sip_endpoint_apply_handler(const struct ast_sorcery *sorcery, void *obj)
1307 {
1308         struct ast_sip_endpoint *endpoint = obj;
1309
1310         if (!(endpoint->persistent = persistent_endpoint_find_or_create(endpoint))) {
1311                 return -1;
1312         }
1313
1314         if (endpoint->extensions.timer.min_se < 90) {
1315                 ast_log(LOG_ERROR, "Session timer minimum expires time must be 90 or greater on endpoint '%s'\n",
1316                         ast_sorcery_object_get_id(endpoint));
1317                 return -1;
1318         } else if (endpoint->extensions.timer.sess_expires < endpoint->extensions.timer.min_se) {
1319                 ast_log(LOG_ERROR, "Session timer expires must be greater than minimum session expires time on endpoint '%s'\n",
1320                         ast_sorcery_object_get_id(endpoint));
1321                 return -1;
1322         }
1323
1324         return 0;
1325 }
1326
1327 const char *ast_sip_get_device_state(const struct ast_sip_endpoint *endpoint)
1328 {
1329         char device[MAX_OBJECT_FIELD];
1330
1331         snprintf(device, MAX_OBJECT_FIELD, "PJSIP/%s", ast_sorcery_object_get_id(endpoint));
1332         return ast_devstate2str(ast_device_state(device));
1333 }
1334
1335 struct ast_endpoint_snapshot *ast_sip_get_endpoint_snapshot(
1336         const struct ast_sip_endpoint *endpoint)
1337 {
1338         return ast_endpoint_latest_snapshot(
1339                 ast_endpoint_get_tech(endpoint->persistent),
1340                 ast_endpoint_get_resource(endpoint->persistent));
1341 }
1342
1343 int ast_sip_for_each_channel_snapshot(
1344         const struct ast_endpoint_snapshot *endpoint_snapshot,
1345         ao2_callback_fn on_channel_snapshot, void *arg)
1346 {
1347         int num, num_channels = endpoint_snapshot->num_channels;
1348
1349         if (!on_channel_snapshot || !num_channels) {
1350                 return 0;
1351         }
1352
1353         for (num = 0; num < num_channels; ++num) {
1354                 RAII_VAR(struct ast_channel_snapshot *, snapshot, NULL, ao2_cleanup);
1355                 int res;
1356
1357                 snapshot = ast_channel_snapshot_get_latest(endpoint_snapshot->channel_ids[num]);
1358                 if (!snapshot) {
1359                         continue;
1360                 }
1361
1362                 res = on_channel_snapshot(snapshot, arg, 0);
1363                 if (res) {
1364                         return -1;
1365                 }
1366         }
1367         return 0;
1368 }
1369
1370 int ast_sip_for_each_channel(
1371         const struct ast_sip_endpoint *endpoint,
1372         ao2_callback_fn on_channel_snapshot, void *arg)
1373 {
1374         RAII_VAR(struct ast_endpoint_snapshot *, endpoint_snapshot, ast_sip_get_endpoint_snapshot(endpoint), ao2_cleanup);
1375         return ast_sip_for_each_channel_snapshot(endpoint_snapshot, on_channel_snapshot, arg);
1376 }
1377
1378 static int active_channels_to_str_cb(void *object, void *arg, int flags)
1379 {
1380         const struct ast_channel_snapshot *snapshot = object;
1381         struct ast_str **buf = arg;
1382         ast_str_append(buf, 0, "%s,", snapshot->name);
1383         return 0;
1384 }
1385
1386 static void active_channels_to_str(const struct ast_sip_endpoint *endpoint,
1387                                    struct ast_str **str)
1388 {
1389
1390         RAII_VAR(struct ast_endpoint_snapshot *, endpoint_snapshot,
1391                  ast_sip_get_endpoint_snapshot(endpoint), ao2_cleanup);
1392
1393         if (endpoint_snapshot) {
1394                 return;
1395         }
1396
1397         ast_sip_for_each_channel_snapshot(endpoint_snapshot,
1398                                           active_channels_to_str_cb, str);
1399         ast_str_truncate(*str, -1);
1400 }
1401
1402 #define AMI_DEFAULT_STR_SIZE 512
1403
1404 struct ast_str *ast_sip_create_ami_event(const char *event, struct ast_sip_ami *ami)
1405 {
1406         struct ast_str *buf = ast_str_create(AMI_DEFAULT_STR_SIZE);
1407
1408         if (!(buf)) {
1409                 astman_send_error_va(ami->s, ami->m, "Unable create event "
1410                                      "for %s\n", event);
1411                 return NULL;
1412         }
1413
1414         ast_str_set(&buf, 0, "Event: %s\r\n", event);
1415         if (!ast_strlen_zero(ami->action_id)) {
1416                 ast_str_append(&buf, 0, "ActionID: %s\r\n", ami->action_id);
1417         }
1418         return buf;
1419 }
1420
1421 static void sip_sorcery_object_ami_set_type_name(const void *obj, struct ast_str **buf)
1422 {
1423         ast_str_append(buf, 0, "ObjectType: %s\r\n",
1424                        ast_sorcery_object_get_type(obj));
1425         ast_str_append(buf, 0, "ObjectName: %s\r\n",
1426                        ast_sorcery_object_get_id(obj));
1427 }
1428
1429 int ast_sip_sorcery_object_to_ami(const void *obj, struct ast_str **buf)
1430 {
1431         RAII_VAR(struct ast_variable *, objset, ast_sorcery_objectset_create2(
1432                          ast_sip_get_sorcery(), obj, AST_HANDLER_ONLY_STRING), ast_variables_destroy);
1433         struct ast_variable *i;
1434
1435         if (!objset) {
1436                 return -1;
1437         }
1438
1439         sip_sorcery_object_ami_set_type_name(obj, buf);
1440
1441         for (i = objset; i; i = i->next) {
1442                 RAII_VAR(char *, camel, ast_to_camel_case(i->name), ast_free);
1443                 ast_str_append(buf, 0, "%s: %s\r\n", camel, i->value);
1444         }
1445
1446         return 0;
1447 }
1448
1449 static int sip_endpoints_aors_ami(void *obj, void *arg, int flags)
1450 {
1451         struct ast_sip_aor *aor = obj;
1452         struct ast_str **buf = arg;
1453
1454         ast_str_append(buf, 0, "Contacts: ");
1455         ast_sip_for_each_contact(aor, ast_sip_contact_to_str, arg);
1456         ast_str_append(buf, 0, "\r\n");
1457
1458         return 0;
1459 }
1460
1461 static int sip_endpoint_to_ami(const struct ast_sip_endpoint *endpoint,
1462                                struct ast_str **buf)
1463 {
1464         if (ast_sip_sorcery_object_to_ami(endpoint, buf)) {
1465                 return -1;
1466         }
1467
1468         ast_str_append(buf, 0, "DeviceState: %s\r\n",
1469                        ast_sip_get_device_state(endpoint));
1470
1471         ast_str_append(buf, 0, "ActiveChannels: ");
1472         active_channels_to_str(endpoint, buf);
1473         ast_str_append(buf, 0, "\r\n");
1474
1475         return 0;
1476 }
1477
1478 static int format_ami_endpoint(const struct ast_sip_endpoint *endpoint,
1479                                struct ast_sip_ami *ami)
1480 {
1481         RAII_VAR(struct ast_str *, buf,
1482                  ast_sip_create_ami_event("EndpointDetail", ami), ast_free);
1483
1484         if (!buf) {
1485                 return -1;
1486         }
1487
1488         sip_endpoint_to_ami(endpoint, &buf);
1489         astman_append(ami->s, "%s\r\n", ast_str_buffer(buf));
1490         return 0;
1491 }
1492
1493 #define AMI_SHOW_ENDPOINTS "PJSIPShowEndpoints"
1494 #define AMI_SHOW_ENDPOINT "PJSIPShowEndpoint"
1495
1496 static int ami_show_endpoint(struct mansession *s, const struct message *m)
1497 {
1498         struct ast_sip_ami ami = { .s = s, .m = m, .action_id = astman_get_header(m, "ActionID"),
1499                 .count = 0, };
1500         RAII_VAR(struct ast_sip_endpoint *, endpoint, NULL, ao2_cleanup);
1501         const char *endpoint_name = astman_get_header(m, "Endpoint");
1502         int count = 0;
1503
1504         if (ast_strlen_zero(endpoint_name)) {
1505                 astman_send_error_va(s, m, "%s requires an endpoint name\n",
1506                         AMI_SHOW_ENDPOINT);
1507                 return 0;
1508         }
1509
1510         if (!strncasecmp(endpoint_name, "pjsip/", 6)) {
1511                 endpoint_name += 6;
1512         }
1513
1514         if (!(endpoint = ast_sorcery_retrieve_by_id(
1515                       ast_sip_get_sorcery(), "endpoint", endpoint_name))) {
1516                 astman_send_error_va(s, m, "Unable to retrieve endpoint %s\n",
1517                         endpoint_name);
1518                 return 0;
1519         }
1520
1521         astman_send_listack(s, m, "Following are Events for each object associated with the the Endpoint",
1522                 "start");
1523
1524         /* the endpoint detail needs to always come first so apply as such */
1525         if (format_ami_endpoint(endpoint, &ami) ||
1526             ast_sip_format_endpoint_ami(endpoint, &ami, &count)) {
1527                 astman_send_error_va(s, m, "Unable to format endpoint %s\n",
1528                         endpoint_name);
1529         }
1530
1531         astman_send_list_complete_start(s, m, "EndpointDetailComplete", ami.count + 1);
1532         astman_send_list_complete_end(s);
1533
1534         return 0;
1535 }
1536
1537 static int format_str_append_auth(const struct ast_sip_auth_vector *auths,
1538                                   struct ast_str **buf)
1539 {
1540         char *str = NULL;
1541         if (ast_sip_auths_to_str(auths, &str)) {
1542                 return -1;
1543         }
1544         ast_str_append(buf, 0, "%s", str ? str : "");
1545         ast_free(str);
1546         return 0;
1547 }
1548
1549 static int format_ami_endpoints(void *obj, void *arg, int flags)
1550 {
1551
1552         struct ast_sip_endpoint *endpoint = obj;
1553         struct ast_sip_ami *ami = arg;
1554         RAII_VAR(struct ast_str *, buf,
1555                  ast_sip_create_ami_event("EndpointList", ami), ast_free);
1556
1557         if (!buf) {
1558                 return CMP_STOP;
1559         }
1560
1561         sip_sorcery_object_ami_set_type_name(endpoint, &buf);
1562         ast_str_append(&buf, 0, "Transport: %s\r\n",
1563                        endpoint->transport);
1564         ast_str_append(&buf, 0, "Aor: %s\r\n",
1565                        endpoint->aors);
1566
1567         ast_str_append(&buf, 0, "Auths: ");
1568         format_str_append_auth(&endpoint->inbound_auths, &buf);
1569         ast_str_append(&buf, 0, "\r\n");
1570
1571         ast_str_append(&buf, 0, "OutboundAuths: ");
1572         format_str_append_auth(&endpoint->outbound_auths, &buf);
1573         ast_str_append(&buf, 0, "\r\n");
1574
1575         ast_sip_for_each_aor(endpoint->aors,
1576                              sip_endpoints_aors_ami, &buf);
1577
1578         ast_str_append(&buf, 0, "DeviceState: %s\r\n",
1579                        ast_sip_get_device_state(endpoint));
1580
1581         ast_str_append(&buf, 0, "ActiveChannels: ");
1582         active_channels_to_str(endpoint, &buf);
1583         ast_str_append(&buf, 0, "\r\n");
1584
1585         astman_append(ami->s, "%s\r\n", ast_str_buffer(buf));
1586         return 0;
1587 }
1588
1589 static int ami_show_endpoints(struct mansession *s, const struct message *m)
1590 {
1591         struct ast_sip_ami ami = { .s = s, .m = m, .action_id = astman_get_header(m, "ActionID"), };
1592         RAII_VAR(struct ao2_container *, endpoints, NULL, ao2_cleanup);
1593         int num;
1594
1595         endpoints = ast_sip_get_endpoints();
1596         if (!endpoints) {
1597                 astman_send_error(s, m, "Could not get endpoints\n");
1598                 return 0;
1599         }
1600
1601         if (!(num = ao2_container_count(endpoints))) {
1602                 astman_send_error(s, m, "No endpoints found\n");
1603                 return 0;
1604         }
1605
1606         astman_send_listack(s, m, "A listing of Endpoints follows, presented as EndpointList events",
1607                 "start");
1608
1609         ao2_callback(endpoints, OBJ_NODATA, format_ami_endpoints, &ami);
1610
1611         astman_send_list_complete_start(s, m, "EndpointListComplete", num);
1612         astman_send_list_complete_end(s);
1613         return 0;
1614 }
1615
1616 static struct ao2_container *cli_endpoint_get_container(const char *regex)
1617 {
1618         RAII_VAR(struct ao2_container *, container, NULL, ao2_cleanup);
1619         struct ao2_container *s_container;
1620
1621         container = ast_sorcery_retrieve_by_regex(sip_sorcery, "endpoint", regex);
1622         if (!container) {
1623                 return NULL;
1624         }
1625
1626         s_container = ao2_container_alloc_list(AO2_ALLOC_OPT_LOCK_NOLOCK, 0,
1627                 (void *)ast_sorcery_object_id_sort, (void *)ast_sorcery_object_id_compare);
1628         if (!s_container) {
1629                 return NULL;
1630         }
1631
1632         if (ao2_container_dup(s_container, container, 0)) {
1633                 ao2_ref(s_container, -1);
1634                 return NULL;
1635         }
1636
1637         return s_container;
1638 }
1639
1640 static int cli_endpoint_iterate(void *obj, ao2_callback_fn callback, void *args)
1641 {
1642         ao2_callback(obj, OBJ_NODATA, callback, args);
1643
1644         return 0;
1645 }
1646
1647 static void *cli_endpoint_retrieve_by_id(const char *id)
1648 {
1649         return ast_sorcery_retrieve_by_id(ast_sip_get_sorcery(), "endpoint", id);
1650 }
1651
1652 static void cli_endpoint_print_child_header(char *type, struct ast_sip_cli_context *context)
1653 {
1654         RAII_VAR(struct ast_sip_cli_formatter_entry *, formatter_entry, NULL, ao2_cleanup);
1655
1656         formatter_entry = ast_sip_lookup_cli_formatter(type);
1657         if (formatter_entry) {
1658                 formatter_entry->print_header(NULL, context, 0);
1659         }
1660 }
1661
1662 static int cli_endpoint_print_header(void *obj, void *arg, int flags)
1663 {
1664         struct ast_sip_cli_context *context = arg;
1665
1666         ast_assert(context->output_buffer != NULL);
1667
1668         ast_str_append(&context->output_buffer, 0,
1669                         " Endpoint:  <Endpoint/CID.....................................>  <State.....>  <Channels.>\n");
1670
1671         if (context->recurse) {
1672                 context->indent_level++;
1673                 cli_endpoint_print_child_header("auth", context);
1674                 cli_endpoint_print_child_header("aor", context);
1675                 cli_endpoint_print_child_header("transport", context);
1676                 cli_endpoint_print_child_header("identify", context);
1677                 cli_endpoint_print_child_header("channel", context);
1678                 context->indent_level--;
1679         }
1680
1681         return 0;
1682 }
1683
1684 static void cli_endpoint_print_child_body(char *type, const void *obj, struct ast_sip_cli_context *context)
1685 {
1686         RAII_VAR(struct ast_sip_cli_formatter_entry *, formatter_entry, NULL, ao2_cleanup);
1687
1688         formatter_entry = ast_sip_lookup_cli_formatter(type);
1689         if (formatter_entry) {
1690                 formatter_entry->iterate((void *)obj, formatter_entry->print_body, context);
1691         }
1692 }
1693
1694 static int cli_endpoint_print_body(void *obj, void *arg, int flags)
1695 {
1696         struct ast_sip_endpoint *endpoint = obj;
1697         RAII_VAR(struct ast_endpoint_snapshot *, endpoint_snapshot, ast_sip_get_endpoint_snapshot(endpoint), ao2_cleanup);
1698         struct ast_sip_cli_context *context = arg;
1699         const char *id = ast_sorcery_object_get_id(endpoint);
1700         char *print_name = NULL;
1701         int print_name_len;
1702         char *number = S_COR(endpoint->id.self.number.valid,
1703                 endpoint->id.self.number.str, NULL);
1704         int indent;
1705         int flexwidth;
1706
1707         ast_assert(context->output_buffer != NULL);
1708
1709         if (number) {
1710                 print_name_len = strlen(id) + strlen(number) + 2;
1711                 print_name = ast_alloca(print_name_len);
1712                 snprintf(print_name, print_name_len, "%s/%s", id, number);
1713         }
1714
1715         indent = CLI_INDENT_TO_SPACES(context->indent_level);
1716         flexwidth = CLI_LAST_TABSTOP - indent - 2;
1717
1718         ast_str_append(&context->output_buffer, 0, "%*s:  %-*.*s  %-12.12s  %d of %.0f\n",
1719                 indent, "Endpoint",
1720                 flexwidth, flexwidth, print_name ? print_name : id,
1721                 ast_sip_get_device_state(endpoint),
1722                 endpoint_snapshot->num_channels,
1723                 (double) endpoint->devicestate_busy_at ? endpoint->devicestate_busy_at :
1724                                                                                                                 INFINITY
1725                                                                                                                 );
1726
1727         if (context->recurse) {
1728                 context->indent_level++;
1729
1730                 context->auth_direction = "Out";
1731                 cli_endpoint_print_child_body("auth", &endpoint->outbound_auths, context);
1732                 context->auth_direction = "In";
1733                 cli_endpoint_print_child_body("auth", &endpoint->inbound_auths, context);
1734
1735                 cli_endpoint_print_child_body("aor", endpoint->aors, context);
1736                 cli_endpoint_print_child_body("transport", endpoint, context);
1737                 cli_endpoint_print_child_body("identify", endpoint, context);
1738                 cli_endpoint_print_child_body("channel", endpoint, context);
1739
1740                 context->indent_level--;
1741
1742                 if (context->indent_level == 0) {
1743                         ast_str_append(&context->output_buffer, 0, "\n");
1744                 }
1745         }
1746
1747         if (context->show_details || (context->show_details_only_level_0 && context->indent_level == 0)) {
1748                 ast_str_append(&context->output_buffer, 0, "\n");
1749                 ast_sip_cli_print_sorcery_objectset(endpoint, context, 0);
1750         }
1751
1752         return 0;
1753 }
1754
1755 static struct ast_cli_entry cli_commands[] = {
1756         AST_CLI_DEFINE(ast_sip_cli_traverse_objects, "List PJSIP Endpoints",
1757                 .command = "pjsip list endpoints",
1758                 .usage = "Usage: pjsip list endpoints [ like <pattern> ]\n"
1759                                 "       List the configured PJSIP endpoints\n"
1760                                 "       Optional regular expression pattern is used to filter the list.\n"),
1761         AST_CLI_DEFINE(ast_sip_cli_traverse_objects, "Show PJSIP Endpoints",
1762                 .command = "pjsip show endpoints",
1763                 .usage = "Usage: pjsip show endpoints [ like <pattern> ]\n"
1764                                 "       List(detailed) the configured PJSIP endpoints\n"
1765                                 "       Optional regular expression pattern is used to filter the list.\n"),
1766         AST_CLI_DEFINE(ast_sip_cli_traverse_objects, "Show PJSIP Endpoint",
1767                 .command = "pjsip show endpoint",
1768                 .usage = "Usage: pjsip show endpoint <id>\n"
1769                                  "       Show the configured PJSIP endpoint\n"),
1770 };
1771
1772 struct ast_sip_cli_formatter_entry *channel_formatter;
1773 struct ast_sip_cli_formatter_entry *endpoint_formatter;
1774
1775 static int on_load_endpoint(void *obj, void *arg, int flags)
1776 {
1777         return sip_endpoint_apply_handler(sip_sorcery, obj);
1778 }
1779
1780 static void load_all_endpoints(void)
1781 {
1782         struct ao2_container *endpoints;
1783
1784         endpoints = ast_sorcery_retrieve_by_fields(sip_sorcery, "endpoint", AST_RETRIEVE_FLAG_MULTIPLE | AST_RETRIEVE_FLAG_ALL, NULL);
1785         if (endpoints) {
1786                 ao2_callback(endpoints, OBJ_NODATA, on_load_endpoint, NULL);
1787                 ao2_ref(endpoints, -1);
1788         }
1789 }
1790
1791 int ast_res_pjsip_initialize_configuration(void)
1792 {
1793         if (ast_manager_register_xml(AMI_SHOW_ENDPOINTS, EVENT_FLAG_SYSTEM, ami_show_endpoints) ||
1794             ast_manager_register_xml(AMI_SHOW_ENDPOINT, EVENT_FLAG_SYSTEM, ami_show_endpoint)) {
1795                 return -1;
1796         }
1797
1798         persistent_endpoints = ao2_container_alloc_hash(AO2_ALLOC_OPT_LOCK_MUTEX, 0,
1799                 PERSISTENT_BUCKETS, persistent_endpoint_hash, NULL, persistent_endpoint_cmp);
1800         if (!persistent_endpoints) {
1801                 return -1;
1802         }
1803
1804         if (!(sip_sorcery = ast_sorcery_open())) {
1805                 ast_log(LOG_ERROR, "Failed to open SIP sorcery failed to open\n");
1806                 return -1;
1807         }
1808
1809         ast_sip_initialize_cli();
1810
1811         if (ast_sip_initialize_sorcery_auth()) {
1812                 ast_log(LOG_ERROR, "Failed to register SIP authentication support\n");
1813                 ast_sorcery_unref(sip_sorcery);
1814                 sip_sorcery = NULL;
1815                 return -1;
1816         }
1817
1818         ast_sorcery_apply_default(sip_sorcery, "endpoint", "config", "pjsip.conf,criteria=type=endpoint");
1819         ast_sorcery_apply_default(sip_sorcery, "nat_hook", "memory", NULL);
1820
1821         if (ast_sorcery_object_register(sip_sorcery, "endpoint", ast_sip_endpoint_alloc, NULL, sip_endpoint_apply_handler)) {
1822                 ast_log(LOG_ERROR, "Failed to register SIP endpoint object with sorcery\n");
1823                 ast_sorcery_unref(sip_sorcery);
1824                 sip_sorcery = NULL;
1825                 return -1;
1826         }
1827
1828         if (ast_sorcery_internal_object_register(sip_sorcery, "nat_hook", sip_nat_hook_alloc, NULL, NULL)) {
1829                 ast_log(LOG_ERROR, "Failed to register nat_hook\n");
1830         }
1831
1832         ast_sorcery_object_field_register(sip_sorcery, "endpoint", "type", "", OPT_NOOP_T, 0, 0);
1833         ast_sorcery_object_field_register(sip_sorcery, "endpoint", "context", "default", OPT_STRINGFIELD_T, 0, STRFLDSET(struct ast_sip_endpoint, context));
1834         ast_sorcery_object_field_register_alias(sip_sorcery, "endpoint", "disallow", "", OPT_CODEC_T, 0, FLDSET(struct ast_sip_endpoint, media.codecs));
1835         ast_sorcery_object_field_register(sip_sorcery, "endpoint", "allow", "", OPT_CODEC_T, 1, FLDSET(struct ast_sip_endpoint, media.codecs));
1836         ast_sorcery_object_field_register_custom(sip_sorcery, "endpoint", "dtmf_mode", "rfc4733", dtmf_handler, dtmf_to_str, NULL, 0, 0);
1837         ast_sorcery_object_field_register(sip_sorcery, "endpoint", "rtp_ipv6", "no", OPT_BOOL_T, 1, FLDSET(struct ast_sip_endpoint, media.rtp.ipv6));
1838         ast_sorcery_object_field_register(sip_sorcery, "endpoint", "rtp_symmetric", "no", OPT_BOOL_T, 1, FLDSET(struct ast_sip_endpoint, media.rtp.symmetric));
1839         ast_sorcery_object_field_register(sip_sorcery, "endpoint", "ice_support", "no", OPT_BOOL_T, 1, FLDSET(struct ast_sip_endpoint, media.rtp.ice_support));
1840         ast_sorcery_object_field_register(sip_sorcery, "endpoint", "use_ptime", "no", OPT_BOOL_T, 1, FLDSET(struct ast_sip_endpoint, media.rtp.use_ptime));
1841         ast_sorcery_object_field_register(sip_sorcery, "endpoint", "force_rport", "yes", OPT_BOOL_T, 1, FLDSET(struct ast_sip_endpoint, nat.force_rport));
1842         ast_sorcery_object_field_register(sip_sorcery, "endpoint", "rewrite_contact", "no", OPT_BOOL_T, 1, FLDSET(struct ast_sip_endpoint, nat.rewrite_contact));
1843         ast_sorcery_object_field_register(sip_sorcery, "endpoint", "transport", "", OPT_STRINGFIELD_T, 0, STRFLDSET(struct ast_sip_endpoint, transport));
1844         ast_sorcery_object_field_register(sip_sorcery, "endpoint", "outbound_proxy", "", OPT_STRINGFIELD_T, 0, STRFLDSET(struct ast_sip_endpoint, outbound_proxy));
1845         ast_sorcery_object_field_register(sip_sorcery, "endpoint", "moh_suggest", "default", OPT_STRINGFIELD_T, 0, STRFLDSET(struct ast_sip_endpoint, mohsuggest));
1846         ast_sorcery_object_field_register_custom(sip_sorcery, "endpoint", "100rel", "yes", prack_handler, prack_to_str, NULL, 0, 0);
1847         ast_sorcery_object_field_register_custom(sip_sorcery, "endpoint", "timers", "yes", timers_handler, timers_to_str, NULL, 0, 0);
1848         ast_sorcery_object_field_register(sip_sorcery, "endpoint", "timers_min_se", "90", OPT_UINT_T, 0, FLDSET(struct ast_sip_endpoint, extensions.timer.min_se));
1849         ast_sorcery_object_field_register(sip_sorcery, "endpoint", "timers_sess_expires", "1800", OPT_UINT_T, 0, FLDSET(struct ast_sip_endpoint, extensions.timer.sess_expires));
1850         ast_sorcery_object_field_register_custom(sip_sorcery, "endpoint", "auth", "", inbound_auth_handler, inbound_auths_to_str, NULL, 0, 0);
1851         ast_sorcery_object_field_register_custom(sip_sorcery, "endpoint", "outbound_auth", "", outbound_auth_handler, outbound_auths_to_str, NULL, 0, 0);
1852         ast_sorcery_object_field_register(sip_sorcery, "endpoint", "aors", "", OPT_STRINGFIELD_T, 0, STRFLDSET(struct ast_sip_endpoint, aors));
1853         ast_sorcery_object_field_register(sip_sorcery, "endpoint", "media_address", "", OPT_STRINGFIELD_T, 0, STRFLDSET(struct ast_sip_endpoint, media.address));
1854         ast_sorcery_object_field_register(sip_sorcery, "endpoint", "bind_rtp_to_media_address", "no", OPT_BOOL_T, 1, STRFLDSET(struct ast_sip_endpoint, media.bind_rtp_to_media_address));
1855         ast_sorcery_object_field_register_custom(sip_sorcery, "endpoint", "identify_by", "username", ident_handler, ident_to_str, NULL, 0, 0);
1856         ast_sorcery_object_field_register(sip_sorcery, "endpoint", "direct_media", "yes", OPT_BOOL_T, 1, FLDSET(struct ast_sip_endpoint, media.direct_media.enabled));
1857         ast_sorcery_object_field_register_custom(sip_sorcery, "endpoint", "direct_media_method", "invite", direct_media_method_handler, direct_media_method_to_str, NULL, 0, 0);
1858         ast_sorcery_object_field_register_custom(sip_sorcery, "endpoint", "connected_line_method", "invite", connected_line_method_handler, connected_line_method_to_str, NULL, 0, 0);
1859         ast_sorcery_object_field_register_custom(sip_sorcery, "endpoint", "direct_media_glare_mitigation", "none", direct_media_glare_mitigation_handler, direct_media_glare_mitigation_to_str, NULL, 0, 0);
1860         ast_sorcery_object_field_register(sip_sorcery, "endpoint", "disable_direct_media_on_nat", "no", OPT_BOOL_T, 1, FLDSET(struct ast_sip_endpoint, media.direct_media.disable_on_nat));
1861         ast_sorcery_object_field_register_custom(sip_sorcery, "endpoint", "callerid", "", caller_id_handler, caller_id_to_str, NULL, 0, 0);
1862         ast_sorcery_object_field_register_custom(sip_sorcery, "endpoint", "callerid_privacy", "allowed_not_screened", caller_id_privacy_handler, caller_id_privacy_to_str, NULL, 0, 0);
1863         ast_sorcery_object_field_register_custom(sip_sorcery, "endpoint", "callerid_tag", "", caller_id_tag_handler, caller_id_tag_to_str, NULL, 0, 0);
1864         ast_sorcery_object_field_register(sip_sorcery, "endpoint", "trust_id_inbound", "no", OPT_BOOL_T, 1, FLDSET(struct ast_sip_endpoint, id.trust_inbound));
1865         ast_sorcery_object_field_register(sip_sorcery, "endpoint", "trust_id_outbound", "no", OPT_BOOL_T, 1, FLDSET(struct ast_sip_endpoint, id.trust_outbound));
1866         ast_sorcery_object_field_register(sip_sorcery, "endpoint", "send_pai", "no", OPT_BOOL_T, 1, FLDSET(struct ast_sip_endpoint, id.send_pai));
1867         ast_sorcery_object_field_register(sip_sorcery, "endpoint", "send_rpid", "no", OPT_BOOL_T, 1, FLDSET(struct ast_sip_endpoint, id.send_rpid));
1868         ast_sorcery_object_field_register(sip_sorcery, "endpoint", "rpid_immediate", "no", OPT_BOOL_T, 1, FLDSET(struct ast_sip_endpoint, id.rpid_immediate));
1869         ast_sorcery_object_field_register(sip_sorcery, "endpoint", "send_diversion", "yes", OPT_BOOL_T, 1, FLDSET(struct ast_sip_endpoint, id.send_diversion));
1870         ast_sorcery_object_field_register(sip_sorcery, "endpoint", "mailboxes", "", OPT_STRINGFIELD_T, 0, STRFLDSET(struct ast_sip_endpoint, subscription.mwi.mailboxes));
1871         ast_sorcery_object_field_register_custom(sip_sorcery, "endpoint", "voicemail_extension", "", voicemail_extension_handler, voicemail_extension_to_str, NULL, 0, 0);
1872         ast_sorcery_object_field_register(sip_sorcery, "endpoint", "aggregate_mwi", "yes", OPT_BOOL_T, 1, FLDSET(struct ast_sip_endpoint, subscription.mwi.aggregate));
1873         ast_sorcery_object_field_register(sip_sorcery, "endpoint", "mwi_subscribe_replaces_unsolicited", "no", OPT_BOOL_T, 1, FLDSET(struct ast_sip_endpoint, subscription.mwi.subscribe_replaces_unsolicited));
1874         ast_sorcery_object_field_register_custom(sip_sorcery, "endpoint", "media_encryption", "no", media_encryption_handler, media_encryption_to_str, NULL, 0, 0);
1875         ast_sorcery_object_field_register(sip_sorcery, "endpoint", "use_avpf", "no", OPT_BOOL_T, 1, FLDSET(struct ast_sip_endpoint, media.rtp.use_avpf));
1876         ast_sorcery_object_field_register(sip_sorcery, "endpoint", "force_avp", "no", OPT_BOOL_T, 1, FLDSET(struct ast_sip_endpoint, media.rtp.force_avp));
1877         ast_sorcery_object_field_register(sip_sorcery, "endpoint", "media_use_received_transport", "no", OPT_BOOL_T, 1, FLDSET(struct ast_sip_endpoint, media.rtp.use_received_transport));
1878         ast_sorcery_object_field_register(sip_sorcery, "endpoint", "rtp_keepalive", "0", OPT_UINT_T, 0, FLDSET(struct ast_sip_endpoint, media.rtp.keepalive));
1879         ast_sorcery_object_field_register(sip_sorcery, "endpoint", "rtp_timeout", "0", OPT_UINT_T, 0, FLDSET(struct ast_sip_endpoint, media.rtp.timeout));
1880         ast_sorcery_object_field_register(sip_sorcery, "endpoint", "rtp_timeout_hold", "0", OPT_UINT_T, 0, FLDSET(struct ast_sip_endpoint, media.rtp.timeout_hold));
1881         ast_sorcery_object_field_register(sip_sorcery, "endpoint", "one_touch_recording", "no", OPT_BOOL_T, 1, FLDSET(struct ast_sip_endpoint, info.recording.enabled));
1882         ast_sorcery_object_field_register(sip_sorcery, "endpoint", "inband_progress", "no", OPT_BOOL_T, 1, FLDSET(struct ast_sip_endpoint, inband_progress));
1883         ast_sorcery_object_field_register_custom(sip_sorcery, "endpoint", "call_group", "", group_handler, callgroup_to_str, NULL, 0, 0);
1884         ast_sorcery_object_field_register_custom(sip_sorcery, "endpoint", "pickup_group", "", group_handler, pickupgroup_to_str, NULL, 0, 0);
1885         ast_sorcery_object_field_register_custom(sip_sorcery, "endpoint", "named_call_group", "", named_groups_handler, named_callgroups_to_str, NULL, 0, 0);
1886         ast_sorcery_object_field_register_custom(sip_sorcery, "endpoint", "named_pickup_group", "", named_groups_handler, named_pickupgroups_to_str, NULL, 0, 0);
1887         ast_sorcery_object_field_register(sip_sorcery, "endpoint", "device_state_busy_at", "0", OPT_UINT_T, 0, FLDSET(struct ast_sip_endpoint, devicestate_busy_at));
1888         ast_sorcery_object_field_register(sip_sorcery, "endpoint", "t38_udptl", "no", OPT_BOOL_T, 1, FLDSET(struct ast_sip_endpoint, media.t38.enabled));
1889         ast_sorcery_object_field_register_custom(sip_sorcery, "endpoint", "t38_udptl_ec", "none", t38udptl_ec_handler, t38udptl_ec_to_str, NULL, 0, 0);
1890         ast_sorcery_object_field_register(sip_sorcery, "endpoint", "t38_udptl_maxdatagram", "0", OPT_UINT_T, 0, FLDSET(struct ast_sip_endpoint, media.t38.maxdatagram));
1891         ast_sorcery_object_field_register(sip_sorcery, "endpoint", "fax_detect", "no", OPT_BOOL_T, 1, FLDSET(struct ast_sip_endpoint, faxdetect));
1892         ast_sorcery_object_field_register(sip_sorcery, "endpoint", "fax_detect_timeout", "0", OPT_UINT_T, 0, FLDSET(struct ast_sip_endpoint, faxdetect_timeout));
1893         ast_sorcery_object_field_register(sip_sorcery, "endpoint", "t38_udptl_nat", "no", OPT_BOOL_T, 1, FLDSET(struct ast_sip_endpoint, media.t38.nat));
1894         ast_sorcery_object_field_register(sip_sorcery, "endpoint", "t38_udptl_ipv6", "no", OPT_BOOL_T, 1, FLDSET(struct ast_sip_endpoint, media.t38.ipv6));
1895         ast_sorcery_object_field_register(sip_sorcery, "endpoint", "tone_zone", "", OPT_STRINGFIELD_T, 0, STRFLDSET(struct ast_sip_endpoint, zone));
1896         ast_sorcery_object_field_register(sip_sorcery, "endpoint", "language", "", OPT_STRINGFIELD_T, 0, STRFLDSET(struct ast_sip_endpoint, language));
1897         ast_sorcery_object_field_register(sip_sorcery, "endpoint", "record_on_feature", "automixmon", OPT_STRINGFIELD_T, 0, STRFLDSET(struct ast_sip_endpoint, info.recording.onfeature));
1898         ast_sorcery_object_field_register(sip_sorcery, "endpoint", "record_off_feature", "automixmon", OPT_STRINGFIELD_T, 0, STRFLDSET(struct ast_sip_endpoint, info.recording.offfeature));
1899         ast_sorcery_object_field_register(sip_sorcery, "endpoint", "allow_transfer", "yes", OPT_BOOL_T, 1, FLDSET(struct ast_sip_endpoint, allowtransfer));
1900         ast_sorcery_object_field_register(sip_sorcery, "endpoint", "user_eq_phone", "no", OPT_BOOL_T, 1, FLDSET(struct ast_sip_endpoint, usereqphone));
1901         ast_sorcery_object_field_register(sip_sorcery, "endpoint", "moh_passthrough", "no", OPT_BOOL_T, 1, FLDSET(struct ast_sip_endpoint, moh_passthrough));
1902         ast_sorcery_object_field_register(sip_sorcery, "endpoint", "sdp_owner", "-", OPT_STRINGFIELD_T, 0, STRFLDSET(struct ast_sip_endpoint, media.sdpowner));
1903         ast_sorcery_object_field_register(sip_sorcery, "endpoint", "sdp_session", "Asterisk", OPT_STRINGFIELD_T, 0, STRFLDSET(struct ast_sip_endpoint, media.sdpsession));
1904         ast_sorcery_object_field_register_custom(sip_sorcery, "endpoint", "tos_audio", "0", tos_handler, tos_audio_to_str, NULL, 0, 0);
1905         ast_sorcery_object_field_register_custom(sip_sorcery, "endpoint", "tos_video", "0", tos_handler, tos_video_to_str, NULL, 0, 0);
1906         ast_sorcery_object_field_register(sip_sorcery, "endpoint", "cos_audio", "0", OPT_UINT_T, 0, FLDSET(struct ast_sip_endpoint, media.cos_audio));
1907         ast_sorcery_object_field_register(sip_sorcery, "endpoint", "cos_video", "0", OPT_UINT_T, 0, FLDSET(struct ast_sip_endpoint, media.cos_video));
1908         ast_sorcery_object_field_register(sip_sorcery, "endpoint", "allow_subscribe", "yes", OPT_BOOL_T, 1, FLDSET(struct ast_sip_endpoint, subscription.allow));
1909         ast_sorcery_object_field_register(sip_sorcery, "endpoint", "sub_min_expiry", "0", OPT_UINT_T, 0, FLDSET(struct ast_sip_endpoint, subscription.minexpiry));
1910         ast_sorcery_object_field_register(sip_sorcery, "endpoint", "from_user", "", OPT_STRINGFIELD_T, 0, STRFLDSET(struct ast_sip_endpoint, fromuser));
1911         ast_sorcery_object_field_register(sip_sorcery, "endpoint", "from_domain", "", OPT_STRINGFIELD_T, 0, STRFLDSET(struct ast_sip_endpoint, fromdomain));
1912         ast_sorcery_object_field_register(sip_sorcery, "endpoint", "mwi_from_user", "", OPT_STRINGFIELD_T, 0, STRFLDSET(struct ast_sip_endpoint, subscription.mwi.fromuser));
1913         ast_sorcery_object_field_register(sip_sorcery, "endpoint", "rtp_engine", "asterisk", OPT_STRINGFIELD_T, 0, STRFLDSET(struct ast_sip_endpoint, media.rtp.engine));
1914         ast_sorcery_object_field_register_custom(sip_sorcery, "endpoint", "dtls_verify", "no", dtls_handler, dtlsverify_to_str, NULL, 0, 0);
1915         ast_sorcery_object_field_register_custom(sip_sorcery, "endpoint", "dtls_rekey", "0", dtls_handler, dtlsrekey_to_str, NULL, 0, 0);
1916         ast_sorcery_object_field_register_custom(sip_sorcery, "endpoint", "dtls_cert_file", "", dtls_handler, dtlscertfile_to_str, NULL, 0, 0);
1917         ast_sorcery_object_field_register_custom(sip_sorcery, "endpoint", "dtls_private_key", "", dtls_handler, dtlsprivatekey_to_str, NULL, 0, 0);
1918         ast_sorcery_object_field_register_custom(sip_sorcery, "endpoint", "dtls_cipher", "", dtls_handler, dtlscipher_to_str, NULL, 0, 0);
1919         ast_sorcery_object_field_register_custom(sip_sorcery, "endpoint", "dtls_ca_file", "", dtls_handler, dtlscafile_to_str, NULL, 0, 0);
1920         ast_sorcery_object_field_register_custom(sip_sorcery, "endpoint", "dtls_ca_path", "", dtls_handler, dtlscapath_to_str, NULL, 0, 0);
1921         ast_sorcery_object_field_register_custom(sip_sorcery, "endpoint", "dtls_setup", "", dtls_handler, dtlssetup_to_str, NULL, 0, 0);
1922         ast_sorcery_object_field_register_custom(sip_sorcery, "endpoint", "dtls_fingerprint", "", dtls_handler, dtlsfingerprint_to_str, NULL, 0, 0);
1923         ast_sorcery_object_field_register(sip_sorcery, "endpoint", "srtp_tag_32", "no", OPT_BOOL_T, 1, FLDSET(struct ast_sip_endpoint, media.rtp.srtp_tag_32));
1924         ast_sorcery_object_field_register(sip_sorcery, "endpoint", "media_encryption_optimistic", "no", OPT_BOOL_T, 1, FLDSET(struct ast_sip_endpoint, media.rtp.encryption_optimistic));
1925         ast_sorcery_object_field_register(sip_sorcery, "endpoint", "g726_non_standard", "no", OPT_BOOL_T, 1, FLDSET(struct ast_sip_endpoint, media.g726_non_standard));
1926         ast_sorcery_object_field_register_custom(sip_sorcery, "endpoint", "redirect_method", "user", redirect_handler, NULL, NULL, 0, 0);
1927         ast_sorcery_object_field_register_custom(sip_sorcery, "endpoint", "set_var", "", set_var_handler, set_var_to_str, set_var_to_vl, 0, 0);
1928         ast_sorcery_object_field_register(sip_sorcery, "endpoint", "message_context", "", OPT_STRINGFIELD_T, 0, STRFLDSET(struct ast_sip_endpoint, message_context));
1929         ast_sorcery_object_field_register(sip_sorcery, "endpoint", "accountcode", "", OPT_STRINGFIELD_T, 0, STRFLDSET(struct ast_sip_endpoint, accountcode));
1930         ast_sorcery_object_field_register_custom(sip_sorcery, "endpoint", "deny", "", endpoint_acl_handler, NULL, NULL, 0, 0);
1931         ast_sorcery_object_field_register_custom(sip_sorcery, "endpoint", "permit", "", endpoint_acl_handler, NULL, NULL, 0, 0);
1932         ast_sorcery_object_field_register_custom(sip_sorcery, "endpoint", "acl", "", endpoint_acl_handler, acl_to_str, NULL, 0, 0);
1933         ast_sorcery_object_field_register_custom(sip_sorcery, "endpoint", "contact_deny", "", endpoint_acl_handler, NULL, NULL, 0, 0);
1934         ast_sorcery_object_field_register_custom(sip_sorcery, "endpoint", "contact_permit", "", endpoint_acl_handler, NULL, NULL, 0, 0);
1935         ast_sorcery_object_field_register_custom(sip_sorcery, "endpoint", "contact_acl", "", endpoint_acl_handler, contact_acl_to_str, NULL, 0, 0);
1936         ast_sorcery_object_field_register(sip_sorcery, "endpoint", "subscribe_context", "", OPT_CHAR_ARRAY_T, 0, CHARFLDSET(struct ast_sip_endpoint, subscription.context));
1937         ast_sorcery_object_field_register_custom(sip_sorcery, "endpoint", "contact_user", "", contact_user_handler, contact_user_to_str, NULL, 0, 0);
1938         ast_sorcery_object_field_register(sip_sorcery, "endpoint", "preferred_codec_only", "no", OPT_BOOL_T, 1, FLDSET(struct ast_sip_endpoint, preferred_codec_only));
1939         ast_sorcery_object_field_register(sip_sorcery, "endpoint", "asymmetric_rtp_codec", "no", OPT_BOOL_T, 1, FLDSET(struct ast_sip_endpoint, asymmetric_rtp_codec));
1940         ast_sorcery_object_field_register(sip_sorcery, "endpoint", "rtcp_mux", "no", OPT_BOOL_T, 1, FLDSET(struct ast_sip_endpoint, media.rtcp_mux));
1941         ast_sorcery_object_field_register(sip_sorcery, "endpoint", "allow_overlap", "yes", OPT_BOOL_T, 1, FLDSET(struct ast_sip_endpoint, allow_overlap));
1942         ast_sorcery_object_field_register(sip_sorcery, "endpoint", "refer_blind_progress", "yes", OPT_BOOL_T, 1, FLDSET(struct ast_sip_endpoint, refer_blind_progress));
1943
1944         if (ast_sip_initialize_sorcery_transport()) {
1945                 ast_log(LOG_ERROR, "Failed to register SIP transport support with sorcery\n");
1946                 ast_sorcery_unref(sip_sorcery);
1947                 sip_sorcery = NULL;
1948                 return -1;
1949         }
1950
1951         if (ast_sip_initialize_sorcery_location()) {
1952                 ast_log(LOG_ERROR, "Failed to register SIP location support with sorcery\n");
1953                 ast_sorcery_unref(sip_sorcery);
1954                 sip_sorcery = NULL;
1955                 return -1;
1956         }
1957
1958         if (ast_sip_initialize_sorcery_qualify()) {
1959                 ast_log(LOG_ERROR, "Failed to register SIP qualify support with sorcery\n");
1960                 ast_sorcery_unref(sip_sorcery);
1961                 sip_sorcery = NULL;
1962                 return -1;
1963         }
1964
1965         ast_sorcery_observer_add(sip_sorcery, "endpoint", &endpoint_observers);
1966         ast_sorcery_observer_add(sip_sorcery, "contact", &state_contact_observer);
1967         ast_sorcery_observer_add(sip_sorcery, CONTACT_STATUS, &state_contact_status_observer);
1968
1969         if (ast_sip_initialize_sorcery_domain_alias()) {
1970                 ast_log(LOG_ERROR, "Failed to register SIP domain aliases support with sorcery\n");
1971                 ast_sorcery_unref(sip_sorcery);
1972                 sip_sorcery = NULL;
1973                 return -1;
1974         }
1975
1976         if (ast_sip_initialize_sorcery_global()) {
1977                 ast_log(LOG_ERROR, "Failed to register SIP Global support\n");
1978                 ast_sorcery_unref(sip_sorcery);
1979                 sip_sorcery = NULL;
1980                 return -1;
1981         }
1982
1983         endpoint_formatter = ao2_alloc(sizeof(struct ast_sip_cli_formatter_entry), NULL);
1984         if (!endpoint_formatter) {
1985                 ast_log(LOG_ERROR, "Unable to allocate memory for endpoint_formatter\n");
1986                 ast_sorcery_unref(sip_sorcery);
1987                 sip_sorcery = NULL;
1988                 return -1;
1989         }
1990         endpoint_formatter->name = "endpoint";
1991         endpoint_formatter->print_header = cli_endpoint_print_header;
1992         endpoint_formatter->print_body = cli_endpoint_print_body;
1993         endpoint_formatter->get_container = cli_endpoint_get_container;
1994         endpoint_formatter->iterate = cli_endpoint_iterate;
1995         endpoint_formatter->retrieve_by_id = cli_endpoint_retrieve_by_id;
1996         endpoint_formatter->get_id = ast_sorcery_object_get_id;
1997
1998         ast_sip_register_cli_formatter(endpoint_formatter);
1999         ast_cli_register_multiple(cli_commands, ARRAY_LEN(cli_commands));
2000
2001         ast_sorcery_load(sip_sorcery);
2002
2003         load_all_endpoints();
2004
2005         return 0;
2006 }
2007
2008 void ast_res_pjsip_destroy_configuration(void)
2009 {
2010         if (!sip_sorcery) {
2011                 return;
2012         }
2013
2014         ast_sorcery_observer_remove(sip_sorcery, CONTACT_STATUS, &state_contact_status_observer);
2015         ast_sorcery_observer_remove(sip_sorcery, "contact", &state_contact_observer);
2016         ast_sip_destroy_sorcery_global();
2017         ast_sip_destroy_sorcery_location();
2018         ast_sip_destroy_sorcery_auth();
2019         ast_sip_destroy_sorcery_transport();
2020         ast_sorcery_unref(sip_sorcery);
2021         sip_sorcery = NULL;
2022         ast_manager_unregister(AMI_SHOW_ENDPOINT);
2023         ast_manager_unregister(AMI_SHOW_ENDPOINTS);
2024         ast_cli_unregister_multiple(cli_commands, ARRAY_LEN(cli_commands));
2025         ast_sip_unregister_cli_formatter(endpoint_formatter);
2026         ast_sip_destroy_cli();
2027         ao2_cleanup(persistent_endpoints);
2028         persistent_endpoints = NULL;
2029 }
2030
2031 int ast_res_pjsip_reload_configuration(void)
2032 {
2033         if (sip_sorcery) {
2034                 ast_sorcery_reload(sip_sorcery);
2035         }
2036         return 0;
2037 }
2038
2039 static void subscription_configuration_destroy(struct ast_sip_endpoint_subscription_configuration *subscription)
2040 {
2041         ast_string_field_free_memory(&subscription->mwi);
2042         ast_free(subscription->mwi.voicemail_extension);
2043 }
2044
2045 static void info_configuration_destroy(struct ast_sip_endpoint_info_configuration *info)
2046 {
2047         ast_string_field_free_memory(&info->recording);
2048 }
2049
2050 static void media_configuration_destroy(struct ast_sip_endpoint_media_configuration *media)
2051 {
2052         ast_string_field_free_memory(&media->rtp);
2053         ast_string_field_free_memory(media);
2054 }
2055
2056 static void endpoint_destructor(void* obj)
2057 {
2058         struct ast_sip_endpoint *endpoint = obj;
2059
2060         ast_string_field_free_memory(endpoint);
2061
2062         ao2_ref(endpoint->media.codecs, -1);
2063         subscription_configuration_destroy(&endpoint->subscription);
2064         info_configuration_destroy(&endpoint->info);
2065         media_configuration_destroy(&endpoint->media);
2066         ast_sip_auth_vector_destroy(&endpoint->inbound_auths);
2067         ast_sip_auth_vector_destroy(&endpoint->outbound_auths);
2068         ast_party_id_free(&endpoint->id.self);
2069         endpoint->pickup.named_callgroups = ast_unref_namedgroups(endpoint->pickup.named_callgroups);
2070         endpoint->pickup.named_pickupgroups = ast_unref_namedgroups(endpoint->pickup.named_pickupgroups);
2071         ao2_cleanup(endpoint->persistent);
2072         ast_variables_destroy(endpoint->channel_vars);
2073         AST_VECTOR_FREE(&endpoint->ident_method_order);
2074         ast_free(endpoint->contact_user);
2075         ast_free_acl_list(endpoint->contact_acl);
2076         ast_free_acl_list(endpoint->acl);
2077 }
2078
2079 static int init_subscription_configuration(struct ast_sip_endpoint_subscription_configuration *subscription)
2080 {
2081         return ast_string_field_init(&subscription->mwi, 64);
2082 }
2083
2084 static int init_info_configuration(struct ast_sip_endpoint_info_configuration *info)
2085 {
2086         return ast_string_field_init(&info->recording, 32);
2087 }
2088
2089 static int init_media_configuration(struct ast_sip_endpoint_media_configuration *media)
2090 {
2091         return ast_string_field_init(media, 64) || ast_string_field_init(&media->rtp, 32);
2092 }
2093
2094 void *ast_sip_endpoint_alloc(const char *name)
2095 {
2096         struct ast_sip_endpoint *endpoint = ast_sorcery_generic_alloc(sizeof(*endpoint), endpoint_destructor);
2097         if (!endpoint) {
2098                 return NULL;
2099         }
2100         if (ast_string_field_init(endpoint, 64)) {
2101                 ao2_cleanup(endpoint);
2102                 return NULL;
2103         }
2104         if (!(endpoint->media.codecs = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT))) {
2105                 ao2_cleanup(endpoint);
2106                 return NULL;
2107         }
2108         if (init_subscription_configuration(&endpoint->subscription)) {
2109                 ao2_cleanup(endpoint);
2110                 return NULL;
2111         }
2112         if (init_info_configuration(&endpoint->info)) {
2113                 ao2_cleanup(endpoint);
2114                 return NULL;
2115         }
2116         if (init_media_configuration(&endpoint->media)) {
2117                 ao2_cleanup(endpoint);
2118                 return NULL;
2119         }
2120         ast_party_id_init(&endpoint->id.self);
2121
2122         if (AST_VECTOR_INIT(&endpoint->ident_method_order, 1)) {
2123                 return NULL;
2124         }
2125
2126         return endpoint;
2127 }
2128
2129 struct ao2_container *ast_sip_get_endpoints(void)
2130 {
2131         struct ao2_container *endpoints;
2132
2133         endpoints = ast_sorcery_retrieve_by_fields(sip_sorcery, "endpoint", AST_RETRIEVE_FLAG_MULTIPLE | AST_RETRIEVE_FLAG_ALL, NULL);
2134
2135         return endpoints;
2136 }
2137
2138 struct ast_sip_endpoint *ast_sip_default_outbound_endpoint(void)
2139 {
2140         RAII_VAR(char *, name, ast_sip_global_default_outbound_endpoint(), ast_free);
2141         return ast_strlen_zero(name) ? NULL : ast_sorcery_retrieve_by_id(
2142                 sip_sorcery, "endpoint", name);
2143 }
2144
2145 int ast_sip_retrieve_auths(const struct ast_sip_auth_vector *auths, struct ast_sip_auth **out)
2146 {
2147         int i;
2148
2149         for (i = 0; i < AST_VECTOR_SIZE(auths); ++i) {
2150                 /* Using AST_VECTOR_GET is safe since the vector is immutable */
2151                 const char *name = AST_VECTOR_GET(auths, i);
2152                 out[i] = ast_sorcery_retrieve_by_id(ast_sip_get_sorcery(), SIP_SORCERY_AUTH_TYPE, name);
2153                 if (!out[i]) {
2154                         ast_log(LOG_NOTICE, "Couldn't find auth '%s'. Cannot authenticate\n", name);
2155                         return -1;
2156                 }
2157         }
2158
2159         return 0;
2160 }
2161
2162 void ast_sip_cleanup_auths(struct ast_sip_auth *auths[], size_t num_auths)
2163 {
2164         int i;
2165         for (i = 0; i < num_auths; ++i) {
2166                 ao2_cleanup(auths[i]);
2167         }
2168 }
2169
2170 struct ast_sorcery *ast_sip_get_sorcery(void)
2171 {
2172         return sip_sorcery;
2173 }