23 #include "asterisk/res_pjsip.h"
29 #include "include/res_pjsip_private.h"
30 #include "asterisk/res_pjsip_cli.h"
31 #include "asterisk/statsd.h"
34 #include "asterisk/res_pjproject.h"
36 static int pj_max_hostname = PJ_MAX_HOSTNAME;
37 static int pjsip_max_url_size = PJSIP_MAX_URL_SIZE;
40 static void aor_destroy(
void *obj)
50 static void *aor_alloc(
const char *name)
72 static int destroy_contact(
void *obj,
void *arg,
int flags)
76 ast_sip_location_delete_contact(contact);
81 static void aor_deleted_observer(
const void *
object)
86 size_t prefix_len = strlen(aor_id) +
sizeof(
";@") - 1;
87 char prefix[prefix_len + 1];
94 sprintf(prefix,
"%s;@", aor_id);
106 .
deleted = aor_deleted_observer,
111 static void contact_destroy(
void *obj)
120 static void *contact_alloc(
const char *name)
125 char *aor_separator = NULL;
132 ao2_cleanup(contact);
137 if ((aor_separator = strstr(
id,
";@")) || (aor_separator = strstr(
id,
"@@"))) {
138 *aor_separator =
'\0';
140 ast_assert(aor_separator != NULL);
147 struct ast_sip_aor *ast_sip_location_retrieve_aor(
const char *aor_name)
153 static int contact_expire(
void *obj,
void *arg,
int flags)
162 ast_sip_location_delete_contact(contact);
168 static int contact_link_static(
void *obj,
void *arg,
int flags)
177 static int contact_remove_unreachable(
void *obj,
void *arg,
int flags)
183 status = ast_sip_get_contact_status(contact);
188 unreachable = (status->
status == UNAVAILABLE);
196 return ast_sip_location_retrieve_first_aor_contact_filtered(aor, AST_SIP_CONTACT_FILTER_DEFAULT);
205 contacts = ast_sip_location_retrieve_aor_contacts_filtered(aor, flags);
210 ao2_cleanup(contacts);
216 return ast_sip_location_retrieve_aor_contacts_nolock_filtered(aor, AST_SIP_CONTACT_FILTER_DEFAULT);
224 char prefix[prefix_len + 1];
240 if (flags & AST_SIP_CONTACT_FILTER_REACHABLE) {
249 return ast_sip_location_retrieve_aor_contacts_filtered(aor, AST_SIP_CONTACT_FILTER_DEFAULT);
258 ao2_lock((
void*)aor);
259 contacts = ast_sip_location_retrieve_aor_contacts_nolock_filtered(aor, flags);
260 ao2_unlock((
void*)aor);
266 void ast_sip_location_retrieve_contact_and_aor_from_list(
const char *aor_list,
struct ast_sip_aor **aor,
269 ast_sip_location_retrieve_contact_and_aor_from_list_filtered(aor_list, AST_SIP_CONTACT_FILTER_DEFAULT, aor, contact);
272 void ast_sip_location_retrieve_contact_and_aor_from_list_filtered(
const char *aor_list,
unsigned int flags,
279 if (ast_strlen_zero(aor_list) || !(rest =
ast_strdupa(aor_list))) {
280 ast_log(LOG_WARNING,
"Unable to determine contacts from empty aor list\n");
287 while ((aor_name =
ast_strip(strsep(&rest,
",")))) {
288 *aor = ast_sip_location_retrieve_aor(aor_name);
293 *contact = ast_sip_location_retrieve_first_aor_contact_filtered(*aor, flags);
304 struct ast_sip_contact *ast_sip_location_retrieve_contact_from_aor_list(
const char *aor_list)
309 ast_sip_location_retrieve_contact_and_aor_from_list(aor_list, &aor, &contact);
316 static int permanent_uri_sort_fn(
const void *obj_left,
const void *obj_right,
int flags);
317 static int cli_contact_populate_container(
void *obj,
void *arg,
int flags);
319 static int gather_contacts_for_aor(
void *obj,
void *arg,
int flags)
325 aor_contacts = ast_sip_location_retrieve_aor_contacts(aor);
335 struct ao2_container *ast_sip_location_retrieve_contacts_from_aor_list(
const char *aor_list)
345 ast_sip_for_each_aor(aor_list, gather_contacts_for_aor, contacts);
350 struct ast_sip_contact *ast_sip_location_retrieve_contact(
const char *contact_name)
385 if (!ast_strlen_zero(user_agent)) {
389 if (!ast_strlen_zero(ast_config_AST_SYSTEM_NAME)) {
393 if (!ast_strlen_zero(via_addr)) {
398 if (!ast_strlen_zero(call_id)) {
416 int ast_sip_location_add_contact_nolock(
struct ast_sip_aor *aor,
const char *uri,
417 struct timeval expiration_time,
const char *path_info,
const char *user_agent,
418 const char *via_addr,
int via_port,
const char *call_id,
423 contact = ast_sip_location_create_contact(aor, uri, expiration_time, path_info,
424 user_agent, via_addr, via_port, call_id, 0, endpoint);
425 ao2_cleanup(contact);
426 return contact ? 0 : -1;
429 int ast_sip_location_add_contact(
struct ast_sip_aor *aor,
const char *uri,
430 struct timeval expiration_time,
const char *path_info,
const char *user_agent,
431 const char *via_addr,
int via_port,
const char *call_id,
437 res = ast_sip_location_add_contact_nolock(aor, uri, expiration_time, path_info, user_agent,
438 via_addr, via_port, call_id,
455 static int prune_boot_contacts_cb(
void *obj,
void *arg,
int flags)
460 && !strcmp(contact->
reg_server, ast_config_AST_SYSTEM_NAME ?:
"")) {
461 ast_verb(3,
"Removed contact '%s' from AOR '%s' due to system boot\n",
462 contact->
uri, contact->
aor);
463 ast_sip_location_delete_contact(contact);
469 void ast_sip_location_prune_boot_contacts(
void)
476 ao2_callback(contacts, 0, prune_boot_contacts_cb, NULL);
489 static int expiration_struct2str(
const void *obj,
const intptr_t *args,
char **buf)
492 char secs[AST_TIME_T_LEN];
498 static int permanent_uri_sort_fn(
const void *obj_left,
const void *obj_right,
int flags)
502 const char *right_key = obj_right;
528 int ast_sip_validate_uri_length(
const char *contact_uri)
530 int max_length = pj_max_hostname - 1;
534 int theres_a_port = 0;
536 if (strlen(contact_uri) > pjsip_max_url_size - 1) {
542 if (!strncasecmp(contact,
"sip:", 4)) {
544 }
else if (!strncasecmp(contact,
"sips:", 5)) {
551 at = strchr(contact,
'@');
557 if (host[0] ==
'[') {
561 close_bracket = strchr(host,
']');
562 if (!close_bracket) {
566 if (*close_bracket ==
':') {
569 *close_bracket =
'\0';
572 host = strsep(&host,
";?");
574 if (strchr(host,
':')) {
576 host = strsep(&host,
":");
580 if (!theres_a_port) {
581 max_length -= strlen(
"_sips.tcp.");
584 if (strlen(host) > max_length) {
599 if (ast_strlen_zero(var->
value)) {
604 while ((contact_uri =
ast_strip(strsep(&contacts,
",")))) {
608 char contact_id[strlen(aor_id) +
sizeof(hash) + 2];
610 if (ast_strlen_zero(contact_uri)) {
614 if (ast_sip_validate_uri_length(contact_uri)) {
615 ast_log(LOG_ERROR,
"Contact uri or hostname length exceeds pjproject limit or is not a sip(s) uri: %s\n", contact_uri);
628 snprintf(contact_id,
sizeof(contact_id),
"%s@@%s", aor_id, hash);
636 status = ast_res_pjsip_find_or_create_contact_status(contact);
650 static int contact_to_var_list(
void *
object,
void *arg,
int flags)
655 ast_variable_list_append(&*var, ast_variable_new(
"contact", wrapper->
contact->
uri,
""));
660 static int contacts_to_var_list(
const void *obj,
struct ast_variable **fields)
664 ast_sip_for_each_contact(aor, contact_to_var_list, fields);
678 static int voicemail_extension_to_str(
const void *obj,
const intptr_t *args,
char **buf)
687 int ast_sip_for_each_aor(
const char *aors,
ao2_callback_fn on_aor,
void *arg)
693 if (!on_aor || ast_strlen_zero(aors)) {
698 while ((name =
ast_strip(strsep(©,
",")))) {
701 aor = ast_sip_location_retrieve_aor(name);
703 res = on_aor(aor, arg, 0);
713 static void contact_wrapper_destroy(
void *obj)
717 ast_free(wrapper->
aor_id);
722 int ast_sip_for_each_contact(
const struct ast_sip_aor *aor,
731 !(contacts = ast_sip_location_retrieve_aor_contacts(aor))) {
736 while ((
object = ao2_iterator_next(&i))) {
761 if ((res = on_contact(wrapper, arg, 0))) {
770 int ast_sip_contact_to_str(
void *
object,
void *arg,
int flags)
796 for (i = objset; i; i = i->
next) {
799 if (strcmp(camel,
"Contact") == 0) {
811 static int contacts_to_str(
const void *obj,
const intptr_t *args,
char **buf)
822 ast_sip_for_each_contact(aor, ast_sip_contact_to_str, &str);
828 return *buf ? 0 : -1;
831 static int format_ami_aor_handler(
void *obj,
void *arg,
int flags)
841 buf = ast_sip_create_ami_event(
"AorDetail", ami);
845 contacts = ast_sip_location_retrieve_aor_contacts(aor);
851 sip_aor_to_ami(aor, &buf);
858 total_contacts - num_permanent);
873 ami->
arg = (
void *)endpoint;
874 return ast_sip_for_each_aor(endpoint->
aors,
875 format_ami_aor_handler, ami);
882 static struct ao2_container *cli_aor_get_container(
const char *regex)
905 static int cli_contact_populate_container(
void *obj,
void *arg,
int flags)
912 static int cli_aor_gather_contacts(
void *obj,
void *arg,
int flags)
916 return ast_sip_for_each_contact(aor, cli_contact_populate_container, arg);
919 static const char *cli_contact_get_id(
const void *obj)
925 static int cli_contact_sort(
const void *obj,
const void *arg,
int flags)
929 const char *right_key = arg;
932 switch (flags & OBJ_SEARCH_MASK) {
937 cmp = strcmp(left_wrapper->
contact_id, right_key);
940 cmp = strncmp(left_wrapper->
contact_id, right_key, strlen(right_key));
950 static int cli_contact_compare(
void *obj,
void *arg,
int flags)
954 const char *right_key = arg;
957 switch (flags & OBJ_SEARCH_MASK) {
962 if (strcmp(left_wrapper->
contact_id, right_key) == 0) {;
967 if (strncmp(left_wrapper->
contact_id, right_key, strlen(right_key)) == 0) {
979 static int cli_contact_iterate(
void *container,
ao2_callback_fn callback,
void *args)
981 return ast_sip_for_each_contact(container, callback, args);
984 static int cli_filter_contacts(
void *obj,
void *arg,
int flags)
987 regex_t *regexbuf = arg;
989 if (!regexec(regexbuf, wrapper->
contact_id, 0, NULL, 0)) {
996 static int cli_gather_contact(
void *obj,
void *arg,
int flags)
1001 if (strcmp(contact->
reg_server, ast_config_AST_SYSTEM_NAME ?:
"")) {
1029 static struct ao2_container *cli_contact_get_container(
const char *regex)
1037 if (!(var_aor = ast_variable_new(
"contact !=",
"",
""))) {
1046 cli_contact_sort, cli_contact_compare);
1047 if (!contacts_container) {
1053 ao2_ref(contacts_container, -1);
1061 ao2_ref(contacts_container, -1);
1067 if (!ast_strlen_zero(regex)) {
1068 if (regcomp(®exbuf, regex, REG_EXTENDED | REG_NOSUB)) {
1069 ao2_ref(contacts_container, -1);
1076 return contacts_container;
1079 static void *cli_contact_retrieve_by_id(
const char *
id)
1084 container = cli_contact_get_container(
"");
1094 static int cli_contact_print_header(
void *obj,
void *arg,
int flags)
1097 int indent = CLI_INDENT_TO_SPACES(context->
indent_level);
1098 int filler = CLI_LAST_TABSTOP - indent - 23;
1103 "%*s: <Aor/ContactUri%*.*s> <Hash....> <Status> <RTT(ms)..>\n",
1104 indent,
"Contact", filler, filler, CLI_HEADER_FILLER);
1109 static int cli_contact_print_body(
void *obj,
void *arg,
int flags)
1117 const char *hash_start = contact_id + strlen(contact->
aor) + 2;
1120 ast_assert(contact->
uri != NULL);
1123 status = ast_sip_get_contact_status(contact);
1126 flexwidth = CLI_LAST_TABSTOP - indent - 9 - strlen(contact->
aor) + 1;
1132 flexwidth, flexwidth,
1135 ast_sip_get_contact_short_status_label(status ? status->
status : UNKNOWN),
1136 (status && (status->
status == AVAILABLE)) ? ((
long long) status->
rtt) / 1000.0 : NAN);
1138 ao2_cleanup(status);
1142 static int cli_aor_iterate(
void *container,
ao2_callback_fn callback,
void *args)
1146 return ast_sip_for_each_aor(aor_list, callback, args);
1149 static void *cli_aor_retrieve_by_id(
const char *
id)
1154 static const char *cli_aor_get_id(
const void *obj)
1159 static int cli_aor_print_header(
void *obj,
void *arg,
int flags)
1162 int indent = CLI_INDENT_TO_SPACES(context->
indent_level);
1163 int filler = CLI_LAST_TABSTOP - indent - 7;
1168 "%*s: <Aor%*.*s> <MaxContact>\n",
1169 indent,
"Aor", filler, filler, CLI_HEADER_FILLER);
1175 formatter_entry = ast_sip_lookup_cli_formatter(
"contact");
1176 if (formatter_entry) {
1186 static int cli_aor_print_body(
void *obj,
void *arg,
int flags)
1198 flexwidth = CLI_LAST_TABSTOP - indent - 12;
1203 flexwidth, flexwidth,
1211 formatter_entry = ast_sip_lookup_cli_formatter(
"contact");
1212 if (formatter_entry) {
1226 ast_sip_cli_print_sorcery_objectset(aor, context, 0);
1242 static int format_ami_aorlist_handler(
void *obj,
void *arg,
int flags)
1248 buf = ast_sip_create_ami_event(
"AorList", ami);
1253 sip_aor_to_ami(aor, &buf);
1268 aors = cli_get_aors();
1294 AST_CLI_DEFINE(ast_sip_cli_traverse_objects,
"List PJSIP Aors",
1296 .
usage =
"Usage: pjsip list aors [ like <pattern> ]\n"
1297 " List the configured PJSIP Aors\n"
1298 " Optional regular expression pattern is used to filter the list.\n"),
1299 AST_CLI_DEFINE(ast_sip_cli_traverse_objects,
"Show PJSIP Aors",
1301 .
usage =
"Usage: pjsip show aors [ like <pattern> ]\n"
1302 " Show the configured PJSIP Aors\n"
1303 " Optional regular expression pattern is used to filter the list.\n"),
1304 AST_CLI_DEFINE(ast_sip_cli_traverse_objects,
"Show PJSIP Aor",
1306 .
usage =
"Usage: pjsip show aor <id>\n"
1307 " Show the configured PJSIP Aor\n"),
1309 AST_CLI_DEFINE(ast_sip_cli_traverse_objects,
"List PJSIP Contacts",
1310 .
command =
"pjsip list contacts",
1311 .
usage =
"Usage: pjsip list contacts [ like <pattern> ]\n"
1312 " List the configured PJSIP contacts\n"
1313 " Optional regular expression pattern is used to filter the list.\n"),
1314 AST_CLI_DEFINE(ast_sip_cli_traverse_objects,
"Show PJSIP Contacts",
1315 .
command =
"pjsip show contacts",
1316 .
usage =
"Usage: pjsip show contacts [ like <pattern> ]\n"
1317 " Show the configured PJSIP contacts\n"
1318 " Optional regular expression pattern is used to filter the list.\n"),
1319 AST_CLI_DEFINE(ast_sip_cli_traverse_objects,
"Show PJSIP Contact",
1320 .
command =
"pjsip show contact",
1321 .
usage =
"Usage: pjsip show contact\n"
1322 " Show the configured PJSIP contact\n"),
1329 static int contact_apply_handler(
const struct ast_sorcery *sorcery,
void *
object)
1334 if (ast_strlen_zero(contact->
uri)) {
1335 ast_log(LOG_ERROR,
"A URI on dynamic contact '%s' is empty\n",
1339 status = ast_res_pjsip_find_or_create_contact_status(contact);
1340 ao2_cleanup(status);
1342 return status ? 0 : -1;
1345 static int aor_apply_outbound_proxy(
void *obj,
void *arg,
int flags)
1355 static int aor_apply_handler(
const struct ast_sorcery *sorcery,
void *
object)
1369 int ast_sip_initialize_sorcery_location(
void)
1371 struct ast_sorcery *sorcery = ast_sip_get_sorcery();
1378 ast_sorcery_apply_default(sorcery,
"contact",
"astdb",
"registrar");
1381 ast_sorcery_apply_default(sorcery,
"aor",
"config",
"pjsip.conf,criteria=type=aor");
1423 ast_sip_register_endpoint_formatter(&endpoint_aor_formatter);
1426 if (!contact_formatter) {
1427 ast_log(LOG_ERROR,
"Unable to allocate memory for contact_formatter\n");
1430 contact_formatter->
name =
"contact";
1431 contact_formatter->
print_header = cli_contact_print_header;
1432 contact_formatter->
print_body = cli_contact_print_body;
1433 contact_formatter->
get_container = cli_contact_get_container;
1434 contact_formatter->
iterate = cli_contact_iterate;
1435 contact_formatter->
get_id = cli_contact_get_id;
1439 if (!aor_formatter) {
1440 ast_log(LOG_ERROR,
"Unable to allocate memory for aor_formatter\n");
1443 aor_formatter->
name =
"aor";
1445 aor_formatter->
print_body = cli_aor_print_body;
1447 aor_formatter->
iterate = cli_aor_iterate;
1448 aor_formatter->
get_id = cli_aor_get_id;
1451 ast_sip_register_cli_formatter(contact_formatter);
1452 ast_sip_register_cli_formatter(aor_formatter);
1464 for (i = 0; i <= REMOVED; i++) {
1465 ast_statsd_log_full_va(
"PJSIP.contacts.states.%s", AST_STATSD_GAUGE, 0, 1.0, ast_sip_get_contact_status_label(i));
1471 int ast_sip_destroy_sorcery_location(
void)
1475 ast_sip_unregister_cli_formatter(contact_formatter);
1476 ast_sip_unregister_cli_formatter(aor_formatter);
1479 ast_sip_unregister_endpoint_formatter(&endpoint_aor_formatter);
struct ast_str * output_buffer
struct ast_variable * next
struct ao2_container *(* get_container)(const char *regex)
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.
void astman_append(struct mansession *s, const char *fmt,...)
Asterisk main include file. File version handling, generic pbx functions.
int ao2_container_count(struct ao2_container *c)
Returns the number of elements in a container.
CLI Formatter Registry Entry.
void(* deleted)(const void *object)
Callback for when an object is deleted.
int( ao2_callback_fn)(void *obj, void *arg, int flags)
Type of a generic callback function.
void ast_variables_destroy(struct ast_variable *var)
Free variable list.
int ast_cli_unregister_multiple(struct ast_cli_entry *e, int len)
Unregister multiple commands.
The arg parameter is a search key, but is not an object.
int ast_time_t_to_string(time_t time, char *buf, size_t length)
Converts to a string representation of a time_t as decimal seconds since the epoch. Returns -1 on failure, zero otherwise.
unsigned int max_contacts
void astman_send_list_complete_start(struct mansession *s, const struct message *m, const char *event_name, int count)
Start the list complete event.
descriptor for a cli entry.
char * ast_str_buffer(const struct ast_str *buf)
Returns the string buffer within the ast_str buf.
#define AST_TASKPROCESSOR_HIGH_WATER_LEVEL
#define ao2_callback(c, flags, cb_fn, arg)
ao2_callback() is a generic function that applies cb_fn() to all objects in a container, as described below.
static struct stasis_rest_handlers mailboxes
REST handler for /api-docs/mailboxes.json.
#define ao2_container_alloc_list(ao2_options, container_options, sort_fn, cmp_fn)
Allocate and initialize a list container.
Structure for variables, used for configurations and for channel variables.
Perform no matching, return all objects.
int ast_sorcery_object_id_compare(void *obj, void *arg, int flags)
ao2 object comparator based on sorcery id.
void * ast_sorcery_lockable_alloc(size_t size, ao2_destructor_fn destructor, void *lockobj)
Allocate a generic sorcery capable object with locking.
Full structure for sorcery.
int(* iterate)(void *container, ao2_callback_fn callback, void *args)
Type for a default handler that should do nothing.
int ast_str_append(struct ast_str **buf, ssize_t max_len, const char *fmt,...)
Append to a thread local dynamic string.
#define ast_cli_register_multiple(e, len)
Register multiple commands.
void ao2_iterator_destroy(struct ao2_iterator *iter)
Destroy a container iterator.
static int copy(char *infile, char *outfile)
Utility function to copy a file.
struct timeval ast_tvnow(void)
Returns current timeval. Meant to replace calls to gettimeofday().
Return all matching objects.
int64_t ast_tvdiff_ms(struct timeval end, struct timeval start)
Computes the difference (in milliseconds) between two struct timeval instances.
#define ast_strdup(str)
A wrapper for strdup()
struct ao2_container * ast_sorcery_retrieve_by_prefix(const struct ast_sorcery *sorcery, const char *type, const char *prefix, const size_t prefix_len)
Retrieve multiple objects whose id begins with the specified prefix.
const ast_string_field outbound_proxy
CLI Formatter Context passed to all formatters.
int ast_get_timeval(const char *src, struct timeval *tv, struct timeval _default, int *consumed)
Parse a time (float) string.
#define ast_to_camel_case(s)
Attempts to convert the given string to camel case using an underscore as the specified delimiter...
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.
char * voicemail_extension
#define ast_asprintf(ret, fmt,...)
A wrapper for asprintf()
int ast_sorcery_object_set_congestion_levels(struct ast_sorcery *sorcery, const char *type, long low_water, long high_water)
Set the high and low alert water marks of the sorcery object type.
const char * ast_sorcery_object_get_type(const void *object)
Get the type of a sorcery object.
char * ast_str_truncate(struct ast_str *buf, ssize_t len)
Truncates the enclosed string to the given length.
const char * astman_get_header(const struct message *m, char *var)
Get header from manager transaction.
void * ast_sorcery_retrieve_by_id(const struct ast_sorcery *sorcery, const char *type, const char *id)
Retrieve an object using its unique identifier.
#define ao2_bump(obj)
Bump refcount on an AO2 object by one, returning the object.
Type for default option handler for bools (ast_true/ast_false)
unsigned int qualify_frequency
char * ast_strip_quoted(char *s, const char *beg_quotes, const char *end_quotes)
Strip leading/trailing whitespace and quotes from a string.
int ast_sorcery_create(const struct ast_sorcery *sorcery, void *object)
Create and potentially persist an object using an available wizard.
#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.
The arg parameter is a partial search key similar to OBJ_SEARCH_KEY.
#define FLDSET(type,...)
Convert a struct and list of fields to an argument list of field offsets.
Asterisk file paths, configured in asterisk.conf.
void astman_send_list_complete_end(struct mansession *s)
End the list complete event.
Type for default option handler for unsigned integers.
#define ast_string_field_init(x, size)
Initialize a field pool and fields.
#define ast_strdupa(s)
duplicate a string in memory from the stack
#define ao2_ref(o, delta)
Reference/unreference an object and return the old refcount.
char * ast_strip(char *s)
Strip leading/trailing whitespace from a string.
In case you didn't read that giant block of text above the mansession_session struct, the 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.
int ast_sorcery_object_id_sort(const void *obj, const void *arg, int flags)
ao2 object sorter based on sorcery id.
const char * ast_sorcery_object_get_id(const void *object)
Get the unique identifier of a sorcery object.
void *(* retrieve_by_id)(const char *id)
#define ast_malloc(len)
A wrapper for malloc()
struct ao2_container * container
int ast_pjproject_get_buildopt(char *option, char *format_string,...)
Retrieve a pjproject build option.
An entity with which Asterisk communicates.
unsigned int support_path
#define ast_sorcery_object_register(sorcery, type, alloc, transform, apply)
Register an object type.
#define MAX_OBJECT_FIELD
Maximum length of an object field name.
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.
int ast_manager_unregister(const char *action)
Unregister a registered manager command.
int ast_sorcery_delete(const struct ast_sorcery *sorcery, void *object)
Delete an object.
Support for dynamic strings.
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.
Interface for a sorcery object type observer.
Type for default option handler for bools (ast_true/ast_false)
void * ast_sorcery_alloc(const struct ast_sorcery *sorcery, const char *type, const char *id)
Allocate an object.
Type for default option handler for doubles.
struct ao2_container * permanent_contacts
#define STRFLDSET(type,...)
Convert a struct and a list of stringfield fields to an argument list of field offsets.
Support for logging to various files, console and syslog Configuration in file logger.conf.
An API for managing task processing threads that can be shared across modules.
const char *(* get_id)(const void *obj)
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.
#define ast_sorcery_object_field_register(sorcery, type, name, default_val, opt_type, flags,...)
Register a field within an object.
The arg parameter is an object of the same type.
void ast_sorcery_observer_remove(const struct ast_sorcery *sorcery, const char *type, const struct ast_sorcery_observer *callbacks)
Remove an observer from a specific object type.
When we need to walk through a container, we use an ao2_iterator to keep track of the current positio...
#define S_OR(a, b)
returns the equivalent of logic or for strings: first one if not empty, otherwise second one...
struct timeval ast_tv(ast_time_t sec, ast_suseconds_t usec)
Returns a timeval from sec, usec.
Type for default option handler for stringfields.
ao2_callback_fn * print_header
Reject objects with duplicate keys in container.
Search option field mask.
void * ast_sorcery_generic_alloc(size_t size, ao2_destructor_fn destructor)
Allocate a generic sorcery capable object.
const ast_string_field aors
#define ast_manager_register_xml(action, authority, func)
Register a manager callback using XML documentation to describe the manager.
ao2_callback_fn * print_body
void ast_md5_hash(char *output, const char *input)
Produces MD5 hash based on input string.
void astman_send_error(struct mansession *s, const struct message *m, char *error)
Send error in manager transaction.
#define RAII_VAR(vartype, varname, initval, dtor)
Declare a variable that will call a destructor function when it goes out of scope.
#define ast_string_field_free_memory(x)
free all memory - to be called before destroying the object
struct ao2_iterator ao2_iterator_init(struct ao2_container *c, int flags) attribute_warn_unused_result
Create an iterator for a container.
#define ast_named_lock_get(lock_type, keyspace, key)
Geta named lock handle.
#define ast_str_create(init_len)
Create a malloc'ed dynamic length string.
Sorcery Data Access Layer API.
int ast_sorcery_update(const struct ast_sorcery *sorcery, void *object)
Update an object.
#define ast_string_field_set(x, field, data)
Set a field to a simple string value.
void astman_send_listack(struct mansession *s, const struct message *m, char *msg, char *listflag)
Send ack in manager transaction to begin a list.
unsigned show_details_only_level_0
#define ao2_link(container, obj)
Add an object to a container.