[asterisk-commits] gtjoseph: branch 12 r410287 - in /branches/12: include/asterisk/ main/ res/ r...
SVN commits to the Asterisk project
asterisk-commits at lists.digium.com
Sat Mar 8 10:41:10 CST 2014
Author: gtjoseph
Date: Sat Mar 8 10:41:04 2014
New Revision: 410287
URL: http://svnview.digium.com/svn/asterisk?view=rev&rev=410287
Log:
pjsip_cli: Create pjsip show channel and contact, and general cli code cleanup.
Created the 'pjsip show channel' and 'pjsip show contact' commands.
Refactored out the hated ast_hashtab. Replaced with ao2_container.
Cleaned up function naming. Internal only, no public name changes.
Cleaned up whitespace and brace formatting in cli code.
Changed some NULL checking from "if"s to ast_asserts.
Fixed some register/unregister ordering to reduce deadlock potential.
Fixed ast_sip_location_add_contact where the 'name' buffer was too short.
Fixed some self-assignment issues in res_pjsip_outbound_registration.
(closes issue ASTERISK-23276)
Review: http://reviewboard.asterisk.org/r/3283/
Modified:
branches/12/include/asterisk/res_pjsip.h
branches/12/include/asterisk/res_pjsip_cli.h
branches/12/include/asterisk/sorcery.h
branches/12/main/sorcery.c
branches/12/res/res_pjsip/config_auth.c
branches/12/res/res_pjsip/config_transport.c
branches/12/res/res_pjsip/location.c
branches/12/res/res_pjsip/pjsip_cli.c
branches/12/res/res_pjsip/pjsip_configuration.c
branches/12/res/res_pjsip_endpoint_identifier_ip.c
branches/12/res/res_pjsip_outbound_registration.c
Modified: branches/12/include/asterisk/res_pjsip.h
URL: http://svnview.digium.com/svn/asterisk/branches/12/include/asterisk/res_pjsip.h?view=diff&rev=410287&r1=410286&r2=410287
==============================================================================
--- branches/12/include/asterisk/res_pjsip.h (original)
+++ branches/12/include/asterisk/res_pjsip.h Sat Mar 8 10:41:04 2014
@@ -218,6 +218,19 @@
struct ao2_container *permanent_contacts;
/*! Determines whether SIP Path headers are supported */
unsigned int support_path;
+};
+
+/*!
+ * \brief A wrapper for contact that adds the aor_id and
+ * a consistent contact id. Used by ast_sip_for_each_contact.
+ */
+struct ast_sip_contact_wrapper {
+ /*! The id of the parent aor. */
+ char *aor_id;
+ /*! The id of contact in form of aor_id/contact_uri. */
+ char *contact_id;
+ /*! Pointer to the actual contact. */
+ struct ast_sip_contact *contact;
};
/*!
@@ -1623,7 +1636,8 @@
* \brief For every contact on an AOR call the given 'on_contact' handler.
*
* \param aor the aor containing a list of contacts to iterate
- * \param on_contact callback on each contact on an AOR
+ * \param on_contact callback on each contact on an AOR. The object
+ * received by the callback will be a ast_sip_contact_wrapper structure.
* \param arg user data passed to handler
* \retval 0 Success, non-zero on failure
*/
Modified: branches/12/include/asterisk/res_pjsip_cli.h
URL: http://svnview.digium.com/svn/asterisk/branches/12/include/asterisk/res_pjsip_cli.h?view=diff&rev=410287&r1=410286&r2=410287
==============================================================================
--- branches/12/include/asterisk/res_pjsip_cli.h (original)
+++ branches/12/include/asterisk/res_pjsip_cli.h Sat Mar 8 10:41:04 2014
@@ -29,23 +29,20 @@
#define CLI_INDENT_TO_SPACES(x) ((x * 2) + 1 + CLI_MAX_TITLE_NAME)
/*
- * \brief CLI Formatter Context
+ * \brief CLI Formatter Context passed to all formatters.
*/
struct ast_sip_cli_context {
- int peers_mon_online;
- int peers_mon_offline;
- int peers_unmon_offline;
- int peers_unmon_online;
+ /*! Buffer used to accumulate cli output. */
struct ast_str *output_buffer;
- const struct ast_cli_args *a;
- const struct ast_sip_endpoint *current_endpoint;
- const struct ast_sip_auth *current_auth;
- const struct ast_sip_aor *current_aor;
+ /*! Used to indicate which direction an auth is used for. "I" or "O" */
char *auth_direction;
- unsigned int print_flags;
+ /*! Allows formatters to know how far to indent their output. */
int indent_level;
+ /*! Tells a formatter to dump its object_set. */
unsigned show_details : 1;
+ /*! Tells a formatter to descend into child objects. */
unsigned recurse : 1;
+ /*! Tells a formatter to dump it's object_set only if it's the root object. */
unsigned show_details_only_level_0 : 1;
};
@@ -53,12 +50,24 @@
* \brief CLI Formatter Registry Entry
*/
struct ast_sip_cli_formatter_entry {
+ /*! A globally unique name for this formatter. If this formatter entry
+ * is for an existing sorcery object type, then this name must match
+ * the sorcery object type. Otherwise it can be any string as long as
+ * it's globally unique.
+ */
const char *name;
+ /*! The callback used to print the object's column headers. */
ao2_callback_fn *print_header;
+ /*! 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);
- int (* iterator)(const void *container, ao2_callback_fn callback, void *args);
- ao2_sort_fn *comparator;
+ /*! 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. */
+ void *(* retrieve_by_id)(const char *id);
+ /*! The function used to retrieve an id string from an object. */
+ const char *(* get_id)(const void *obj);
};
/*!
Modified: branches/12/include/asterisk/sorcery.h
URL: http://svnview.digium.com/svn/asterisk/branches/12/include/asterisk/sorcery.h?view=diff&rev=410287&r1=410286&r2=410287
==============================================================================
--- branches/12/include/asterisk/sorcery.h (original)
+++ branches/12/include/asterisk/sorcery.h Sat Mar 8 10:41:04 2014
@@ -924,9 +924,19 @@
int ast_sorcery_object_set_extended(const void *object, const char *name, const char *value);
/*!
- * \brief Sorcery object comparator based on id.
- */
-int ast_sorcery_object_id_compare(const void *obj_left, const void *obj_right, int flags);
+ * \brief ao2 object comparator based on sorcery id.
+ */
+int ast_sorcery_object_id_compare(void *obj, void *arg, int flags);
+
+/*!
+ * \brief ao2 object sorter based on sorcery id.
+ */
+int ast_sorcery_object_id_sort(const void *obj, const void *arg, int flags);
+
+/*!
+ * \brief ao2 object hasher based on sorcery id.
+ */
+int ast_sorcery_object_id_hash(const void *obj, int flags);
/*!
* \brief Get the sorcery object type given a type name.
Modified: branches/12/main/sorcery.c
URL: http://svnview.digium.com/svn/asterisk/branches/12/main/sorcery.c?view=diff&rev=410287&r1=410286&r2=410287
==============================================================================
--- branches/12/main/sorcery.c (original)
+++ branches/12/main/sorcery.c Sat Mar 8 10:41:04 2014
@@ -1832,12 +1832,61 @@
sorcery_observer_remove, cbs);
}
-int ast_sorcery_object_id_compare(const void *obj_left, const void *obj_right, int flags)
-{
- if (!obj_left || !obj_right) {
- return 0;
- }
- return strcmp(ast_sorcery_object_get_id(obj_left), ast_sorcery_object_get_id(obj_right));
+int ast_sorcery_object_id_sort(const void *obj, const void *arg, int flags)
+{
+ const char *right_key = arg;
+ int cmp;
+
+ switch (flags & OBJ_SEARCH_MASK) {
+ case OBJ_SEARCH_OBJECT:
+ right_key = ast_sorcery_object_get_id(arg);
+ /* Fall through */
+ case OBJ_SEARCH_KEY:
+ cmp = strcmp(ast_sorcery_object_get_id(obj), right_key);
+ break;
+ case OBJ_SEARCH_PARTIAL_KEY:
+ cmp = strncmp(ast_sorcery_object_get_id(obj), right_key, strlen(right_key));
+ break;
+ default:
+ cmp = 0;
+ break;
+ }
+ return cmp;
+}
+
+int ast_sorcery_object_id_compare(void *obj, void *arg, int flags)
+{
+ const char *right_key = arg;
+ int cmp = 0;
+
+ switch (flags & OBJ_SEARCH_MASK) {
+ case OBJ_SEARCH_OBJECT:
+ right_key = ast_sorcery_object_get_id(arg);
+ /* Fall through */
+ case OBJ_SEARCH_KEY:
+ if (strcmp(ast_sorcery_object_get_id(obj), right_key) == 0) {
+ cmp = CMP_MATCH | CMP_STOP;
+ }
+ break;
+ case OBJ_SEARCH_PARTIAL_KEY:
+ if (strncmp(ast_sorcery_object_get_id(obj), right_key, strlen(right_key)) == 0) {
+ cmp = CMP_MATCH;
+ }
+ break;
+ default:
+ cmp = 0;
+ break;
+ }
+ return cmp;
+}
+
+int ast_sorcery_object_id_hash(const void *obj, int flags) {
+ if (flags & OBJ_SEARCH_OBJECT) {
+ return ast_str_hash(ast_sorcery_object_get_id(obj));
+ } else if (flags & OBJ_SEARCH_KEY) {
+ return ast_str_hash(obj);
+ }
+ return -1;
}
struct ast_sorcery_object_type *ast_sorcery_get_object_type(const struct ast_sorcery *sorcery,
Modified: branches/12/res/res_pjsip/config_auth.c
URL: http://svnview.digium.com/svn/asterisk/branches/12/res/res_pjsip/config_auth.c?view=diff&rev=410287&r1=410286&r2=410287
==============================================================================
--- branches/12/res/res_pjsip/config_auth.c (original)
+++ branches/12/res/res_pjsip/config_auth.c Sat Mar 8 10:41:04 2014
@@ -198,10 +198,10 @@
.format_ami = format_ami_endpoint_auth
};
-static struct ao2_container *cli_get_auth_container(void)
+static struct ao2_container *cli_get_container(void)
{
RAII_VAR(struct ao2_container *, container, NULL, ao2_cleanup);
- RAII_VAR(struct ao2_container *, s_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);
@@ -210,34 +210,36 @@
}
s_container = ao2_container_alloc_list(AO2_ALLOC_OPT_LOCK_NOLOCK, 0,
- ast_sorcery_object_id_compare, NULL);
+ ast_sorcery_object_id_sort, ast_sorcery_object_id_compare);
if (!s_container) {
return NULL;
}
if (ao2_container_dup(s_container, container, 0)) {
- return NULL;
- }
- ao2_ref(s_container, +1);
+ ao2_ref(s_container, -1);
+ return NULL;
+ }
+
return s_container;
}
-static int cli_iterator(const void *container, ao2_callback_fn callback, void *args)
-{
- const struct ast_sip_auth_array *array = container;
-
- return ast_sip_for_each_auth(array, callback, args);
-}
-
-static int cli_print_auth_header(void *obj, void *arg, int flags)
+static int cli_iterator(void *container, ao2_callback_fn callback, void *args)
+{
+ return ast_sip_for_each_auth(container, callback, args);
+}
+
+static void *cli_retrieve_by_id(const char *id)
+{
+ return ast_sorcery_retrieve_by_id(ast_sip_get_sorcery(), SIP_SORCERY_AUTH_TYPE, id);
+}
+
+static int cli_print_header(void *obj, void *arg, int flags)
{
struct ast_sip_cli_context *context = arg;
int indent = CLI_INDENT_TO_SPACES(context->indent_level);
int filler = CLI_MAX_WIDTH - indent - 20;
- if (!context->output_buffer) {
- return -1;
- }
+ ast_assert(context->output_buffer != NULL);
ast_str_append(&context->output_buffer, 0,
"%*s: <AuthId/UserName%*.*s>\n", indent, "I/OAuth", filler, filler,
@@ -246,17 +248,13 @@
return 0;
}
-static int cli_print_auth_body(void *obj, void *arg, int flags)
+static int cli_print_body(void *obj, void *arg, int flags)
{
struct ast_sip_auth *auth = obj;
struct ast_sip_cli_context *context = arg;
char title[32];
- context->current_auth = auth;
-
- if (!context->output_buffer) {
- return -1;
- }
+ ast_assert(context->output_buffer != NULL);
snprintf(title, 32, "%sAuth", context->auth_direction ? context->auth_direction : "");
@@ -272,15 +270,6 @@
return 0;
}
-
-static struct ast_sip_cli_formatter_entry cli_auth_formatter = {
- .name = SIP_SORCERY_AUTH_TYPE,
- .print_header = cli_print_auth_header,
- .print_body = cli_print_auth_body,
- .get_container = cli_get_auth_container,
- .iterator = cli_iterator,
- .comparator = ast_sorcery_object_id_compare,
-};
static struct ast_cli_entry cli_commands[] = {
AST_CLI_DEFINE(ast_sip_cli_traverse_objects, "List PJSIP Auths",
@@ -297,6 +286,8 @@
" Show the configured PJSIP Auth\n"),
};
+static struct ast_sip_cli_formatter_entry *cli_formatter;
+
/*! \brief Initialize sorcery with auth support */
int ast_sip_initialize_sorcery_auth(void)
{
@@ -324,7 +315,21 @@
"userpass", auth_type_handler, auth_type_to_str, NULL, 0, 0);
ast_sip_register_endpoint_formatter(&endpoint_auth_formatter);
- ast_sip_register_cli_formatter(&cli_auth_formatter);
+
+ cli_formatter = ao2_alloc(sizeof(struct ast_sip_cli_formatter_entry), NULL);
+ if (!cli_formatter) {
+ ast_log(LOG_ERROR, "Unable to allocate memory for cli formatter\n");
+ return -1;
+ }
+ cli_formatter->name = SIP_SORCERY_AUTH_TYPE;
+ cli_formatter->print_header = cli_print_header;
+ cli_formatter->print_body = cli_print_body;
+ cli_formatter->get_container = cli_get_container;
+ cli_formatter->iterate = cli_iterator;
+ cli_formatter->get_id = ast_sorcery_object_get_id;
+ cli_formatter->retrieve_by_id = cli_retrieve_by_id;
+
+ ast_sip_register_cli_formatter(cli_formatter);
ast_cli_register_multiple(cli_commands, ARRAY_LEN(cli_commands));
return 0;
@@ -333,6 +338,7 @@
int ast_sip_destroy_sorcery_auth(void)
{
ast_cli_unregister_multiple(cli_commands, ARRAY_LEN(cli_commands));
- ast_sip_unregister_cli_formatter(&cli_auth_formatter);
- return 0;
-}
+ ast_sip_unregister_cli_formatter(cli_formatter);
+
+ return 0;
+}
Modified: branches/12/res/res_pjsip/config_transport.c
URL: http://svnview.digium.com/svn/asterisk/branches/12/res/res_pjsip/config_transport.c?view=diff&rev=410287&r1=410286&r2=410287
==============================================================================
--- branches/12/res/res_pjsip/config_transport.c (original)
+++ branches/12/res/res_pjsip/config_transport.c Sat Mar 8 10:41:04 2014
@@ -509,7 +509,7 @@
static struct ao2_container *cli_get_container(void)
{
RAII_VAR(struct ao2_container *, container, NULL, ao2_cleanup);
- RAII_VAR(struct ao2_container *, s_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);
@@ -518,19 +518,20 @@
}
s_container = ao2_container_alloc_list(AO2_ALLOC_OPT_LOCK_NOLOCK, 0,
- ast_sorcery_object_id_compare, NULL);
+ ast_sorcery_object_id_sort, ast_sorcery_object_id_compare);
if (!s_container) {
return NULL;
}
if (ao2_container_dup(s_container, container, 0)) {
+ ao2_ref(s_container, -1);
return NULL;
}
- ao2_ref(s_container, +1);
+
return s_container;
}
-static int cli_iterator(const void *container, ao2_callback_fn callback, void *args)
+static int cli_iterate(void *container, ao2_callback_fn callback, void *args)
{
const struct ast_sip_endpoint *endpoint = container;
struct ast_sip_transport *transport = ast_sorcery_retrieve_by_id(ast_sip_get_sorcery(),
@@ -539,7 +540,13 @@
if (!transport) {
return -1;
}
+
return callback(transport, args, 0);
+}
+
+static void *cli_retrieve_by_id(const char *id)
+{
+ return ast_sorcery_retrieve_by_id(ast_sip_get_sorcery(), "transport", id);
}
static int cli_print_header(void *obj, void *arg, int flags)
@@ -548,9 +555,7 @@
int indent = CLI_INDENT_TO_SPACES(context->indent_level);
int filler = CLI_MAX_WIDTH - indent - 61;
- if (!context->output_buffer) {
- return -1;
- }
+ ast_assert(context->output_buffer != NULL);
ast_str_append(&context->output_buffer, 0,
"%*s: <TransportId........> <Type> <cos> <tos> <BindAddress%*.*s>\n",
@@ -565,9 +570,7 @@
struct ast_sip_cli_context *context = arg;
char hoststr[PJ_INET6_ADDRSTRLEN];
- if (!context->output_buffer) {
- return -1;
- }
+ ast_assert(context->output_buffer != NULL);
pj_sockaddr_print(&transport->host, hoststr, sizeof(hoststr), 3);
@@ -585,15 +588,6 @@
return 0;
}
-
-static struct ast_sip_cli_formatter_entry cli_formatter = {
- .name = "transport",
- .print_header = cli_print_header,
- .print_body = cli_print_body,
- .get_container = cli_get_container,
- .iterator = cli_iterator,
- .comparator = ast_sorcery_object_id_compare,
-};
static struct ast_cli_entry cli_commands[] = {
AST_CLI_DEFINE(ast_sip_cli_traverse_objects, "List PJSIP Transports",
@@ -609,6 +603,8 @@
.usage = "Usage: pjsip show transport <id>\n"
" Show the configured PJSIP Transport\n"),
};
+
+static struct ast_sip_cli_formatter_entry *cli_formatter;
/*! \brief Initialize sorcery with transport support */
int ast_sip_initialize_sorcery_transport(void)
@@ -643,7 +639,21 @@
ast_sorcery_object_field_register(sorcery, "transport", "cos", "0", OPT_UINT_T, 0, FLDSET(struct ast_sip_transport, cos));
ast_sip_register_endpoint_formatter(&endpoint_transport_formatter);
- ast_sip_register_cli_formatter(&cli_formatter);
+
+ cli_formatter = ao2_alloc(sizeof(struct ast_sip_cli_formatter_entry), NULL);
+ if (!cli_formatter) {
+ ast_log(LOG_ERROR, "Unable to allocate memory for cli formatter\n");
+ return -1;
+ }
+ cli_formatter->name = "transport";
+ cli_formatter->print_header = cli_print_header;
+ cli_formatter->print_body = cli_print_body;
+ cli_formatter->get_container = cli_get_container;
+ cli_formatter->iterate = cli_iterate;
+ cli_formatter->get_id = ast_sorcery_object_get_id;
+ cli_formatter->retrieve_by_id = cli_retrieve_by_id;
+
+ ast_sip_register_cli_formatter(cli_formatter);
ast_cli_register_multiple(cli_commands, ARRAY_LEN(cli_commands));
return 0;
@@ -652,6 +662,7 @@
int ast_sip_destroy_sorcery_transport(void)
{
ast_cli_unregister_multiple(cli_commands, ARRAY_LEN(cli_commands));
- ast_sip_unregister_cli_formatter(&cli_formatter);
- return 0;
-}
+ ast_sip_unregister_cli_formatter(cli_formatter);
+
+ return 0;
+}
Modified: branches/12/res/res_pjsip/location.c
URL: http://svnview.digium.com/svn/asterisk/branches/12/res/res_pjsip/location.c?view=diff&rev=410287&r1=410286&r2=410287
==============================================================================
--- branches/12/res/res_pjsip/location.c (original)
+++ branches/12/res/res_pjsip/location.c Sat Mar 8 10:41:04 2014
@@ -181,7 +181,7 @@
int ast_sip_location_add_contact(struct ast_sip_aor *aor, const char *uri,
struct timeval expiration_time, const char *path_info, const char *user_agent)
{
- char name[AST_UUID_STR_LEN];
+ char name[MAX_OBJECT_FIELD * 2 + 3];
RAII_VAR(struct ast_sip_contact *, contact, NULL, ao2_cleanup);
snprintf(name, sizeof(name), "%s;@%s", ast_sorcery_object_get_id(aor), uri);
@@ -279,21 +279,21 @@
return 0;
}
-static int contact_to_vl(void *object, void *arg, int flags)
-{
- struct ast_sip_contact *contact = object;
+static int contact_to_var_list(void *object, void *arg, int flags)
+{
+ struct ast_sip_contact_wrapper *wrapper = object;
struct ast_variable **var = arg;
- ast_variable_list_append(&*var, ast_variable_new("contact", contact->uri, ""));
-
- return 0;
-}
-
-static int contacts_to_vl(const void *obj, struct ast_variable **fields)
+ ast_variable_list_append(&*var, ast_variable_new("contact", wrapper->contact->uri, ""));
+
+ return 0;
+}
+
+static int contacts_to_var_list(const void *obj, struct ast_variable **fields)
{
const struct ast_sip_aor *aor = obj;
- ast_sip_for_each_contact(aor, contact_to_vl, fields);
+ ast_sip_for_each_contact(aor, contact_to_var_list, fields);
return 0;
}
@@ -323,12 +323,21 @@
return 0;
}
+static void contact_wrapper_destroy(void *obj)
+{
+ struct ast_sip_contact_wrapper *wrapper = obj;
+ ast_free(wrapper->aor_id);
+ ast_free(wrapper->contact_id);
+ ao2_ref(wrapper->contact, -1);
+}
+
int ast_sip_for_each_contact(const struct ast_sip_aor *aor,
ao2_callback_fn on_contact, void *arg)
{
RAII_VAR(struct ao2_container *, contacts, NULL, ao2_cleanup);
- struct ast_sip_contact *contact;
struct ao2_iterator i;
+ int res = 0;
+ void *object = NULL;
if (!on_contact ||
!(contacts = ast_sip_location_retrieve_aor_contacts(aor))) {
@@ -336,26 +345,44 @@
}
i = ao2_iterator_init(contacts, 0);
- while ((contact = ao2_iterator_next(&i))) {
- int res;
-
- ast_sorcery_object_set_extended(contact, "@aor_id", ast_sorcery_object_get_id(aor));
- if ((res = on_contact(contact, arg, 0))) {
- ao2_iterator_destroy(&i);
- return -1;
+ while ((object = ao2_iterator_next(&i))) {
+ RAII_VAR(struct ast_sip_contact *, contact, object, ao2_cleanup);
+ RAII_VAR(struct ast_sip_contact_wrapper *, wrapper, NULL, ao2_cleanup);
+ const char *aor_id = ast_sorcery_object_get_id(aor);
+
+ wrapper = ao2_alloc(sizeof(struct ast_sip_contact_wrapper), contact_wrapper_destroy);
+ if (!wrapper) {
+ res = -1;
+ break;
+ }
+ wrapper->contact_id = ast_malloc(strlen(aor_id) + strlen(contact->uri) + 2);
+ if (!wrapper->contact_id) {
+ res = -1;
+ break;
+ }
+ sprintf(wrapper->contact_id, "%s/%s", aor_id, contact->uri);
+ wrapper->aor_id = ast_strdup(aor_id);
+ if (!wrapper->aor_id) {
+ res = -1;
+ break;
+ }
+ wrapper->contact = contact;
+ ao2_bump(wrapper->contact);
+
+ if ((res = on_contact(wrapper, arg, 0))) {
+ break;
}
}
ao2_iterator_destroy(&i);
- return 0;
+ return res;
}
int ast_sip_contact_to_str(void *object, void *arg, int flags)
{
- struct ast_sip_contact *contact = object;
+ struct ast_sip_contact_wrapper *wrapper = object;
struct ast_str **buf = arg;
- ast_str_append(buf, 0, "%s/%s,",
- ast_sorcery_object_get_extended(contact, "aor_id"), contact->uri);
+ ast_str_append(buf, 0, "%s,", wrapper->contact_id);
return 0;
}
@@ -448,10 +475,10 @@
.format_ami = format_ami_endpoint_aor
};
-static struct ao2_container *cli_get_aor_container(void)
+static struct ao2_container *cli_aor_get_container(void)
{
RAII_VAR(struct ao2_container *, container, NULL, ao2_cleanup);
- RAII_VAR(struct ao2_container *, s_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);
@@ -460,90 +487,144 @@
}
s_container = ao2_container_alloc_list(AO2_ALLOC_OPT_LOCK_NOLOCK, 0,
- ast_sorcery_object_id_compare, NULL);
+ ast_sorcery_object_id_sort, ast_sorcery_object_id_compare);
if (!s_container) {
return NULL;
}
if (ao2_container_dup(s_container, container, 0)) {
- return NULL;
- }
- ao2_ref(s_container, +1);
+ ao2_ref(s_container, -1);
+ return NULL;
+ }
+
return s_container;
}
-static int populate_contact_container(void *obj, void *arg, int flags)
-{
- struct ast_sip_contact *contact = obj;
- struct ao2_container *container = arg;
-
- ao2_link(container, contact);
- return 0;
-}
-
-static int gather_aor_contacts(void *obj, void *arg, int flags)
+static int cli_contact_populate_container(void *obj, void *arg, int flags)
+{
+ ao2_link(arg, obj);
+
+ return 0;
+}
+
+static int cli_aor_gather_contacts(void *obj, void *arg, int flags)
{
struct ast_sip_aor *aor = obj;
- struct ao2_container *container = arg;
- ast_sip_for_each_contact(aor, populate_contact_container, container);
- return 0;
-}
-
-static int cli_contact_compare(const void *left, const void *right, int flags)
-{
- const struct ast_sip_contact *left_contact = left;
- const struct ast_sip_contact *right_contact = right;
- int rc;
-
- if (!left_contact || !right_contact) {
- return 0;
- }
- rc = strcmp(ast_sorcery_object_get_extended(left_contact, "aor_id"),
- ast_sorcery_object_get_extended(right_contact, "aor_id"));
- if (rc) {
- return rc;
- }
- return strcmp(left_contact->uri, right_contact->uri);
-}
-
-static struct ao2_container *cli_get_contact_container(void)
+
+ return ast_sip_for_each_contact(aor, cli_contact_populate_container, arg);
+}
+
+static const char *cli_contact_get_id(const void *obj)
+{
+ const struct ast_sip_contact_wrapper *wrapper = obj;
+ return wrapper->contact_id;
+}
+
+static int cli_contact_sort(const void *obj, const void *arg, int flags)
+{
+ const struct ast_sip_contact_wrapper *left_wrapper = obj;
+ const struct ast_sip_contact_wrapper *right_wrapper = arg;
+ const char *right_key = arg;
+ int cmp = 0;
+
+ switch (flags & OBJ_SEARCH_MASK) {
+ case OBJ_SEARCH_OBJECT:
+ right_key = right_wrapper->contact_id;
+ /* Fall through */
+ case OBJ_SEARCH_KEY:
+ cmp = strcmp(left_wrapper->contact_id, right_key);
+ break;
+ case OBJ_SEARCH_PARTIAL_KEY:
+ cmp = strncmp(left_wrapper->contact_id, right_key, strlen(right_key));
+ break;
+ default:
+ cmp = 0;
+ break;
+ }
+
+ return cmp;
+}
+
+static int cli_contact_compare(void *obj, void *arg, int flags)
+{
+ const struct ast_sip_contact_wrapper *left_wrapper = obj;
+ const struct ast_sip_contact_wrapper *right_wrapper = arg;
+ const char *right_key = arg;
+ int cmp = 0;
+
+ switch (flags & OBJ_SEARCH_MASK) {
+ case OBJ_SEARCH_OBJECT:
+ right_key = right_wrapper->contact_id;
+ /* Fall through */
+ case OBJ_SEARCH_KEY:
+ if (strcmp(left_wrapper->contact_id, right_key) == 0) {;
+ cmp = CMP_MATCH | CMP_STOP;
+ }
+ break;
+ case OBJ_SEARCH_PARTIAL_KEY:
+ if (strncmp(left_wrapper->contact_id, right_key, strlen(right_key)) == 0) {
+ cmp = CMP_MATCH;
+ }
+ break;
+ default:
+ cmp = 0;
+ break;
+ }
+
+ return cmp;
+}
+
+static int cli_contact_hash(const void *obj, int flags)
+{
+ const struct ast_sip_contact_wrapper *wrapper = obj;
+ if (flags & OBJ_SEARCH_OBJECT) {
+ return ast_str_hash(wrapper->contact_id);
+ } else if (flags & OBJ_SEARCH_KEY) {
+ return ast_str_hash(obj);
+ }
+
+ return -1;
+}
+
+static int cli_contact_iterate(void *container, ao2_callback_fn callback, void *args)
+{
+ return ast_sip_for_each_contact(container, callback, args);
+}
+
+static struct ao2_container *cli_contact_get_container(void)
{
RAII_VAR(struct ao2_container *, parent_container, NULL, ao2_cleanup);
struct ao2_container *child_container;
- parent_container = cli_get_aor_container();
+ parent_container = cli_aor_get_container();
if (!parent_container) {
return NULL;
}
- child_container = ao2_container_alloc_list(AO2_ALLOC_OPT_LOCK_NOLOCK, 0,
- cli_contact_compare, NULL);
+ child_container = ao2_container_alloc_hash(AO2_ALLOC_OPT_LOCK_NOLOCK, 0, 17,
+ cli_contact_hash, cli_contact_sort, cli_contact_compare);
if (!child_container) {
return NULL;
}
- ao2_ref(child_container, +1);
- ao2_callback(parent_container, OBJ_NODATA, gather_aor_contacts, child_container);
+ ao2_callback(parent_container, OBJ_NODATA, cli_aor_gather_contacts, child_container);
return child_container;
}
-static int cli_contact_iterator(const void *container, ao2_callback_fn callback, void *args)
-{
- const struct ast_sip_aor *array = container;
-
- return ast_sip_for_each_contact(array, callback, args);
-}
-
-static int cli_print_contact_header(void *obj, void *arg, int flags)
+static void *cli_contact_retrieve_by_id(const char *id)
+{
+ return ao2_find(cli_contact_get_container(), id, OBJ_KEY | OBJ_NOLOCK);
+}
+
+static int cli_contact_print_header(void *obj, void *arg, int flags)
{
struct ast_sip_cli_context *context = arg;
int indent = CLI_INDENT_TO_SPACES(context->indent_level);
int filler = CLI_LAST_TABSTOP - indent - 18;
- if (!context->output_buffer) {
- return -1;
- }
+ ast_assert(context->output_buffer != NULL);
+
ast_str_append(&context->output_buffer, 0,
"%*s: <Aor/ContactUri%*.*s> <Status....> <RTT(ms)..>\n",
indent, "Contact", filler, filler, CLI_HEADER_FILLER);
@@ -551,27 +632,20 @@
return 0;
}
-static int cli_print_contact_body(void *obj, void *arg, int flags)
-{
- struct ast_sip_contact *contact = obj;
+static int cli_contact_print_body(void *obj, void *arg, int flags)
+{
+ struct ast_sip_contact_wrapper *wrapper = obj;
+ struct ast_sip_contact *contact = wrapper->contact;
struct ast_sip_cli_context *context = arg;
- char *print_name = NULL;
- int print_name_len;
int indent;
int flexwidth;
- const char *aor_id = ast_sorcery_object_get_extended(contact, "aor_id");
RAII_VAR(struct ast_sip_contact_status *, status,
ast_sorcery_retrieve_by_id( ast_sip_get_sorcery(), CONTACT_STATUS, ast_sorcery_object_get_id(contact)),
ao2_cleanup);
- if (!context->output_buffer) {
- return -1;
- }
-
- print_name_len = strlen(aor_id) + strlen(contact->uri) + 2;
- print_name = ast_alloca(print_name_len);
- snprintf(print_name, print_name_len, "%s/%s", aor_id, contact->uri);
+ ast_assert(contact->uri != NULL);
+ ast_assert(context->output_buffer != NULL);
indent = CLI_INDENT_TO_SPACES(context->indent_level);
flexwidth = CLI_LAST_TABSTOP - indent - 2;
@@ -580,31 +654,40 @@
indent,
"Contact",
flexwidth, flexwidth,
- print_name,
+ wrapper->contact_id,
(status ? (status->status == AVAILABLE ? "Avail" : "Unavail") : "Unknown"),
(status ? ((long long) status->rtt) / 1000.0 : NAN));
return 0;
}
-static int cli_aor_iterator(const void *container, ao2_callback_fn callback, void *args)
+static int cli_aor_iterate(void *container, ao2_callback_fn callback, void *args)
{
const char *aor_list = container;
return ast_sip_for_each_aor(aor_list, callback, args);
}
-static int cli_print_aor_header(void *obj, void *arg, int flags)
+static void *cli_aor_retrieve_by_id(const char *id)
+{
+ return ast_sorcery_retrieve_by_id(ast_sip_get_sorcery(), "aor", id);
+}
+
+static const char *cli_aor_get_id(const void *obj)
+{
+ return ast_sorcery_object_get_id(obj);
+}
+
+static int cli_aor_print_header(void *obj, void *arg, int flags)
{
struct ast_sip_cli_context *context = arg;
- struct ast_sip_cli_formatter_entry *formatter_entry;
+ RAII_VAR(struct ast_sip_cli_formatter_entry *, formatter_entry, NULL, ao2_cleanup);
int indent = CLI_INDENT_TO_SPACES(context->indent_level);
int filler = CLI_LAST_TABSTOP - indent - 7;
- if (!context->output_buffer) {
- return -1;
- }
+ ast_assert(context->output_buffer != NULL);
+
ast_str_append(&context->output_buffer, 0,
"%*s: <Aor%*.*s> <MaxContact>\n",
indent, "Aor", filler, filler, CLI_HEADER_FILLER);
@@ -612,27 +695,26 @@
if (context->recurse) {
context->indent_level++;
formatter_entry = ast_sip_lookup_cli_formatter("contact");
- if (formatter_entry && formatter_entry->print_header) {
+ if (formatter_entry) {
formatter_entry->print_header(NULL, context, 0);
}
context->indent_level--;
}
- return 0;
-}
-
-static int cli_print_aor_body(void *obj, void *arg, int flags)
+
+ return 0;
+}
+
+static int cli_aor_print_body(void *obj, void *arg, int flags)
{
struct ast_sip_aor *aor = obj;
struct ast_sip_cli_context *context = arg;
- struct ast_sip_cli_formatter_entry *formatter_entry;
+ RAII_VAR(struct ast_sip_cli_formatter_entry *, formatter_entry, NULL, ao2_cleanup);
int indent;
int flexwidth;
- if (!context->output_buffer) {
- return -1;
- }
-
- context->current_aor = aor;
+ ast_assert(context->output_buffer != NULL);
+
+// context->current_aor = aor;
indent = CLI_INDENT_TO_SPACES(context->indent_level);
flexwidth = CLI_LAST_TABSTOP - indent - 12;
@@ -647,8 +729,8 @@
context->indent_level++;
formatter_entry = ast_sip_lookup_cli_formatter("contact");
- if (formatter_entry && formatter_entry->print_body && formatter_entry->iterator) {
- formatter_entry->iterator(aor, formatter_entry->print_body, context);
+ if (formatter_entry) {
+ formatter_entry->iterate(aor, formatter_entry->print_body, context);
}
context->indent_level--;
@@ -665,24 +747,6 @@
return 0;
}
-
-static struct ast_sip_cli_formatter_entry cli_contact_formatter = {
- .name = "contact",
- .print_header = cli_print_contact_header,
- .print_body = cli_print_contact_body,
- .get_container = cli_get_contact_container,
- .iterator = cli_contact_iterator,
- .comparator = cli_contact_compare,
-};
-
-static struct ast_sip_cli_formatter_entry cli_aor_formatter = {
- .name = "aor",
- .print_header = cli_print_aor_header,
- .print_body = cli_print_aor_body,
- .get_container = cli_get_aor_container,
- .iterator = cli_aor_iterator,
- .comparator = ast_sorcery_object_id_compare,
-};
static struct ast_cli_entry cli_commands[] = {
AST_CLI_DEFINE(ast_sip_cli_traverse_objects, "List PJSIP Aors",
@@ -706,7 +770,14 @@
.command = "pjsip show contacts",
.usage = "Usage: pjsip show contacts\n"
" Show the configured PJSIP contacts\n"),
+ AST_CLI_DEFINE(ast_sip_cli_traverse_objects, "Show PJSIP Contact",
+ .command = "pjsip show contact",
+ .usage = "Usage: pjsip show contact\n"
+ " Show the configured PJSIP contact\n"),
};
+
+struct ast_sip_cli_formatter_entry *contact_formatter;
+struct ast_sip_cli_formatter_entry *aor_formatter;
/*! \brief Initialize sorcery with location support */
int ast_sip_initialize_sorcery_location(void)
@@ -737,23 +808,52 @@
ast_sorcery_object_field_register(sorcery, "aor", "authenticate_qualify", "no", OPT_BOOL_T, 1, FLDSET(struct ast_sip_aor, authenticate_qualify));
ast_sorcery_object_field_register(sorcery, "aor", "max_contacts", "0", OPT_UINT_T, 0, FLDSET(struct ast_sip_aor, max_contacts));
ast_sorcery_object_field_register(sorcery, "aor", "remove_existing", "no", OPT_BOOL_T, 1, FLDSET(struct ast_sip_aor, remove_existing));
- ast_sorcery_object_field_register_custom(sorcery, "aor", "contact", "", permanent_uri_handler, contacts_to_str, contacts_to_vl, 0, 0);
+ ast_sorcery_object_field_register_custom(sorcery, "aor", "contact", "", permanent_uri_handler, contacts_to_str, contacts_to_var_list, 0, 0);
ast_sorcery_object_field_register(sorcery, "aor", "mailboxes", "", OPT_STRINGFIELD_T, 0, STRFLDSET(struct ast_sip_aor, mailboxes));
ast_sorcery_object_field_register(sorcery, "aor", "outbound_proxy", "", OPT_STRINGFIELD_T, 0, STRFLDSET(struct ast_sip_aor, outbound_proxy));
ast_sorcery_object_field_register(sorcery, "aor", "support_path", "no", OPT_BOOL_T, 1, FLDSET(struct ast_sip_aor, support_path));
ast_sip_register_endpoint_formatter(&endpoint_aor_formatter);
- ast_sip_register_cli_formatter(&cli_contact_formatter);
- ast_sip_register_cli_formatter(&cli_aor_formatter);
+
+ contact_formatter = ao2_alloc(sizeof(struct ast_sip_cli_formatter_entry), NULL);
+ if (!contact_formatter) {
+ ast_log(LOG_ERROR, "Unable to allocate memory for contact_formatter\n");
+ return -1;
+ }
+ contact_formatter->name = "contact";
+ contact_formatter->print_header = cli_contact_print_header;
+ contact_formatter->print_body = cli_contact_print_body;
+ contact_formatter->get_container = cli_contact_get_container;
+ contact_formatter->iterate = cli_contact_iterate;
+ contact_formatter->get_id = cli_contact_get_id;
+ contact_formatter->retrieve_by_id = cli_contact_retrieve_by_id;
+
+ aor_formatter = ao2_alloc(sizeof(struct ast_sip_cli_formatter_entry), NULL);
+ if (!aor_formatter) {
+ ast_log(LOG_ERROR, "Unable to allocate memory for aor_formatter\n");
+ return -1;
+ }
+ aor_formatter->name = "aor";
+ aor_formatter->print_header = cli_aor_print_header;
+ aor_formatter->print_body = cli_aor_print_body;
+ aor_formatter->get_container = cli_aor_get_container;
+ aor_formatter->iterate = cli_aor_iterate;
+ aor_formatter->get_id = cli_aor_get_id;
+ aor_formatter->retrieve_by_id = cli_aor_retrieve_by_id;
+
+ ast_sip_register_cli_formatter(contact_formatter);
+ ast_sip_register_cli_formatter(aor_formatter);
ast_cli_register_multiple(cli_commands, ARRAY_LEN(cli_commands));
+
return 0;
}
int ast_sip_destroy_sorcery_location(void)
{
ast_cli_unregister_multiple(cli_commands, ARRAY_LEN(cli_commands));
- ast_sip_unregister_cli_formatter(&cli_contact_formatter);
- ast_sip_unregister_cli_formatter(&cli_aor_formatter);
- return 0;
-}
-
+ ast_sip_unregister_cli_formatter(contact_formatter);
+ ast_sip_unregister_cli_formatter(aor_formatter);
+
+ return 0;
+}
+
Modified: branches/12/res/res_pjsip/pjsip_cli.c
URL: http://svnview.digium.com/svn/asterisk/branches/12/res/res_pjsip/pjsip_cli.c?view=diff&rev=410287&r1=410286&r2=410287
==============================================================================
--- branches/12/res/res_pjsip/pjsip_cli.c (original)
+++ branches/12/res/res_pjsip/pjsip_cli.c Sat Mar 8 10:41:04 2014
@@ -31,15 +31,7 @@
#include "asterisk/utils.h"
#include "asterisk/sorcery.h"
-static struct ast_hashtab *formatter_registry;
-
-struct ast_sip_cli_formatter_entry *ast_sip_lookup_cli_formatter(const char *name)
-{
- struct ast_sip_cli_formatter_entry fake_entry = {
- .name = name,
- };
- return ast_hashtab_lookup(formatter_registry, &fake_entry);
-}
+static struct ao2_container *formatter_registry;
int ast_sip_cli_print_sorcery_objectset(void *obj, void *arg, int flags)
{
@@ -91,6 +83,7 @@
}
static char *complete_show_sorcery_object(struct ao2_container *container,
+ struct ast_sip_cli_formatter_entry *formatter_entry,
const char *word, int state)
{
char *result = NULL;
@@ -101,9 +94,10 @@
void *object;
while ((object = ao2_t_iterator_next(&i, "iterate thru endpoints table"))) {
- if (!strncasecmp(word, ast_sorcery_object_get_id(object), wordlen)
+ const char *id = formatter_entry->get_id(object);
+ if (!strncasecmp(word, id, wordlen)
&& ++which > state) {
- result = ast_strdup(ast_sorcery_object_get_id(object));
+ result = ast_strdup(id);
}
ao2_t_ref(object, -1, "toss iterator endpoint ptr before break");
if (result) {
@@ -111,6 +105,7 @@
}
}
ao2_iterator_destroy(&i);
+
return result;
}
@@ -123,20 +118,15 @@
char *ast_sip_cli_traverse_objects(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
{
RAII_VAR(struct ao2_container *, container, NULL, ao2_cleanup);
+ RAII_VAR(struct ast_sip_cli_formatter_entry *, formatter_entry, NULL, ao2_cleanup);
RAII_VAR(void *, object, NULL, ao2_cleanup);
int is_container = 0;
const char *cmd1;
const char *cmd2;
const char *object_id;
char formatter_type[64];
- struct ast_sip_cli_formatter_entry *formatter_entry;
struct ast_sip_cli_context context = {
- .peers_mon_online = 0,
- .peers_mon_offline = 0,
- .peers_unmon_online = 0,
- .peers_unmon_offline = 0,
- .a = a,
.indent_level = 0,
.show_details = 0,
.show_details_only_level_0 = 0,
@@ -203,7 +193,7 @@
if (cmd == CLI_GENERATE) {
ast_free(context.output_buffer);
- return complete_show_sorcery_object(container, a->word, a->n);
+ return complete_show_sorcery_object(container, formatter_entry, a->word, a->n);
}
if (is_container) {
@@ -219,8 +209,8 @@
ast_cli(a->fd, "No object specified.\n");
return CLI_FAILURE;
}
- object = ast_sorcery_retrieve_by_id(ast_sip_get_sorcery(), formatter_type,
- object_id);
+
+ object = formatter_entry->retrieve_by_id(object_id);
if (!object) {
dump_str_and_free(a->fd, context.output_buffer);
ast_cli(a->fd, "Unable to find object %s.\n\n", object_id);
@@ -234,44 +224,110 @@
return CLI_SUCCESS;
}
-static int compare_formatters(const void *a, const void *b)
-{
- const struct ast_sip_cli_formatter_entry *afe = a;
- const struct ast_sip_cli_formatter_entry *bfe = b;
- if (!afe || !bfe) {
- ast_log(LOG_ERROR, "One of the arguments to compare_formatters was NULL\n");
- return -1;
- }
- return strcmp(afe->name, bfe->name);
-}
-
-static unsigned int hash_formatters(const void *a)
-{
- const struct ast_sip_cli_formatter_entry *afe = a;
- return ast_hashtab_hash_string(afe->name);
+static int formatter_sort(const void *obj, const void *arg, int flags)
+{
+ const struct ast_sip_cli_formatter_entry *left_obj = obj;
+ const struct ast_sip_cli_formatter_entry *right_obj = arg;
+ const char *right_key = arg;
+ int cmp = 0;
+
+ switch (flags & OBJ_SEARCH_MASK) {
+ case OBJ_SEARCH_OBJECT:
+ right_key = right_obj->name;
+ /* Fall through */
+ case OBJ_SEARCH_KEY:
+ cmp = strcmp(left_obj->name, right_key);
+ break;
+ case OBJ_SEARCH_PARTIAL_KEY:
+ cmp = strncmp(left_obj->name, right_key, strlen(right_key));
+ break;
+ default:
+ cmp = 0;
+ break;
+ }
+
+ return cmp;
+}
+
+static int formatter_compare(void *obj, void *arg, int flags)
+{
+ const struct ast_sip_cli_formatter_entry *left_obj = obj;
+ const struct ast_sip_cli_formatter_entry *right_obj = arg;
+ const char *right_key = arg;
+ int cmp = 0;
+
+ switch (flags & OBJ_SEARCH_MASK) {
+ case OBJ_SEARCH_OBJECT:
+ right_key = right_obj->name;
+ /* Fall through */
[... 960 lines stripped ...]
More information about the asterisk-commits
mailing list