Asterisk - The Open Source Telephony Project  18.5.0
pjsip_configuration.c
Go to the documentation of this file.
1 /*
2  * Asterisk -- An open source telephony toolkit.
3  *
4  * Copyright (C) 2013, Digium, Inc.
5  *
6  * Matt Jordan <[email protected]>
7  *
8  * See http://www.asterisk.org for more information about
9  * the Asterisk project. Please do not directly contact
10  * any of the maintainers of this project for assistance;
11  * the project provides a web site, mailing lists and IRC
12  * channels for your use.
13  *
14  * This program is free software, distributed under the terms of
15  * the GNU General Public License Version 2. See the LICENSE file
16  * at the top of the source tree.
17  */
18 
19 #include "asterisk.h"
20 
21 #include <pjsip.h>
22 #include <pjsip_ua.h>
23 
24 #include "asterisk/res_pjsip.h"
26 #include "asterisk/res_pjsip_cli.h"
27 #include "asterisk/acl.h"
28 #include "asterisk/manager.h"
29 #include "asterisk/astobj2.h"
30 #include "asterisk/utils.h"
31 #include "asterisk/sorcery.h"
32 #include "asterisk/callerid.h"
33 #include "asterisk/test.h"
34 #include "asterisk/statsd.h"
35 #include "asterisk/pbx.h"
36 #include "asterisk/stream.h"
37 #include "asterisk/stasis.h"
39 
40 /*! \brief Number of buckets for persistent endpoint information */
41 #define PERSISTENT_BUCKETS 53
42 
43 /*! \brief Persistent endpoint information */
45  /*! \brief Asterisk endpoint itself */
47 };
48 
49 /*! \brief Container for persistent endpoint information */
51 
52 static struct ast_sorcery *sip_sorcery;
53 
55 
56 /*! \brief Hashing function for persistent endpoint information */
57 static int persistent_endpoint_hash(const void *obj, const int flags)
58 {
59  const struct sip_persistent_endpoint *persistent = obj;
60  const char *id = (flags & OBJ_KEY ? obj : ast_endpoint_get_resource(persistent->endpoint));
61 
62  return ast_str_hash(id);
63 }
64 
65 /*! \brief Comparison function for persistent endpoint information */
66 static int persistent_endpoint_cmp(void *obj, void *arg, int flags)
67 {
68  const struct sip_persistent_endpoint *persistent1 = obj;
69  const struct sip_persistent_endpoint *persistent2 = arg;
70  const char *id = (flags & OBJ_KEY ? arg : ast_endpoint_get_resource(persistent2->endpoint));
71 
72  return !strcmp(ast_endpoint_get_resource(persistent1->endpoint), id) ? CMP_MATCH | CMP_STOP : 0;
73 }
74 
75 static void endpoint_deleted_observer(const void *object)
76 {
77  const struct ast_sip_endpoint *endpoint = object;
78 
79  ao2_find(persistent_endpoints, ast_endpoint_get_resource(endpoint->persistent),
81 }
82 
85 };
86 
87 static int endpoint_acl_handler(const struct aco_option *opt, struct ast_variable *var, void *obj)
88 {
89  struct ast_sip_endpoint *endpoint = obj;
90  int error = 0;
91  int ignore;
92 
93  if (ast_strlen_zero(var->value)) return 0;
94 
95  if (!strncmp(var->name, "contact_", 8)) {
96  ast_append_acl(var->name + 8, var->value, &endpoint->contact_acl, &error, &ignore);
97  } else {
98  ast_append_acl(var->name, var->value, &endpoint->acl, &error, &ignore);
99  }
100 
101  return error;
102 }
103 
104 static int acl_to_str(const void *obj, const intptr_t *args, char **buf)
105 {
106  const struct ast_sip_endpoint *endpoint = obj;
107  struct ast_acl_list *acl_list;
108  struct ast_acl *first_acl;
109 
110  if (endpoint && !ast_acl_list_is_empty(acl_list=endpoint->acl)) {
111  AST_LIST_LOCK(acl_list);
112  first_acl = AST_LIST_FIRST(acl_list);
113  if (ast_strlen_zero(first_acl->name)) {
114  *buf = "deny/permit";
115  } else {
116  *buf = first_acl->name;
117  }
118  AST_LIST_UNLOCK(acl_list);
119  }
120 
121  *buf = ast_strdup(*buf);
122  return 0;
123 }
124 
125 static int contact_acl_to_str(const void *obj, const intptr_t *args, char **buf)
126 {
127  const struct ast_sip_endpoint *endpoint = obj;
128  struct ast_acl_list *acl_list;
129  struct ast_acl *first_acl;
130 
131  if (endpoint && !ast_acl_list_is_empty(acl_list=endpoint->contact_acl)) {
132  AST_LIST_LOCK(acl_list);
133  first_acl = AST_LIST_FIRST(acl_list);
134  if (ast_strlen_zero(first_acl->name)) {
135  *buf = "deny/permit";
136  } else {
137  *buf = first_acl->name;
138  }
139  AST_LIST_UNLOCK(acl_list);
140  }
141 
142  *buf = ast_strdup(*buf);
143  return 0;
144 }
145 
146 static int dtmf_handler(const struct aco_option *opt, struct ast_variable *var, void *obj)
147 {
148  struct ast_sip_endpoint *endpoint = obj;
149  int dtmf = ast_sip_str_to_dtmf(var->value);
150 
151  if (dtmf == -1) {
152  return -1;
153  }
154 
155  endpoint->dtmf = dtmf;
156  return 0;
157 }
158 
159 static int dtmf_to_str(const void *obj, const intptr_t *args, char **buf)
160 {
161  const struct ast_sip_endpoint *endpoint = obj;
162  char dtmf_str[20];
163  int result = -1;
164 
165  result = ast_sip_dtmf_to_str(endpoint->dtmf, dtmf_str, sizeof(dtmf_str));
166 
167  if (result == 0) {
168  *buf = ast_strdup(dtmf_str);
169  } else {
170  *buf = ast_strdup("none");
171  }
172  return 0;
173 }
174 
175 static int prack_handler(const struct aco_option *opt, struct ast_variable *var, void *obj)
176 {
177  struct ast_sip_endpoint *endpoint = obj;
178 
179  /* clear all */
180  endpoint->extensions.flags &= ~(PJSIP_INV_SUPPORT_100REL | PJSIP_INV_REQUIRE_100REL);
181 
182  if (ast_true(var->value)) {
183  endpoint->extensions.flags |= PJSIP_INV_SUPPORT_100REL;
184  } else if (!strcasecmp(var->value, "required")) {
185  endpoint->extensions.flags |= PJSIP_INV_REQUIRE_100REL;
186  } else if (!ast_false(var->value)){
187  return -1;
188  }
189 
190  return 0;
191 }
192 
193 static int prack_to_str(const void *obj, const intptr_t *args, char **buf)
194 {
195  const struct ast_sip_endpoint *endpoint = obj;
196 
197  if (endpoint->extensions.flags & PJSIP_INV_REQUIRE_100REL) {
198  *buf = "required";
199  } else if (endpoint->extensions.flags & PJSIP_INV_SUPPORT_100REL) {
200  *buf = "yes";
201  } else {
202  *buf = "no";
203  }
204 
205  *buf = ast_strdup(*buf);
206  return 0;
207 }
208 
209 static int timers_handler(const struct aco_option *opt, struct ast_variable *var, void *obj)
210 {
211  struct ast_sip_endpoint *endpoint = obj;
212 
213  /* clear all */
214  endpoint->extensions.flags &= ~(PJSIP_INV_SUPPORT_TIMER | PJSIP_INV_REQUIRE_TIMER
215  | PJSIP_INV_ALWAYS_USE_TIMER);
216 
217  /* set only the specified flag and let pjsip normalize if needed */
218  if (ast_true(var->value)) {
219  endpoint->extensions.flags |= PJSIP_INV_SUPPORT_TIMER;
220  } else if (!strcasecmp(var->value, "required")) {
221  endpoint->extensions.flags |= PJSIP_INV_REQUIRE_TIMER;
222  } else if (!strcasecmp(var->value, "always") || !strcasecmp(var->value, "forced")) {
223  endpoint->extensions.flags |= PJSIP_INV_ALWAYS_USE_TIMER;
224  } else if (!ast_false(var->value)) {
225  return -1;
226  }
227 
228  return 0;
229 }
230 
231 static int timers_to_str(const void *obj, const intptr_t *args, char **buf)
232 {
233  const struct ast_sip_endpoint *endpoint = obj;
234 
235  if (endpoint->extensions.flags & PJSIP_INV_ALWAYS_USE_TIMER) {
236  *buf = "always";
237  } else if (endpoint->extensions.flags & PJSIP_INV_REQUIRE_TIMER) {
238  *buf = "required";
239  } else if (endpoint->extensions.flags & PJSIP_INV_SUPPORT_TIMER) {
240  *buf = "yes";
241  } else {
242  *buf = "no";
243  }
244 
245  *buf = ast_strdup(*buf);
246  return 0;
247 }
248 
250 {
251  int i;
252  size_t size;
253 
254  if (!auths) {
255  return;
256  }
257 
258  size = AST_VECTOR_SIZE(auths);
259 
260  for (i = 0; i < size; ++i) {
261  const char *name = AST_VECTOR_REMOVE_UNORDERED(auths, 0);
262  ast_free((char *) name);
263  }
264  AST_VECTOR_FREE(auths);
265 }
266 
267 int ast_sip_auth_vector_init(struct ast_sip_auth_vector *auths, const char *value)
268 {
269  char *auth_names = ast_strdupa(value);
270  char *val;
271 
272  ast_assert(auths != NULL);
273 
274  if (AST_VECTOR_SIZE(auths)) {
276  }
277  if (AST_VECTOR_INIT(auths, 1)) {
278  return -1;
279  }
280 
281  while ((val = ast_strip(strsep(&auth_names, ",")))) {
282  if (ast_strlen_zero(val)) {
283  continue;
284  }
285 
286  val = ast_strdup(val);
287  if (!val) {
288  goto failure;
289  }
290  if (AST_VECTOR_APPEND(auths, val)) {
291  ast_free(val);
292 
293  goto failure;
294  }
295  }
296  return 0;
297 
298 failure:
300  return -1;
301 }
302 
303 static int inbound_auth_handler(const struct aco_option *opt, struct ast_variable *var, void *obj)
304 {
305  struct ast_sip_endpoint *endpoint = obj;
306 
307  return ast_sip_auth_vector_init(&endpoint->inbound_auths, var->value);
308 }
309 
310 static int outbound_auth_handler(const struct aco_option *opt, struct ast_variable *var, void *obj)
311 {
312  struct ast_sip_endpoint *endpoint = obj;
313 
314  return ast_sip_auth_vector_init(&endpoint->outbound_auths, var->value);
315 }
316 
317 int ast_sip_auths_to_str(const struct ast_sip_auth_vector *auths, char **buf)
318 {
319  if (!auths || !AST_VECTOR_SIZE(auths)) {
320  return 0;
321  }
322 
323  if (!(*buf = ast_calloc(MAX_OBJECT_FIELD, sizeof(char)))) {
324  return -1;
325  }
326 
327  /* I feel like accessing the vector's elem array directly is cheating...*/
328  ast_join_delim(*buf, MAX_OBJECT_FIELD, auths->elems, AST_VECTOR_SIZE(auths), ',');
329  return 0;
330 }
331 
332 static int inbound_auths_to_str(const void *obj, const intptr_t *args, char **buf)
333 {
334  const struct ast_sip_endpoint *endpoint = obj;
335  return ast_sip_auths_to_str(&endpoint->inbound_auths, buf);
336 }
337 
338 static int outbound_auths_to_str(const void *obj, const intptr_t *args, char **buf)
339 {
340  const struct ast_sip_endpoint *endpoint = obj;
341  return ast_sip_auths_to_str(&endpoint->outbound_auths, buf);
342 }
343 
344 /*!
345  * \internal
346  * \brief Convert identify_by method to string.
347  *
348  * \param method Method value to convert to string
349  *
350  * \return String representation.
351  */
353 {
354  const char *str = "<unknown>";
355 
356  switch (method) {
358  str = "username";
359  break;
361  str = "auth_username";
362  break;
364  str = "ip";
365  break;
367  str = "header";
368  break;
369  }
370  return str;
371 }
372 
373 /*!
374  * \internal
375  * \brief Convert string to an endpoint identifier token.
376  *
377  * \param str String to convert
378  *
379  * \retval enum ast_sip_endpoint_identifier_type token value on success.
380  * \retval -1 on failure.
381  */
382 static int sip_endpoint_identifier_str2type(const char *str)
383 {
384  int method;
385 
386  if (!strcasecmp(str, "username")) {
388  } else if (!strcasecmp(str, "auth_username")) {
390  } else if (!strcasecmp(str, "ip")) {
392  } else if (!strcasecmp(str, "header")) {
394  } else {
395  method = -1;
396  }
397  return method;
398 }
399 
400 static int ident_handler(const struct aco_option *opt, struct ast_variable *var, void *obj)
401 {
402  struct ast_sip_endpoint *endpoint = obj;
403  char *idents = ast_strdupa(var->value);
404  char *val;
405  int method;
406 
407  /*
408  * If there's already something in the vector when we get here,
409  * it's the default value so we need to clean it out.
410  */
411  if (AST_VECTOR_SIZE(&endpoint->ident_method_order)) {
413  endpoint->ident_method = 0;
414  }
415 
416  while ((val = ast_strip(strsep(&idents, ",")))) {
417  if (ast_strlen_zero(val)) {
418  continue;
419  }
420 
421  method = sip_endpoint_identifier_str2type(val);
422  if (method == -1) {
423  ast_log(LOG_ERROR, "Unrecognized identification method %s specified for endpoint %s\n",
424  val, ast_sorcery_object_get_id(endpoint));
426  endpoint->ident_method = 0;
427  return -1;
428  }
429  if (endpoint->ident_method & method) {
430  /* We are already indentifying by this method. No need to do it again. */
431  continue;
432  }
433 
434  endpoint->ident_method |= method;
435  AST_VECTOR_APPEND(&endpoint->ident_method_order, method);
436  }
437 
438  return 0;
439 }
440 
441 static int ident_to_str(const void *obj, const intptr_t *args, char **buf)
442 {
443  const struct ast_sip_endpoint *endpoint = obj;
444  int methods;
445  int idx;
446  int buf_used = 0;
447  int buf_size = MAX_OBJECT_FIELD;
448 
449  methods = AST_VECTOR_SIZE(&endpoint->ident_method_order);
450  if (!methods) {
451  return 0;
452  }
453 
454  *buf = ast_malloc(buf_size);
455  if (!*buf) {
456  return -1;
457  }
458 
459  for (idx = 0; idx < methods; ++idx) {
461  const char *method_str;
462 
463  method = AST_VECTOR_GET(&endpoint->ident_method_order, idx);
464  method_str = sip_endpoint_identifier_type2str(method);
465 
466  /* Should never have an "<unknown>" method string */
467  ast_assert(strcmp(method_str, "<unknown>"));
468  if (!strcmp(method_str, "<unknown>")) {
469  continue;
470  }
471 
472  buf_used += snprintf(*buf + buf_used, buf_size - buf_used, "%s%s",
473  method_str, idx < methods - 1 ? "," : "");
474  if (buf_size <= buf_used) {
475  /* Need more room than available, truncating. */
476  *(*buf + (buf_size - 1)) = '\0';
477  ast_log(LOG_WARNING, "Truncated identify_by string: %s\n", *buf);
478  break;
479  }
480  }
481 
482  return 0;
483 }
484 
485 static int redirect_handler(const struct aco_option *opt, struct ast_variable *var, void *obj)
486 {
487  struct ast_sip_endpoint *endpoint = obj;
488 
489  if (!strcasecmp(var->value, "user")) {
491  } else if (!strcasecmp(var->value, "uri_core")) {
493  } else if (!strcasecmp(var->value, "uri_pjsip")) {
495  } else {
496  ast_log(LOG_ERROR, "Unrecognized redirect method %s specified for endpoint %s\n",
497  var->value, ast_sorcery_object_get_id(endpoint));
498  return -1;
499  }
500 
501  return 0;
502 }
503 
504 static int direct_media_method_handler(const struct aco_option *opt, struct ast_variable *var, void *obj)
505 {
506  struct ast_sip_endpoint *endpoint = obj;
507 
508  if (!strcasecmp(var->value, "invite") || !strcasecmp(var->value, "reinvite")) {
510  } else if (!strcasecmp(var->value, "update")) {
512  } else {
513  ast_log(LOG_NOTICE, "Unrecognized option value %s for %s on endpoint %s\n",
514  var->value, var->name, ast_sorcery_object_get_id(endpoint));
515  return -1;
516  }
517  return 0;
518 }
519 
520 static const char *id_configuration_refresh_methods[] = {
523 };
524 
525 static int direct_media_method_to_str(const void *obj, const intptr_t *args, char **buf)
526 {
527  const struct ast_sip_endpoint *endpoint = obj;
530  }
531  return 0;
532 }
533 
534 static int connected_line_method_handler(const struct aco_option *opt, struct ast_variable *var, void *obj)
535 {
536  struct ast_sip_endpoint *endpoint = obj;
537 
538  if (!strcasecmp(var->value, "invite") || !strcasecmp(var->value, "reinvite")) {
540  } else if (!strcasecmp(var->value, "update")) {
542  } else {
543  ast_log(LOG_NOTICE, "Unrecognized option value %s for %s on endpoint %s\n",
544  var->value, var->name, ast_sorcery_object_get_id(endpoint));
545  return -1;
546  }
547  return 0;
548 }
549 
550 static int connected_line_method_to_str(const void *obj, const intptr_t *args, char **buf)
551 {
552  const struct ast_sip_endpoint *endpoint = obj;
554  return 0;
555 }
556 
557 static int direct_media_glare_mitigation_handler(const struct aco_option *opt, struct ast_variable *var, void *obj)
558 {
559  struct ast_sip_endpoint *endpoint = obj;
560 
561  if (!strcasecmp(var->value, "none")) {
563  } else if (!strcasecmp(var->value, "outgoing")) {
565  } else if (!strcasecmp(var->value, "incoming")) {
567  } else {
568  ast_log(LOG_NOTICE, "Unrecognized option value %s for %s on endpoint %s\n",
569  var->value, var->name, ast_sorcery_object_get_id(endpoint));
570  return -1;
571  }
572 
573  return 0;
574 }
575 
576 static const char *direct_media_glare_mitigation_map[] = {
580 };
581 
582 static int direct_media_glare_mitigation_to_str(const void *obj, const intptr_t *args, char **buf)
583 {
584  const struct ast_sip_endpoint *endpoint = obj;
587  }
588 
589  return 0;
590 }
591 
592 static int caller_id_handler(const struct aco_option *opt, struct ast_variable *var, void *obj)
593 {
594  struct ast_sip_endpoint *endpoint = obj;
595  char cid_name[80] = { '\0' };
596  char cid_num[80] = { '\0' };
597 
598  ast_free(endpoint->id.self.name.str);
599  endpoint->id.self.name.str = NULL;
600  endpoint->id.self.name.valid = 0;
601  ast_free(endpoint->id.self.number.str);
602  endpoint->id.self.number.str = NULL;
603  endpoint->id.self.number.valid = 0;
604 
605  ast_callerid_split(var->value, cid_name, sizeof(cid_name), cid_num, sizeof(cid_num));
606  if (!ast_strlen_zero(cid_name)) {
607  endpoint->id.self.name.str = ast_strdup(cid_name);
608  if (!endpoint->id.self.name.str) {
609  return -1;
610  }
611  endpoint->id.self.name.valid = 1;
612  }
613  if (!ast_strlen_zero(cid_num)) {
614  endpoint->id.self.number.str = ast_strdup(cid_num);
615  if (!endpoint->id.self.number.str) {
616  return -1;
617  }
618  endpoint->id.self.number.valid = 1;
619  }
620  return 0;
621 }
622 
623 static int caller_id_to_str(const void *obj, const intptr_t *args, char **buf)
624 {
625  const struct ast_sip_endpoint *endpoint = obj;
626  const char *name = S_COR(endpoint->id.self.name.valid,
627  endpoint->id.self.name.str, NULL);
628  const char *number = S_COR(endpoint->id.self.number.valid,
629  endpoint->id.self.number.str, NULL);
630 
631  /* make sure size is at least 10 - that should cover the "<unknown>"
632  case as well as any additional formatting characters added in
633  the name and/or number case. */
634  int size = 10;
635  size += name ? strlen(name) : 0;
636  size += number ? strlen(number) : 0;
637 
638  if (!(*buf = ast_calloc(size + 1, sizeof(char)))) {
639  return -1;
640  }
641 
642  ast_callerid_merge(*buf, size + 1, name, number, NULL);
643  return 0;
644 }
645 
646 static int caller_id_privacy_handler(const struct aco_option *opt, struct ast_variable *var, void *obj)
647 {
648  struct ast_sip_endpoint *endpoint = obj;
649  int callingpres = ast_parse_caller_presentation(var->value);
650  if (callingpres == -1 && sscanf(var->value, "%d", &callingpres) != 1) {
651  return -1;
652  }
653  endpoint->id.self.number.presentation = callingpres;
654  endpoint->id.self.name.presentation = callingpres;
655  return 0;
656 }
657 
658 static int caller_id_privacy_to_str(const void *obj, const intptr_t *args, char **buf)
659 {
660  const struct ast_sip_endpoint *endpoint = obj;
661  const char *presentation = ast_named_caller_presentation(
662  endpoint->id.self.name.presentation);
663 
664  *buf = ast_strdup(presentation);
665  return 0;
666 }
667 
668 static int caller_id_tag_handler(const struct aco_option *opt, struct ast_variable *var, void *obj)
669 {
670  struct ast_sip_endpoint *endpoint = obj;
671 
672  ast_free(endpoint->id.self.tag);
673  endpoint->id.self.tag = ast_strdup(var->value);
674 
675  return endpoint->id.self.tag ? 0 : -1;
676 }
677 
678 static int caller_id_tag_to_str(const void *obj, const intptr_t *args, char **buf)
679 {
680  const struct ast_sip_endpoint *endpoint = obj;
681  *buf = ast_strdup(endpoint->id.self.tag);
682  return 0;
683 }
684 
685 static int media_encryption_handler(const struct aco_option *opt, struct ast_variable *var, void *obj)
686 {
687  struct ast_sip_endpoint *endpoint = obj;
688 
689  if (!strcasecmp("no", var->value)) {
691  } else if (!strcasecmp("sdes", var->value)) {
693  } else if (!strcasecmp("dtls", var->value)) {
695  return ast_rtp_dtls_cfg_parse(&endpoint->media.rtp.dtls_cfg, "dtlsenable", "yes");
696  } else {
697  return -1;
698  }
699 
700  return 0;
701 }
702 
703 static const char *media_encryption_map[] = {
704  [AST_SIP_MEDIA_TRANSPORT_INVALID] = "invalid",
706  [AST_SIP_MEDIA_ENCRYPT_SDES] = "sdes",
707  [AST_SIP_MEDIA_ENCRYPT_DTLS] = "dtls",
708 };
709 
710 static int media_encryption_to_str(const void *obj, const intptr_t *args, char **buf)
711 {
712  const struct ast_sip_endpoint *endpoint = obj;
715  endpoint->media.rtp.encryption]);
716  }
717  return 0;
718 }
719 
720 static int group_handler(const struct aco_option *opt,
721  struct ast_variable *var, void *obj)
722 {
723  struct ast_sip_endpoint *endpoint = obj;
724 
725  if (!strncmp(var->name, "call_group", 10)) {
726  endpoint->pickup.callgroup = ast_get_group(var->value);
727  } else if (!strncmp(var->name, "pickup_group", 12)) {
728  endpoint->pickup.pickupgroup = ast_get_group(var->value);
729  } else {
730  return -1;
731  }
732 
733  return 0;
734 }
735 
736 static int callgroup_to_str(const void *obj, const intptr_t *args, char **buf)
737 {
738  const struct ast_sip_endpoint *endpoint = obj;
739 
740  if (!(*buf = ast_calloc(MAX_OBJECT_FIELD, sizeof(char)))) {
741  return -1;
742  }
743 
745  return 0;
746 }
747 
748 static int pickupgroup_to_str(const void *obj, const intptr_t *args, char **buf)
749 {
750  const struct ast_sip_endpoint *endpoint = obj;
751 
752  if (!(*buf = ast_calloc(MAX_OBJECT_FIELD, sizeof(char)))) {
753  return -1;
754  }
755 
757  return 0;
758 }
759 
760 static int named_groups_handler(const struct aco_option *opt,
761  struct ast_variable *var, void *obj)
762 {
763  struct ast_sip_endpoint *endpoint = obj;
764 
765  if (!strncmp(var->name, "named_call_group", 16)) {
766  if (ast_strlen_zero(var->value)) {
767  endpoint->pickup.named_callgroups =
769  } else if (!(endpoint->pickup.named_callgroups =
770  ast_get_namedgroups(var->value))) {
771  return -1;
772  }
773  } else if (!strncmp(var->name, "named_pickup_group", 18)) {
774  if (ast_strlen_zero(var->value)) {
775  endpoint->pickup.named_pickupgroups =
777  } else if (!(endpoint->pickup.named_pickupgroups =
778  ast_get_namedgroups(var->value))) {
779  return -1;
780  }
781  } else {
782  return -1;
783  }
784 
785  return 0;
786 }
787 
788 static int named_callgroups_to_str(const void *obj, const intptr_t *args, char **buf)
789 {
790  const struct ast_sip_endpoint *endpoint = obj;
792 
794  *buf = ast_strdup(ast_str_buffer(str));
795  return 0;
796 }
797 
798 static int named_pickupgroups_to_str(const void *obj, const intptr_t *args, char **buf)
799 {
800  const struct ast_sip_endpoint *endpoint = obj;
802 
804  *buf = ast_strdup(ast_str_buffer(str));
805  return 0;
806 }
807 
808 static int dtls_handler(const struct aco_option *opt,
809  struct ast_variable *var, void *obj)
810 {
811  struct ast_sip_endpoint *endpoint = obj;
812  char *name = ast_strdupa(var->name);
813  char *front = NULL;
814  char *back = NULL;
815  char *buf = name;
816 
817  /* strip out underscores in the name */
818  front = strtok_r(buf, "_", &back);
819  while (front) {
820  int size = strlen(front);
821  ast_copy_string(buf, front, size + 1);
822  buf += size;
823  front = strtok_r(NULL, "_", &back);
824  }
825 
826  return ast_rtp_dtls_cfg_parse(&endpoint->media.rtp.dtls_cfg, name, var->value);
827 }
828 
829 static int dtlsverify_to_str(const void *obj, const intptr_t *args, char **buf)
830 {
831  const struct ast_sip_endpoint *endpoint = obj;
832  *buf = ast_strdup(AST_YESNO(endpoint->media.rtp.dtls_cfg.verify));
833  return 0;
834 }
835 
836 static int dtlsrekey_to_str(const void *obj, const intptr_t *args, char **buf)
837 {
838  const struct ast_sip_endpoint *endpoint = obj;
839 
840  return ast_asprintf(
841  buf, "%u", endpoint->media.rtp.dtls_cfg.rekey) >=0 ? 0 : -1;
842 }
843 
844 static int dtlsautogeneratecert_to_str(const void *obj, const intptr_t *args, char **buf)
845 {
846  const struct ast_sip_endpoint *endpoint = obj;
848  return 0;
849 }
850 
851 static int dtlscertfile_to_str(const void *obj, const intptr_t *args, char **buf)
852 {
853  const struct ast_sip_endpoint *endpoint = obj;
854  *buf = ast_strdup(endpoint->media.rtp.dtls_cfg.certfile);
855  return 0;
856 }
857 
858 static int dtlsprivatekey_to_str(const void *obj, const intptr_t *args, char **buf)
859 {
860  const struct ast_sip_endpoint *endpoint = obj;
861  *buf = ast_strdup(endpoint->media.rtp.dtls_cfg.pvtfile);
862  return 0;
863 }
864 
865 static int dtlscipher_to_str(const void *obj, const intptr_t *args, char **buf)
866 {
867  const struct ast_sip_endpoint *endpoint = obj;
868  *buf = ast_strdup(endpoint->media.rtp.dtls_cfg.cipher);
869  return 0;
870 }
871 
872 static int dtlscafile_to_str(const void *obj, const intptr_t *args, char **buf)
873 {
874  const struct ast_sip_endpoint *endpoint = obj;
875  *buf = ast_strdup(endpoint->media.rtp.dtls_cfg.cafile);
876  return 0;
877 }
878 
879 static int dtlscapath_to_str(const void *obj, const intptr_t *args, char **buf)
880 {
881  const struct ast_sip_endpoint *endpoint = obj;
882  *buf = ast_strdup(endpoint->media.rtp.dtls_cfg.capath);
883  return 0;
884 }
885 
886 static const char *ast_rtp_dtls_setup_map[] = {
887  [AST_RTP_DTLS_SETUP_ACTIVE] = "active",
888  [AST_RTP_DTLS_SETUP_PASSIVE] = "passive",
889  [AST_RTP_DTLS_SETUP_ACTPASS] = "actpass",
890  [AST_RTP_DTLS_SETUP_HOLDCONN] = "holdconn",
891 };
892 
893 static int dtlssetup_to_str(const void *obj, const intptr_t *args, char **buf)
894 {
895  const struct ast_sip_endpoint *endpoint = obj;
898  }
899  return 0;
900 }
901 
902 static const char *ast_rtp_dtls_fingerprint_map[] = {
903  [AST_RTP_DTLS_HASH_SHA256] = "SHA-256",
904  [AST_RTP_DTLS_HASH_SHA1] = "SHA-1",
905 };
906 
907 static int dtlsfingerprint_to_str(const void *obj, const intptr_t *args, char **buf)
908 {
909  const struct ast_sip_endpoint *endpoint = obj;
912  }
913  return 0;
914 }
915 
916 static int t38udptl_ec_handler(const struct aco_option *opt,
917  struct ast_variable *var, void *obj)
918 {
919  struct ast_sip_endpoint *endpoint = obj;
920 
921  if (!strcmp(var->value, "none")) {
923  } else if (!strcmp(var->value, "fec")) {
925  } else if (!strcmp(var->value, "redundancy")) {
927  } else {
928  return -1;
929  }
930 
931  return 0;
932 }
933 
934 static const char *ast_t38_ec_modes_map[] = {
935  [UDPTL_ERROR_CORRECTION_NONE] = "none",
936  [UDPTL_ERROR_CORRECTION_FEC] = "fec",
937  [UDPTL_ERROR_CORRECTION_REDUNDANCY] = "redundancy"
938 };
939 
940 static int t38udptl_ec_to_str(const void *obj, const intptr_t *args, char **buf)
941 {
942  const struct ast_sip_endpoint *endpoint = obj;
945  endpoint->media.t38.error_correction]);
946  }
947  return 0;
948 }
949 
950 static int tos_handler(const struct aco_option *opt,
951  struct ast_variable *var, void *obj)
952 {
953  struct ast_sip_endpoint *endpoint = obj;
954  unsigned int value;
955 
956  if (ast_str2tos(var->value, &value)) {
957  ast_log(LOG_ERROR, "Error configuring endpoint '%s' - Could not "
958  "interpret '%s' value '%s'\n",
959  ast_sorcery_object_get_id(endpoint), var->name, var->value);
960  return -1;
961  }
962 
963  if (!strcmp(var->name, "tos_audio")) {
964  endpoint->media.tos_audio = value;
965  } else if (!strcmp(var->name, "tos_video")) {
966  endpoint->media.tos_video = value;
967  } else {
968  /* If we reach this point, someone called the tos_handler when they shouldn't have. */
969  ast_assert(0);
970  return -1;
971  }
972  return 0;
973 }
974 
975 static int tos_audio_to_str(const void *obj, const intptr_t *args, char **buf)
976 {
977  const struct ast_sip_endpoint *endpoint = obj;
978 
979  if (ast_asprintf(buf, "%u", endpoint->media.tos_audio) == -1) {
980  return -1;
981  }
982  return 0;
983 }
984 
985 static int tos_video_to_str(const void *obj, const intptr_t *args, char **buf)
986 {
987  const struct ast_sip_endpoint *endpoint = obj;
988 
989  if (ast_asprintf(buf, "%u", endpoint->media.tos_video) == -1) {
990  return -1;
991  }
992  return 0;
993 }
994 
995 static int from_user_handler(const struct aco_option *opt,
996  struct ast_variable *var, void *obj)
997 {
998  struct ast_sip_endpoint *endpoint = obj;
999  /* Valid non-alphanumeric characters for URI */
1000  char *valid_uri_marks = "-._~%!$&'()*+,;=:";
1001  const char *val;
1002 
1003  for (val = var->value; *val; val++) {
1004  if (!isalpha(*val) && !isdigit(*val) && !strchr(valid_uri_marks, *val)) {
1005  ast_log(LOG_ERROR, "Error configuring endpoint '%s' - '%s' field "
1006  "contains invalid character '%c'\n",
1007  ast_sorcery_object_get_id(endpoint), var->name, *val);
1008  return -1;
1009  }
1010  }
1011 
1012  ast_string_field_set(endpoint, fromuser, var->value);
1013 
1014  return 0;
1015 }
1016 
1017 static int from_user_to_str(const void *obj, const intptr_t *args, char **buf)
1018 {
1019  const struct ast_sip_endpoint *endpoint = obj;
1020 
1021  *buf = ast_strdup(endpoint->fromuser);
1022 
1023  return 0;
1024 }
1025 
1026 static int set_var_handler(const struct aco_option *opt,
1027  struct ast_variable *var, void *obj)
1028 {
1029  struct ast_sip_endpoint *endpoint = obj;
1030  struct ast_variable *new_var;
1031  char *name;
1032  char *val;
1033 
1034  if (ast_strlen_zero(var->value)) {
1035  return 0;
1036  }
1037 
1038  name = ast_strdupa(var->value);
1039  val = strchr(name, '=');
1040 
1041  if (!val) {
1042  return -1;
1043  }
1044 
1045  *val++ = '\0';
1046 
1047  if (!(new_var = ast_variable_new(name, val, ""))) {
1048  return -1;
1049  }
1050 
1051  if (ast_variable_list_replace(&endpoint->channel_vars, new_var)) {
1052  ast_variable_list_append(&endpoint->channel_vars, new_var);
1053  }
1054 
1055  return 0;
1056 }
1057 
1058 static int set_var_to_str(const void *obj, const intptr_t *args, char **buf)
1059 {
1061  const struct ast_sip_endpoint *endpoint = obj;
1062  struct ast_variable *var;
1063 
1064  for (var = endpoint->channel_vars; var; var = var->next) {
1065  ast_str_append(&str, 0, "%s=%s,", var->name, var->value);
1066  }
1067 
1068  *buf = ast_strdup(ast_str_truncate(str, -1));
1069  ast_free(str);
1070  return 0;
1071 }
1072 
1073 static int set_var_to_vl(const void *obj, struct ast_variable **fields)
1074 {
1075  const struct ast_sip_endpoint *endpoint = obj;
1076  if (endpoint->channel_vars) {
1077  *fields = ast_variables_dup(endpoint->channel_vars);
1078  }
1079  return 0;
1080 }
1081 
1082 static int voicemail_extension_handler(const struct aco_option *opt, struct ast_variable *var, void *obj)
1083 {
1084  struct ast_sip_endpoint *endpoint = obj;
1085 
1088 
1089  return endpoint->subscription.mwi.voicemail_extension ? 0 : -1;
1090 }
1091 
1092 static int voicemail_extension_to_str(const void *obj, const intptr_t *args, char **buf)
1093 {
1094  const struct ast_sip_endpoint *endpoint = obj;
1095 
1096  *buf = ast_strdup(endpoint->subscription.mwi.voicemail_extension);
1097 
1098  return 0;
1099 }
1100 
1101 static int contact_user_handler(const struct aco_option *opt,
1102  struct ast_variable *var, void *obj)
1103 {
1104  struct ast_sip_endpoint *endpoint = obj;
1105 
1106  ast_free(endpoint->contact_user);
1107  endpoint->contact_user = ast_strdup(var->value);
1108 
1109  return endpoint->contact_user ? 0 : -1;
1110 }
1111 
1112 static int contact_user_to_str(const void *obj, const intptr_t *args, char **buf)
1113 {
1114  const struct ast_sip_endpoint *endpoint = obj;
1115 
1116  *buf = ast_strdup(endpoint->contact_user);
1117  if (!(*buf)) {
1118  return -1;
1119  }
1120 
1121  return 0;
1122 }
1123 
1124 static int call_offer_pref_handler(const struct aco_option *opt,
1125  struct ast_variable *var, void *obj)
1126 {
1127  struct ast_sip_endpoint *endpoint = obj;
1128  struct ast_flags pref = { 0, };
1129  int outgoing = strcmp(var->name, "outgoing_call_offer_pref") == 0;
1130 
1131  int res = ast_sip_call_codec_str_to_pref(&pref, var->value, outgoing);
1132  if (res != 0) {
1133  return -1;
1134  }
1135 
1136  if (outgoing) {
1137  endpoint->media.outgoing_call_offer_pref = pref;
1138  } else {
1139  endpoint->media.incoming_call_offer_pref = pref;
1140  }
1141 
1142  return 0;
1143 }
1144 
1145 static int incoming_call_offer_pref_to_str(const void *obj, const intptr_t *args, char **buf)
1146 {
1147  const struct ast_sip_endpoint *endpoint = obj;
1148 
1150  if (!(*buf)) {
1151  return -1;
1152  }
1153 
1154  return 0;
1155 }
1156 
1157 static int outgoing_call_offer_pref_to_str(const void *obj, const intptr_t *args, char **buf)
1158 {
1159  const struct ast_sip_endpoint *endpoint = obj;
1160 
1162  if (!(*buf)) {
1163  return -1;
1164  }
1165 
1166  return 0;
1167 }
1168 
1169 static int codec_prefs_handler(const struct aco_option *opt,
1170  struct ast_variable *var, void *obj)
1171 {
1172  struct ast_sip_endpoint *endpoint = obj;
1173  struct ast_stream_codec_negotiation_prefs *option_prefs;
1175  struct ast_str *error_message = ast_str_create(128);
1178  int res = 0;
1179 
1180  res = ast_stream_codec_prefs_parse(var->value, &prefs, &error_message);
1181  if (res < 0) {
1182  ast_log(LOG_ERROR, "Endpoint '%s': %s for option '%s'\n",
1183  ast_sorcery_object_get_id(endpoint), ast_str_buffer(error_message), var->name);
1184  ast_free(error_message);
1185  return -1;
1186  }
1187  ast_free(error_message);
1188 
1189  if (strcmp(var->name, "codec_prefs_incoming_offer") == 0) {
1191  ast_log(LOG_ERROR, "Endpoint '%s': Codec preference '%s' has invalid value '%s' for option: '%s'",
1192  ast_sorcery_object_get_id(endpoint),
1195  var->name);
1196  return -1;
1197  }
1198  option_prefs = &endpoint->media.codec_prefs_incoming_offer;
1199  default_prefer = CODEC_NEGOTIATION_PREFER_PENDING;
1200  default_operation = CODEC_NEGOTIATION_OPERATION_INTERSECT;
1201  } else if (strcmp(var->name, "codec_prefs_outgoing_offer") == 0) {
1202  option_prefs = &endpoint->media.codec_prefs_outgoing_offer;
1203  default_prefer = CODEC_NEGOTIATION_PREFER_PENDING;
1204  default_operation = CODEC_NEGOTIATION_OPERATION_UNION;
1205  } else if (strcmp(var->name, "codec_prefs_incoming_answer") == 0) {
1206  option_prefs = &endpoint->media.codec_prefs_incoming_answer;
1207  default_prefer = CODEC_NEGOTIATION_PREFER_PENDING;
1208  default_operation = CODEC_NEGOTIATION_OPERATION_INTERSECT;
1209  } else if (strcmp(var->name, "codec_prefs_outgoing_answer") == 0) {
1210  option_prefs = &endpoint->media.codec_prefs_outgoing_answer;
1211  default_prefer = CODEC_NEGOTIATION_PREFER_PENDING;
1212  default_operation = CODEC_NEGOTIATION_OPERATION_INTERSECT;
1213  } else {
1214  ast_log(LOG_ERROR, "Endpoint '%s': Unsupported option '%s'\n",
1215  ast_sorcery_object_get_id(endpoint),
1216  var->name);
1217  return -1;
1218  }
1219 
1221  prefs.prefer = default_prefer;
1222  }
1223 
1225  prefs.operation = default_operation;
1226  }
1227 
1230  }
1231 
1234  }
1235 
1236  /* Now that defaults have been applied as needed we apply the full codec
1237  * preference configuration to the option.
1238  */
1239  *option_prefs = prefs;
1240 
1241  return 0;
1242 }
1243 
1245  const void *obj, const intptr_t *args, char **buf)
1246 {
1248 
1249  if (!codecs) {
1250  return -1;
1251  }
1252 
1253  *buf = ast_strdup(ast_stream_codec_prefs_to_str(prefs, &codecs));
1254  ast_free(codecs);
1255 
1256  return 0;
1257 }
1258 
1259 static int incoming_offer_codec_prefs_to_str(const void *obj, const intptr_t *args, char **buf)
1260 {
1261  const struct ast_sip_endpoint *endpoint = obj;
1262  return codec_prefs_to_str(&endpoint->media.codec_prefs_incoming_offer, obj, args, buf);
1263 }
1264 
1265 static int outgoing_offer_codec_prefs_to_str(const void *obj, const intptr_t *args, char **buf)
1266 {
1267  const struct ast_sip_endpoint *endpoint = obj;
1268  return codec_prefs_to_str(&endpoint->media.codec_prefs_outgoing_offer, obj, args, buf);
1269 }
1270 
1271 static int incoming_answer_codec_prefs_to_str(const void *obj, const intptr_t *args, char **buf)
1272 {
1273  const struct ast_sip_endpoint *endpoint = obj;
1274  return codec_prefs_to_str(&endpoint->media.codec_prefs_incoming_answer, obj, args, buf);
1275 }
1276 
1277 static int outgoing_answer_codec_prefs_to_str(const void *obj, const intptr_t *args, char **buf)
1278 {
1279  const struct ast_sip_endpoint *endpoint = obj;
1280  return codec_prefs_to_str(&endpoint->media.codec_prefs_outgoing_answer, obj, args, buf);
1281 }
1282 
1283 static void *sip_nat_hook_alloc(const char *name)
1284 {
1285  return ast_sorcery_generic_alloc(sizeof(struct ast_sip_nat_hook), NULL);
1286 }
1287 
1288 /*! \brief Destructor function for persistent endpoint information */
1289 static void persistent_endpoint_destroy(void *obj)
1290 {
1291  struct sip_persistent_endpoint *persistent = obj;
1292 
1293  ast_endpoint_shutdown(persistent->endpoint);
1294 }
1295 
1296 static int add_to_regcontext(void *obj, void *arg, int flags)
1297 {
1298  struct sip_persistent_endpoint *persistent = obj;
1299  const char *regcontext = arg;
1300 
1301  if (ast_endpoint_get_state(persistent->endpoint) == AST_ENDPOINT_ONLINE) {
1303  persistent->endpoint), 1, NULL)) {
1304  ast_add_extension(regcontext, 1, ast_endpoint_get_resource(persistent->endpoint), 1, NULL, NULL,
1305  "Noop", ast_strdup(ast_endpoint_get_resource(persistent->endpoint)), ast_free_ptr, "PJSIP");
1306  }
1307  }
1308 
1309  return 0;
1310 }
1311 
1313 {
1314  if (ast_strlen_zero(regcontext)) {
1315  return 0;
1316  }
1317 
1318  /* Make sure the regcontext exists */
1319  if (!ast_context_find_or_create(NULL, NULL, regcontext, "PJSIP")) {
1320  ast_log(LOG_ERROR, "Failed to create regcontext '%s'\n", regcontext);
1321  return -1;
1322  }
1323 
1324  /* Add any online endpoints */
1325  ao2_callback(persistent_endpoints, OBJ_NODATA, add_to_regcontext, (void *)regcontext);
1326  return 0;
1327 }
1328 
1330 {
1331  struct sip_persistent_endpoint *persistent;
1332  struct ast_json *blob;
1333  char *regcontext;
1334 
1335  persistent = ao2_find(persistent_endpoints, endpoint_name, OBJ_SEARCH_KEY);
1336  if (!persistent) {
1337  return -1;
1338  }
1339 
1340  /* If there was no state change, don't publish anything. */
1341  if (ast_endpoint_get_state(persistent->endpoint) == state) {
1342  ao2_ref(persistent, -1);
1343  return 0;
1344  }
1345 
1346  regcontext = ast_sip_get_regcontext();
1347 
1348  if (state == AST_ENDPOINT_ONLINE) {
1350  blob = ast_json_pack("{s: s}", "peer_status", "Reachable");
1351 
1352  if (!ast_strlen_zero(regcontext)) {
1353  if (!ast_exists_extension(NULL, regcontext, ast_endpoint_get_resource(persistent->endpoint), 1, NULL)) {
1354  ast_add_extension(regcontext, 1, ast_endpoint_get_resource(persistent->endpoint), 1, NULL, NULL,
1355  "Noop", ast_strdup(ast_endpoint_get_resource(persistent->endpoint)), ast_free_ptr, "PJSIP");
1356  }
1357  }
1358 
1359  ast_verb(2, "Endpoint %s is now Reachable\n", ast_endpoint_get_resource(persistent->endpoint));
1360  } else {
1362  blob = ast_json_pack("{s: s}", "peer_status", "Unreachable");
1363 
1364  if (!ast_strlen_zero(regcontext)) {
1365  struct pbx_find_info q = { .stacklen = 0 };
1366 
1367  if (pbx_find_extension(NULL, NULL, &q, regcontext, ast_endpoint_get_resource(persistent->endpoint), 1, NULL, "", E_MATCH)) {
1369  }
1370  }
1371 
1372  ast_verb(2, "Endpoint %s is now Unreachable\n", ast_endpoint_get_resource(persistent->endpoint));
1373  }
1374 
1375  ast_free(regcontext);
1376 
1378  ast_json_unref(blob);
1380 
1381  ao2_ref(persistent, -1);
1382 
1383  return 0;
1384 }
1385 
1386 void ast_sip_persistent_endpoint_publish_contact_state(const char *endpoint_name, const struct ast_sip_contact_status *contact_status)
1387 {
1388  struct sip_persistent_endpoint *persistent;
1389  struct ast_json *blob;
1390  char rtt[32];
1391 
1392  persistent = ao2_find(persistent_endpoints, endpoint_name, OBJ_SEARCH_KEY);
1393  if (!persistent) {
1394  return;
1395  }
1396 
1397  snprintf(rtt, sizeof(rtt), "%" PRId64, contact_status->rtt);
1398  blob = ast_json_pack("{s: s, s: s, s: s, s: s, s: s}",
1399  "contact_status", ast_sip_get_contact_status_label(contact_status->status),
1400  "aor", contact_status->aor,
1401  "uri", contact_status->uri,
1402  "roundtrip_usec", rtt,
1403  "endpoint_name", ast_endpoint_get_resource(persistent->endpoint));
1404  if (blob) {
1406  ast_json_unref(blob);
1407  }
1408 
1409  ao2_ref(persistent, -1);
1410 }
1411 
1412 /*! \brief Internal function which finds (or creates) persistent endpoint information */
1414 {
1415  RAII_VAR(struct sip_persistent_endpoint *, persistent, NULL, ao2_cleanup);
1416  SCOPED_AO2LOCK(lock, persistent_endpoints);
1417 
1418  persistent = ao2_find(persistent_endpoints, ast_sorcery_object_get_id(endpoint),
1420  if (!persistent) {
1421  persistent = ao2_alloc_options(sizeof(*persistent), persistent_endpoint_destroy,
1423  if (!persistent) {
1424  return NULL;
1425  }
1426 
1427  persistent->endpoint = ast_endpoint_create("PJSIP",
1428  ast_sorcery_object_get_id(endpoint));
1429  if (!persistent->endpoint) {
1430  return NULL;
1431  }
1432 
1433  ast_endpoint_set_state(persistent->endpoint, AST_ENDPOINT_OFFLINE);
1434 
1435  ao2_link_flags(persistent_endpoints, persistent, OBJ_NOLOCK);
1436  }
1437 
1438  ao2_ref(persistent->endpoint, +1);
1439  return persistent->endpoint;
1440 }
1441 
1442 /*! \brief Callback function for when an object is finalized */
1443 static int sip_endpoint_apply_handler(const struct ast_sorcery *sorcery, void *obj)
1444 {
1445  struct ast_sip_endpoint *endpoint = obj;
1446 
1447  if (!(endpoint->persistent = persistent_endpoint_find_or_create(endpoint))) {
1448  return -1;
1449  }
1450 
1451  if (endpoint->extensions.timer.min_se < 90) {
1452  ast_log(LOG_ERROR, "Session timer minimum expires time must be 90 or greater on endpoint '%s'\n",
1453  ast_sorcery_object_get_id(endpoint));
1454  return -1;
1455  } else if (endpoint->extensions.timer.sess_expires < endpoint->extensions.timer.min_se) {
1456  ast_log(LOG_ERROR, "Session timer expires must be greater than minimum session expires time on endpoint '%s'\n",
1457  ast_sorcery_object_get_id(endpoint));
1458  return -1;
1459  }
1460 
1461  if (ast_rtp_dtls_cfg_validate(&endpoint->media.rtp.dtls_cfg)) {
1462  return -1;
1463  }
1464 
1465  if (endpoint->preferred_codec_only) {
1467  ast_log(LOG_ERROR, "Setting both preferred_codec_only and incoming_call_offer_pref is not supported on endpoint '%s'\n",
1468  ast_sorcery_object_get_id(endpoint));
1469  return -1;
1470  }
1473  }
1474 
1476  if (!endpoint->media.topology) {
1477  return -1;
1478  }
1479 
1480  endpoint->media.rtcp_mux |= endpoint->media.bundle;
1481 
1482  /*
1483  * If webrtc has been enabled then enable those attributes, and default
1484  * some, that are needed in order for webrtc to work.
1485  */
1486  endpoint->media.bundle |= endpoint->media.webrtc;
1487  endpoint->media.rtcp_mux |= endpoint->media.webrtc;
1488  endpoint->media.rtp.use_avpf |= endpoint->media.webrtc;
1489  endpoint->media.rtp.ice_support |= endpoint->media.webrtc;
1490  endpoint->media.rtp.use_received_transport |= endpoint->media.webrtc;
1491 
1492  if (endpoint->media.webrtc) {
1494  endpoint->media.rtp.dtls_cfg.enabled = 1;
1497 
1498  if (ast_strlen_zero(endpoint->media.rtp.dtls_cfg.certfile)) {
1499  /* If no certificate has been specified, try to automatically create one */
1500  endpoint->media.rtp.dtls_cfg.ephemeral_cert = 1;
1501  }
1502  }
1503 
1504  return 0;
1505 }
1506 
1508 {
1509  char device[MAX_OBJECT_FIELD];
1510 
1511  snprintf(device, MAX_OBJECT_FIELD, "PJSIP/%s", ast_sorcery_object_get_id(endpoint));
1512  return ast_devstate2str(ast_device_state(device));
1513 }
1514 
1516  const struct ast_sip_endpoint *endpoint)
1517 {
1519  ast_endpoint_get_tech(endpoint->persistent),
1521 }
1522 
1524  const struct ast_endpoint_snapshot *endpoint_snapshot,
1525  ao2_callback_fn on_channel_snapshot, void *arg)
1526 {
1527  int num, num_channels = endpoint_snapshot->num_channels;
1528 
1529  if (!on_channel_snapshot || !num_channels) {
1530  return 0;
1531  }
1532 
1533  for (num = 0; num < num_channels; ++num) {
1534  RAII_VAR(struct ast_channel_snapshot *, snapshot, NULL, ao2_cleanup);
1535  int res;
1536 
1537  snapshot = ast_channel_snapshot_get_latest(endpoint_snapshot->channel_ids[num]);
1538  if (!snapshot) {
1539  continue;
1540  }
1541 
1542  res = on_channel_snapshot(snapshot, arg, 0);
1543  if (res) {
1544  return -1;
1545  }
1546  }
1547  return 0;
1548 }
1549 
1551  const struct ast_sip_endpoint *endpoint,
1552  ao2_callback_fn on_channel_snapshot, void *arg)
1553 {
1554  RAII_VAR(struct ast_endpoint_snapshot *, endpoint_snapshot, ast_sip_get_endpoint_snapshot(endpoint), ao2_cleanup);
1555  return ast_sip_for_each_channel_snapshot(endpoint_snapshot, on_channel_snapshot, arg);
1556 }
1557 
1558 static int active_channels_to_str_cb(void *object, void *arg, int flags)
1559 {
1560  const struct ast_channel_snapshot *snapshot = object;
1561  struct ast_str **buf = arg;
1562  ast_str_append(buf, 0, "%s,", snapshot->base->name);
1563  return 0;
1564 }
1565 
1567  struct ast_str **str)
1568 {
1569 
1570  RAII_VAR(struct ast_endpoint_snapshot *, endpoint_snapshot,
1572 
1573  if (endpoint_snapshot) {
1574  return;
1575  }
1576 
1577  ast_sip_for_each_channel_snapshot(endpoint_snapshot,
1579  ast_str_truncate(*str, -1);
1580 }
1581 
1582 #define AMI_DEFAULT_STR_SIZE 512
1583 
1584 struct ast_str *ast_sip_create_ami_event(const char *event, struct ast_sip_ami *ami)
1585 {
1587 
1588  if (!(buf)) {
1589  astman_send_error_va(ami->s, ami->m, "Unable create event "
1590  "for %s\n", event);
1591  return NULL;
1592  }
1593 
1594  ast_str_set(&buf, 0, "Event: %s\r\n", event);
1595  if (!ast_strlen_zero(ami->action_id)) {
1596  ast_str_append(&buf, 0, "ActionID: %s\r\n", ami->action_id);
1597  }
1598  return buf;
1599 }
1600 
1601 static void sip_sorcery_object_ami_set_type_name(const void *obj, struct ast_str **buf)
1602 {
1603  ast_str_append(buf, 0, "ObjectType: %s\r\n",
1605  ast_str_append(buf, 0, "ObjectName: %s\r\n",
1607 }
1608 
1609 int ast_sip_sorcery_object_to_ami(const void *obj, struct ast_str **buf)
1610 {
1613  struct ast_variable *i;
1614 
1615  if (!objset) {
1616  return -1;
1617  }
1618 
1620 
1621  for (i = objset; i; i = i->next) {
1622  RAII_VAR(char *, camel, ast_to_camel_case(i->name), ast_free);
1623  ast_str_append(buf, 0, "%s: %s\r\n", camel, i->value);
1624  }
1625 
1626  return 0;
1627 }
1628 
1629 static int sip_endpoints_aors_ami(void *obj, void *arg, int flags)
1630 {
1631  struct ast_sip_aor *aor = obj;
1632  struct ast_str **buf = arg;
1633 
1634  ast_str_append(buf, 0, "Contacts: ");
1636  ast_str_append(buf, 0, "\r\n");
1637 
1638  return 0;
1639 }
1640 
1642  struct ast_str **buf)
1643 {
1644  if (ast_sip_sorcery_object_to_ami(endpoint, buf)) {
1645  return -1;
1646  }
1647 
1648  ast_str_append(buf, 0, "DeviceState: %s\r\n",
1649  ast_sip_get_device_state(endpoint));
1650 
1651  ast_str_append(buf, 0, "ActiveChannels: ");
1652  active_channels_to_str(endpoint, buf);
1653  ast_str_append(buf, 0, "\r\n");
1654 
1655  return 0;
1656 }
1657 
1659  struct ast_sip_ami *ami)
1660 {
1661  RAII_VAR(struct ast_str *, buf,
1662  ast_sip_create_ami_event("EndpointDetail", ami), ast_free);
1663 
1664  if (!buf) {
1665  return -1;
1666  }
1667 
1668  sip_endpoint_to_ami(endpoint, &buf);
1669  astman_append(ami->s, "%s\r\n", ast_str_buffer(buf));
1670  return 0;
1671 }
1672 
1673 #define AMI_SHOW_ENDPOINTS "PJSIPShowEndpoints"
1674 #define AMI_SHOW_ENDPOINT "PJSIPShowEndpoint"
1675 
1676 static int ami_show_endpoint(struct mansession *s, const struct message *m)
1677 {
1678  struct ast_sip_ami ami = { .s = s, .m = m, .action_id = astman_get_header(m, "ActionID"),
1679  .count = 0, };
1681  const char *endpoint_name = astman_get_header(m, "Endpoint");
1682  int count = 0;
1683 
1684  if (ast_strlen_zero(endpoint_name)) {
1685  astman_send_error_va(s, m, "%s requires an endpoint name\n",
1687  return 0;
1688  }
1689 
1690  if (!strncasecmp(endpoint_name, "pjsip/", 6)) {
1691  endpoint_name += 6;
1692  }
1693 
1695  ast_sip_get_sorcery(), "endpoint", endpoint_name))) {
1696  astman_send_error_va(s, m, "Unable to retrieve endpoint %s\n",
1697  endpoint_name);
1698  return 0;
1699  }
1700 
1701  astman_send_listack(s, m, "Following are Events for each object associated with the Endpoint",
1702  "start");
1703 
1704  /* the endpoint detail needs to always come first so apply as such */
1705  if (format_ami_endpoint(endpoint, &ami) ||
1706  ast_sip_format_endpoint_ami(endpoint, &ami, &count)) {
1707  astman_send_error_va(s, m, "Unable to format endpoint %s\n",
1708  endpoint_name);
1709  }
1710 
1711  astman_send_list_complete_start(s, m, "EndpointDetailComplete", ami.count + 1);
1713 
1714  return 0;
1715 }
1716 
1717 static int format_str_append_auth(const struct ast_sip_auth_vector *auths,
1718  struct ast_str **buf)
1719 {
1720  char *str = NULL;
1721  if (ast_sip_auths_to_str(auths, &str)) {
1722  return -1;
1723  }
1724  ast_str_append(buf, 0, "%s", str ? str : "");
1725  ast_free(str);
1726  return 0;
1727 }
1728 
1729 static int format_ami_endpoints(void *obj, void *arg, int flags)
1730 {
1731 
1732  struct ast_sip_endpoint *endpoint = obj;
1733  struct ast_sip_ami *ami = arg;
1734  RAII_VAR(struct ast_str *, buf,
1735  ast_sip_create_ami_event("EndpointList", ami), ast_free);
1736 
1737  if (!buf) {
1738  return CMP_STOP;
1739  }
1740 
1742  ast_str_append(&buf, 0, "Transport: %s\r\n",
1743  endpoint->transport);
1744  ast_str_append(&buf, 0, "Aor: %s\r\n",
1745  endpoint->aors);
1746 
1747  ast_str_append(&buf, 0, "Auths: ");
1749  ast_str_append(&buf, 0, "\r\n");
1750 
1751  ast_str_append(&buf, 0, "OutboundAuths: ");
1753  ast_str_append(&buf, 0, "\r\n");
1754 
1755  ast_sip_for_each_aor(endpoint->aors,
1757 
1758  ast_str_append(&buf, 0, "DeviceState: %s\r\n",
1759  ast_sip_get_device_state(endpoint));
1760 
1761  ast_str_append(&buf, 0, "ActiveChannels: ");
1762  active_channels_to_str(endpoint, &buf);
1763  ast_str_append(&buf, 0, "\r\n");
1764 
1765  astman_append(ami->s, "%s\r\n", ast_str_buffer(buf));
1766  return 0;
1767 }
1768 
1769 static int ami_show_endpoints(struct mansession *s, const struct message *m)
1770 {
1771  struct ast_sip_ami ami = { .s = s, .m = m, .action_id = astman_get_header(m, "ActionID"), };
1773  int num;
1774 
1776  if (!endpoints) {
1777  astman_send_error(s, m, "Could not get endpoints\n");
1778  return 0;
1779  }
1780 
1781  if (!(num = ao2_container_count(endpoints))) {
1782  astman_send_error(s, m, "No endpoints found\n");
1783  return 0;
1784  }
1785 
1786  astman_send_listack(s, m, "A listing of Endpoints follows, presented as EndpointList events",
1787  "start");
1788 
1790 
1791  astman_send_list_complete_start(s, m, "EndpointListComplete", num);
1793  return 0;
1794 }
1795 
1797 {
1799  struct ao2_container *s_container;
1800 
1801  container = ast_sorcery_retrieve_by_regex(sip_sorcery, "endpoint", regex);
1802  if (!container) {
1803  return NULL;
1804  }
1805 
1808  if (!s_container) {
1809  return NULL;
1810  }
1811 
1812  if (ao2_container_dup(s_container, container, 0)) {
1813  ao2_ref(s_container, -1);
1814  return NULL;
1815  }
1816 
1817  return s_container;
1818 }
1819 
1820 static int cli_endpoint_iterate(void *obj, ao2_callback_fn callback, void *args)
1821 {
1822  ao2_callback(obj, OBJ_NODATA, callback, args);
1823 
1824  return 0;
1825 }
1826 
1827 static void *cli_endpoint_retrieve_by_id(const char *id)
1828 {
1829  return ast_sorcery_retrieve_by_id(ast_sip_get_sorcery(), "endpoint", id);
1830 }
1831 
1833 {
1834  RAII_VAR(struct ast_sip_cli_formatter_entry *, formatter_entry, NULL, ao2_cleanup);
1835 
1836  formatter_entry = ast_sip_lookup_cli_formatter(type);
1837  if (formatter_entry) {
1838  formatter_entry->print_header(NULL, context, 0);
1839  }
1840 }
1841 
1842 static int cli_endpoint_print_header(void *obj, void *arg, int flags)
1843 {
1844  struct ast_sip_cli_context *context = arg;
1845 
1846  ast_assert(context->output_buffer != NULL);
1847 
1848  ast_str_append(&context->output_buffer, 0,
1849  " Endpoint: <Endpoint/CID.....................................> <State.....> <Channels.>\n");
1850 
1851  if (context->recurse) {
1852  context->indent_level++;
1853  cli_endpoint_print_child_header("auth", context);
1854  cli_endpoint_print_child_header("aor", context);
1855  cli_endpoint_print_child_header("transport", context);
1856  cli_endpoint_print_child_header("identify", context);
1857  cli_endpoint_print_child_header("channel", context);
1858  context->indent_level--;
1859  }
1860 
1861  return 0;
1862 }
1863 
1864 static void cli_endpoint_print_child_body(char *type, const void *obj, struct ast_sip_cli_context *context)
1865 {
1866  RAII_VAR(struct ast_sip_cli_formatter_entry *, formatter_entry, NULL, ao2_cleanup);
1867 
1868  formatter_entry = ast_sip_lookup_cli_formatter(type);
1869  if (formatter_entry) {
1870  formatter_entry->iterate((void *)obj, formatter_entry->print_body, context);
1871  }
1872 }
1873 
1874 static int cli_endpoint_print_body(void *obj, void *arg, int flags)
1875 {
1876  struct ast_sip_endpoint *endpoint = obj;
1877  RAII_VAR(struct ast_endpoint_snapshot *, endpoint_snapshot, ast_sip_get_endpoint_snapshot(endpoint), ao2_cleanup);
1878  struct ast_sip_cli_context *context = arg;
1879  const char *id = ast_sorcery_object_get_id(endpoint);
1880  char *print_name = NULL;
1881  int print_name_len;
1882  char *number = S_COR(endpoint->id.self.number.valid,
1883  endpoint->id.self.number.str, NULL);
1884  int indent;
1885  int flexwidth;
1886 
1887  ast_assert(context->output_buffer != NULL);
1888 
1889  if (number) {
1890  print_name_len = strlen(id) + strlen(number) + 2;
1891  print_name = ast_alloca(print_name_len);
1892  snprintf(print_name, print_name_len, "%s/%s", id, number);
1893  }
1894 
1895  indent = CLI_INDENT_TO_SPACES(context->indent_level);
1896  flexwidth = CLI_LAST_TABSTOP - indent - 2;
1897 
1898  ast_str_append(&context->output_buffer, 0, "%*s: %-*.*s %-12.12s %d of %.0f\n",
1899  indent, "Endpoint",
1900  flexwidth, flexwidth, print_name ? print_name : id,
1901  ast_sip_get_device_state(endpoint),
1902  endpoint_snapshot->num_channels,
1903  (double) endpoint->devicestate_busy_at ? endpoint->devicestate_busy_at :
1904  INFINITY
1905  );
1906 
1907  if (context->recurse) {
1908  context->indent_level++;
1909 
1910  context->auth_direction = "Out";
1911  cli_endpoint_print_child_body("auth", &endpoint->outbound_auths, context);
1912  context->auth_direction = "In";
1913  cli_endpoint_print_child_body("auth", &endpoint->inbound_auths, context);
1914 
1915  cli_endpoint_print_child_body("aor", endpoint->aors, context);
1916  cli_endpoint_print_child_body("transport", endpoint, context);
1917  cli_endpoint_print_child_body("identify", endpoint, context);
1918  cli_endpoint_print_child_body("channel", endpoint, context);
1919 
1920  context->indent_level--;
1921 
1922  if (context->indent_level == 0) {
1923  ast_str_append(&context->output_buffer, 0, "\n");
1924  }
1925  }
1926 
1927  if (context->show_details || (context->show_details_only_level_0 && context->indent_level == 0)) {
1928  ast_str_append(&context->output_buffer, 0, "\n");
1929  ast_sip_cli_print_sorcery_objectset(endpoint, context, 0);
1930  }
1931 
1932  return 0;
1933 }
1934 
1935 static struct ast_cli_entry cli_commands[] = {
1936  AST_CLI_DEFINE(ast_sip_cli_traverse_objects, "List PJSIP Endpoints",
1937  .command = "pjsip list endpoints",
1938  .usage = "Usage: pjsip list endpoints [ like <pattern> ]\n"
1939  " List the configured PJSIP endpoints\n"
1940  " Optional regular expression pattern is used to filter the list.\n"),
1941  AST_CLI_DEFINE(ast_sip_cli_traverse_objects, "Show PJSIP Endpoints",
1942  .command = "pjsip show endpoints",
1943  .usage = "Usage: pjsip show endpoints [ like <pattern> ]\n"
1944  " List(detailed) the configured PJSIP endpoints\n"
1945  " Optional regular expression pattern is used to filter the list.\n"),
1946  AST_CLI_DEFINE(ast_sip_cli_traverse_objects, "Show PJSIP Endpoint",
1947  .command = "pjsip show endpoint",
1948  .usage = "Usage: pjsip show endpoint <id>\n"
1949  " Show the configured PJSIP endpoint\n"),
1950 };
1951 
1954 
1955 static void load_all_endpoints(void)
1956 {
1957  struct ao2_container *endpoints;
1958 
1960  ao2_cleanup(endpoints);
1961 }
1962 
1963 static void acl_change_stasis_cb(void *data, struct stasis_subscription *sub,
1964  struct stasis_message *message)
1965 {
1966  if (stasis_message_type(message) != ast_named_acl_change_type()) {
1967  return;
1968  }
1969 
1970  ast_sorcery_force_reload_object(sip_sorcery, "endpoint");
1971 }
1972 
1974 {
1977  return -1;
1978  }
1979 
1980  persistent_endpoints = ao2_container_alloc_hash(AO2_ALLOC_OPT_LOCK_MUTEX, 0,
1982  if (!persistent_endpoints) {
1983  return -1;
1984  }
1985 
1986  if (!(sip_sorcery = ast_sorcery_open())) {
1987  ast_log(LOG_ERROR, "Failed to open SIP sorcery failed to open\n");
1988  return -1;
1989  }
1990 
1992 
1994  ast_log(LOG_ERROR, "Failed to register SIP authentication support\n");
1995  ast_sorcery_unref(sip_sorcery);
1996  sip_sorcery = NULL;
1997  return -1;
1998  }
1999 
2000  ast_sorcery_apply_default(sip_sorcery, "endpoint", "config", "pjsip.conf,criteria=type=endpoint");
2001  ast_sorcery_apply_default(sip_sorcery, "nat_hook", "memory", NULL);
2002 
2004  ast_log(LOG_ERROR, "Failed to register SIP endpoint object with sorcery\n");
2005  ast_sorcery_unref(sip_sorcery);
2006  sip_sorcery = NULL;
2007  return -1;
2008  }
2009 
2010  if (ast_sorcery_internal_object_register(sip_sorcery, "nat_hook", sip_nat_hook_alloc, NULL, NULL)) {
2011  ast_log(LOG_ERROR, "Failed to register nat_hook\n");
2012  }
2013 
2014  ast_sorcery_object_field_register(sip_sorcery, "endpoint", "type", "", OPT_NOOP_T, 0, 0);
2015  ast_sorcery_object_field_register(sip_sorcery, "endpoint", "context", "default", OPT_STRINGFIELD_T, 0, STRFLDSET(struct ast_sip_endpoint, context));
2016  ast_sorcery_object_field_register_alias(sip_sorcery, "endpoint", "disallow", "", OPT_CODEC_T, 0, FLDSET(struct ast_sip_endpoint, media.codecs));
2017  ast_sorcery_object_field_register(sip_sorcery, "endpoint", "allow", "", OPT_CODEC_T, 1, FLDSET(struct ast_sip_endpoint, media.codecs));
2018  ast_sorcery_object_field_register_custom(sip_sorcery, "endpoint", "dtmf_mode", "rfc4733", dtmf_handler, dtmf_to_str, NULL, 0, 0);
2019  ast_sorcery_object_field_register(sip_sorcery, "endpoint", "rtp_ipv6", "no", OPT_BOOL_T, 1, FLDSET(struct ast_sip_endpoint, media.rtp.ipv6));
2020  ast_sorcery_object_field_register(sip_sorcery, "endpoint", "rtp_symmetric", "no", OPT_BOOL_T, 1, FLDSET(struct ast_sip_endpoint, media.rtp.symmetric));
2021  ast_sorcery_object_field_register(sip_sorcery, "endpoint", "ice_support", "no", OPT_BOOL_T, 1, FLDSET(struct ast_sip_endpoint, media.rtp.ice_support));
2022  ast_sorcery_object_field_register(sip_sorcery, "endpoint", "use_ptime", "no", OPT_BOOL_T, 1, FLDSET(struct ast_sip_endpoint, media.rtp.use_ptime));
2023  ast_sorcery_object_field_register(sip_sorcery, "endpoint", "force_rport", "yes", OPT_BOOL_T, 1, FLDSET(struct ast_sip_endpoint, nat.force_rport));
2024  ast_sorcery_object_field_register(sip_sorcery, "endpoint", "rewrite_contact", "no", OPT_BOOL_T, 1, FLDSET(struct ast_sip_endpoint, nat.rewrite_contact));
2025  ast_sorcery_object_field_register(sip_sorcery, "endpoint", "transport", "", OPT_STRINGFIELD_T, 0, STRFLDSET(struct ast_sip_endpoint, transport));
2026  ast_sorcery_object_field_register(sip_sorcery, "endpoint", "outbound_proxy", "", OPT_STRINGFIELD_T, 0, STRFLDSET(struct ast_sip_endpoint, outbound_proxy));
2027  ast_sorcery_object_field_register(sip_sorcery, "endpoint", "moh_suggest", "default", OPT_STRINGFIELD_T, 0, STRFLDSET(struct ast_sip_endpoint, mohsuggest));
2028  ast_sorcery_object_field_register_custom(sip_sorcery, "endpoint", "100rel", "yes", prack_handler, prack_to_str, NULL, 0, 0);
2029  ast_sorcery_object_field_register_custom(sip_sorcery, "endpoint", "timers", "yes", timers_handler, timers_to_str, NULL, 0, 0);
2030  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));
2031  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));
2032  ast_sorcery_object_field_register_custom(sip_sorcery, "endpoint", "auth", "", inbound_auth_handler, inbound_auths_to_str, NULL, 0, 0);
2033  ast_sorcery_object_field_register_custom(sip_sorcery, "endpoint", "outbound_auth", "", outbound_auth_handler, outbound_auths_to_str, NULL, 0, 0);
2034  ast_sorcery_object_field_register(sip_sorcery, "endpoint", "aors", "", OPT_STRINGFIELD_T, 0, STRFLDSET(struct ast_sip_endpoint, aors));
2035  ast_sorcery_object_field_register(sip_sorcery, "endpoint", "media_address", "", OPT_STRINGFIELD_T, 0, STRFLDSET(struct ast_sip_endpoint, media.address));
2036  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));
2037  ast_sorcery_object_field_register_custom(sip_sorcery, "endpoint", "identify_by", "username,ip", ident_handler, ident_to_str, NULL, 0, 0);
2038  ast_sorcery_object_field_register(sip_sorcery, "endpoint", "direct_media", "yes", OPT_BOOL_T, 1, FLDSET(struct ast_sip_endpoint, media.direct_media.enabled));
2039  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);
2040  ast_sorcery_object_field_register(sip_sorcery, "endpoint", "trust_connected_line", "yes", OPT_YESNO_T, 1, FLDSET(struct ast_sip_endpoint, id.trust_connected_line));
2041  ast_sorcery_object_field_register(sip_sorcery, "endpoint", "send_connected_line", "yes", OPT_YESNO_T, 1, FLDSET(struct ast_sip_endpoint, id.send_connected_line));
2042  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);
2043  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);
2044  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));
2045  ast_sorcery_object_field_register_custom(sip_sorcery, "endpoint", "callerid", "", caller_id_handler, caller_id_to_str, NULL, 0, 0);
2046  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);
2047  ast_sorcery_object_field_register_custom(sip_sorcery, "endpoint", "callerid_tag", "", caller_id_tag_handler, caller_id_tag_to_str, NULL, 0, 0);
2048  ast_sorcery_object_field_register(sip_sorcery, "endpoint", "trust_id_inbound", "no", OPT_BOOL_T, 1, FLDSET(struct ast_sip_endpoint, id.trust_inbound));
2049  ast_sorcery_object_field_register(sip_sorcery, "endpoint", "trust_id_outbound", "no", OPT_BOOL_T, 1, FLDSET(struct ast_sip_endpoint, id.trust_outbound));
2050  ast_sorcery_object_field_register(sip_sorcery, "endpoint", "send_pai", "no", OPT_BOOL_T, 1, FLDSET(struct ast_sip_endpoint, id.send_pai));
2051  ast_sorcery_object_field_register(sip_sorcery, "endpoint", "send_rpid", "no", OPT_BOOL_T, 1, FLDSET(struct ast_sip_endpoint, id.send_rpid));
2052  ast_sorcery_object_field_register(sip_sorcery, "endpoint", "rpid_immediate", "no", OPT_BOOL_T, 1, FLDSET(struct ast_sip_endpoint, id.rpid_immediate));
2053  ast_sorcery_object_field_register(sip_sorcery, "endpoint", "send_diversion", "yes", OPT_BOOL_T, 1, FLDSET(struct ast_sip_endpoint, id.send_diversion));
2054  ast_sorcery_object_field_register(sip_sorcery, "endpoint", "send_history_info", "no", OPT_BOOL_T, 1, FLDSET(struct ast_sip_endpoint, id.send_history_info));
2055  ast_sorcery_object_field_register(sip_sorcery, "endpoint", "mailboxes", "", OPT_STRINGFIELD_T, 0, STRFLDSET(struct ast_sip_endpoint, subscription.mwi.mailboxes));
2056  ast_sorcery_object_field_register_custom(sip_sorcery, "endpoint", "voicemail_extension", "", voicemail_extension_handler, voicemail_extension_to_str, NULL, 0, 0);
2057  ast_sorcery_object_field_register(sip_sorcery, "endpoint", "aggregate_mwi", "yes", OPT_BOOL_T, 1, FLDSET(struct ast_sip_endpoint, subscription.mwi.aggregate));
2058  ast_sorcery_object_field_register(sip_sorcery, "endpoint", "mwi_subscribe_replaces_unsolicited", "no", OPT_YESNO_T, 1, FLDSET(struct ast_sip_endpoint, subscription.mwi.subscribe_replaces_unsolicited));
2059  ast_sorcery_object_field_register_custom(sip_sorcery, "endpoint", "media_encryption", "no", media_encryption_handler, media_encryption_to_str, NULL, 0, 0);
2060  ast_sorcery_object_field_register(sip_sorcery, "endpoint", "use_avpf", "no", OPT_BOOL_T, 1, FLDSET(struct ast_sip_endpoint, media.rtp.use_avpf));
2061  ast_sorcery_object_field_register(sip_sorcery, "endpoint", "force_avp", "no", OPT_BOOL_T, 1, FLDSET(struct ast_sip_endpoint, media.rtp.force_avp));
2062  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));
2063  ast_sorcery_object_field_register(sip_sorcery, "endpoint", "rtp_keepalive", "0", OPT_UINT_T, 0, FLDSET(struct ast_sip_endpoint, media.rtp.keepalive));
2064  ast_sorcery_object_field_register(sip_sorcery, "endpoint", "rtp_timeout", "0", OPT_UINT_T, 0, FLDSET(struct ast_sip_endpoint, media.rtp.timeout));
2065  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));
2066  ast_sorcery_object_field_register(sip_sorcery, "endpoint", "one_touch_recording", "no", OPT_BOOL_T, 1, FLDSET(struct ast_sip_endpoint, info.recording.enabled));
2067  ast_sorcery_object_field_register(sip_sorcery, "endpoint", "inband_progress", "no", OPT_BOOL_T, 1, FLDSET(struct ast_sip_endpoint, inband_progress));
2068  ast_sorcery_object_field_register_custom(sip_sorcery, "endpoint", "call_group", "", group_handler, callgroup_to_str, NULL, 0, 0);
2069  ast_sorcery_object_field_register_custom(sip_sorcery, "endpoint", "pickup_group", "", group_handler, pickupgroup_to_str, NULL, 0, 0);
2070  ast_sorcery_object_field_register_custom(sip_sorcery, "endpoint", "named_call_group", "", named_groups_handler, named_callgroups_to_str, NULL, 0, 0);
2071  ast_sorcery_object_field_register_custom(sip_sorcery, "endpoint", "named_pickup_group", "", named_groups_handler, named_pickupgroups_to_str, NULL, 0, 0);
2072  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));
2073  ast_sorcery_object_field_register(sip_sorcery, "endpoint", "t38_udptl", "no", OPT_BOOL_T, 1, FLDSET(struct ast_sip_endpoint, media.t38.enabled));
2074  ast_sorcery_object_field_register_custom(sip_sorcery, "endpoint", "t38_udptl_ec", "none", t38udptl_ec_handler, t38udptl_ec_to_str, NULL, 0, 0);
2075  ast_sorcery_object_field_register(sip_sorcery, "endpoint", "t38_udptl_maxdatagram", "0", OPT_UINT_T, 0, FLDSET(struct ast_sip_endpoint, media.t38.maxdatagram));
2076  ast_sorcery_object_field_register(sip_sorcery, "endpoint", "fax_detect", "no", OPT_BOOL_T, 1, FLDSET(struct ast_sip_endpoint, faxdetect));
2077  ast_sorcery_object_field_register(sip_sorcery, "endpoint", "fax_detect_timeout", "0", OPT_UINT_T, 0, FLDSET(struct ast_sip_endpoint, faxdetect_timeout));
2078  ast_sorcery_object_field_register(sip_sorcery, "endpoint", "t38_udptl_nat", "no", OPT_BOOL_T, 1, FLDSET(struct ast_sip_endpoint, media.t38.nat));
2079  ast_sorcery_object_field_register(sip_sorcery, "endpoint", "t38_udptl_ipv6", "no", OPT_BOOL_T, 1, FLDSET(struct ast_sip_endpoint, media.t38.ipv6));
2080  ast_sorcery_object_field_register(sip_sorcery, "endpoint", "tone_zone", "", OPT_STRINGFIELD_T, 0, STRFLDSET(struct ast_sip_endpoint, zone));
2081  ast_sorcery_object_field_register(sip_sorcery, "endpoint", "language", "", OPT_STRINGFIELD_T, 0, STRFLDSET(struct ast_sip_endpoint, language));
2082  ast_sorcery_object_field_register(sip_sorcery, "endpoint", "record_on_feature", "automixmon", OPT_STRINGFIELD_T, 0, STRFLDSET(struct ast_sip_endpoint, info.recording.onfeature));
2083  ast_sorcery_object_field_register(sip_sorcery, "endpoint", "record_off_feature", "automixmon", OPT_STRINGFIELD_T, 0, STRFLDSET(struct ast_sip_endpoint, info.recording.offfeature));
2084  ast_sorcery_object_field_register(sip_sorcery, "endpoint", "allow_transfer", "yes", OPT_BOOL_T, 1, FLDSET(struct ast_sip_endpoint, allowtransfer));
2085  ast_sorcery_object_field_register(sip_sorcery, "endpoint", "user_eq_phone", "no", OPT_BOOL_T, 1, FLDSET(struct ast_sip_endpoint, usereqphone));
2086  ast_sorcery_object_field_register(sip_sorcery, "endpoint", "moh_passthrough", "no", OPT_BOOL_T, 1, FLDSET(struct ast_sip_endpoint, moh_passthrough));
2087  ast_sorcery_object_field_register(sip_sorcery, "endpoint", "sdp_owner", "-", OPT_STRINGFIELD_T, 0, STRFLDSET(struct ast_sip_endpoint, media.sdpowner));
2088  ast_sorcery_object_field_register(sip_sorcery, "endpoint", "sdp_session", "Asterisk", OPT_STRINGFIELD_T, 0, STRFLDSET(struct ast_sip_endpoint, media.sdpsession));
2089  ast_sorcery_object_field_register_custom(sip_sorcery, "endpoint", "tos_audio", "0", tos_handler, tos_audio_to_str, NULL, 0, 0);
2090  ast_sorcery_object_field_register_custom(sip_sorcery, "endpoint", "tos_video", "0", tos_handler, tos_video_to_str, NULL, 0, 0);
2091  ast_sorcery_object_field_register(sip_sorcery, "endpoint", "cos_audio", "0", OPT_UINT_T, 0, FLDSET(struct ast_sip_endpoint, media.cos_audio));
2092  ast_sorcery_object_field_register(sip_sorcery, "endpoint", "cos_video", "0", OPT_UINT_T, 0, FLDSET(struct ast_sip_endpoint, media.cos_video));
2093  ast_sorcery_object_field_register(sip_sorcery, "endpoint", "allow_subscribe", "yes", OPT_BOOL_T, 1, FLDSET(struct ast_sip_endpoint, subscription.allow));
2094  ast_sorcery_object_field_register(sip_sorcery, "endpoint", "sub_min_expiry", "0", OPT_UINT_T, 0, FLDSET(struct ast_sip_endpoint, subscription.minexpiry));
2095  ast_sorcery_object_field_register_custom(sip_sorcery, "endpoint", "from_user", "", from_user_handler, from_user_to_str, NULL, 0, 0);
2096  ast_sorcery_object_field_register(sip_sorcery, "endpoint", "from_domain", "", OPT_STRINGFIELD_T, 0, STRFLDSET(struct ast_sip_endpoint, fromdomain));
2097  ast_sorcery_object_field_register(sip_sorcery, "endpoint", "mwi_from_user", "", OPT_STRINGFIELD_T, 0, STRFLDSET(struct ast_sip_endpoint, subscription.mwi.fromuser));
2098  ast_sorcery_object_field_register(sip_sorcery, "endpoint", "rtp_engine", "asterisk", OPT_STRINGFIELD_T, 0, STRFLDSET(struct ast_sip_endpoint, media.rtp.engine));
2099  ast_sorcery_object_field_register_custom(sip_sorcery, "endpoint", "dtls_verify", "no", dtls_handler, dtlsverify_to_str, NULL, 0, 0);
2100  ast_sorcery_object_field_register_custom(sip_sorcery, "endpoint", "dtls_rekey", "0", dtls_handler, dtlsrekey_to_str, NULL, 0, 0);
2101  ast_sorcery_object_field_register_custom(sip_sorcery, "endpoint", "dtls_auto_generate_cert", "no", dtls_handler, dtlsautogeneratecert_to_str, NULL, 0, 0);
2102  ast_sorcery_object_field_register_custom(sip_sorcery, "endpoint", "dtls_cert_file", "", dtls_handler, dtlscertfile_to_str, NULL, 0, 0);
2103  ast_sorcery_object_field_register_custom(sip_sorcery, "endpoint", "dtls_private_key", "", dtls_handler, dtlsprivatekey_to_str, NULL, 0, 0);
2104  ast_sorcery_object_field_register_custom(sip_sorcery, "endpoint", "dtls_cipher", "", dtls_handler, dtlscipher_to_str, NULL, 0, 0);
2105  ast_sorcery_object_field_register_custom(sip_sorcery, "endpoint", "dtls_ca_file", "", dtls_handler, dtlscafile_to_str, NULL, 0, 0);
2106  ast_sorcery_object_field_register_custom(sip_sorcery, "endpoint", "dtls_ca_path", "", dtls_handler, dtlscapath_to_str, NULL, 0, 0);
2107  ast_sorcery_object_field_register_custom(sip_sorcery, "endpoint", "dtls_setup", "", dtls_handler, dtlssetup_to_str, NULL, 0, 0);
2108  ast_sorcery_object_field_register_custom(sip_sorcery, "endpoint", "dtls_fingerprint", "", dtls_handler, dtlsfingerprint_to_str, NULL, 0, 0);
2109  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));
2110  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));
2111  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));
2112  ast_sorcery_object_field_register_custom(sip_sorcery, "endpoint", "redirect_method", "user", redirect_handler, NULL, NULL, 0, 0);
2113  ast_sorcery_object_field_register_custom(sip_sorcery, "endpoint", "set_var", "", set_var_handler, set_var_to_str, set_var_to_vl, 0, 0);
2114  ast_sorcery_object_field_register(sip_sorcery, "endpoint", "message_context", "", OPT_STRINGFIELD_T, 0, STRFLDSET(struct ast_sip_endpoint, message_context));
2115  ast_sorcery_object_field_register(sip_sorcery, "endpoint", "accountcode", "", OPT_STRINGFIELD_T, 0, STRFLDSET(struct ast_sip_endpoint, accountcode));
2116  ast_sorcery_object_field_register_custom(sip_sorcery, "endpoint", "deny", "", endpoint_acl_handler, NULL, NULL, 0, 0);
2117  ast_sorcery_object_field_register_custom(sip_sorcery, "endpoint", "permit", "", endpoint_acl_handler, NULL, NULL, 0, 0);
2118  ast_sorcery_object_field_register_custom(sip_sorcery, "endpoint", "acl", "", endpoint_acl_handler, acl_to_str, NULL, 0, 0);
2119  ast_sorcery_object_field_register_custom(sip_sorcery, "endpoint", "contact_deny", "", endpoint_acl_handler, NULL, NULL, 0, 0);
2120  ast_sorcery_object_field_register_custom(sip_sorcery, "endpoint", "contact_permit", "", endpoint_acl_handler, NULL, NULL, 0, 0);
2121  ast_sorcery_object_field_register_custom(sip_sorcery, "endpoint", "contact_acl", "", endpoint_acl_handler, contact_acl_to_str, NULL, 0, 0);
2122  ast_sorcery_object_field_register(sip_sorcery, "endpoint", "subscribe_context", "", OPT_CHAR_ARRAY_T, 0, CHARFLDSET(struct ast_sip_endpoint, subscription.context));
2123  ast_sorcery_object_field_register_custom(sip_sorcery, "endpoint", "contact_user", "", contact_user_handler, contact_user_to_str, NULL, 0, 0);
2124  ast_sorcery_object_field_register(sip_sorcery, "endpoint", "preferred_codec_only", "no", OPT_BOOL_T, 1, FLDSET(struct ast_sip_endpoint, preferred_codec_only));
2125  ast_sorcery_object_field_register(sip_sorcery, "endpoint", "asymmetric_rtp_codec", "no", OPT_BOOL_T, 1, FLDSET(struct ast_sip_endpoint, asymmetric_rtp_codec));
2126  ast_sorcery_object_field_register(sip_sorcery, "endpoint", "rtcp_mux", "no", OPT_BOOL_T, 1, FLDSET(struct ast_sip_endpoint, media.rtcp_mux));
2127  ast_sorcery_object_field_register(sip_sorcery, "endpoint", "allow_overlap", "yes", OPT_BOOL_T, 1, FLDSET(struct ast_sip_endpoint, allow_overlap));
2128  ast_sorcery_object_field_register(sip_sorcery, "endpoint", "refer_blind_progress", "yes", OPT_BOOL_T, 1, FLDSET(struct ast_sip_endpoint, refer_blind_progress));
2129  ast_sorcery_object_field_register(sip_sorcery, "endpoint", "notify_early_inuse_ringing", "no", OPT_BOOL_T, 1, FLDSET(struct ast_sip_endpoint, notify_early_inuse_ringing));
2130  ast_sorcery_object_field_register(sip_sorcery, "endpoint", "max_audio_streams", "1", OPT_UINT_T, 0, FLDSET(struct ast_sip_endpoint, media.max_audio_streams));
2131  ast_sorcery_object_field_register(sip_sorcery, "endpoint", "max_video_streams", "1", OPT_UINT_T, 0, FLDSET(struct ast_sip_endpoint, media.max_video_streams));
2132  ast_sorcery_object_field_register(sip_sorcery, "endpoint", "bundle", "no", OPT_BOOL_T, 1, FLDSET(struct ast_sip_endpoint, media.bundle));
2133  ast_sorcery_object_field_register(sip_sorcery, "endpoint", "webrtc", "no", OPT_YESNO_T, 1, FLDSET(struct ast_sip_endpoint, media.webrtc));
2134  ast_sorcery_object_field_register(sip_sorcery, "endpoint", "incoming_mwi_mailbox", "", OPT_STRINGFIELD_T, 0, STRFLDSET(struct ast_sip_endpoint, incoming_mwi_mailbox));
2135  ast_sorcery_object_field_register(sip_sorcery, "endpoint", "follow_early_media_fork", "yes", OPT_BOOL_T, 1, FLDSET(struct ast_sip_endpoint, media.rtp.follow_early_media_fork));
2136  ast_sorcery_object_field_register(sip_sorcery, "endpoint", "accept_multiple_sdp_answers", "no", OPT_BOOL_T, 1, FLDSET(struct ast_sip_endpoint, media.rtp.accept_multiple_sdp_answers));
2137  ast_sorcery_object_field_register(sip_sorcery, "endpoint", "suppress_q850_reason_headers", "no", OPT_BOOL_T, 1, FLDSET(struct ast_sip_endpoint, suppress_q850_reason_headers));
2138  ast_sorcery_object_field_register(sip_sorcery, "endpoint", "ignore_183_without_sdp", "no", OPT_BOOL_T, 1, FLDSET(struct ast_sip_endpoint, ignore_183_without_sdp));
2139  ast_sorcery_object_field_register_custom(sip_sorcery, "endpoint", "incoming_call_offer_pref", "local",
2141  ast_sorcery_object_field_register_custom(sip_sorcery, "endpoint", "outgoing_call_offer_pref", "remote_merge",
2143  ast_sorcery_object_field_register_custom(sip_sorcery, "endpoint", "codec_prefs_incoming_offer",
2144  "prefer: pending, operation: intersect, keep: all, transcode: allow",
2146  ast_sorcery_object_field_register_custom(sip_sorcery, "endpoint", "codec_prefs_outgoing_offer",
2147  "prefer: pending, operation: union, keep: all, transcode: allow",
2149  ast_sorcery_object_field_register_custom(sip_sorcery, "endpoint", "codec_prefs_incoming_answer",
2150  "prefer: pending, operation: intersect, keep: all",
2152  ast_sorcery_object_field_register_custom(sip_sorcery, "endpoint", "codec_prefs_outgoing_answer",
2153  "prefer: pending, operation: intersect, keep: all",
2155  ast_sorcery_object_field_register(sip_sorcery, "endpoint", "stir_shaken", "no", OPT_BOOL_T, 1, FLDSET(struct ast_sip_endpoint, stir_shaken));
2156  ast_sorcery_object_field_register(sip_sorcery, "endpoint", "allow_unauthenticated_options", "no", OPT_BOOL_T, 1, FLDSET(struct ast_sip_endpoint, allow_unauthenticated_options));
2157 
2159  ast_log(LOG_ERROR, "Failed to register SIP transport support with sorcery\n");
2160  ast_sorcery_unref(sip_sorcery);
2161  sip_sorcery = NULL;
2162  return -1;
2163  }
2164 
2166  ast_log(LOG_ERROR, "Failed to register SIP location support with sorcery\n");
2167  ast_sorcery_unref(sip_sorcery);
2168  sip_sorcery = NULL;
2169  return -1;
2170  }
2171 
2172  ast_sorcery_observer_add(sip_sorcery, "endpoint", &endpoint_observers);
2173 
2175  ast_log(LOG_ERROR, "Failed to register SIP domain aliases support with sorcery\n");
2176  ast_sorcery_unref(sip_sorcery);
2177  sip_sorcery = NULL;
2178  return -1;
2179  }
2180 
2182  ast_log(LOG_ERROR, "Failed to register SIP Global support\n");
2183  ast_sorcery_unref(sip_sorcery);
2184  sip_sorcery = NULL;
2185  return -1;
2186  }
2187 
2188  endpoint_formatter = ao2_alloc(sizeof(struct ast_sip_cli_formatter_entry), NULL);
2189  if (!endpoint_formatter) {
2190  ast_log(LOG_ERROR, "Unable to allocate memory for endpoint_formatter\n");
2191  ast_sorcery_unref(sip_sorcery);
2192  sip_sorcery = NULL;
2193  return -1;
2194  }
2195  endpoint_formatter->name = "endpoint";
2196  endpoint_formatter->print_header = cli_endpoint_print_header;
2197  endpoint_formatter->print_body = cli_endpoint_print_body;
2198  endpoint_formatter->get_container = cli_endpoint_get_container;
2199  endpoint_formatter->iterate = cli_endpoint_iterate;
2200  endpoint_formatter->retrieve_by_id = cli_endpoint_retrieve_by_id;
2201  endpoint_formatter->get_id = ast_sorcery_object_get_id;
2202 
2203  ast_sip_register_cli_formatter(endpoint_formatter);
2204  ast_cli_register_multiple(cli_commands, ARRAY_LEN(cli_commands));
2205 
2206  ast_sorcery_load(sip_sorcery);
2207 
2209 
2211 
2215 
2216  return 0;
2217 }
2218 
2220 {
2221  if (!sip_sorcery) {
2222  return;
2223  }
2224 
2225  acl_change_sub = stasis_unsubscribe_and_join(acl_change_sub);
2230  ast_sorcery_unref(sip_sorcery);
2231  sip_sorcery = NULL;
2234  ast_cli_unregister_multiple(cli_commands, ARRAY_LEN(cli_commands));
2235  ast_sip_unregister_cli_formatter(endpoint_formatter);
2237  ao2_cleanup(persistent_endpoints);
2238  persistent_endpoints = NULL;
2239 }
2240 
2242 {
2243  if (sip_sorcery) {
2244  ast_sorcery_reload(sip_sorcery);
2245  }
2246  return 0;
2247 }
2248 
2250 {
2251  ast_string_field_free_memory(&subscription->mwi);
2252  ast_free(subscription->mwi.voicemail_extension);
2253 }
2254 
2256 {
2258 }
2259 
2261 {
2265 }
2266 
2267 static void endpoint_destructor(void* obj)
2268 {
2269  struct ast_sip_endpoint *endpoint = obj;
2270 
2271  ast_string_field_free_memory(endpoint);
2272 
2273  ao2_cleanup(endpoint->media.codecs);
2276  info_configuration_destroy(&endpoint->info);
2277  media_configuration_destroy(&endpoint->media);
2280  ast_party_id_free(&endpoint->id.self);
2283  ao2_cleanup(endpoint->persistent);
2285  AST_VECTOR_FREE(&endpoint->ident_method_order);
2286  ast_free(endpoint->contact_user);
2287  ast_free_acl_list(endpoint->contact_acl);
2288  ast_free_acl_list(endpoint->acl);
2289 }
2290 
2292 {
2293  return ast_string_field_init(&subscription->mwi, 64);
2294 }
2295 
2297 {
2298  return ast_string_field_init(&info->recording, 32);
2299 }
2300 
2302 {
2303  return ast_string_field_init(media, 64) || ast_string_field_init(&media->rtp, 32);
2304 }
2305 
2306 void *ast_sip_endpoint_alloc(const char *name)
2307 {
2309  if (!endpoint) {
2310  return NULL;
2311  }
2312  if (ast_string_field_init(endpoint, 64)) {
2313  ao2_cleanup(endpoint);
2314  return NULL;
2315  }
2316 
2318  ao2_cleanup(endpoint);
2319  return NULL;
2320  }
2322  ao2_cleanup(endpoint);
2323  return NULL;
2324  }
2325  if (init_info_configuration(&endpoint->info)) {
2326  ao2_cleanup(endpoint);
2327  return NULL;
2328  }
2329  if (init_media_configuration(&endpoint->media)) {
2330  ao2_cleanup(endpoint);
2331  return NULL;
2332  }
2333 
2334  ast_party_id_init(&endpoint->id.self);
2335  endpoint->id.self.tag = ast_strdup("");
2336 
2337  if (AST_VECTOR_INIT(&endpoint->ident_method_order, 1)) {
2338  return NULL;
2339  }
2340 
2341  return endpoint;
2342 }
2343 
2345 {
2346  struct ao2_container *endpoints;
2347 
2349 
2350  return endpoints;
2351 }
2352 
2354 {
2357  sip_sorcery, "endpoint", name);
2358 }
2359 
2361 {
2362  int i;
2363 
2364  for (i = 0; i < AST_VECTOR_SIZE(auths); ++i) {
2365  /* Using AST_VECTOR_GET is safe since the vector is immutable */
2366  const char *name = AST_VECTOR_GET(auths, i);
2367  out[i] = ast_sorcery_retrieve_by_id(ast_sip_get_sorcery(), SIP_SORCERY_AUTH_TYPE, name);
2368  if (!out[i]) {
2369  ast_log(LOG_NOTICE, "Couldn't find auth '%s'. Cannot authenticate\n", name);
2370  return -1;
2371  }
2372  }
2373 
2374  return 0;
2375 }
2376 
2377 void ast_sip_cleanup_auths(struct ast_sip_auth *auths[], size_t num_auths)
2378 {
2379  int i;
2380  for (i = 0; i < num_auths; ++i) {
2381  ao2_cleanup(auths[i]);
2382  }
2383 }
2384 
2386  struct ast_sip_auth_objects_vector *auth_objects)
2387 {
2388  int i;
2389 
2390  for (i = 0; i < AST_VECTOR_SIZE(auth_ids); ++i) {
2391  /* Using AST_VECTOR_GET is safe since the vector is immutable */
2392  const char *name = AST_VECTOR_GET(auth_ids, i);
2393  struct ast_sip_auth *auth_object = ast_sorcery_retrieve_by_id(ast_sip_get_sorcery(), SIP_SORCERY_AUTH_TYPE, name);
2394  if (!auth_object) {
2395  ast_log(LOG_WARNING, "Auth object '%s' could not be found\n", name);
2396  } else {
2397  AST_VECTOR_APPEND(auth_objects, auth_object);
2398  }
2399  }
2400 
2401  return AST_VECTOR_SIZE(auth_objects) == AST_VECTOR_SIZE(auth_ids) ? 0 : -1;
2402 }
2403 
2405 {
2406  return sip_sorcery;
2407 }
void ast_sip_persistent_endpoint_publish_contact_state(const char *endpoint_name, const struct ast_sip_contact_status *contact_status)
Publish the change of state for a contact.
#define AST_VECTOR_FREE(vec)
Deallocates this vector.
Definition: vector.h:174
int ast_sip_call_codec_str_to_pref(struct ast_flags *pref, const char *pref_str, int is_outgoing)
Convert a call codec preference string to preference flags.
Definition: res_pjsip.c:5557
struct ast_sip_endpoint_pickup_configuration pickup
Definition: res_pjsip.h:851
static int direct_media_glare_mitigation_to_str(const void *obj, const intptr_t *args, char **buf)
struct ast_str * output_buffer
Definition: res_pjsip_cli.h:36
struct ast_variable * next
const char ** elems
Definition: res_pjsip.h:467
Type for default option handler for format capabilities.
static const char * ast_rtp_dtls_setup_map[]
static int dtlsverify_to_str(const void *obj, const intptr_t *args, char **buf)
static const char type[]
Definition: chan_ooh323.c:109
struct ao2_container *(* get_container)(const char *regex)
Definition: res_pjsip_cli.h:64
#define ARRAY_IN_BOUNDS(v, a)
Checks to see if value is within the bounds of the given array.
Definition: utils.h:658
int ast_sip_retrieve_auths(const struct ast_sip_auth_vector *auths, struct ast_sip_auth **out)
Retrieve relevant SIP auth structures from sorcery.
static char accountcode[AST_MAX_ACCOUNT_CODE]
Definition: chan_iax2.c:428
int presentation
Q.931 encoded presentation-indicator encoded field.
Definition: channel.h:278
static int init_info_configuration(struct ast_sip_endpoint_info_configuration *info)
const char * ast_devstate2str(enum ast_device_state devstate) attribute_pure
Convert device state to text string for output.
Definition: devicestate.c:237
int ast_rtp_dtls_cfg_parse(struct ast_rtp_dtls_cfg *dtls_cfg, const char *name, const char *value)
Parse DTLS related configuration options.
Definition: rtp_engine.c:3020
static int named_groups_handler(const struct aco_option *opt, struct ast_variable *var, void *obj)
struct ast_endpoint * endpoint
Asterisk endpoint itself.
void ast_join_delim(char *s, size_t len, const char *const w[], unsigned int size, char delim)
Definition: main/utils.c:2130
static int codec_prefs_handler(const struct aco_option *opt, struct ast_variable *var, void *obj)
static int outgoing_answer_codec_prefs_to_str(const void *obj, const intptr_t *args, char **buf)
#define AST_CLI_DEFINE(fn, txt,...)
Definition: cli.h:197
ast_device_state
Device States.
Definition: devicestate.h:52
enum ast_sip_dtmf_mode dtmf
Definition: res_pjsip.h:857
struct ast_sip_mwi_configuration mwi
Definition: res_pjsip.h:608
char * str
Subscriber phone number (Malloced)
Definition: channel.h:292
int ast_sip_initialize_sorcery_domain_alias(void)
Initialize sorcery with domain alias support.
const char * ast_named_caller_presentation(int data)
Convert caller ID pres value to text code.
Definition: callerid.c:1182
int ast_sip_auths_to_str(const struct ast_sip_auth_vector *auths, char **buf)
Converts an auths array to a string of comma separated values.
#define AST_LIST_LOCK(head)
Locks a list.
Definition: linkedlists.h:39
A contact&#39;s status.
Definition: res_pjsip.h:341
struct ast_channel_snapshot_base * base
struct ast_variable * ast_sorcery_objectset_create2(const struct ast_sorcery *sorcery, const void *object, enum ast_sorcery_field_handler_flags flags)
Create an object set (KVP list) for an object.
Definition: sorcery.c:1511
void astman_append(struct mansession *s, const char *fmt,...)
Definition: manager.c:3080
enum ast_endpoint_state ast_endpoint_get_state(const struct ast_endpoint *endpoint)
Gets the state of the given endpoint.
unsigned int sess_expires
Definition: res_pjsip.h:567
Asterisk main include file. File version handling, generic pbx functions.
const ast_string_field fromuser
Definition: res_pjsip.h:829
#define AST_LIST_FIRST(head)
Returns the first entry contained in a list.
Definition: linkedlists.h:420
int ast_sip_for_each_channel_snapshot(const struct ast_endpoint_snapshot *endpoint_snapshot, ao2_callback_fn on_channel_snapshot, void *arg)
For every channel snapshot on an endpoint snapshot call the given &#39;on_channel_snapshot&#39; handler...
A SIP address of record.
Definition: res_pjsip.h:361
static int pickupgroup_to_str(const void *obj, const intptr_t *args, char **buf)
int ao2_container_count(struct ao2_container *c)
Returns the number of elements in a container.
const char * ast_stream_codec_prefs_to_str(const struct ast_stream_codec_negotiation_prefs *prefs, struct ast_str **buf)
Return a string representing the codec preferences.
Definition: stream.c:132
int ast_sip_for_each_aor(const char *aors, ao2_callback_fn on_aor, void *arg)
For every aor in the comma separated aors string call the given &#39;on_aor&#39; handler. ...
Definition: location.c:684
#define ARRAY_LEN(a)
Definition: isdn_lib.c:42
static int caller_id_privacy_to_str(const void *obj, const intptr_t *args, char **buf)
static void media_configuration_destroy(struct ast_sip_endpoint_media_configuration *media)
static int dtlscapath_to_str(const void *obj, const intptr_t *args, char **buf)
static const char * id_configuration_refresh_methods[]
char * ast_sip_get_regcontext(void)
Retrieve the global regcontext setting.
Definition: res_pjsip_cli.h:52
struct ast_json * ast_json_pack(char const *format,...)
Helper for creating complex JSON values.
Definition: json.c:591
Endpoint configuration options for INFO packages.
Definition: res_pjsip.h:681
struct ast_flags outgoing_call_offer_pref
Definition: res_pjsip.h:798
Security Event Reporting API.
void(* deleted)(const void *object)
Callback for when an object is deleted.
Definition: sorcery.h:340
static int timers_handler(const struct aco_option *opt, struct ast_variable *var, void *obj)
static int acl_to_str(const void *obj, const intptr_t *args, char **buf)
int ast_callerid_split(const char *src, char *name, int namelen, char *num, int numlen)
Definition: callerid.c:1092
#define CLI_LAST_TABSTOP
Definition: res_pjsip_cli.h:27
#define INFINITY
int presentation
Q.931 presentation-indicator and screening-indicator encoded fields.
Definition: channel.h:296
static int init_subscription_configuration(struct ast_sip_endpoint_subscription_configuration *subscription)
static int set_var_handler(const struct aco_option *opt, struct ast_variable *var, void *obj)
CallerID (and other GR30) management and generation Includes code and algorithms from the Zapata libr...
void ast_variables_destroy(struct ast_variable *var)
Free variable list.
Definition: extconf.c:1263
Definition: ast_expr2.c:325
void ast_res_pjsip_destroy_configuration(void)
static int format_ami_endpoint(const struct ast_sip_endpoint *endpoint, struct ast_sip_ami *ami)
Persistent endpoint information.
int ast_cli_unregister_multiple(struct ast_cli_entry *e, int len)
Unregister multiple commands.
Definition: clicompat.c:30
void ast_sorcery_force_reload_object(const struct ast_sorcery *sorcery, const char *type)
Inform any wizards of a specific object type to reload persistent objects even if no changes determin...
Definition: sorcery.c:1457
struct ast_rtp_dtls_cfg dtls_cfg
DTLS-SRTP configuration information.
Definition: res_pjsip.h:707
static int init_media_configuration(struct ast_sip_endpoint_media_configuration *media)
struct ast_endpoint * ast_endpoint_create(const char *tech, const char *resource)
Create an endpoint struct.
The arg parameter is a search key, but is not an object.
Definition: astobj2.h:1105
struct stasis_topic * ast_security_topic(void)
A stasis_topic which publishes messages for security related issues.
const ast_string_field transport
Definition: res_pjsip.h:817
static const char * media_encryption_map[]
static int add_to_regcontext(void *obj, void *arg, int flags)
void ast_json_unref(struct ast_json *value)
Decrease refcount on value. If refcount reaches zero, value is freed.
Definition: json.c:73
unsigned int devicestate_busy_at
Definition: res_pjsip.h:867
struct ast_party_name name
Subscriber name.
Definition: channel.h:341
#define OBJ_KEY
Definition: astobj2.h:1155
const struct message * m
Definition: res_pjsip.h:2741
char buf[BUFSIZE]
Definition: eagi_proxy.c:66
int ast_sip_initialize_cli(void)
Definition: pjsip_cli.c:360
struct ast_sip_endpoint_nat_configuration nat
Definition: res_pjsip.h:845
#define ast_sorcery_object_field_register_alias(sorcery, type, name, default_val, opt_type, flags,...)
Register a field within an object as an alias.
Definition: sorcery.h:971
static int format_ami_endpoints(void *obj, void *arg, int flags)
static int dtlscafile_to_str(const void *obj, const intptr_t *args, char **buf)
const char * ast_sip_get_device_state(const struct ast_sip_endpoint *endpoint)
Retrieve the device state for an endpoint.
static int voicemail_extension_to_str(const void *obj, const intptr_t *args, char **buf)
const char * ast_endpoint_get_tech(const struct ast_endpoint *endpoint)
Gets the technology of the given endpoint.
int ast_sip_sorcery_object_to_ami(const void *obj, struct ast_str **buf)
Converts a sorcery object to a string of object properties.
#define AST_STREAM_MAX_CODEC_PREFS_LENGTH
Define for allocating buffer space for to_str() functions.
Definition: stream.h:307
#define ast_set_flag(p, flag)
Definition: utils.h:70
enum ast_t38_ec_modes error_correction
Definition: res_pjsip.h:744
void astman_send_list_complete_start(struct mansession *s, const struct message *m, const char *event_name, int count)
Start the list complete event.
Definition: manager.c:3237
Endpoint subscription configuration.
Definition: res_pjsip.h:602
Stasis Message Bus API. See Stasis Message Bus API for detailed documentation.
static int direct_media_method_handler(const struct aco_option *opt, struct ast_variable *var, void *obj)
descriptor for a cli entry.
Definition: cli.h:171
#define LOG_WARNING
Definition: logger.h:274
#define AST_LIST_UNLOCK(head)
Attempts to unlock a list.
Definition: linkedlists.h:139
static int nat
Definition: chan_mgcp.c:168
char * ast_str_buffer(const struct ast_str *buf)
Returns the string buffer within the ast_str buf.
Definition: strings.h:714
char * contact_user
Definition: res_pjsip.h:887
#define ao2_callback(c, flags, cb_fn, arg)
Definition: astobj2.h:1716
static int sip_endpoints_aors_ami(void *obj, void *arg, int flags)
struct ast_endpoint_snapshot * ast_endpoint_latest_snapshot(const char *tech, const char *resource)
Retrieve the most recent snapshot for the endpoint with the given name.
static int ami_show_endpoint(struct mansession *s, const struct message *m)
static int contact_acl_to_str(const void *obj, const intptr_t *args, char **buf)
void * arg
Definition: res_pjsip.h:2745
AMI variable container.
Definition: res_pjsip.h:2737
char name[ACL_NAME_LENGTH]
Definition: acl.h:71
#define ao2_container_alloc_list(ao2_options, container_options, sort_fn, cmp_fn)
Definition: astobj2.h:1335
static void endpoint_deleted_observer(const void *object)
unsigned int flags
Definition: utils.h:200
enum ast_stream_codec_negotiation_prefs_operation_values operation
Definition: stream.h:296
static int set_var_to_str(const void *obj, const intptr_t *args, char **buf)
Structure for variables, used for configurations and for channel variables.
#define AST_VECTOR_APPEND(vec, elem)
Append an element to a vector, growing the vector if needed.
Definition: vector.h:256
struct ast_sip_auth_vector outbound_auths
Definition: res_pjsip.h:855
#define var
Definition: ast_expr2f.c:614
Structure representing a snapshot of channel state.
static int outgoing_offer_codec_prefs_to_str(const void *obj, const intptr_t *args, char **buf)
static int connected_line_method_handler(const struct aco_option *opt, struct ast_variable *var, void *obj)
struct ast_sip_info_recording_configuration recording
Definition: res_pjsip.h:683
static int sip_endpoint_identifier_str2type(const char *str)
void ast_sip_auth_vector_destroy(struct ast_sip_auth_vector *auths)
Free contents of an auth vector.
static void * cli_endpoint_retrieve_by_id(const char *id)
struct ast_format_cap * codecs
Definition: res_pjsip.h:770
struct ast_sip_endpoint_subscription_configuration subscription
Definition: res_pjsip.h:843
Test Framework API.
Perform no matching, return all objects.
Definition: sorcery.h:123
int ast_sorcery_object_id_compare(void *obj, void *arg, int flags)
ao2 object comparator based on sorcery id.
Definition: sorcery.c:2459
const ast_string_field context
Definition: res_pjsip.h:815
static int outbound_auths_to_str(const void *obj, const intptr_t *args, char **buf)
Assume that the ao2_container is already locked.
Definition: astobj2.h:1067
#define CHARFLDSET(type, field)
A helper macro to pass the appropriate arguments to aco_option_register for OPT_CHAR_ARRAY_T.
Full structure for sorcery.
Definition: sorcery.c:230
struct stasis_message_type * stasis_message_type(const struct stasis_message *msg)
Get the message type for a stasis_message.
int(* iterate)(void *container, ao2_callback_fn callback, void *args)
Definition: res_pjsip_cli.h:66
Type for a default handler that should do nothing.
int stasis_subscription_set_filter(struct stasis_subscription *subscription, enum stasis_subscription_message_filter filter)
Set the message type filtering level on a subscription.
Definition: stasis.c:1079
struct stasis_message_type * ast_named_acl_change_type(void)
a stasis_message_type for changes against a named ACL or the set of all named ACLs ...
char * str
Subscriber name (Malloced)
Definition: channel.h:265
enum ast_sip_session_refresh_method method
Definition: res_pjsip.h:733
#define AST_VECTOR_REMOVE_UNORDERED(vec, idx)
Remove an element from an unordered vector by index.
Definition: vector.h:438
Definition: astman.c:222
static int named_callgroups_to_str(const void *obj, const intptr_t *args, char **buf)
static struct stasis_subscription * acl_change_sub
static int t38udptl_ec_to_str(const void *obj, const intptr_t *args, char **buf)
int ast_str_append(struct ast_str **buf, ssize_t max_len, const char *fmt,...)
Append to a thread local dynamic string.
Definition: strings.h:1091
#define ast_cli_register_multiple(e, len)
Register multiple commands.
Definition: cli.h:265
enum ast_stream_codec_negotiation_prefs_prefer_values prefer
Definition: stream.h:294
static int connected_line_method_to_str(const void *obj, const intptr_t *args, char **buf)
static int caller_id_privacy_handler(const struct aco_option *opt, struct ast_variable *var, void *obj)
Return all matching objects.
Definition: sorcery.h:120
struct ast_stream_topology * ast_stream_topology_create_from_format_cap(struct ast_format_cap *cap)
A helper function that, given a format capabilities structure, creates a topology and separates the m...
Definition: stream.c:848
void ast_endpoint_set_state(struct ast_endpoint *endpoint, enum ast_endpoint_state state)
Updates the state of the given endpoint.
static int incoming_call_offer_pref_to_str(const void *obj, const intptr_t *args, char **buf)
static struct @481 methods[]
static int callgroup_to_str(const void *obj, const intptr_t *args, char **buf)
Wrapper for an ast_acl linked list.
Definition: acl.h:76
#define ao2_alloc_options(data_size, destructor_fn, options)
Definition: astobj2.h:406
#define ast_assert(a)
Definition: utils.h:695
#define ao2_link_flags(container, obj, flags)
Definition: astobj2.h:1572
#define AMI_SHOW_ENDPOINT
const char * ast_sip_get_contact_status_label(const enum ast_sip_contact_status_type status)
translate ast_sip_contact_status_type to character string.
static int sip_endpoint_apply_handler(const struct ast_sorcery *sorcery, void *obj)
Callback function for when an object is finalized.
void ast_party_id_free(struct ast_party_id *doomed)
Destroy the party id contents.
Definition: channel.c:1811
#define ast_strdup(str)
A wrapper for strdup()
Definition: astmm.h:243
static int persistent_endpoint_hash(const void *obj, const int flags)
Hashing function for persistent endpoint information.
int ast_sip_str_to_dtmf(const char *dtmf_mode)
Convert the DTMF mode name into an enum.
Definition: res_pjsip.c:5513
const char * str
Definition: app_jack.c:147
int ast_sip_contact_to_str(void *object, void *arg, int flags)
Handler used to convert a contact to a string.
Definition: location.c:767
int ast_str2tos(const char *value, unsigned int *tos)
Convert a string to the appropriate TOS value.
Definition: acl.c:967
static struct ao2_container * cli_endpoint_get_container(const char *regex)
const char * args
#define NULL
Definition: resample.c:96
static int set_var_to_vl(const void *obj, struct ast_variable **fields)
static int outbound_auth_handler(const struct aco_option *opt, struct ast_variable *var, void *obj)
int value
Definition: syslog.c:37
#define ast_to_camel_case(s)
Definition: strings.h:509
const ast_string_field uri
Definition: res_pjsip.h:347
int ast_sip_dtmf_to_str(const enum ast_sip_dtmf_mode dtmf, char *buf, size_t buf_len)
Convert the DTMF mode enum value into a string.
Definition: res_pjsip.c:5484
static int media_encryption_to_str(const void *obj, const intptr_t *args, char **buf)
struct ao2_container * ast_sip_get_endpoints(void)
Retrieve any endpoints available to sorcery.
void ast_free_ptr(void *ptr)
free() wrapper
Definition: astmm.c:1771
static char cid_num[AST_MAX_EXTENSION]
Definition: chan_mgcp.c:164
static int ident_handler(const struct aco_option *opt, struct ast_variable *var, void *obj)
struct ast_sip_direct_media_configuration direct_media
Definition: res_pjsip.h:766
void astman_send_error_va(struct mansession *s, const struct message *m, const char *fmt,...)
Send error in manager transaction (with va_args support)
Definition: manager.c:3164
ast_endpoint_state
Valid states for an endpoint.
Definition: endpoints.h:51
static int dtlscertfile_to_str(const void *obj, const intptr_t *args, char **buf)
#define ast_verb(level,...)
Definition: logger.h:463
const char * ast_endpoint_get_resource(const struct ast_endpoint *endpoint)
Gets the resource name of the given endpoint.
char * ast_sip_cli_traverse_objects(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
Definition: pjsip_cli.c:109
enum ast_sip_endpoint_identifier_type ident_method
Definition: res_pjsip.h:859
unsigned int use_received_transport
Definition: res_pjsip.h:705
Media Stream API.
static void acl_change_stasis_cb(void *data, struct stasis_subscription *sub, struct stasis_message *message)
struct ao2_container * ast_sorcery_retrieve_by_regex(const struct ast_sorcery *sorcery, const char *type, const char *regex)
Retrieve multiple objects using a regular expression on their id.
Definition: sorcery.c:1949
int ast_context_remove_extension(const char *context, const char *extension, int priority, const char *registrar)
Simply remove extension from context.
Definition: pbx.c:4952
Utility functions.
char * ast_print_group(char *buf, int buflen, ast_group_t group)
Print call and pickup groups into buffer.
Definition: channel.c:8133
#define ast_asprintf(ret, fmt,...)
A wrapper for asprintf()
Definition: astmm.h:269
const char * ast_sorcery_object_get_type(const void *object)
Get the type of a sorcery object.
Definition: sorcery.c:2324
char * ast_str_truncate(struct ast_str *buf, ssize_t len)
Truncates the enclosed string to the given length.
Definition: strings.h:738
const char * astman_get_header(const struct message *m, char *var)
Get header from mananger transaction.
Definition: manager.c:2820
static struct ast_endpoint * persistent_endpoint_find_or_create(const struct ast_sip_endpoint *endpoint)
Internal function which finds (or creates) persistent endpoint information.
#define ast_strlen_zero(foo)
Definition: strings.h:52
#define AMI_DEFAULT_STR_SIZE
void * ast_sorcery_retrieve_by_id(const struct ast_sorcery *sorcery, const char *type, const char *id)
Retrieve an object using its unique identifier.
Definition: sorcery.c:1853
int ast_res_pjsip_initialize_configuration(void)
int ast_sip_register_cli_formatter(struct ast_sip_cli_formatter_entry *formatter)
Registers a CLI formatter.
Definition: pjsip_cli.c:310
struct ast_acl_list * acl
Definition: res_pjsip.h:881
#define ast_sorcery_unref(sorcery)
Decrease the reference count of a sorcery structure.
Definition: sorcery.h:1502
static int incoming_offer_codec_prefs_to_str(const void *obj, const intptr_t *args, char **buf)
static void cli_endpoint_print_child_header(char *type, struct ast_sip_cli_context *context)
static int tos_handler(const struct aco_option *opt, struct ast_variable *var, void *obj)
struct ast_sip_endpoint_media_configuration media
Definition: res_pjsip.h:841
Number structure.
Definition: app_followme.c:154
Type for default option handler for character array strings.
struct ast_sip_cli_formatter_entry * endpoint_formatter
static int dtlssetup_to_str(const void *obj, const intptr_t *args, char **buf)
int ast_str_set(struct ast_str **buf, ssize_t max_len, const char *fmt,...)
Set a dynamic string using variable arguments.
Definition: strings.h:1065
Type for default option handler for bools (ast_true/ast_false)
unsigned int min_se
Definition: res_pjsip.h:565
static int call_offer_pref_handler(const struct aco_option *opt, struct ast_variable *var, void *obj)
static int dtls_handler(const struct aco_option *opt, struct ast_variable *var, void *obj)
static int dtlsfingerprint_to_str(const void *obj, const intptr_t *args, char **buf)
struct ast_sip_cli_formatter_entry * channel_formatter
#define ast_stream_codec_operation_to_str(value)
Safely get the name of an "operation" parameter value.
Definition: stream.h:264
#define EVENT_FLAG_SYSTEM
Definition: manager.h:71
static const char * sip_endpoint_identifier_type2str(enum ast_sip_endpoint_identifier_type method)
int() ao2_callback_fn(void *obj, void *arg, int flags)
Type of a generic callback function.
Definition: astobj2.h:1230
#define ast_log
Definition: astobj2.c:42
static int direct_media_glare_mitigation_handler(const struct aco_option *opt, struct ast_variable *var, void *obj)
static const char * ast_t38_ec_modes_map[]
#define ast_sorcery_object_field_register_custom(sorcery, type, name, default_val, config_handler, sorcery_handler, multiple_handler, flags,...)
Register a field within an object with custom handlers.
Definition: sorcery.h:1005
static struct ast_cli_entry cli_commands[]
struct ast_sip_endpoint * ast_sip_default_outbound_endpoint(void)
Retrieve the default outbound endpoint.
struct ast_sip_identify_by_vector ident_method_order
Definition: res_pjsip.h:861
Structure for SIP nat hook information.
Definition: res_pjsip.h:271
static int contact_user_to_str(const void *obj, const intptr_t *args, char **buf)
#define FLDSET(type,...)
Convert a struct and list of fields to an argument list of field offsets.
#define AST_VECTOR_INIT(vec, size)
Initialize a vector.
Definition: vector.h:113
int ast_devstate_changed(enum ast_device_state state, enum ast_devstate_cache cachable, const char *fmt,...)
Tells Asterisk the State for Device is changed.
Definition: devicestate.c:510
char * ast_callerid_merge(char *buf, int bufsiz, const char *name, const char *num, const char *unknown)
Definition: callerid.c:1073
struct ast_namedgroups * named_pickupgroups
Definition: res_pjsip.h:663
const char * ast_sip_call_codec_pref_to_str(struct ast_flags pref)
Convert the call codec preference flags to a string.
Definition: res_pjsip.c:5534
static int persistent_endpoint_cmp(void *obj, void *arg, int flags)
Comparison function for persistent endpoint information.
void astman_send_list_complete_end(struct mansession *s)
End the list complete event.
Definition: manager.c:3245
int ast_sip_retrieve_auths_vector(const struct ast_sip_auth_vector *auth_ids, struct ast_sip_auth_objects_vector *auth_objects)
int ast_sip_initialize_sorcery_transport(void)
Initialize sorcery with transport support.
static int dtmf_to_str(const void *obj, const intptr_t *args, char **buf)
struct ast_acl_list * contact_acl
Definition: res_pjsip.h:883
#define AST_VECTOR_ELEM_CLEANUP_NOOP(elem)
Vector element cleanup that does nothing.
Definition: vector.h:573
#define RAII_VAR(vartype, varname, initval, dtor)
Declare a variable that will call a destructor function when it goes out of scope.
Definition: utils.h:911
Type for default option handler for unsigned integers.
int ast_variable_list_replace(struct ast_variable **head, struct ast_variable *replacement)
Replace a variable in the given list with a new value.
Definition: main/config.c:668
static int dtlscipher_to_str(const void *obj, const intptr_t *args, char **buf)
int ast_sip_format_endpoint_ami(struct ast_sip_endpoint *endpoint, struct ast_sip_ami *ami, int *count)
Formats the endpoint and sends over AMI.
Definition: res_pjsip.c:3699
#define ast_string_field_init(x, size)
Initialize a field pool and fields.
Definition: stringfields.h:353
#define CLI_INDENT_TO_SPACES(x)
Definition: res_pjsip_cli.h:29
static int dtlsautogeneratecert_to_str(const void *obj, const intptr_t *args, char **buf)
int ast_sip_auth_vector_init(struct ast_sip_auth_vector *auths, const char *value)
Initialize an auth vector with the configured values.
Access Control of various sorts.
static struct ao2_container * codecs
Registered codecs.
Definition: codec.c:48
static int tos_audio_to_str(const void *obj, const intptr_t *args, char **buf)
ast_mutex_t lock
Definition: app_meetme.c:1091
static char mohsuggest[MAX_MUSICCLASS]
Definition: chan_iax2.c:430
static int sip_endpoint_to_ami(const struct ast_sip_endpoint *endpoint, struct ast_str **buf)
char * ast_strip(char *s)
Strip leading/trailing whitespace from a string.
Definition: strings.h:219
struct ast_sip_media_rtp_configuration rtp
Definition: res_pjsip.h:764
static struct ao2_container * endpoints
void ast_sip_destroy_cli(void)
Definition: pjsip_cli.c:375
#define ao2_ref(o, delta)
Definition: astobj2.h:464
#define S_COR(a, b, c)
returns the equivalent of logic or for strings, with an additional boolean check: second one if not e...
Definition: strings.h:85
Use string handler only.
Definition: sorcery.h:137
In case you didn&#39;t read that giant block of text above the mansession_session struct, the struct mansession is named this solely to keep the API the same in Asterisk. This structure really represents data that is different from Manager action to Manager action. The mansession_session pointer contained within points to session-specific data.
Definition: manager.c:1625
int ast_sip_destroy_sorcery_auth(void)
Definition: config_auth.c:426
#define ast_strdupa(s)
duplicate a string in memory from the stack
Definition: astmm.h:300
int ast_sorcery_object_id_sort(const void *obj, const void *arg, int flags)
ao2 object sorter based on sorcery id.
Definition: sorcery.c:2435
static int inbound_auth_handler(const struct aco_option *opt, struct ast_variable *var, void *obj)
char * ast_sip_global_default_outbound_endpoint(void)
const char * ast_sorcery_object_get_id(const void *object)
Get the unique identifier of a sorcery object.
Definition: sorcery.c:2312
struct ast_stream_codec_negotiation_prefs codec_prefs_outgoing_answer
Definition: res_pjsip.h:806
void *(* retrieve_by_id)(const char *id)
Definition: res_pjsip_cli.h:68
struct ast_namedgroups * named_callgroups
Definition: res_pjsip.h:661
ast_stream_codec_negotiation_prefs_operation_values
The "operation" values.
Definition: stream.h:159
const char * method
Definition: res_pjsip.c:4335
struct mansession * s
Definition: res_pjsip.h:2739
static char language[MAX_LANGUAGE]
Definition: chan_alsa.c:117
enum ast_rtp_dtls_hash hash
Definition: rtp_engine.h:559
#define ast_malloc(len)
A wrapper for malloc()
Definition: astmm.h:193
struct ao2_container * container
Definition: res_fax.c:502
static void sip_sorcery_object_ami_set_type_name(const void *obj, struct ast_str **buf)
static void load_all_endpoints(void)
static int cli_endpoint_print_header(void *obj, void *arg, int flags)
#define ast_variable_new(name, value, filename)
ast_group_t ast_get_group(const char *s)
Definition: channel.c:7718
an ast_acl is a linked list node of ast_ha structs which may have names.
Definition: acl.h:67
int ast_sip_unregister_cli_formatter(struct ast_sip_cli_formatter_entry *formatter)
Unregisters a CLI formatter.
Definition: pjsip_cli.c:326
An entity with which Asterisk communicates.
Definition: res_pjsip.h:812
static int timers_to_str(const void *obj, const intptr_t *args, char **buf)
static int voicemail_extension_handler(const struct aco_option *opt, struct ast_variable *var, void *obj)
int ast_exists_extension(struct ast_channel *c, const char *context, const char *exten, int priority, const char *callerid)
Determine whether an extension exists.
Definition: pbx.c:4179
enum ast_sip_session_refresh_method refresh_method
Definition: res_pjsip.h:647
#define ast_format_cap_alloc(flags)
Definition: format_cap.h:52
static struct ao2_container * persistent_endpoints
Container for persistent endpoint information.
#define ast_sorcery_object_register(sorcery, type, alloc, transform, apply)
Register an object type.
Definition: sorcery.h:838
#define MAX_OBJECT_FIELD
Maximum length of an object field name.
Definition: sorcery.h:110
void ast_sip_cleanup_auths(struct ast_sip_auth *auths[], size_t num_auths)
Clean up retrieved auth structures from memory.
Core PBX routines and definitions.
int ast_parse_caller_presentation(const char *data)
Convert caller ID text code to value (used in config file parsing)
Definition: callerid.c:1143
static int tos_video_to_str(const void *obj, const intptr_t *args, char **buf)
void * ast_sip_endpoint_alloc(const char *name)
Allocate a new SIP endpoint.
enum ast_stream_codec_negotiation_prefs_keep_values keep
Definition: stream.h:298
ast_sip_endpoint_identifier_type
Different methods by which incoming requests can be matched to endpoints.
Definition: res_pjsip.h:472
A snapshot of an endpoint&#39;s state.
int ast_acl_list_is_empty(struct ast_acl_list *acl_list)
Determines if an ACL is empty or if it contains entries.
Definition: acl.c:541
#define stasis_subscribe(topic, callback, data)
Definition: stasis.h:652
int ast_sorcery_observer_add(const struct ast_sorcery *sorcery, const char *type, const struct ast_sorcery_observer *callbacks)
Add an observer to a specific object type.
Definition: sorcery.c:2386
enum ast_sip_contact_status_type status
Definition: res_pjsip.h:351
#define ast_alloca(size)
call __builtin_alloca to ensure we get gcc builtin semantics
Definition: astmm.h:290
struct ast_sip_endpoint_id_configuration id
Definition: res_pjsip.h:847
static void * sip_nat_hook_alloc(const char *name)
enum ast_sip_session_media_encryption encryption
Definition: res_pjsip.h:711
int ast_manager_unregister(const char *action)
Unregister a registered manager command.
Definition: manager.c:7258
The AMI - Asterisk Manager Interface - is a TCP protocol created to manage Asterisk with third-party ...
int ast_stream_codec_prefs_parse(const char *pref_string, struct ast_stream_codec_negotiation_prefs *prefs, struct ast_str **error_message)
Parses a string representing the codec prefs into a ast_stream_codec_negotiation_pref structure...
Definition: stream.c:181
static int t38udptl_ec_handler(const struct aco_option *opt, struct ast_variable *var, void *obj)
static void endpoint_destructor(void *obj)
static void persistent_endpoint_destroy(void *obj)
Destructor function for persistent endpoint information.
unsigned int enabled
Definition: rtp_engine.h:555
enum ast_rtp_dtls_setup default_setup
Definition: rtp_engine.h:557
static int outgoing_call_offer_pref_to_str(const void *obj, const intptr_t *args, char **buf)
void ast_sip_location_prune_boot_contacts(void)
Prune the prune_on_boot contacts.
Definition: location.c:469
struct ast_namedgroups * ast_get_namedgroups(const char *s)
Create an ast_namedgroups set with group names from comma separated string.
Definition: channel.c:7775
struct ast_sip_endpoint_info_configuration info
Definition: res_pjsip.h:849
#define LOG_ERROR
Definition: logger.h:285
#define ao2_container_alloc_hash(ao2_options, container_options, n_buckets, hash_fn, sort_fn, cmp_fn)
Definition: astobj2.h:1310
struct ast_sorcery * ast_sip_get_sorcery(void)
Get a pointer to the SIP sorcery structure.
#define ast_sorcery_internal_object_register(sorcery, type, alloc, transform, apply)
Register an internal, hidden object type.
Definition: sorcery.h:868
int attribute_pure ast_true(const char *val)
Make sure something is true. Determine if a string containing a boolean value is "true". This function checks to see whether a string passed to it is an indication of an "true" value. It checks to see if the string is "yes", "true", "y", "t", "on" or "1".
Definition: main/utils.c:1951
struct ast_sip_auth_vector inbound_auths
Definition: res_pjsip.h:853
struct ast_str * ast_sip_create_ami_event(const char *event, struct ast_sip_ami *ami)
Creates a string to store AMI event data in.
The descriptor of a dynamic string XXX storage will be optimized later if needed We use the ts field ...
Definition: strings.h:584
char * usage
Definition: utils/frame.c:37
enum ast_rtp_dtls_verify verify
Definition: rtp_engine.h:560
int ao2_container_dup(struct ao2_container *dest, struct ao2_container *src, enum search_flags flags)
Copy all object references in the src container into the dest container.
static struct ast_sorcery * sip_sorcery
Media configuration for SIP endpoints.
Definition: res_pjsip.h:756
Interface for a sorcery object type observer.
Definition: sorcery.h:332
static int active_channels_to_str_cb(void *object, void *arg, int flags)
Type for default option handler for bools (ast_true/ast_false)
struct ast_acl_list * ast_free_acl_list(struct ast_acl_list *acl)
Free a list of ACLs.
Definition: acl.c:233
def info(msg)
struct stasis_message_type * ast_endpoint_state_type(void)
Message type for endpoint state changes.
static int ident_to_str(const void *obj, const intptr_t *args, char **buf)
#define ast_sorcery_apply_default(sorcery, type, name, data)
Definition: sorcery.h:477
struct ast_endpoint_snapshot * ast_sip_get_endpoint_snapshot(const struct ast_sip_endpoint *endpoint)
Retrieve the endpoint snapshot for an endpoint.
static int media_encryption_handler(const struct aco_option *opt, struct ast_variable *var, void *obj)
static int ami_show_endpoints(struct mansession *s, const struct message *m)
static int contact_user_handler(const struct aco_option *opt, struct ast_variable *var, void *obj)
static int group_handler(const struct aco_option *opt, struct ast_variable *var, void *obj)
def ignore(key=None, val=None, section=None, pjsip=None, nmapped=None, type='endpoint')
Definition: sip_to_pjsip.py:48
static int incoming_answer_codec_prefs_to_str(const void *obj, const intptr_t *args, char **buf)
#define ao2_alloc(data_size, destructor_fn)
Definition: astobj2.h:411
static int from_user_to_str(const void *obj, const intptr_t *args, char **buf)
struct ast_sip_t38_configuration t38
Definition: res_pjsip.h:768
const char * action_id
Definition: res_pjsip.h:2743
static int caller_id_tag_to_str(const void *obj, const intptr_t *args, char **buf)
#define LOG_NOTICE
Definition: logger.h:263
int ast_sip_destroy_sorcery_global(void)
static void cli_endpoint_print_child_body(char *type, const void *obj, struct ast_sip_cli_context *context)
int ast_rtp_dtls_cfg_validate(struct ast_rtp_dtls_cfg *dtls_cfg)
Validates DTLS related configuration options.
Definition: rtp_engine.c:3094
unsigned int preferred_codec_only
Definition: res_pjsip.h:889
static const char * direct_media_glare_mitigation_map[]
struct ast_sip_timer_options timer
Definition: res_pjsip.h:580
#define SCOPED_AO2LOCK(varname, obj)
scoped lock specialization for ao2 mutexes.
Definition: lock.h:602
static const char name[]
Definition: cdr_mysql.c:74
#define ast_free(a)
Definition: astmm.h:182
char * command
Definition: cli.h:186
#define ast_calloc(num, len)
A wrapper for calloc()
Definition: astmm.h:204
#define AST_VECTOR_RESET(vec, cleanup)
Reset vector.
Definition: vector.h:627
static int regex(struct ast_channel *chan, const char *cmd, char *parse, char *buf, size_t len)
Definition: func_strings.c:948
static int prack_handler(const struct aco_option *opt, struct ast_variable *var, void *obj)
static void subscription_configuration_destroy(struct ast_sip_endpoint_subscription_configuration *subscription)
static void info_configuration_destroy(struct ast_sip_endpoint_info_configuration *info)
enum ast_sip_direct_media_glare_mitigation glare_mitigation
Definition: res_pjsip.h:735
static const char * ast_rtp_dtls_fingerprint_map[]
int stacklen
Definition: extconf.h:238
struct ast_stream_codec_negotiation_prefs codec_prefs_incoming_answer
Definition: res_pjsip.h:804
#define STRFLDSET(type,...)
Convert a struct and a list of stringfield fields to an argument list of field offsets.
struct stasis_subscription * stasis_unsubscribe_and_join(struct stasis_subscription *subscription)
Cancel a subscription, blocking until the last message is processed.
Definition: stasis.c:1136
static int prack_to_str(const void *obj, const intptr_t *args, char **buf)
#define ao2_find(container, arg, flags)
Definition: astobj2.h:1756
unsigned int ephemeral_cert
Definition: rtp_engine.h:566
const char *(* get_id)(const void *obj)
Definition: res_pjsip_cli.h:70
void ast_party_id_init(struct ast_party_id *init)
Initialize the given party id structure.
Definition: channel.c:1757
int ast_sip_initialize_sorcery_auth(void)
Initialize sorcery with auth support.
Definition: config_auth.c:370
static int caller_id_to_str(const void *obj, const intptr_t *args, char **buf)
static int endpoint_acl_handler(const struct aco_option *opt, struct ast_variable *var, void *obj)
Structure used to handle boolean flags.
Definition: utils.h:199
#define PERSISTENT_BUCKETS
Number of buckets for persistent endpoint information.
#define ast_clear_flag(p, flag)
Definition: utils.h:77
static char cid_name[AST_MAX_EXTENSION]
Definition: chan_mgcp.c:165
void * ast_sorcery_retrieve_by_fields(const struct ast_sorcery *sorcery, const char *type, unsigned int flags, struct ast_variable *fields)
Retrieve an object or multiple objects using specific fields.
Definition: sorcery.c:1897
void ast_endpoint_blob_publish(struct ast_endpoint *endpoint, struct stasis_message_type *type, struct ast_json *blob)
Creates and publishes a ast_endpoint_blob message.
#define ast_sorcery_object_field_register(sorcery, type, name, default_val, opt_type, flags,...)
Register a field within an object.
Definition: sorcery.h:955
void ast_sorcery_load(const struct ast_sorcery *sorcery)
Inform any wizards to load persistent objects.
Definition: sorcery.c:1377
#define AST_YESNO(x)
return Yes or No depending on the argument.
Definition: strings.h:139
int ast_sip_destroy_sorcery_location(void)
Definition: location.c:1467
char * tag
User-set "tag".
Definition: channel.h:355
void ast_sorcery_reload(const struct ast_sorcery *sorcery)
Inform any wizards to reload persistent objects.
Definition: sorcery.c:1408
struct ast_endpoint * persistent
Definition: res_pjsip.h:865
static int caller_id_tag_handler(const struct aco_option *opt, struct ast_variable *var, void *obj)
static int dtlsprivatekey_to_str(const void *obj, const intptr_t *args, char **buf)
#define AST_VECTOR_GET(vec, idx)
Get an element from a vector.
Definition: vector.h:682
static int codec_prefs_to_str(const struct ast_stream_codec_negotiation_prefs *prefs, const void *obj, const intptr_t *args, char **buf)
char * strsep(char **str, const char *delims)
int ast_res_pjsip_reload_configuration(void)
FILE * out
Definition: utils/frame.c:33
static struct ast_sorcery * sorcery
int ast_add_extension(const char *context, int replace, const char *extension, int priority, const char *label, const char *callerid, const char *application, void *data, void(*datad)(void *), const char *registrar)
Add and extension to an extension context.
Definition: pbx.c:6970
struct ast_stream_topology * topology
Definition: res_pjsip.h:772
struct ast_channel_snapshot * ast_channel_snapshot_get_latest(const char *uniqueid)
Obtain the latest ast_channel_snapshot from the Stasis Message Bus API cache. This is an ao2 object...
#define ao2_cleanup(obj)
Definition: astobj2.h:1958
struct ast_party_id self
Definition: res_pjsip.h:629
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition: strings.h:401
void ast_append_acl(const char *sense, const char *stuff, struct ast_acl_list **path, int *error, int *named_acl_flag)
Add a rule to an ACL struct.
Definition: acl.c:430
static int dtmf_handler(const struct aco_option *opt, struct ast_variable *var, void *obj)
void ast_rtp_dtls_cfg_free(struct ast_rtp_dtls_cfg *dtls_cfg)
Free contents of a DTLS configuration structure.
Definition: rtp_engine.c:3131
int attribute_pure ast_false(const char *val)
Make sure something is false. Determine if a string containing a boolean value is "false"...
Definition: main/utils.c:1968
enum ast_stream_codec_negotiation_prefs_transcode_values transcode
Definition: stream.h:300
int ast_sip_persistent_endpoint_add_to_regcontext(const char *regcontext)
static PGresult * result
Definition: cel_pgsql.c:88
int ast_sip_initialize_sorcery_global(void)
int stasis_subscription_accept_message_type(struct stasis_subscription *subscription, const struct stasis_message_type *type)
Indicate to a subscription that we are interested in a message type.
Definition: stasis.c:1025
static int direct_media_method_to_str(const void *obj, const intptr_t *args, char **buf)
struct stasis_forward * sub
Definition: res_corosync.c:240
#define ast_sorcery_open()
Definition: sorcery.h:408
static int from_user_handler(const struct aco_option *opt, struct ast_variable *var, void *obj)
static int cli_endpoint_iterate(void *obj, ao2_callback_fn callback, void *args)
static void active_channels_to_str(const struct ast_sip_endpoint *endpoint, struct ast_str **str)
static char regcontext[AST_MAX_CONTEXT]
Definition: chan_iax2.c:321
struct stasis_message_type * ast_endpoint_contact_state_type(void)
Message type for endpoint contact state changes.
struct ast_sip_endpoint_extensions extensions
Definition: res_pjsip.h:839
Abstract JSON element (object, array, string, int, ...).
Type for default option handler for stringfields.
#define ast_stream_codec_param_to_str(value)
Safely get the name of a preference parameter.
Definition: stream.h:244
ao2_callback_fn * print_header
Definition: res_pjsip_cli.h:60
static int named_pickupgroups_to_str(const void *obj, const intptr_t *args, char **buf)
ast_stream_codec_negotiation_prefs_prefer_values
The "prefer" values.
Definition: stream.h:145
int error(const char *format,...)
Definition: utils/frame.c:999
struct ast_sip_cli_formatter_entry * ast_sip_lookup_cli_formatter(const char *name)
Looks up a CLI formatter by type.
Definition: pjsip_cli.c:305
Generic container type.
unsigned char valid
TRUE if the name information is valid/present.
Definition: channel.h:280
struct ast_namedgroups * ast_unref_namedgroups(struct ast_namedgroups *groups)
Definition: channel.c:7832
static char context[AST_MAX_CONTEXT]
Definition: chan_alsa.c:116
struct ast_variable * channel_vars
Definition: res_pjsip.h:875
int ast_sip_destroy_sorcery_transport(void)
static int redirect_handler(const struct aco_option *opt, struct ast_variable *var, void *obj)
void * ast_sorcery_generic_alloc(size_t size, ao2_destructor_fn destructor)
Allocate a generic sorcery capable object.
Definition: sorcery.c:1728
struct ast_context * ast_context_find_or_create(struct ast_context **extcontexts, struct ast_hashtab *exttable, const char *name, const char *registrar)
Register a new context or find an existing one.
Definition: pbx.c:6198
int ast_sip_for_each_contact(const struct ast_sip_aor *aor, ao2_callback_fn on_contact, void *arg)
For every contact on an AOR call the given &#39;on_contact&#39; handler.
Definition: location.c:719
void ast_stream_topology_free(struct ast_stream_topology *topology)
Unreference and destroy a stream topology.
Definition: stream.c:743
const ast_string_field aors
Definition: res_pjsip.h:821
static const struct ast_sorcery_observer endpoint_observers
struct ast_flags incoming_call_offer_pref
Definition: res_pjsip.h:796
#define ast_manager_register_xml(action, authority, func)
Register a manager callback using XML documentation to describe the manager.
Definition: manager.h:186
int ast_sip_persistent_endpoint_update_state(const char *endpoint_name, enum ast_endpoint_state state)
Change state of a persistent endpoint.
static int cli_endpoint_print_body(void *obj, void *arg, int flags)
ao2_callback_fn * print_body
Definition: res_pjsip_cli.h:62
void ast_endpoint_shutdown(struct ast_endpoint *endpoint)
Shutsdown an ast_endpoint.
static int format_str_append_auth(const struct ast_sip_auth_vector *auths, struct ast_str **buf)
void astman_send_error(struct mansession *s, const struct message *m, char *error)
Send error in manager transaction.
Definition: manager.c:3159
int ast_sip_cli_print_sorcery_objectset(void *obj, void *arg, int flags)
Prints a sorcery object&#39;s ast_variable list.
Definition: pjsip_cli.c:36
const char * name
Definition: res_pjsip_cli.h:58
unsigned int rekey
Definition: rtp_engine.h:556
struct ast_exten * pbx_find_extension(struct ast_channel *chan, struct ast_context *bypass, struct pbx_find_info *q, const char *context, const char *exten, int priority, const char *label, const char *callerid, enum ext_match_t action)
Definition: ael_main.c:152
char * ast_print_namedgroups(struct ast_str **buf, struct ast_namedgroups *groups)
Print named call groups and named pickup groups.
Definition: channel.c:8158
struct ast_stream_codec_negotiation_prefs codec_prefs_outgoing_offer
Definition: res_pjsip.h:802
struct ast_stream_codec_negotiation_prefs codec_prefs_incoming_offer
Definition: res_pjsip.h:800
static int inbound_auths_to_str(const void *obj, const intptr_t *args, char **buf)
#define ast_string_field_free_memory(x)
free all memory - to be called before destroying the object
Definition: stringfields.h:368
enum ast_sip_session_redirect redirect_method
Definition: res_pjsip.h:873
int ast_sip_initialize_sorcery_location(void)
Initialize sorcery with location support.
Definition: location.c:1366
static int dtlsrekey_to_str(const void *obj, const intptr_t *args, char **buf)
struct ast_variable * ast_variables_dup(struct ast_variable *var)
Duplicate variable list.
Definition: main/config.c:545
unsigned char valid
TRUE if the number information is valid/present.
Definition: channel.h:298
const ast_string_field aor
Definition: res_pjsip.h:347
#define AST_VECTOR_SIZE(vec)
Get the number of elements in a vector.
Definition: vector.h:611
#define ast_variable_list_append(head, new_var)
const ast_string_field name
#define ast_str_create(init_len)
Create a malloc&#39;ed dynamic length string.
Definition: strings.h:620
Sorcery Data Access Layer API.
static int caller_id_handler(const struct aco_option *opt, struct ast_variable *var, void *obj)
static force_inline int attribute_pure ast_str_hash(const char *str)
Compute a hash value on a string.
Definition: strings.h:1206
#define ast_string_field_set(x, field, data)
Set a field to a simple string value.
Definition: stringfields.h:514
#define AMI_SHOW_ENDPOINTS
void astman_send_listack(struct mansession *s, const struct message *m, char *msg, char *listflag)
Send ack in manager transaction to begin a list.
Definition: manager.c:3201
unsigned show_details_only_level_0
Definition: res_pjsip_cli.h:46
struct ast_party_number number
Subscriber phone number.
Definition: channel.h:343
int ast_sip_for_each_channel(const struct ast_sip_endpoint *endpoint, ao2_callback_fn on_channel_snapshot, void *arg)
For every channel snapshot on an endpoint all the given &#39;on_channel_snapshot&#39; handler.