[asterisk-commits] mjordan: branch mjordan/pjsip-cli r404399 - in /team/mjordan/pjsip-cli: inclu...
SVN commits to the Asterisk project
asterisk-commits at lists.digium.com
Thu Dec 19 22:03:21 CST 2013
Author: mjordan
Date: Thu Dec 19 22:03:18 2013
New Revision: 404399
URL: http://svnview.digium.com/svn/asterisk?view=rev&rev=404399
Log:
Add George Joseph's patch
Added:
team/mjordan/pjsip-cli/include/asterisk/res_pjsip_cli.h (with props)
team/mjordan/pjsip-cli/include/asterisk/res_pjsip_endpoint_identifier_ip.h (with props)
team/mjordan/pjsip-cli/res/res_pjsip/pjsip_cli.c (with props)
team/mjordan/pjsip-cli/res/res_pjsip_endpoint_identifier_ip.exports.in (with props)
Modified:
team/mjordan/pjsip-cli/include/asterisk/config.h
team/mjordan/pjsip-cli/include/asterisk/res_pjsip.h
team/mjordan/pjsip-cli/include/asterisk/sorcery.h
team/mjordan/pjsip-cli/main/config.c
team/mjordan/pjsip-cli/main/sorcery.c
team/mjordan/pjsip-cli/res/res_pjsip/config_auth.c
team/mjordan/pjsip-cli/res/res_pjsip/include/res_pjsip_private.h
team/mjordan/pjsip-cli/res/res_pjsip/location.c
team/mjordan/pjsip-cli/res/res_pjsip/pjsip_configuration.c
team/mjordan/pjsip-cli/res/res_pjsip_endpoint_identifier_ip.c
team/mjordan/pjsip-cli/res/res_pjsip_registrar.c
Modified: team/mjordan/pjsip-cli/include/asterisk/config.h
URL: http://svnview.digium.com/svn/asterisk/team/mjordan/pjsip-cli/include/asterisk/config.h?view=diff&rev=404399&r1=404398&r2=404399
==============================================================================
--- team/mjordan/pjsip-cli/include/asterisk/config.h (original)
+++ team/mjordan/pjsip-cli/include/asterisk/config.h Thu Dec 19 22:03:18 2013
@@ -691,6 +691,7 @@
void ast_variable_append(struct ast_category *category, struct ast_variable *variable);
void ast_variable_insert(struct ast_category *category, struct ast_variable *variable, const char *line);
int ast_variable_delete(struct ast_category *category, const char *variable, const char *match, const char *line);
+struct ast_variable *ast_variable_list_sort(struct ast_variable *start);
/*!
* \brief Update variable value within a config
Modified: team/mjordan/pjsip-cli/include/asterisk/res_pjsip.h
URL: http://svnview.digium.com/svn/asterisk/team/mjordan/pjsip-cli/include/asterisk/res_pjsip.h?view=diff&rev=404399&r1=404398&r2=404399
==============================================================================
--- team/mjordan/pjsip-cli/include/asterisk/res_pjsip.h (original)
+++ team/mjordan/pjsip-cli/include/asterisk/res_pjsip.h Thu Dec 19 22:03:18 2013
@@ -38,6 +38,9 @@
#include <pjlib.h>
/* Needed for ast_rtp_dtls_cfg struct */
#include "asterisk/rtp_engine.h"
+/* Needed for ast_sip_for_each_channel_snapshot struct */
+#include "asterisk/stasis_channels.h"
+#include "asterisk/stasis_endpoints.h"
/* Forward declarations of PJSIP stuff */
struct pjsip_rx_data;
@@ -209,6 +212,17 @@
unsigned int remove_existing;
/*! Any permanent configured contacts */
struct ao2_container *permanent_contacts;
+};
+
+/*!
+ * \brief Aor/Contact pair used for ast_sip_for_each_contact callback.
+ */
+struct ast_sip_aor_contact_pair {
+ SORCERY_OBJECT(details);
+ /*! Aor */
+ struct ast_sip_aor *aor;
+ /*! Contact */
+ struct ast_sip_contact *contact;
};
/*!
@@ -669,6 +683,11 @@
struct ast_sip_endpoint *(*identify_endpoint)(pjsip_rx_data *rdata);
};
+struct ast_sip_channel_snapshot {
+ SORCERY_OBJECT(details);
+ struct ast_channel_snapshot channel_snapshot;
+};
+
/*!
* \brief Register a SIP service in Asterisk.
*
@@ -1550,13 +1569,6 @@
mod_data[id] = ast_sip_dict_set(pool, mod_data[id], key, val)
/*!
- * \brief Function pointer for contact callbacks.
- */
-typedef int (*on_contact_t)(const struct ast_sip_aor *aor,
- const struct ast_sip_contact *contact,
- int last, void *arg);
-
-/*!
* \brief For every contact on an AOR call the given 'on_contact' handler.
*
* \param aor the aor containing a list of contacts to iterate
@@ -1564,21 +1576,18 @@
* \param arg user data passed to handler
* \retval 0 Success, non-zero on failure
*/
-int ast_sip_for_each_contact(const struct ast_sip_aor *aor,
- on_contact_t on_contact, void *arg);
+int ast_sip_for_each_contact(struct ast_sip_aor *aor,
+ ao2_callback_fn on_contact, void *arg);
/*!
* \brief Handler used to convert a contact to a string.
*
- * \param aor the aor containing a list of contacts to iterate
- * \param contact the contact to convert
- * \param last is this the last contact
+ * \param object the ast_sip_aor_contact_pair containing a list of contacts to iterate and the contact
* \param arg user data passed to handler
+ * \param flags
* \retval 0 Success, non-zero on failure
*/
-int ast_sip_contact_to_str(const struct ast_sip_aor *aor,
- const struct ast_sip_contact *contact,
- int last, void *arg);
+int ast_sip_contact_to_str(void *object, void *arg, int flags);
/*!
* \brief For every aor in the comma separated aors string call the
@@ -1699,4 +1708,47 @@
int ast_sip_format_auths_ami(const struct ast_sip_auth_array *auths,
struct ast_sip_ami *ami);
+/*!
+ * \brief Retrieve the endpoint snapshot for an endpoint
+ *
+ * \param endpoint The endpoint whose snapshot is to be retreieved.
+ * \retval The endpoint snapshot
+ */
+struct ast_endpoint_snapshot *ast_sip_get_endpoint_snapshot(
+ const struct ast_sip_endpoint *endpoint);
+
+/*!
+ * \brief Retrieve the device state for an endpoint.
+ *
+ * \param endpoint The endpoint whose state is to be retrieved.
+ * \retval The device state.
+ */
+const char *ast_sip_get_device_state(const struct ast_sip_endpoint *endpoint);
+
+/*!
+ * \brief For every channel snapshot on an endpoint snapshot call the given
+ * 'on_channel_snapshot' handler.
+ *
+ * \param endpoint_snapshot snapshot of an endpoint
+ * \param on_channel_snapshot callback for each channel snapshot
+ * \param arg user data passed to handler
+ * \retval 0 Success, non-zero on failure
+ */
+int ast_sip_for_each_channel_snapshot(const struct ast_endpoint_snapshot *endpoint_snapshot,
+ ao2_callback_fn on_channel_snapshot,
+ void *arg);
+
+/*!
+ * \brief For every channel snapshot on an endpoint all the given
+ * 'on_channel_snapshot' handler.
+ *
+ * \param endpoint endpoint
+ * \param on_channel_snapshot callback for each channel snapshot
+ * \param arg user data passed to handler
+ * \retval 0 Success, non-zero on failure
+ */
+int ast_sip_for_each_channel(const struct ast_sip_endpoint *endpoint,
+ ao2_callback_fn on_channel_snapshot,
+ void *arg);
+
#endif /* _RES_PJSIP_H */
Added: team/mjordan/pjsip-cli/include/asterisk/res_pjsip_cli.h
URL: http://svnview.digium.com/svn/asterisk/team/mjordan/pjsip-cli/include/asterisk/res_pjsip_cli.h?view=auto&rev=404399
==============================================================================
--- team/mjordan/pjsip-cli/include/asterisk/res_pjsip_cli.h (added)
+++ team/mjordan/pjsip-cli/include/asterisk/res_pjsip_cli.h Thu Dec 19 22:03:18 2013
@@ -1,0 +1,95 @@
+/*
+ * Asterisk -- An open source telephony toolkit.
+ *
+ * Copyright (C) 2013, Fairview 5 Engineering, LLC.
+ *
+ * George Joseph <george.joseph at fairview5.com>
+ *
+ * See http://www.asterisk.org for more information about
+ * the Asterisk project. Please do not directly contact
+ * any of the maintainers of this project for assistance;
+ * the project provides a web site, mailing lists and IRC
+ * channels for your use.
+ *
+ * This program is free software, distributed under the terms of
+ * the GNU General Public License Version 2. See the LICENSE file
+ * at the top of the source tree.
+ */
+
+#ifndef RES_PJSIP_CLI_H_
+#define RES_PJSIP_CLI_H_
+
+#define CLI_HEADER_FILLER ".........................................................................................."
+#define CLI_DETAIL_FILLER " "
+#define CLI_MAX_WIDTH 90
+#define CLI_LAST_TABSTOP 62
+#define CLI_MAX_TITLE_NAME 8
+#define CLI_INDENT_TO_SPACES(x) ((x * 2) + 1 + CLI_MAX_TITLE_NAME)
+
+/*
+ * \brief CLI Formatter Context
+ */
+struct ast_sip_cli_context {
+ int peers_mon_online;
+ int peers_mon_offline;
+ int peers_unmon_offline;
+ int peers_unmon_online;
+ 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;
+ char *auth_direction;
+ unsigned int print_flags;
+ int indent_level;
+ unsigned show_details : 1;
+ unsigned recurse : 1;
+ unsigned show_details_only_level_0 : 1;
+};
+
+/*
+ * \brief CLI Formatter Registry Entry
+ */
+struct ast_sip_cli_formatter_entry {
+ const char *name;
+ ao2_callback_fn *print_header;
+ ao2_callback_fn *print_body;
+ struct ao2_container *(* get_container)(struct ast_sorcery *);
+};
+
+/*!
+ * \brief Registers a CLI formatter.
+ *
+ * \param name The name of the formatter, usually the sorcery object type.
+ * \param formatter An ao2_callback_fn that outputs the formatted data.
+ * \retval 0 Success, non-zero on failure
+ */
+int ast_sip_register_cli_formatter(struct ast_sip_cli_formatter_entry *formatter);
+
+/*!
+ * \brief Unregisters a CLI formatter.
+ *
+ * \param name The name of the formatter, usually the sorcery object type.
+ * \retval 0 Success, non-zero on failure
+ */
+int ast_sip_unregister_cli_formatter(struct ast_sip_cli_formatter_entry *formatter);
+
+/*!
+ * \brief Looks up a CLI formatter by type.
+ *
+ * \param name The name of the formatter, usually the sorcery object type.
+ * \retval Pointer to formatter entry structure
+ */
+struct ast_sip_cli_formatter_entry *ast_sip_lookup_cli_formatter(const char *name);
+
+/*!
+ * \brief Prints a sorcery object's ast_variable list
+ *
+ * \param obj The sorcery object
+ * \param arg The ast_sip_cli_context.
+ * \retval 0 Success, non-zero on failure
+ */
+int ast_sip_cli_print_sorcery_objectset(void *obj, void *arg, int flags);
+
+
+#endif /* RES_PJSIP_CLI_H_ */
Propchange: team/mjordan/pjsip-cli/include/asterisk/res_pjsip_cli.h
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: team/mjordan/pjsip-cli/include/asterisk/res_pjsip_cli.h
------------------------------------------------------------------------------
svn:keywords = Author Date Id Revision
Propchange: team/mjordan/pjsip-cli/include/asterisk/res_pjsip_cli.h
------------------------------------------------------------------------------
svn:mime-type = text/plain
Added: team/mjordan/pjsip-cli/include/asterisk/res_pjsip_endpoint_identifier_ip.h
URL: http://svnview.digium.com/svn/asterisk/team/mjordan/pjsip-cli/include/asterisk/res_pjsip_endpoint_identifier_ip.h?view=auto&rev=404399
==============================================================================
--- team/mjordan/pjsip-cli/include/asterisk/res_pjsip_endpoint_identifier_ip.h (added)
+++ team/mjordan/pjsip-cli/include/asterisk/res_pjsip_endpoint_identifier_ip.h Thu Dec 19 22:03:18 2013
@@ -1,0 +1,106 @@
+/*
+ * Asterisk -- An open source telephony toolkit.
+ *
+ * Copyright (C) 2013, Fairview 5 Engineering, LLC
+ *
+ * George Joseph <george.joseph at fairview5.com>
+ *
+ * See http://www.asterisk.org for more information about
+ * the Asterisk project. Please do not directly contact
+ * any of the maintainers of this project for assistance;
+ * the project provides a web site, mailing lists and IRC
+ * channels for your use.
+ *
+ * This program is free software, distributed under the terms of
+ * the GNU General Public License Version 2. See the LICENSE file
+ * at the top of the source tree.
+ */
+
+#ifndef _RES_PJSIP_ENDPOINT_IDENTIFIER_IP_H
+#define _RES_PJSIP_ENDPOINT_IDENTIFIER_IP_H
+
+#include "asterisk/stringfields.h"
+#include "asterisk/linkedlists.h"
+#include "asterisk/pbx.h"
+#include "asterisk/sorcery.h"
+
+/*!
+ * \brief Structure for an IP identification matching object
+ */
+struct ast_sip_ip_identify_match {
+ /*! \brief Sorcery object details */
+ SORCERY_OBJECT(details);
+ /*! \brief Stringfields */
+ AST_DECLARE_STRING_FIELDS(
+ /*! The name of the endpoint */
+ AST_STRING_FIELD(endpoint_name);
+ );
+ /*! \brief Networks or addresses that should match this */
+ struct ast_ha *matches;
+};
+
+/*!
+ * \brief For every identify field in an endpoint execute the 'on_identify' handler.
+ *
+ * \param endpoint endpoint
+ * \param on_identify callback for each identify
+ * \param arg user data passed to handler
+ * \retval 0 Success, non-zero on failure
+ */
+int ast_sip_for_each_identify(const struct ast_sip_endpoint *endpoint,
+ ao2_callback_fn on_identify, void *arg);
+
+#endif /* _RES_PJSIP_ENDPOINT_IDENTIFIER_IP_H */
+/*
+ * Asterisk -- An open source telephony toolkit.
+ *
+ * Copyright (C) 2013, Fairview 5 Engineering, LLC
+ *
+ * George Joseph <george.joseph at fairview5.com>
+ *
+ * See http://www.asterisk.org for more information about
+ * the Asterisk project. Please do not directly contact
+ * any of the maintainers of this project for assistance;
+ * the project provides a web site, mailing lists and IRC
+ * channels for your use.
+ *
+ * This program is free software, distributed under the terms of
+ * the GNU General Public License Version 2. See the LICENSE file
+ * at the top of the source tree.
+ */
+
+#ifndef _RES_PJSIP_ENDPOINT_IDENTIFIER_IP_H
+#define _RES_PJSIP_ENDPOINT_IDENTIFIER_IP_H
+
+#include "asterisk/stringfields.h"
+#include "asterisk/linkedlists.h"
+#include "asterisk/pbx.h"
+#include "asterisk/sorcery.h"
+
+/*!
+ * \brief Structure for an IP identification matching object
+ */
+struct ast_sip_ip_identify_match {
+ /*! \brief Sorcery object details */
+ SORCERY_OBJECT(details);
+ /*! \brief Stringfields */
+ AST_DECLARE_STRING_FIELDS(
+ /*! The name of the endpoint */
+ AST_STRING_FIELD(endpoint_name);
+ );
+ /*! \brief Networks or addresses that should match this */
+ struct ast_ha *matches;
+};
+
+/*!
+ * \brief For every identify field in an endpoint execute the 'on_identify' handler.
+ *
+ * \param endpoint endpoint
+ * \param on_identify callback for each identify
+ * \param arg user data passed to handler
+ * \retval 0 Success, non-zero on failure
+ */
+int ast_sip_for_each_identify(const struct ast_sip_endpoint *endpoint,
+ ao2_callback_fn on_identify, void *arg);
+
+#endif /* _RES_PJSIP_ENDPOINT_IDENTIFIER_IP_H */
Propchange: team/mjordan/pjsip-cli/include/asterisk/res_pjsip_endpoint_identifier_ip.h
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: team/mjordan/pjsip-cli/include/asterisk/res_pjsip_endpoint_identifier_ip.h
------------------------------------------------------------------------------
svn:keywords = Author Date Id Revision
Propchange: team/mjordan/pjsip-cli/include/asterisk/res_pjsip_endpoint_identifier_ip.h
------------------------------------------------------------------------------
svn:mime-type = text/plain
Modified: team/mjordan/pjsip-cli/include/asterisk/sorcery.h
URL: http://svnview.digium.com/svn/asterisk/team/mjordan/pjsip-cli/include/asterisk/sorcery.h?view=diff&rev=404399&r1=404398&r2=404399
==============================================================================
--- team/mjordan/pjsip-cli/include/asterisk/sorcery.h (original)
+++ team/mjordan/pjsip-cli/include/asterisk/sorcery.h Thu Dec 19 22:03:18 2013
@@ -823,6 +823,12 @@
*/
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);
+
+
#if defined(__cplusplus) || defined(c_plusplus)
}
#endif
Modified: team/mjordan/pjsip-cli/main/config.c
URL: http://svnview.digium.com/svn/asterisk/team/mjordan/pjsip-cli/main/config.c?view=diff&rev=404399&r1=404398&r2=404399
==============================================================================
--- team/mjordan/pjsip-cli/main/config.c (original)
+++ team/mjordan/pjsip-cli/main/config.c Thu Dec 19 22:03:18 2013
@@ -70,6 +70,7 @@
static struct ao2_container *cfg_hooks;
static void config_hook_exec(const char *filename, const char *module, struct ast_config *cfg);
+inline struct ast_variable *variable_list_switch(struct ast_variable *l1, struct ast_variable *l2);
/*! \brief Structure to keep comments for rewriting configuration files */
struct ast_comment {
@@ -579,6 +580,39 @@
}
return (cat) ? cat->root : NULL;
+}
+
+inline struct ast_variable *variable_list_switch(struct ast_variable *l1, struct ast_variable *l2)
+{
+ l1->next = l2->next;
+ l2->next = l1;
+ return l2;
+}
+
+struct ast_variable *ast_variable_list_sort(struct ast_variable *start)
+{
+ struct ast_variable *p, *q, *top;
+ int changed = 1;
+ top = ast_calloc(1, sizeof(struct ast_variable));
+ top->next = start;
+ if (start != NULL && start->next != NULL) {
+ while (changed) {
+ changed = 0;
+ q = top;
+ p = top->next;
+ while (p->next != NULL) {
+ if (p->next != NULL && strcmp(p->name, p->next->name) > 0) {
+ q->next = variable_list_switch(p, p->next);
+
+ changed = 1;
+ }
+ q = p;
+ if (p->next != NULL)
+ p = p->next;
+ }
+ }
+ }
+ return top->next;
}
const char *ast_config_option(struct ast_config *cfg, const char *cat, const char *var)
Modified: team/mjordan/pjsip-cli/main/sorcery.c
URL: http://svnview.digium.com/svn/asterisk/team/mjordan/pjsip-cli/main/sorcery.c?view=diff&rev=404399&r1=404398&r2=404399
==============================================================================
--- team/mjordan/pjsip-cli/main/sorcery.c (original)
+++ team/mjordan/pjsip-cli/main/sorcery.c Thu Dec 19 22:03:18 2013
@@ -1583,3 +1583,11 @@
ao2_callback(object_type->observers, OBJ_NODATA | OBJ_UNLINK,
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));
+}
Modified: team/mjordan/pjsip-cli/res/res_pjsip/config_auth.c
URL: http://svnview.digium.com/svn/asterisk/team/mjordan/pjsip-cli/res/res_pjsip/config_auth.c?view=diff&rev=404399&r1=404398&r2=404399
==============================================================================
--- team/mjordan/pjsip-cli/res/res_pjsip/config_auth.c (original)
+++ team/mjordan/pjsip-cli/res/res_pjsip/config_auth.c Thu Dec 19 22:03:18 2013
@@ -23,7 +23,9 @@
#include "asterisk/res_pjsip.h"
#include "asterisk/logger.h"
#include "asterisk/sorcery.h"
+#include "asterisk/cli.h"
#include "include/res_pjsip_private.h"
+#include "asterisk/res_pjsip_cli.h"
static void auth_destroy(void *obj)
{
@@ -194,6 +196,59 @@
static struct ast_sip_endpoint_formatter endpoint_auth_formatter = {
.format_ami = format_ami_endpoint_auth
+};
+
+static struct ao2_container *cli_get_auth_container(struct ast_sorcery *sip_sorcery)
+{
+ return ast_sorcery_retrieve_by_fields(sip_sorcery, "auth",
+ AST_RETRIEVE_FLAG_MULTIPLE | AST_RETRIEVE_FLAG_ALL, NULL);
+}
+
+static int cli_print_auth_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_str_append(&context->output_buffer, 0,
+ "%*s: <AuthId/UserName%*.*s>\n", indent, "I/OAuth", filler, filler, CLI_HEADER_FILLER);
+
+ return 0;
+}
+
+static int cli_print_auth_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;
+ }
+
+ snprintf(title, 32, "%sAuth",context->auth_direction ? context->auth_direction : "");
+
+ ast_str_append(&context->output_buffer, 0, "%*s: %s/%s\n",
+ CLI_INDENT_TO_SPACES(context->indent_level), title,
+ ast_sorcery_object_get_id(auth), auth->auth_user);
+
+ if (context->show_details || (context->show_details_only_level_0 && context->indent_level == 0)) {
+ ast_str_append(&context->output_buffer, 0, "\n");
+ ast_sip_cli_print_sorcery_objectset(auth, context, 0);
+ }
+
+ 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,
};
/*! \brief Initialize sorcery with auth support */
@@ -221,5 +276,7 @@
"userpass", auth_type_handler, auth_type_to_str, 0, 0);
ast_sip_register_endpoint_formatter(&endpoint_auth_formatter);
- return 0;
-}
+ ast_sip_register_cli_formatter(&cli_auth_formatter);
+
+ return 0;
+}
Modified: team/mjordan/pjsip-cli/res/res_pjsip/include/res_pjsip_private.h
URL: http://svnview.digium.com/svn/asterisk/team/mjordan/pjsip-cli/res/res_pjsip/include/res_pjsip_private.h?view=diff&rev=404399&r1=404398&r2=404399
==============================================================================
--- team/mjordan/pjsip-cli/res/res_pjsip/include/res_pjsip_private.h (original)
+++ team/mjordan/pjsip-cli/res/res_pjsip/include/res_pjsip_private.h Thu Dec 19 22:03:18 2013
@@ -9,8 +9,6 @@
#define RES_PJSIP_PRIVATE_H_
#include "asterisk/module.h"
-#include "asterisk/stasis_channels.h"
-#include "asterisk/stasis_endpoints.h"
struct ao2_container;
struct ast_threadpool_options;
@@ -87,25 +85,6 @@
void sip_get_threadpool_options(struct ast_threadpool_options *threadpool_options);
/*!
- * \brief Function pointer for channel snapshot callbacks.
- */
-typedef int (*on_channel_snapshot_t)(
- const struct ast_channel_snapshot *snapshot, int last, void *arg);
-
-/*!
- * \brief For every channel snapshot on an endpoint snapshot call the given
- * 'on_channel_snapshot' handler.
- *
- * \param endpoint_snapshot snapshot of an endpoint
- * \param on_channel_snapshot callback for each channel snapshot
- * \param arg user data passed to handler
- * \retval 0 Success, non-zero on failure
- */
-int ast_sip_for_each_channel_snapshot(const struct ast_endpoint_snapshot *endpoint_snapshot,
- on_channel_snapshot_t on_channel_snapshot,
- void *arg);
-
-/*!
* \brief Retrieve the name of the default outbound endpoint.
*
* \note This returns a memory allocated copy of the name that
@@ -116,4 +95,10 @@
*/
char *ast_sip_global_default_outbound_endpoint(void);
+/*!
+ * \brief Functions for initializing and destroying the CLI.
+ */
+int ast_sip_initialize_cli(struct ast_sorcery *sip_sorcery);
+void ast_sip_destroy_cli(void);
+
#endif /* RES_PJSIP_PRIVATE_H_ */
Modified: team/mjordan/pjsip-cli/res/res_pjsip/location.c
URL: http://svnview.digium.com/svn/asterisk/team/mjordan/pjsip-cli/res/res_pjsip/location.c?view=diff&rev=404399&r1=404398&r2=404399
==============================================================================
--- team/mjordan/pjsip-cli/res/res_pjsip/location.c (original)
+++ team/mjordan/pjsip-cli/res/res_pjsip/location.c Thu Dec 19 22:03:18 2013
@@ -25,6 +25,7 @@
#include "asterisk/astobj2.h"
#include "asterisk/sorcery.h"
#include "include/res_pjsip_private.h"
+#include "asterisk/res_pjsip_cli.h"
/*! \brief Destructor for AOR */
static void aor_destroy(void *obj)
@@ -284,12 +285,11 @@
return 0;
}
-int ast_sip_for_each_contact(const struct ast_sip_aor *aor,
- on_contact_t on_contact, void *arg)
+int ast_sip_for_each_contact(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;
- int num;
struct ao2_iterator i;
if (!on_contact ||
@@ -297,12 +297,18 @@
return 0;
}
- num = ao2_container_count(contacts);
i = ao2_iterator_init(contacts, 0);
while ((contact = ao2_iterator_next(&i))) {
- int res = on_contact(aor, contact, --num == 0, arg);
-
+ int res;
+ RAII_VAR(struct ast_sip_aor_contact_pair *, acp, NULL, ao2_cleanup);
+ acp = ao2_alloc(sizeof(struct ast_sip_aor_contact_pair), NULL);
+ ao2_ref(aor, +1);
+ ao2_ref(acp, +1);
+ acp->aor = aor;
+ acp->contact = contact;
+ res = on_contact(acp, arg, 0);
ao2_ref(contact, -1);
+ ao2_ref(aor, -1);
if (res) {
return -1;
}
@@ -311,18 +317,13 @@
return 0;
}
-int ast_sip_contact_to_str(const struct ast_sip_aor *aor,
- const struct ast_sip_contact *contact,
- int last, void *arg)
-{
+int ast_sip_contact_to_str(void *object, void *arg, int flags)
+{
+ struct ast_sip_aor_contact_pair *acp = object;
struct ast_str **buf = arg;
- ast_str_append(buf, 0, "%s/%s",
- ast_sorcery_object_get_id(aor), contact->uri);
-
- if (!last) {
- ast_str_append(buf, 0, ",");
- }
+ ast_str_append(buf, 0, "%s/%s,",
+ ast_sorcery_object_get_id(acp->aor), acp->contact->uri);
return 0;
}
@@ -334,7 +335,7 @@
static int format_ami_aor_handler(void *obj, void *arg, int flags)
{
- const struct ast_sip_aor *aor = obj;
+ struct ast_sip_aor *aor = obj;
struct ast_sip_ami *ami = arg;
const struct ast_sip_endpoint *endpoint = ami->arg;
RAII_VAR(struct ast_str *, buf,
@@ -351,6 +352,7 @@
sip_aor_to_ami(aor, &buf);
ast_str_append(&buf, 0, "Contacts: ");
ast_sip_for_each_contact(aor, ast_sip_contact_to_str, &buf);
+ ast_str_truncate(buf, -1);
ast_str_append(&buf, 0, "\r\n");
num = ao2_container_count(contacts);
@@ -374,6 +376,180 @@
struct ast_sip_endpoint_formatter endpoint_aor_formatter = {
.format_ami = format_ami_endpoint_aor
+};
+
+static int populate_contact_container(void *obj, void *arg, int flags) {
+ struct ast_sip_aor_contact_pair *acp = obj;
+ struct ao2_container *container = arg;
+ ao2_link_flags(container, acp, OBJ_NOLOCK);
+ return 0;
+}
+
+static int gather_aor_channels(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 struct ao2_container *cli_get_contact_container(struct ast_sorcery *sip_sorcery)
+{
+ RAII_VAR(struct ao2_container *, parent_container, NULL, ao2_cleanup);
+ RAII_VAR(struct ao2_container *, s_parent_container, NULL, ao2_cleanup);
+ RAII_VAR(struct ao2_container *, child_container, NULL, ao2_cleanup);
+
+ parent_container = ast_sorcery_retrieve_by_fields(sip_sorcery, "aor",
+ AST_RETRIEVE_FLAG_MULTIPLE | AST_RETRIEVE_FLAG_ALL, NULL);
+
+ s_parent_container = ao2_container_alloc_list(AO2_ALLOC_OPT_LOCK_NOLOCK, 0, &ast_sorcery_object_id_compare, NULL);
+ ao2_container_dup(s_parent_container, parent_container, OBJ_ORDER_ASCENDING);
+
+ child_container = ao2_container_alloc_list(AO2_ALLOC_OPT_LOCK_NOLOCK, 0, NULL, NULL);
+ ao2_ref(child_container, +1);
+ ao2_callback(s_parent_container, OBJ_NODATA, gather_aor_channels, child_container);
+
+ return child_container;
+}
+
+
+static int cli_print_contact_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_str_append(&context->output_buffer, 0,
+ "%*s: <Aor/ContactUri%*.*s> <Status....> <RTT(ms)..>\n",
+ indent, "Contact", filler, filler, CLI_HEADER_FILLER);
+
+ return 0;
+}
+
+static int cli_print_contact_body(void *obj, void *arg, int flags)
+{
+ struct ast_sip_aor_contact_pair *acp = obj;
+ struct ast_sip_cli_context *context = arg;
+ char *print_name = NULL;
+ int print_name_len;
+ int indent;
+ int flexwidth;
+
+ RAII_VAR(struct ast_sip_contact_status *, status,
+ ast_sorcery_retrieve_by_id( ast_sip_get_sorcery(), CONTACT_STATUS, ast_sorcery_object_get_id(acp->contact)),
+ ao2_cleanup);
+
+ if (!context->output_buffer) {
+ return -1;
+ }
+
+ print_name_len = strlen(ast_sorcery_object_get_id(acp->aor))
+ + strlen(acp->contact->uri) + 2;
+ if (!(print_name = alloca(print_name_len))) {
+ return -1;
+ }
+ snprintf(print_name, print_name_len, "%s/%s",
+ ast_sorcery_object_get_id(acp->aor), acp->contact->uri);
+
+ indent = CLI_INDENT_TO_SPACES(context->indent_level);
+ flexwidth = CLI_LAST_TABSTOP - indent - 2;
+
+ ast_str_append(&context->output_buffer, 0, "%*s: %-*.*s %-12.12s %11.3f\n",
+ indent,
+ "Contact",
+ flexwidth, flexwidth,
+ print_name,
+ (status ? (status->status == AVAILABLE ? "Avail" : "Unavail") : "Unknown"),
+ (status ? ((long long) status->rtt) / 1000.0 : NAN));
+
+ return 0;
+}
+
+static struct ao2_container *cli_get_aor_container(struct ast_sorcery *sip_sorcery)
+{
+ return ast_sorcery_retrieve_by_fields(sip_sorcery, "aor",
+ AST_RETRIEVE_FLAG_MULTIPLE | AST_RETRIEVE_FLAG_ALL, NULL);
+}
+
+static int cli_print_aor_header(void *obj, void *arg, int flags)
+{
+ struct ast_sip_cli_context *context = arg;
+ struct ast_sip_cli_formatter_entry *formatter_entry;
+
+ int indent = CLI_INDENT_TO_SPACES(context->indent_level);
+ int filler = CLI_LAST_TABSTOP - indent - 7;
+
+ if (!context->output_buffer) {
+ return -1;
+ }
+ ast_str_append(&context->output_buffer, 0,
+ "%*s: <Aor%*.*s> <MaxContact>\n",
+ indent, "Aor", filler, filler, CLI_HEADER_FILLER);
+
+ if (context->recurse) {
+ context->indent_level++;
+ formatter_entry = ast_sip_lookup_cli_formatter("contact");
+ 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) {
+ struct ast_sip_aor *aor = obj;
+ struct ast_sip_cli_context *context = arg;
+ struct ast_sip_cli_formatter_entry *formatter_entry;
+ int indent;
+ int flexwidth;
+
+ if (!context->output_buffer) {
+ return -1;
+ }
+
+ context->current_aor = aor;
+
+ indent = CLI_INDENT_TO_SPACES(context->indent_level);
+ flexwidth = CLI_LAST_TABSTOP - indent - 12;
+
+ ast_str_append(&context->output_buffer, 0, "%*s: %-*.*s %12d\n",
+ indent,
+ "Aor",
+ flexwidth, flexwidth,
+ ast_sorcery_object_get_id(aor), aor->max_contacts);
+
+ if (context->recurse) {
+ context->indent_level++;
+ formatter_entry = ast_sip_lookup_cli_formatter("contact");
+ if (formatter_entry) {
+ ast_sip_for_each_contact(aor, formatter_entry->print_body, context);
+ }
+ context->indent_level--;
+ }
+
+ if (context->show_details || (context->show_details_only_level_0 && context->indent_level == 0)) {
+ ast_str_append(&context->output_buffer, 0, "\n");
+ ast_sip_cli_print_sorcery_objectset(aor, context, 0);
+ }
+
+ 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,
+};
+
+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,
};
/*! \brief Initialize sorcery with location support */
@@ -407,6 +583,8 @@
ast_sorcery_object_field_register(sorcery, "aor", "outbound_proxy", "", OPT_STRINGFIELD_T, 0, STRFLDSET(struct ast_sip_aor, outbound_proxy));
ast_sip_register_endpoint_formatter(&endpoint_aor_formatter);
- return 0;
-}
-
+ ast_sip_register_cli_formatter(&cli_contact_formatter);
+ ast_sip_register_cli_formatter(&cli_aor_formatter);
+ return 0;
+}
+
Added: team/mjordan/pjsip-cli/res/res_pjsip/pjsip_cli.c
URL: http://svnview.digium.com/svn/asterisk/team/mjordan/pjsip-cli/res/res_pjsip/pjsip_cli.c?view=auto&rev=404399
==============================================================================
--- team/mjordan/pjsip-cli/res/res_pjsip/pjsip_cli.c (added)
+++ team/mjordan/pjsip-cli/res/res_pjsip/pjsip_cli.c Thu Dec 19 22:03:18 2013
@@ -1,0 +1,640 @@
+/*
+ * Asterisk -- An open source telephony toolkit.
+ *
+ * Copyright (C) 2013, Fairview 5 Engineering, LLC
+ *
+ * George Joseph <george.joseph at fairview5.com>
+ *
+ * See http://www.asterisk.org for more information about
+ * the Asterisk project. Please do not directly contact
+ * any of the maintainers of this project for assistance;
+ * the project provides a web site, mailing lists and IRC
+ * channels for your use.
+ *
+ * This program is free software, distributed under the terms of
+ * the GNU General Public License Version 2. See the LICENSE file
+ * at the top of the source tree.
+ */
+
+#include "asterisk.h"
+
+#include <pjsip.h>
+#include <pjsip_ua.h>
+#include "asterisk/res_pjsip.h"
+#include "asterisk/res_pjsip_endpoint_identifier_ip.h"
+#include "include/res_pjsip_private.h"
+#include "asterisk/res_pjsip_cli.h"
+#include "asterisk/acl.h"
+#include "asterisk/cli.h"
+#include "asterisk/astobj2.h"
+#include "asterisk/hashtab.h"
+#include "asterisk/utils.h"
+#include "asterisk/sorcery.h"
+
+static struct ast_hashtab *formatter_registry;
+
+static struct ast_sorcery *sip_sorcery;
+
+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);
+}
+
+int ast_sip_cli_print_sorcery_objectset(void *obj, void *arg, int flags)
+{
+ struct ast_sip_cli_context *context = arg;
+ struct ast_variable *i;
+ int max_name_width = 13;
+ int max_value_width = 14;
+ int width;
+ char *separator;
+ struct ast_variable *objset;
+
+ if (!context->output_buffer) {
+ return -1;
+ }
+
+ objset = ast_sorcery_objectset_create(ast_sip_get_sorcery(),obj);
+ if (!objset) {
+ return -1;
+ }
+
+ for (i = objset; i; i = i->next) {
+ if (i->name) {
+ width = strlen(i->name);
+ max_name_width = width > max_name_width ? width : max_name_width;
+ }
+ if (i->value) {
+ width = strlen(i->value);
+ max_value_width = width > max_value_width ? width : max_value_width;
+ }
+ }
+
+ if (!(separator = alloca(max_name_width + max_value_width + 8))) {
+ return -1;
+ }
+ memset(separator, '=', max_name_width + max_value_width + 3);
+ separator[max_name_width + max_value_width + 3] = 0;
+
+ ast_str_append(&context->output_buffer, 0, " %-*s : %s\n", max_name_width, "ParameterName", "ParameterValue");
+ ast_str_append(&context->output_buffer, 0, " %s\n", separator);
+
+ objset = ast_variable_list_sort(objset);
+
+ for (i = objset; i; i = i->next) {
+ ast_str_append(&context->output_buffer, 0, " %-*s : %s\n", max_name_width, i->name, i->value);
+ }
+
+ return 0;
+}
+
+static char *complete_show_sorcery_object(struct ao2_container *container,
+ const char *word, int state)
+{
+ char *result = NULL;
+ int wordlen = strlen(word);
+ int which = 0;
+
+ struct ao2_iterator i = ao2_iterator_init(container, 0);
+ void *object;
+
+ while ((object = ao2_t_iterator_next(&i, "iterate thru endpoints table"))) {
+ if (!strncasecmp(word, ast_sorcery_object_get_id(object), wordlen)
+ && ++which > state) {
+ result = ast_strdup(ast_sorcery_object_get_id(object));
+ }
+ ao2_t_ref(object, -1, "toss iterator endpoint ptr before break");
+ if (result) {
+ break;
+ }
+ }
+ ao2_iterator_destroy(&i);
+ return result;
+}
+
+static void dump_str_and_free(int fd, struct ast_str *buf) {
+ ast_cli(fd, "%s", ast_str_buffer(buf));
+ ast_free(buf);
+}
+
+static char *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 ao2_container *, s_container, NULL, ao2_cleanup);
+ RAII_VAR(void *, object, NULL, ao2_cleanup);
+ int is_container = 0;
+ const char *cmd1 = NULL;
+ const char *cmd2 = NULL;
+ const char *object_id = NULL;
+ char formatter_type[64];
+ struct ast_sip_cli_formatter_entry *formatter_entry;
+ int is_plural = 0;
+
+ 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,
+ };
+
+ if (cmd == CLI_INIT) {
+ return NULL;
+ }
+
+ cmd1 = e->cmda[1];
+ cmd2 = e->cmda[2];
+ object_id = a->argv[3];
+
+ if (!ast_ends_with(cmd2, "s")) {
+ ast_copy_string(formatter_type, cmd2, strlen(cmd2)+1);
+ is_plural = 0;
+ } else {
+ ast_copy_string(formatter_type, cmd2, strlen(cmd2));
+ is_plural = 1;
+ }
+
+ if (!strcmp(cmd1, "show")) {
+ if (is_plural) {
+ context.recurse = 1;
+ context.show_details = 0;
+ context.show_details_only_level_0 = 0;
+ is_container = 1;
+ } else {
+ context.recurse = 1;
+ context.show_details = 0;
+ context.show_details_only_level_0 = 1;
+ is_container = 0;
+ }
+ } else {
+ context.recurse = 0;
+ context.show_details = 0;
+ context.show_details_only_level_0 = 0;
+ is_container = 1;
+ }
+
+ context.output_buffer = ast_str_create(256);
+ formatter_entry = ast_sip_lookup_cli_formatter(formatter_type);
+ if (!formatter_entry) {
+ ast_log(LOG_ERROR, "CLI TRAVERSE failure. No container found for object type %s\n", formatter_type);
+ return CLI_FAILURE;
+ }
+ ast_str_append(&context.output_buffer, 0, "\n");
+ formatter_entry->print_header(NULL, &context, 0);
+ ast_str_append(&context.output_buffer, 0, " =========================================================================================\n\n");
+
+ if (is_container || cmd == CLI_GENERATE) {
+ container = formatter_entry->get_container(sip_sorcery);
+ if (!container) {
+ ast_cli(a->fd, "CLI TRAVERSE failure. No container found for object type %s\n", formatter_type);
+ return CLI_FAILURE ;
+ }
+ }
+
+ if (!is_container && cmd == CLI_GENERATE) {
+ return complete_show_sorcery_object(container, a->word, a->n);
+ }
+
+ if (is_container) {
+ if (!ao2_container_count(container)) {
+ dump_str_and_free(a->fd, context.output_buffer);
+ ast_cli(a->fd, "No objects found.\n\n");
+ return CLI_SUCCESS ;
+ }
+
+ if (!strcmp(formatter_type, "channel") || !strcmp(formatter_type, "contact")) {
+ s_container = ao2_container_alloc_list(AO2_ALLOC_OPT_LOCK_NOLOCK, 0, NULL, NULL);
+ } else {
+ s_container = ao2_container_alloc_list(AO2_ALLOC_OPT_LOCK_NOLOCK, 0, &ast_sorcery_object_id_compare, NULL);
+ }
+
+ ao2_container_dup(s_container, container, OBJ_ORDER_ASCENDING);
+
+ ao2_callback(s_container, OBJ_NODATA, formatter_entry->print_body, &context);
+ } else {
+ if (!(object = ast_sorcery_retrieve_by_id(
+ ast_sip_get_sorcery(), formatter_type, object_id))) {
+ dump_str_and_free(a->fd, context.output_buffer);
+ ast_cli(a->fd, "Unable to retrieve object %s\n", object_id);
+ return CLI_FAILURE ;
+ }
+ formatter_entry->print_body(object, &context, 0);
+ }
+
+ ast_str_append(&context.output_buffer, 0, "\n");
+ dump_str_and_free(a->fd, context.output_buffer);
+ return CLI_SUCCESS ;
+}
+
+static struct ast_cli_entry cli_commands[] = {
+ AST_CLI_DEFINE(cli_traverse_objects, "List PJSIP Channels", .command = "pjsip list channels",
+ .usage = "Usage: pjsip list channels\n List the active PJSIP channels\n"),
+ AST_CLI_DEFINE(cli_traverse_objects, "Show PJSIP Channels", .command = "pjsip show channels",
+ .usage = "Usage: pjsip show channels\n List(detailed) the active PJSIP channels\n"),
+
+ AST_CLI_DEFINE(cli_traverse_objects, "List PJSIP Aors", .command = "pjsip list aors",
+ .usage = "Usage: pjsip list aors\n List the configured PJSIP Aors\n"),
+ AST_CLI_DEFINE(cli_traverse_objects, "Show PJSIP Aors", .command = "pjsip show aors",
+ .usage = "Usage: pjsip show aors\n Show the configured PJSIP Aors\n"),
+ AST_CLI_DEFINE(cli_traverse_objects, "Show PJSIP Aor", .command = "pjsip show aor",
+ .usage = "Usage: pjsip show aor\n Show the configured PJSIP Aor\n"),
+
+ AST_CLI_DEFINE(cli_traverse_objects, "List PJSIP Contacts", .command = "pjsip list contacts",
+ .usage = "Usage: pjsip list contacts\n List the configured PJSIP contacts\n"),
+
+ AST_CLI_DEFINE(cli_traverse_objects, "List PJSIP Endpoints", .command = "pjsip list endpoints",
[... 1265 lines stripped ...]
More information about the asterisk-commits
mailing list