outbound registration, registration is retried at the given interval up to
'max_retries'.
+res_pjsip
+------------------
+ * The ability to use "like" has been added to the pjsip list and show
+ CLI commands. For instance: CLI> pjsip list endpoints like abc
+
------------------------------------------------------------------------------
--- Functionality changes from Asterisk 13.5.0 to Asterisk 13.6.0 ------------
------------------------------------------------------------------------------
/*! The callback used to print the details of the object. */
ao2_callback_fn *print_body;
/*! The function used to retrieve a container of all objects of this type. */
- struct ao2_container *(* get_container)(void);
+ struct ao2_container *(* get_container)(const char *regex);
/*! The function used to iterate over a container of objects. */
int (* iterate)(void *container, ao2_callback_fn callback, void *args);
/*! The function used to retrieve a specific object from it's container. */
.format_ami = format_ami_endpoint_auth
};
-static struct ao2_container *cli_get_container(void)
+static struct ao2_container *cli_get_container(const char *regex)
{
RAII_VAR(struct ao2_container *, container, NULL, ao2_cleanup);
struct ao2_container *s_container;
- container = ast_sorcery_retrieve_by_fields(ast_sip_get_sorcery(), "auth",
- AST_RETRIEVE_FLAG_MULTIPLE | AST_RETRIEVE_FLAG_ALL, NULL);
+ container = ast_sorcery_retrieve_by_regex(ast_sip_get_sorcery(), "auth", regex);
if (!container) {
return NULL;
}
static struct ast_cli_entry cli_commands[] = {
AST_CLI_DEFINE(ast_sip_cli_traverse_objects, "List PJSIP Auths",
.command = "pjsip list auths",
- .usage = "Usage: pjsip list auths\n"
- " List the configured PJSIP Auths\n"),
+ .usage = "Usage: pjsip list auths [ like <pattern> ]\n"
+ " List the configured PJSIP Auths\n"
+ " Optional regular expression pattern is used to filter the list.\n"),
AST_CLI_DEFINE(ast_sip_cli_traverse_objects, "Show PJSIP Auths",
.command = "pjsip show auths",
- .usage = "Usage: pjsip show auths\n"
- " Show the configured PJSIP Auths\n"),
+ .usage = "Usage: pjsip show auths [ like <pattern> ]\n"
+ " Show the configured PJSIP Auths\n"
+ " Optional regular expression pattern is used to filter the list.\n"),
AST_CLI_DEFINE(ast_sip_cli_traverse_objects, "Show PJSIP Auth",
.command = "pjsip show auth",
.usage = "Usage: pjsip show auth <id>\n"
return 0;
}
-static struct ao2_container *cli_get_container(void)
+static struct ao2_container *cli_get_container(const char *regex)
{
RAII_VAR(struct ao2_container *, container, NULL, ao2_cleanup);
struct ao2_container *s_container;
- container = ast_sorcery_retrieve_by_fields(ast_sip_get_sorcery(), "transport",
- AST_RETRIEVE_FLAG_MULTIPLE | AST_RETRIEVE_FLAG_ALL, NULL);
+ container = ast_sorcery_retrieve_by_regex(ast_sip_get_sorcery(), "transport",
+ regex);
if (!container) {
return NULL;
}
AST_CLI_DEFINE(handle_pjsip_list_ciphers, "List available OpenSSL cipher names"),
AST_CLI_DEFINE(ast_sip_cli_traverse_objects, "List PJSIP Transports",
.command = "pjsip list transports",
- .usage = "Usage: pjsip list transports\n"
- " List the configured PJSIP Transports\n"),
+ .usage = "Usage: pjsip list transports [ like <pattern> ]\n"
+ " List the configured PJSIP Transports\n"
+ " Optional regular expression pattern is used to filter the list.\n"),
AST_CLI_DEFINE(ast_sip_cli_traverse_objects, "Show PJSIP Transports",
.command = "pjsip show transports",
- .usage = "Usage: pjsip show transports\n"
- " Show the configured PJSIP Transport\n"),
+ .usage = "Usage: pjsip show transports [ like <pattern> ]\n"
+ " Show the configured PJSIP Transport\n"
+ " Optional regular expression pattern is used to filter the list.\n"),
AST_CLI_DEFINE(ast_sip_cli_traverse_objects, "Show PJSIP Transport",
.command = "pjsip show transport",
.usage = "Usage: pjsip show transport <id>\n"
.format_ami = format_ami_endpoint_aor
};
-static struct ao2_container *cli_aor_get_container(void)
+static struct ao2_container *cli_aor_get_container(const char *regex)
{
RAII_VAR(struct ao2_container *, container, NULL, ao2_cleanup);
struct ao2_container *s_container;
- container = ast_sorcery_retrieve_by_fields(ast_sip_get_sorcery(), "aor",
- AST_RETRIEVE_FLAG_MULTIPLE | AST_RETRIEVE_FLAG_ALL, NULL);
+ container = ast_sorcery_retrieve_by_regex(ast_sip_get_sorcery(), "aor", regex);
if (!container) {
return NULL;
}
return ast_sip_for_each_contact(container, callback, args);
}
-static struct ao2_container *cli_contact_get_container(void)
+static int cli_filter_contacts(void *obj, void *arg, int flags)
+{
+ struct ast_sip_contact_wrapper *wrapper = obj;
+ regex_t *regexbuf = arg;
+
+ if (!regexec(regexbuf, wrapper->contact_id, 0, NULL, 0)) {
+ return 0;
+ }
+
+ return CMP_MATCH;
+}
+
+static struct ao2_container *cli_contact_get_container(const char *regex)
{
RAII_VAR(struct ao2_container *, parent_container, NULL, ao2_cleanup);
struct ao2_container *child_container;
+ regex_t regexbuf;
- parent_container = cli_aor_get_container();
+ parent_container = cli_aor_get_container("");
if (!parent_container) {
return NULL;
}
ao2_callback(parent_container, OBJ_NODATA, cli_aor_gather_contacts, child_container);
+ if (!ast_strlen_zero(regex)) {
+ if (regcomp(®exbuf, regex, REG_EXTENDED | REG_NOSUB)) {
+ ao2_ref(child_container, -1);
+ return NULL;
+ }
+ ao2_callback(child_container, OBJ_UNLINK | OBJ_MULTIPLE | OBJ_NODATA, cli_filter_contacts, ®exbuf);
+ regfree(®exbuf);
+ }
+
return child_container;
}
static void *cli_contact_retrieve_by_id(const char *id)
{
- return ao2_find(cli_contact_get_container(), id, OBJ_KEY | OBJ_NOLOCK);
+ RAII_VAR(struct ao2_container *, container, cli_contact_get_container(""), ao2_cleanup);
+
+ return ao2_find(container, id, OBJ_KEY | OBJ_NOLOCK);
}
static int cli_contact_print_header(void *obj, void *arg, int flags)
static struct ast_cli_entry cli_commands[] = {
AST_CLI_DEFINE(ast_sip_cli_traverse_objects, "List PJSIP Aors",
.command = "pjsip list aors",
- .usage = "Usage: pjsip list aors\n"
- " List the configured PJSIP Aors\n"),
+ .usage = "Usage: pjsip list aors [ like <pattern> ]\n"
+ " List the configured PJSIP Aors\n"
+ " Optional regular expression pattern is used to filter the list.\n"),
AST_CLI_DEFINE(ast_sip_cli_traverse_objects, "Show PJSIP Aors",
.command = "pjsip show aors",
- .usage = "Usage: pjsip show aors\n"
- " Show the configured PJSIP Aors\n"),
+ .usage = "Usage: pjsip show aors [ like <pattern> ]\n"
+ " Show the configured PJSIP Aors\n"
+ " Optional regular expression pattern is used to filter the list.\n"),
AST_CLI_DEFINE(ast_sip_cli_traverse_objects, "Show PJSIP Aor",
.command = "pjsip show aor",
.usage = "Usage: pjsip show aor <id>\n"
AST_CLI_DEFINE(ast_sip_cli_traverse_objects, "List PJSIP Contacts",
.command = "pjsip list contacts",
- .usage = "Usage: pjsip list contacts\n"
- " List the configured PJSIP contacts\n"),
+ .usage = "Usage: pjsip list contacts [ like <pattern> ]\n"
+ " List the configured PJSIP contacts\n"
+ " Optional regular expression pattern is used to filter the list.\n"),
AST_CLI_DEFINE(ast_sip_cli_traverse_objects, "Show PJSIP Contacts",
.command = "pjsip show contacts",
- .usage = "Usage: pjsip show contacts\n"
- " Show the configured PJSIP contacts\n"),
+ .usage = "Usage: pjsip show contacts [ like <pattern> ]\n"
+ " Show the configured PJSIP contacts\n"
+ " Optional regular expression pattern is used to filter the list.\n"),
AST_CLI_DEFINE(ast_sip_cli_traverse_objects, "Show PJSIP Contact",
.command = "pjsip show contact",
.usage = "Usage: pjsip show contact\n"
const char *cmd2;
const char *object_id;
char formatter_type[64];
+ const char *regex;
struct ast_sip_cli_context context = {
.indent_level = 0,
is_container = 1;
}
+ if (cmd != CLI_GENERATE
+ && is_container
+ && a->argc >= 4
+ && strcmp(object_id, "like") == 0) {
+ if (ast_strlen_zero(a->argv[4])) {
+ return CLI_SHOWUSAGE;
+ }
+ regex = a->argv[4];
+ } else {
+ regex = "";
+ }
+
if (cmd == CLI_GENERATE
&& (is_container
|| a->argc > 4
" =========================================================================================\n\n");
if (is_container || cmd == CLI_GENERATE) {
- container = formatter_entry->get_container();
+ container = formatter_entry->get_container(regex);
if (!container) {
ast_cli(a->fd, "No container returned for object type %s.\n",
formatter_type);
return 0;
}
-static struct ao2_container *cli_endpoint_get_container(void)
+static struct ao2_container *cli_endpoint_get_container(const char *regex)
{
RAII_VAR(struct ao2_container *, container, NULL, ao2_cleanup);
struct ao2_container *s_container;
- container = ast_sorcery_retrieve_by_fields(sip_sorcery, "endpoint",
- AST_RETRIEVE_FLAG_MULTIPLE | AST_RETRIEVE_FLAG_ALL, NULL);
+ container = ast_sorcery_retrieve_by_regex(sip_sorcery, "endpoint", regex);
if (!container) {
return NULL;
}
return 0;
}
-static struct ao2_container *cli_channel_get_container(void)
+static int cli_filter_channels(void *obj, void *arg, int flags)
+{
+ struct ast_channel_snapshot *channel = obj;
+ regex_t *regexbuf = arg;
+
+ if (!regexec(regexbuf, channel->name, 0, NULL, 0)
+ || !regexec(regexbuf, channel->appl, 0, NULL, 0)) {
+ return 0;
+ }
+
+ return CMP_MATCH;
+}
+
+static struct ao2_container *cli_channel_get_container(const char *regex)
{
RAII_VAR(struct ao2_container *, parent_container, NULL, ao2_cleanup);
struct ao2_container *child_container;
+ regex_t regexbuf;
- parent_container = cli_endpoint_get_container();
+ parent_container = cli_endpoint_get_container("");
if (!parent_container) {
return NULL;
}
ao2_callback(parent_container, OBJ_NODATA, cli_endpoint_gather_channels, child_container);
+ if (!ast_strlen_zero(regex)) {
+ if (regcomp(®exbuf, regex, REG_EXTENDED | REG_NOSUB)) {
+ ao2_ref(child_container, -1);
+ return NULL;
+ }
+ ao2_callback(child_container, OBJ_UNLINK | OBJ_MULTIPLE | OBJ_NODATA, cli_filter_channels, ®exbuf);
+ regfree(®exbuf);
+ }
+
return child_container;
}
static void *cli_channel_retrieve_by_id(const char *id)
{
- RAII_VAR(struct ao2_container *, container, cli_channel_get_container(), ao2_cleanup);
+ RAII_VAR(struct ao2_container *, container, cli_channel_get_container(""), ao2_cleanup);
return ao2_find(container, id, OBJ_KEY | OBJ_NOLOCK);
}
static struct ast_cli_entry cli_commands[] = {
AST_CLI_DEFINE(ast_sip_cli_traverse_objects, "List PJSIP Channels",
.command = "pjsip list channels",
- .usage = "Usage: pjsip list channels\n"
- " List the active PJSIP channels\n"),
+ .usage = "Usage: pjsip list channels [ like <pattern> ]\n"
+ " List the active PJSIP channels\n"
+ " Optional regular expression pattern is used to filter the list.\n"),
AST_CLI_DEFINE(ast_sip_cli_traverse_objects, "Show PJSIP Channels",
.command = "pjsip show channels",
- .usage = "Usage: pjsip show channels\n"
- " List(detailed) the active PJSIP channels\n"),
+ .usage = "Usage: pjsip show channels [ like <pattern> ]\n"
+ " List(detailed) the active PJSIP channels\n"
+ " Optional regular expression pattern is used to filter the list.\n"),
AST_CLI_DEFINE(ast_sip_cli_traverse_objects, "Show PJSIP Channel",
.command = "pjsip show channel",
.usage = "Usage: pjsip show channel\n"
AST_CLI_DEFINE(ast_sip_cli_traverse_objects, "List PJSIP Endpoints",
.command = "pjsip list endpoints",
- .usage = "Usage: pjsip list endpoints\n"
- " List the configured PJSIP endpoints\n"),
+ .usage = "Usage: pjsip list endpoints [ like <pattern> ]\n"
+ " List the configured PJSIP endpoints\n"
+ " Optional regular expression pattern is used to filter the list.\n"),
AST_CLI_DEFINE(ast_sip_cli_traverse_objects, "Show PJSIP Endpoints",
.command = "pjsip show endpoints",
- .usage = "Usage: pjsip show endpoints\n"
- " List(detailed) the configured PJSIP endpoints\n"),
+ .usage = "Usage: pjsip show endpoints [ like <pattern> ]\n"
+ " List(detailed) the configured PJSIP endpoints\n"
+ " Optional regular expression pattern is used to filter the list.\n"),
AST_CLI_DEFINE(ast_sip_cli_traverse_objects, "Show PJSIP Endpoint",
.command = "pjsip show endpoint",
.usage = "Usage: pjsip show endpoint <id>\n"
.format_ami = format_ami_endpoint_identify
};
-static int cli_populate_container(void *obj, void *arg, int flags)
-{
- ao2_link(arg, obj);
-
- return 0;
-}
-
static int cli_iterator(void *container, ao2_callback_fn callback, void *args)
{
const struct ast_sip_endpoint *endpoint = container;
return 0;
}
-static int cli_endpoint_gather_identifies(void *obj, void *arg, int flags)
+static struct ao2_container *cli_get_container(const char *regex)
{
- struct ast_sip_endpoint *endpoint = obj;
- struct ao2_container *container = arg;
-
- cli_iterator(endpoint, cli_populate_container, container);
-
- return 0;
-}
+ RAII_VAR(struct ao2_container *, container, NULL, ao2_cleanup);
+ struct ao2_container *s_container;
-static struct ao2_container *cli_get_container(void)
-{
- RAII_VAR(struct ao2_container *, parent_container, NULL, ao2_cleanup);
- RAII_VAR(struct ao2_container *, s_parent_container, NULL, ao2_cleanup);
- struct ao2_container *child_container;
-
- parent_container = ast_sorcery_retrieve_by_fields(ast_sip_get_sorcery(), "endpoint",
- AST_RETRIEVE_FLAG_MULTIPLE | AST_RETRIEVE_FLAG_ALL, NULL);
- if (!parent_container) {
+ container = ast_sorcery_retrieve_by_regex(ast_sip_get_sorcery(), "identify", regex);
+ if (!container) {
return NULL;
}
- s_parent_container = ao2_container_alloc_list(AO2_ALLOC_OPT_LOCK_NOLOCK, 0,
+ s_container = ao2_container_alloc_list(AO2_ALLOC_OPT_LOCK_NOLOCK, 0,
ast_sorcery_object_id_sort, ast_sorcery_object_id_compare);
- if (!s_parent_container) {
- return NULL;
- }
-
- if (ao2_container_dup(s_parent_container, parent_container, 0)) {
+ if (!s_container) {
return NULL;
}
- child_container = ao2_container_alloc_list(AO2_ALLOC_OPT_LOCK_NOLOCK, 0,
- ast_sorcery_object_id_sort, ast_sorcery_object_id_compare);
- if (!child_container) {
+ if (ao2_container_dup(s_container, container, 0)) {
+ ao2_ref(s_container, -1);
return NULL;
}
- ao2_callback(s_parent_container, OBJ_NODATA, cli_endpoint_gather_identifies, child_container);
-
- return child_container;
+ return s_container;
}
static void *cli_retrieve_by_id(const char *id)
static struct ast_cli_entry cli_identify[] = {
AST_CLI_DEFINE(my_cli_traverse_objects, "List PJSIP Identifies",
.command = "pjsip list identifies",
- .usage = "Usage: pjsip list identifies\n"
- " List the configured PJSIP Identifies\n"),
+ .usage = "Usage: pjsip list identifies [ like <pattern> ]\n"
+ " List the configured PJSIP Identifies\n"
+ " Optional regular expression pattern is used to filter the list.\n"),
AST_CLI_DEFINE(my_cli_traverse_objects, "Show PJSIP Identifies",
.command = "pjsip show identifies",
- .usage = "Usage: pjsip show identifies\n"
- " Show the configured PJSIP Identifies\n"),
+ .usage = "Usage: pjsip show identifies [ like <pattern> ]\n"
+ " Show the configured PJSIP Identifies\n"
+ " Optional regular expression pattern is used to filter the list.\n"),
AST_CLI_DEFINE(my_cli_traverse_objects, "Show PJSIP Identify",
.command = "pjsip show identify",
.usage = "Usage: pjsip show identify <id>\n"
return 0;
}
-static struct ao2_container *cli_get_container(void)
+static struct ao2_container *cli_get_container(const char *regex)
{
- RAII_VAR(struct ao2_container *, container, get_registrations(), ao2_cleanup);
+ RAII_VAR(struct ao2_container *, container, NULL, ao2_cleanup);
struct ao2_container *s_container;
+ container = ast_sorcery_retrieve_by_regex(ast_sip_get_sorcery(), "registration", regex);
if (!container) {
return NULL;
}
AST_CLI_DEFINE(cli_register, "Registers an outbound registration target"),
AST_CLI_DEFINE(my_cli_traverse_objects, "List PJSIP Registrations",
.command = "pjsip list registrations",
- .usage = "Usage: pjsip list registrations\n"
- " List the configured PJSIP Registrations\n"),
+ .usage = "Usage: pjsip list registrations [ like <pattern> ]\n"
+ " List the configured PJSIP Registrations\n"
+ " Optional regular expression pattern is used to filter the list.\n"),
AST_CLI_DEFINE(my_cli_traverse_objects, "Show PJSIP Registrations",
.command = "pjsip show registrations",
- .usage = "Usage: pjsip show registrations\n"
- " Show the configured PJSIP Registrations\n"),
+ .usage = "Usage: pjsip show registrations [ like <pattern> ]\n"
+ " Show the configured PJSIP Registrations\n"
+ " Optional regular expression pattern is used to filter the list.\n"),
AST_CLI_DEFINE(my_cli_traverse_objects, "Show PJSIP Registration",
.command = "pjsip show registration",
.usage = "Usage: pjsip show registration <id>\n"