summaryrefslogtreecommitdiff
path: root/res/res_pjsip/pjsip_configuration.c
diff options
context:
space:
mode:
Diffstat (limited to 'res/res_pjsip/pjsip_configuration.c')
-rw-r--r--res/res_pjsip/pjsip_configuration.c664
1 files changed, 636 insertions, 28 deletions
diff --git a/res/res_pjsip/pjsip_configuration.c b/res/res_pjsip/pjsip_configuration.c
index d8e781a56..24c53e8a9 100644
--- a/res/res_pjsip/pjsip_configuration.c
+++ b/res/res_pjsip/pjsip_configuration.c
@@ -13,11 +13,11 @@
#include "asterisk/res_pjsip.h"
#include "include/res_pjsip_private.h"
#include "asterisk/cli.h"
+#include "asterisk/manager.h"
#include "asterisk/astobj2.h"
#include "asterisk/utils.h"
#include "asterisk/sorcery.h"
#include "asterisk/callerid.h"
-#include "asterisk/stasis_endpoints.h"
/*! \brief Number of buckets for persistent endpoint information */
#define PERSISTENT_BUCKETS 53
@@ -242,6 +242,25 @@ static int dtmf_handler(const struct aco_option *opt, struct ast_variable *var,
return 0;
}
+static int dtmf_to_str(const void *obj, const intptr_t *args, char **buf)
+{
+ const struct ast_sip_endpoint *endpoint = obj;
+
+ switch (endpoint->dtmf) {
+ case AST_SIP_DTMF_RFC_4733 :
+ *buf = "rfc4733"; break;
+ case AST_SIP_DTMF_INBAND :
+ *buf = "inband"; break;
+ case AST_SIP_DTMF_INFO :
+ *buf = "info"; break;
+ default:
+ *buf = "none";
+ }
+
+ *buf = ast_strdup(*buf);
+ return 0;
+}
+
static int prack_handler(const struct aco_option *opt, struct ast_variable *var, void *obj)
{
struct ast_sip_endpoint *endpoint = obj;
@@ -259,6 +278,22 @@ static int prack_handler(const struct aco_option *opt, struct ast_variable *var,
return 0;
}
+static int prack_to_str(const void *obj, const intptr_t *args, char **buf)
+{
+ const struct ast_sip_endpoint *endpoint = obj;
+
+ if (endpoint->extensions.flags & PJSIP_INV_REQUIRE_100REL) {
+ *buf = "required";
+ } else if (endpoint->extensions.flags & PJSIP_INV_SUPPORT_100REL) {
+ *buf = "yes";
+ } else {
+ *buf = "no";
+ }
+
+ *buf = ast_strdup(*buf);
+ return 0;
+}
+
static int timers_handler(const struct aco_option *opt, struct ast_variable *var, void *obj)
{
struct ast_sip_endpoint *endpoint = obj;
@@ -278,6 +313,24 @@ static int timers_handler(const struct aco_option *opt, struct ast_variable *var
return 0;
}
+static int timers_to_str(const void *obj, const intptr_t *args, char **buf)
+{
+ const struct ast_sip_endpoint *endpoint = obj;
+
+ if (endpoint->extensions.flags & PJSIP_INV_ALWAYS_USE_TIMER) {
+ *buf = "always";
+ } else if (endpoint->extensions.flags & PJSIP_INV_REQUIRE_TIMER) {
+ *buf = "required";
+ } else if (endpoint->extensions.flags & PJSIP_INV_SUPPORT_TIMER) {
+ *buf = "yes";
+ } else {
+ *buf = "no";
+ }
+
+ *buf = ast_strdup(*buf);
+ return 0;
+}
+
void ast_sip_auth_array_destroy(struct ast_sip_auth_array *auths)
{
int i;
@@ -344,6 +397,32 @@ static int outbound_auth_handler(const struct aco_option *opt, struct ast_variab
return ast_sip_auth_array_init(&endpoint->outbound_auths, var->value);
}
+int ast_sip_auths_to_str(const struct ast_sip_auth_array *auths, char **buf)
+{
+ if (!auths || !auths->num) {
+ return 0;
+ }
+
+ if (!(*buf = ast_calloc(MAX_OBJECT_FIELD, sizeof(char)))) {
+ return -1;
+ }
+
+ ast_join_delim(*buf, MAX_OBJECT_FIELD, auths->names, auths->num, ',');
+ return 0;
+}
+
+static int inbound_auths_to_str(const void *obj, const intptr_t *args, char **buf)
+{
+ const struct ast_sip_endpoint *endpoint = obj;
+ return ast_sip_auths_to_str(&endpoint->inbound_auths, buf);
+}
+
+static int outbound_auths_to_str(const void *obj, const intptr_t *args, char **buf)
+{
+ const struct ast_sip_endpoint *endpoint = obj;
+ return ast_sip_auths_to_str(&endpoint->outbound_auths, buf);
+}
+
static int ident_handler(const struct aco_option *opt, struct ast_variable *var, void *obj)
{
struct ast_sip_endpoint *endpoint = obj;
@@ -362,6 +441,20 @@ static int ident_handler(const struct aco_option *opt, struct ast_variable *var,
return 0;
}
+static int ident_to_str(const void *obj, const intptr_t *args, char **buf)
+{
+ const struct ast_sip_endpoint *endpoint = obj;
+ switch (endpoint->ident_method) {
+ case AST_SIP_ENDPOINT_IDENTIFY_BY_USERNAME :
+ *buf = "username"; break;
+ default:
+ return 0;
+ }
+
+ *buf = ast_strdup(*buf);
+ return 0;
+}
+
static int direct_media_method_handler(const struct aco_option *opt, struct ast_variable *var, void *obj)
{
struct ast_sip_endpoint *endpoint = obj;
@@ -378,6 +471,20 @@ static int direct_media_method_handler(const struct aco_option *opt, struct ast_
return 0;
}
+static const char *id_configuration_refresh_methods[] = {
+ [AST_SIP_SESSION_REFRESH_METHOD_INVITE] = "invite",
+ [AST_SIP_SESSION_REFRESH_METHOD_UPDATE] = "update"
+};
+
+static int direct_media_method_to_str(const void *obj, const intptr_t *args, char **buf)
+{
+ const struct ast_sip_endpoint *endpoint = obj;
+ if (ARRAY_IN_BOUNDS(endpoint->id.refresh_method, id_configuration_refresh_methods)) {
+ *buf = ast_strdup(id_configuration_refresh_methods[endpoint->id.refresh_method]);
+ }
+ return 0;
+}
+
static int connected_line_method_handler(const struct aco_option *opt, struct ast_variable *var, void *obj)
{
struct ast_sip_endpoint *endpoint = obj;
@@ -394,6 +501,13 @@ static int connected_line_method_handler(const struct aco_option *opt, struct as
return 0;
}
+static int connected_line_method_to_str(const void *obj, const intptr_t *args, char **buf)
+{
+ const struct ast_sip_endpoint *endpoint = obj;
+ *buf = ast_strdup(id_configuration_refresh_methods[endpoint->id.refresh_method]);
+ return 0;
+}
+
static int direct_media_glare_mitigation_handler(const struct aco_option *opt, struct ast_variable *var, void *obj)
{
struct ast_sip_endpoint *endpoint = obj;
@@ -413,6 +527,22 @@ static int direct_media_glare_mitigation_handler(const struct aco_option *opt, s
return 0;
}
+static const char *direct_media_glare_mitigation_map[] = {
+ [AST_SIP_DIRECT_MEDIA_GLARE_MITIGATION_NONE] = "none",
+ [AST_SIP_DIRECT_MEDIA_GLARE_MITIGATION_OUTGOING] = "outgoing",
+ [AST_SIP_DIRECT_MEDIA_GLARE_MITIGATION_INCOMING] = "incoming"
+};
+
+static int direct_media_glare_mitigation_to_str(const void *obj, const intptr_t *args, char **buf)
+{
+ const struct ast_sip_endpoint *endpoint = obj;
+ if (ARRAY_IN_BOUNDS(endpoint->media.direct_media.glare_mitigation, direct_media_glare_mitigation_map)) {
+ *buf = ast_strdup(direct_media_glare_mitigation_map[endpoint->media.direct_media.glare_mitigation]);
+ }
+
+ return 0;
+}
+
static int caller_id_handler(const struct aco_option *opt, struct ast_variable *var, void *obj)
{
struct ast_sip_endpoint *endpoint = obj;
@@ -437,6 +567,29 @@ static int caller_id_handler(const struct aco_option *opt, struct ast_variable *
return 0;
}
+static int caller_id_to_str(const void *obj, const intptr_t *args, char **buf)
+{
+ const struct ast_sip_endpoint *endpoint = obj;
+ const char *name = S_COR(endpoint->id.self.name.valid,
+ endpoint->id.self.name.str, NULL);
+ const char *number = S_COR(endpoint->id.self.number.valid,
+ endpoint->id.self.number.str, NULL);
+
+ /* make sure size is at least 10 - that should cover the "<unknown>"
+ case as well as any additional formatting characters added in
+ the name and/or number case. */
+ int size = 10;
+ size += name ? strlen(name) : 0;
+ size += number ? strlen(number) : 0;
+
+ if (!(*buf = ast_calloc(size + 1, sizeof(char)))) {
+ return -1;
+ }
+
+ ast_callerid_merge(*buf, size + 1, name, number, NULL);
+ return 0;
+}
+
static int caller_id_privacy_handler(const struct aco_option *opt, struct ast_variable *var, void *obj)
{
struct ast_sip_endpoint *endpoint = obj;
@@ -449,6 +602,16 @@ static int caller_id_privacy_handler(const struct aco_option *opt, struct ast_va
return 0;
}
+static int caller_id_privacy_to_str(const void *obj, const intptr_t *args, char **buf)
+{
+ const struct ast_sip_endpoint *endpoint = obj;
+ const char *presentation = ast_named_caller_presentation(
+ endpoint->id.self.name.presentation);
+
+ *buf = ast_strdup(presentation);
+ return 0;
+}
+
static int caller_id_tag_handler(const struct aco_option *opt, struct ast_variable *var, void *obj)
{
struct ast_sip_endpoint *endpoint = obj;
@@ -456,6 +619,13 @@ static int caller_id_tag_handler(const struct aco_option *opt, struct ast_variab
return endpoint->id.self.tag ? 0 : -1;
}
+static int caller_id_tag_to_str(const void *obj, const intptr_t *args, char **buf)
+{
+ const struct ast_sip_endpoint *endpoint = obj;
+ *buf = ast_strdup(endpoint->id.self.tag);
+ return 0;
+}
+
static int media_encryption_handler(const struct aco_option *opt, struct ast_variable *var, void *obj)
{
struct ast_sip_endpoint *endpoint = obj;
@@ -474,6 +644,23 @@ static int media_encryption_handler(const struct aco_option *opt, struct ast_var
return 0;
}
+static const char *media_encryption_map[] = {
+ [AST_SIP_MEDIA_TRANSPORT_INVALID] = "invalid",
+ [AST_SIP_MEDIA_ENCRYPT_NONE] = "none",
+ [AST_SIP_MEDIA_ENCRYPT_SDES] = "sdes",
+ [AST_SIP_MEDIA_ENCRYPT_DTLS] = "dtls",
+};
+
+static int media_encryption_to_str(const void *obj, const intptr_t *args, char **buf)
+{
+ const struct ast_sip_endpoint *endpoint = obj;
+ if (ARRAY_IN_BOUNDS(endpoint->media.rtp.encryption, media_encryption_map)) {
+ *buf = ast_strdup(media_encryption_map[
+ endpoint->media.rtp.encryption]);
+ }
+ return 0;
+}
+
static int group_handler(const struct aco_option *opt,
struct ast_variable *var, void *obj)
{
@@ -494,6 +681,30 @@ static int group_handler(const struct aco_option *opt,
return 0;
}
+static int callgroup_to_str(const void *obj, const intptr_t *args, char **buf)
+{
+ const struct ast_sip_endpoint *endpoint = obj;
+
+ if (!(*buf = ast_calloc(MAX_OBJECT_FIELD, sizeof(char)))) {
+ return -1;
+ }
+
+ ast_print_group(*buf, MAX_OBJECT_FIELD, endpoint->pickup.callgroup);
+ return 0;
+}
+
+static int pickupgroup_to_str(const void *obj, const intptr_t *args, char **buf)
+{
+ const struct ast_sip_endpoint *endpoint = obj;
+
+ if (!(*buf = ast_calloc(MAX_OBJECT_FIELD, sizeof(char)))) {
+ return -1;
+ }
+
+ ast_print_group(*buf, MAX_OBJECT_FIELD, endpoint->pickup.pickupgroup);
+ return 0;
+}
+
static int named_groups_handler(const struct aco_option *opt,
struct ast_variable *var, void *obj)
{
@@ -516,6 +727,26 @@ static int named_groups_handler(const struct aco_option *opt,
return 0;
}
+static int named_callgroups_to_str(const void *obj, const intptr_t *args, char **buf)
+{
+ const struct ast_sip_endpoint *endpoint = obj;
+ RAII_VAR(struct ast_str *, str, ast_str_create(MAX_OBJECT_FIELD), ast_free);
+
+ ast_print_namedgroups(&str, endpoint->pickup.named_callgroups);
+ *buf = ast_strdup(ast_str_buffer(str));
+ return 0;
+}
+
+static int named_pickupgroups_to_str(const void *obj, const intptr_t *args, char **buf)
+{
+ const struct ast_sip_endpoint *endpoint = obj;
+ RAII_VAR(struct ast_str *, str, ast_str_create(MAX_OBJECT_FIELD), ast_free);
+
+ ast_print_namedgroups(&str, endpoint->pickup.named_pickupgroups);
+ *buf = ast_strdup(ast_str_buffer(str));
+ return 0;
+}
+
static int dtls_handler(const struct aco_option *opt,
struct ast_variable *var, void *obj)
{
@@ -535,6 +766,72 @@ static int dtls_handler(const struct aco_option *opt,
return ast_rtp_dtls_cfg_parse(&endpoint->media.rtp.dtls_cfg, name, var->value);
}
+static int dtlsverify_to_str(const void *obj, const intptr_t *args, char **buf)
+{
+ const struct ast_sip_endpoint *endpoint = obj;
+ *buf = ast_strdup(AST_YESNO(endpoint->media.rtp.dtls_cfg.verify));
+ return 0;
+}
+
+static int dtlsrekey_to_str(const void *obj, const intptr_t *args, char **buf)
+{
+ const struct ast_sip_endpoint *endpoint = obj;
+
+ return ast_asprintf(
+ buf, "%d", endpoint->media.rtp.dtls_cfg.rekey) >=0 ? 0 : -1;
+}
+
+static int dtlscertfile_to_str(const void *obj, const intptr_t *args, char **buf)
+{
+ const struct ast_sip_endpoint *endpoint = obj;
+ *buf = ast_strdup(endpoint->media.rtp.dtls_cfg.certfile);
+ return 0;
+}
+
+static int dtlsprivatekey_to_str(const void *obj, const intptr_t *args, char **buf)
+{
+ const struct ast_sip_endpoint *endpoint = obj;
+ *buf = ast_strdup(endpoint->media.rtp.dtls_cfg.pvtfile);
+ return 0;
+}
+
+static int dtlscipher_to_str(const void *obj, const intptr_t *args, char **buf)
+{
+ const struct ast_sip_endpoint *endpoint = obj;
+ *buf = ast_strdup(endpoint->media.rtp.dtls_cfg.cipher);
+ return 0;
+}
+
+static int dtlscafile_to_str(const void *obj, const intptr_t *args, char **buf)
+{
+ const struct ast_sip_endpoint *endpoint = obj;
+ *buf = ast_strdup(endpoint->media.rtp.dtls_cfg.cafile);
+ return 0;
+}
+
+static int dtlscapath_to_str(const void *obj, const intptr_t *args, char **buf)
+{
+ const struct ast_sip_endpoint *endpoint = obj;
+ *buf = ast_strdup(endpoint->media.rtp.dtls_cfg.capath);
+ return 0;
+}
+
+static const char *ast_rtp_dtls_setup_map[] = {
+ [AST_RTP_DTLS_SETUP_ACTIVE] = "active",
+ [AST_RTP_DTLS_SETUP_PASSIVE] = "passive",
+ [AST_RTP_DTLS_SETUP_ACTPASS] = "actpass",
+ [AST_RTP_DTLS_SETUP_HOLDCONN] = "holdconn",
+};
+
+static int dtlssetup_to_str(const void *obj, const intptr_t *args, char **buf)
+{
+ const struct ast_sip_endpoint *endpoint = obj;
+ if (ARRAY_IN_BOUNDS(endpoint->media.rtp.dtls_cfg.default_setup, ast_rtp_dtls_setup_map)) {
+ *buf = ast_strdup(ast_rtp_dtls_setup_map[endpoint->media.rtp.dtls_cfg.default_setup]);
+ }
+ return 0;
+}
+
static int t38udptl_ec_handler(const struct aco_option *opt,
struct ast_variable *var, void *obj)
{
@@ -553,6 +850,22 @@ static int t38udptl_ec_handler(const struct aco_option *opt,
return 0;
}
+static const char *ast_t38_ec_modes_map[] = {
+ [UDPTL_ERROR_CORRECTION_NONE] = "none",
+ [UDPTL_ERROR_CORRECTION_FEC] = "fec",
+ [UDPTL_ERROR_CORRECTION_REDUNDANCY] = "redundancy"
+};
+
+static int t38udptl_ec_to_str(const void *obj, const intptr_t *args, char **buf)
+{
+ const struct ast_sip_endpoint *endpoint = obj;
+ if (ARRAY_IN_BOUNDS(endpoint->media.t38.error_correction, ast_t38_ec_modes_map)) {
+ *buf = ast_strdup(ast_t38_ec_modes_map[
+ endpoint->media.t38.error_correction]);
+ }
+ return 0;
+}
+
static void *sip_nat_hook_alloc(const char *name)
{
return ast_sorcery_generic_alloc(sizeof(struct ast_sip_nat_hook), NULL);
@@ -631,12 +944,305 @@ static int sip_endpoint_apply_handler(const struct ast_sorcery *sorcery, void *o
return 0;
}
-int ast_res_pjsip_initialize_configuration(void)
+static const char *get_device_state(const struct ast_sip_endpoint *endpoint)
+{
+ char device[MAX_OBJECT_FIELD];
+
+ snprintf(device, MAX_OBJECT_FIELD, "PJSIP/%s", ast_sorcery_object_get_id(endpoint));
+ return ast_devstate2str(ast_device_state(device));
+}
+
+static struct ast_endpoint_snapshot *sip_get_endpoint_snapshot(
+ const struct ast_sip_endpoint *endpoint)
+{
+ return ast_endpoint_latest_snapshot(
+ ast_endpoint_get_tech(endpoint->persistent),
+ ast_endpoint_get_resource(endpoint->persistent));
+}
+
+int ast_sip_for_each_channel_snapshot(
+ const struct ast_endpoint_snapshot *endpoint_snapshot,
+ on_channel_snapshot_t on_channel_snapshot, void *arg)
+{
+ int num, num_channels = endpoint_snapshot->num_channels;
+ RAII_VAR(struct stasis_cache *, cache, NULL, ao2_cleanup);
+
+ if (!on_channel_snapshot || !num_channels ||
+ !(cache = ast_channel_cache())) {
+ return 0;
+ }
+
+ ao2_ref(cache, +1);
+
+ for (num = 0; num < num_channels; ++num) {
+ RAII_VAR(struct stasis_message *, msg, NULL, ao2_cleanup);
+ struct ast_channel_snapshot *snapshot;
+
+ msg = stasis_cache_get(cache, ast_channel_snapshot_type(),
+ endpoint_snapshot->channel_ids[num]);
+
+ if (!(snapshot = stasis_message_data(msg))) {
+ continue;
+ }
+
+ if (on_channel_snapshot(
+ snapshot, num == (num_channels - 1), arg)) {
+ return -1;
+ }
+ }
+ return 0;
+}
+
+static int active_channels_to_str_cb(const struct ast_channel_snapshot *snapshot,
+ int last, void *arg)
+{
+ struct ast_str **buf = arg;
+ if (last) {
+ ast_str_append(buf, 0, "%s", snapshot->name);
+ } else {
+ ast_str_append(buf, 0, "%s,", snapshot->name);
+ }
+ return 0;
+}
+
+static void active_channels_to_str(const struct ast_sip_endpoint *endpoint,
+ struct ast_str **str)
+{
+
+ RAII_VAR(struct ast_endpoint_snapshot *, endpoint_snapshot,
+ sip_get_endpoint_snapshot(endpoint), ao2_cleanup);
+
+ if (endpoint_snapshot) {
+ return;
+ }
+
+ ast_sip_for_each_channel_snapshot(endpoint_snapshot,
+ active_channels_to_str_cb, str);
+}
+
+#define AMI_DEFAULT_STR_SIZE 512
+
+struct ast_str *ast_sip_create_ami_event(const char *event, struct ast_sip_ami *ami)
+{
+ struct ast_str *buf = ast_str_create(AMI_DEFAULT_STR_SIZE);
+
+ if (!(buf)) {
+ astman_send_error_va(ami->s, ami->m, "Unable create event "
+ "for %s\n", event);
+ return NULL;
+ }
+
+ ast_str_set(&buf, 0, "Event: %s\r\n", event);
+ return buf;
+}
+
+static void sip_sorcery_object_ami_set_type_name(const void *obj, struct ast_str **buf)
+{
+ ast_str_append(buf, 0, "ObjectType: %s\r\n",
+ ast_sorcery_object_get_type(obj));
+ ast_str_append(buf, 0, "ObjectName: %s\r\n",
+ ast_sorcery_object_get_id(obj));
+}
+
+int ast_sip_sorcery_object_to_ami(const void *obj, struct ast_str **buf)
+{
+ RAII_VAR(struct ast_variable *, objset, ast_sorcery_objectset_create(
+ ast_sip_get_sorcery(), obj), ast_variables_destroy);
+ struct ast_variable *i;
+
+ if (!objset) {
+ return -1;
+ }
+
+ sip_sorcery_object_ami_set_type_name(obj, buf);
+
+ for (i = objset; i; i = i->next) {
+ RAII_VAR(char *, camel, ast_to_camel_case(i->name), ast_free);
+ ast_str_append(buf, 0, "%s: %s\r\n", camel, i->value);
+ }
+
+ return 0;
+}
+
+static int sip_endpoints_aors_ami(void *obj, void *arg, int flags)
+{
+ const struct ast_sip_aor *aor = obj;
+ struct ast_str **buf = arg;
+
+ ast_str_append(buf, 0, "Contacts: ");
+ ast_sip_for_each_contact(aor, ast_sip_contact_to_str, arg);
+ ast_str_append(buf, 0, "\r\n");
+
+ return 0;
+}
+
+static int sip_endpoint_to_ami(const struct ast_sip_endpoint *endpoint,
+ struct ast_str **buf)
+{
+ if (ast_sip_sorcery_object_to_ami(endpoint, buf)) {
+ return -1;
+ }
+
+ ast_str_append(buf, 0, "DeviceState: %s\r\n",
+ get_device_state(endpoint));
+
+ ast_str_append(buf, 0, "ActiveChannels: ");
+ active_channels_to_str(endpoint, buf);
+ ast_str_append(buf, 0, "\r\n");
+
+ return 0;
+}
+
+static int format_ami_endpoint(const struct ast_sip_endpoint *endpoint,
+ struct ast_sip_ami *ami)
+{
+ RAII_VAR(struct ast_str *, buf,
+ ast_sip_create_ami_event("EndpointDetail", ami), ast_free);
+
+ if (!buf) {
+ return -1;
+ }
+
+ sip_endpoint_to_ami(endpoint, &buf);
+ astman_append(ami->s, "%s\r\n", ast_str_buffer(buf));
+ return 0;
+}
+
+#define AMI_SHOW_ENDPOINTS "PJSIPShowEndpoints"
+#define AMI_SHOW_ENDPOINT "PJSIPShowEndpoint"
+
+static int ami_show_endpoint(struct mansession *s, const struct message *m)
+{
+ struct ast_sip_ami ami = { .s = s, .m = m };
+ RAII_VAR(struct ast_sip_endpoint *, endpoint, NULL, ao2_cleanup);
+ const char *endpoint_name = astman_get_header(m, "Endpoint");
+ int count = 0;
+
+ if (ast_strlen_zero(endpoint_name)) {
+ astman_send_error_va(s, m, "%s requires an endpoint name\n",
+ AMI_SHOW_ENDPOINT);
+ return 0;
+ }
+
+ if (!strncasecmp(endpoint_name, "pjsip/", 6)) {
+ endpoint_name += 6;
+ }
+
+ if (!(endpoint = ast_sorcery_retrieve_by_id(
+ ast_sip_get_sorcery(), "endpoint", endpoint_name))) {
+ astman_send_error_va(s, m, "Unable to retrieve endpoint %s\n",
+ endpoint_name);
+ return -1;
+ }
+
+ astman_send_listack(s, m, "Following are Events for each object "
+ "associated with the the Endpoint", "start");
+
+ /* the endpoint detail needs to always come first so apply as such */
+ if (format_ami_endpoint(endpoint, &ami) ||
+ ast_sip_format_endpoint_ami(endpoint, &ami, &count)) {
+ astman_send_error_va(s, m, "Unable to format endpoint %s\n",
+ endpoint_name);
+ }
+
+ astman_append(s,
+ "Event: EndpointDetailComplete\r\n"
+ "EventList: Complete\r\n"
+ "ListItems: %d\r\n\r\n", count + 1);
+ return 0;
+}
+
+static int format_str_append_auth(const struct ast_sip_auth_array *auths,
+ struct ast_str **buf)
+{
+ char *str = NULL;
+ if (ast_sip_auths_to_str(auths, &str)) {
+ return -1;
+ }
+ ast_str_append(buf, 0, "%s", str ? str : "");
+ ast_free(str);
+ return 0;
+}
+
+static int format_ami_endpoints(void *obj, void *arg, int flags)
+{
+
+ struct ast_sip_endpoint *endpoint = obj;
+ struct ast_sip_ami *ami = arg;
+ RAII_VAR(struct ast_str *, buf,
+ ast_sip_create_ami_event("EndpointList", ami), ast_free);
+
+ if (!buf) {
+ return -1;
+ }
+
+ sip_sorcery_object_ami_set_type_name(endpoint, &buf);
+ ast_str_append(&buf, 0, "Transport: %s\r\n",
+ endpoint->transport);
+ ast_str_append(&buf, 0, "Aor: %s\r\n",
+ endpoint->aors);
+
+ ast_str_append(&buf, 0, "Auths: ");
+ format_str_append_auth(&endpoint->inbound_auths, &buf);
+ ast_str_append(&buf, 0, "\r\n");
+
+ ast_str_append(&buf, 0, "OutboundAuths: ");
+ format_str_append_auth(&endpoint->outbound_auths, &buf);
+ ast_str_append(&buf, 0, "\r\n");
+
+ ast_sip_for_each_aor(endpoint->aors,
+ sip_endpoints_aors_ami, &buf);
+
+ ast_str_append(&buf, 0, "DeviceState: %s\r\n",
+ get_device_state(endpoint));
+
+ ast_str_append(&buf, 0, "ActiveChannels: ");
+ active_channels_to_str(endpoint, &buf);
+ ast_str_append(&buf, 0, "\r\n");
+
+ astman_append(ami->s, "%s\r\n", ast_str_buffer(buf));
+ return 0;
+}
+
+static int ami_show_endpoints(struct mansession *s, const struct message *m)
+{
+ struct ast_sip_ami ami = { .s = s, .m = m };
+ RAII_VAR(struct ao2_container *, endpoints, NULL, ao2_cleanup);
+ int num;
+
+ endpoints = ast_sip_get_endpoints();
+ if (!endpoints) {
+ return -1;
+ }
+
+ if (!(num = ao2_container_count(endpoints))) {
+ astman_send_error(s, m, "No endpoints found\n");
+ return 0;
+ }
+
+ astman_send_listack(s, m, "A listing of Endpoints follows, "
+ "presented as EndpointList events", "start");
+
+ ao2_callback(endpoints, OBJ_NODATA, format_ami_endpoints, &ami);
+
+ astman_append(s,
+ "Event: EndpointListComplete\r\n"
+ "EventList: Complete\r\n"
+ "ListItems: %d\r\n\r\n", num);
+ return 0;
+}
+
+int ast_res_pjsip_initialize_configuration(const struct ast_module_info *ast_module_info)
{
if (ast_cli_register_multiple(cli_commands, ARRAY_LEN(cli_commands))) {
return -1;
}
+ if (ast_manager_register_xml(AMI_SHOW_ENDPOINTS, EVENT_FLAG_SYSTEM, ami_show_endpoints) ||
+ ast_manager_register_xml(AMI_SHOW_ENDPOINT, EVENT_FLAG_SYSTEM, ami_show_endpoint)) {
+ return -1;
+ }
+
if (!(persistent_endpoints = ao2_container_alloc(PERSISTENT_BUCKETS, persistent_endpoint_hash, persistent_endpoint_cmp))) {
return -1;
}
@@ -672,7 +1278,7 @@ int ast_res_pjsip_initialize_configuration(void)
ast_sorcery_object_field_register(sip_sorcery, "endpoint", "context", "default", OPT_STRINGFIELD_T, 0, STRFLDSET(struct ast_sip_endpoint, context));
ast_sorcery_object_field_register(sip_sorcery, "endpoint", "disallow", "", OPT_CODEC_T, 0, FLDSET(struct ast_sip_endpoint, media.prefs, media.codecs));
ast_sorcery_object_field_register(sip_sorcery, "endpoint", "allow", "", OPT_CODEC_T, 1, FLDSET(struct ast_sip_endpoint, media.prefs, media.codecs));
- ast_sorcery_object_field_register_custom(sip_sorcery, "endpoint", "dtmf_mode", "rfc4733", dtmf_handler, NULL, 0, 0);
+ ast_sorcery_object_field_register_custom(sip_sorcery, "endpoint", "dtmf_mode", "rfc4733", dtmf_handler, dtmf_to_str, 0, 0);
ast_sorcery_object_field_register(sip_sorcery, "endpoint", "rtp_ipv6", "no", OPT_BOOL_T, 1, FLDSET(struct ast_sip_endpoint, media.rtp.ipv6));
ast_sorcery_object_field_register(sip_sorcery, "endpoint", "rtp_symmetric", "no", OPT_BOOL_T, 1, FLDSET(struct ast_sip_endpoint, media.rtp.symmetric));
ast_sorcery_object_field_register(sip_sorcery, "endpoint", "ice_support", "no", OPT_BOOL_T, 1, FLDSET(struct ast_sip_endpoint, media.rtp.ice_support));
@@ -682,23 +1288,23 @@ int ast_res_pjsip_initialize_configuration(void)
ast_sorcery_object_field_register(sip_sorcery, "endpoint", "transport", "", OPT_STRINGFIELD_T, 0, STRFLDSET(struct ast_sip_endpoint, transport));
ast_sorcery_object_field_register(sip_sorcery, "endpoint", "outbound_proxy", "", OPT_STRINGFIELD_T, 0, STRFLDSET(struct ast_sip_endpoint, outbound_proxy));
ast_sorcery_object_field_register(sip_sorcery, "endpoint", "moh_suggest", "default", OPT_STRINGFIELD_T, 0, STRFLDSET(struct ast_sip_endpoint, mohsuggest));
- ast_sorcery_object_field_register_custom(sip_sorcery, "endpoint", "100rel", "yes", prack_handler, NULL, 0, 0);
- ast_sorcery_object_field_register_custom(sip_sorcery, "endpoint", "timers", "yes", timers_handler, NULL, 0, 0);
+ ast_sorcery_object_field_register_custom(sip_sorcery, "endpoint", "100rel", "yes", prack_handler, prack_to_str, 0, 0);
+ ast_sorcery_object_field_register_custom(sip_sorcery, "endpoint", "timers", "yes", timers_handler, timers_to_str, 0, 0);
ast_sorcery_object_field_register(sip_sorcery, "endpoint", "timers_min_se", "90", OPT_UINT_T, 0, FLDSET(struct ast_sip_endpoint, extensions.timer.min_se));
ast_sorcery_object_field_register(sip_sorcery, "endpoint", "timers_sess_expires", "1800", OPT_UINT_T, 0, FLDSET(struct ast_sip_endpoint, extensions.timer.sess_expires));
- ast_sorcery_object_field_register_custom(sip_sorcery, "endpoint", "auth", "", inbound_auth_handler, NULL, 0, 0);
- ast_sorcery_object_field_register_custom(sip_sorcery, "endpoint", "outbound_auth", "", outbound_auth_handler, NULL, 0, 0);
+ ast_sorcery_object_field_register_custom(sip_sorcery, "endpoint", "auth", "", inbound_auth_handler, inbound_auths_to_str, 0, 0);
+ ast_sorcery_object_field_register_custom(sip_sorcery, "endpoint", "outbound_auth", "", outbound_auth_handler, outbound_auths_to_str, 0, 0);
ast_sorcery_object_field_register(sip_sorcery, "endpoint", "aors", "", OPT_STRINGFIELD_T, 0, STRFLDSET(struct ast_sip_endpoint, aors));
ast_sorcery_object_field_register(sip_sorcery, "endpoint", "media_address", "", OPT_STRINGFIELD_T, 0, STRFLDSET(struct ast_sip_endpoint, media.address));
- ast_sorcery_object_field_register_custom(sip_sorcery, "endpoint", "identify_by", "username", ident_handler, NULL, 0, 0);
+ ast_sorcery_object_field_register_custom(sip_sorcery, "endpoint", "identify_by", "username", ident_handler, ident_to_str, 0, 0);
ast_sorcery_object_field_register(sip_sorcery, "endpoint", "direct_media", "yes", OPT_BOOL_T, 1, FLDSET(struct ast_sip_endpoint, media.direct_media.enabled));
- ast_sorcery_object_field_register_custom(sip_sorcery, "endpoint", "direct_media_method", "invite", direct_media_method_handler, NULL, 0, 0);
- ast_sorcery_object_field_register_custom(sip_sorcery, "endpoint", "connected_line_method", "invite", connected_line_method_handler, NULL, 0, 0);
- ast_sorcery_object_field_register_custom(sip_sorcery, "endpoint", "direct_media_glare_mitigation", "none", direct_media_glare_mitigation_handler, NULL, 0, 0);
+ ast_sorcery_object_field_register_custom(sip_sorcery, "endpoint", "direct_media_method", "invite", direct_media_method_handler, direct_media_method_to_str, 0, 0);
+ ast_sorcery_object_field_register_custom(sip_sorcery, "endpoint", "connected_line_method", "invite", connected_line_method_handler, connected_line_method_to_str, 0, 0);
+ ast_sorcery_object_field_register_custom(sip_sorcery, "endpoint", "direct_media_glare_mitigation", "none", direct_media_glare_mitigation_handler, direct_media_glare_mitigation_to_str, 0, 0);
ast_sorcery_object_field_register(sip_sorcery, "endpoint", "disable_direct_media_on_nat", "no", OPT_BOOL_T, 1, FLDSET(struct ast_sip_endpoint, media.direct_media.disable_on_nat));
- ast_sorcery_object_field_register_custom(sip_sorcery, "endpoint", "callerid", "", caller_id_handler, NULL, 0, 0);
- ast_sorcery_object_field_register_custom(sip_sorcery, "endpoint", "callerid_privacy", "", caller_id_privacy_handler, NULL, 0, 0);
- ast_sorcery_object_field_register_custom(sip_sorcery, "endpoint", "callerid_tag", "", caller_id_tag_handler, NULL, 0, 0);
+ ast_sorcery_object_field_register_custom(sip_sorcery, "endpoint", "callerid", "", caller_id_handler, caller_id_to_str, 0, 0);
+ ast_sorcery_object_field_register_custom(sip_sorcery, "endpoint", "callerid_privacy", "", caller_id_privacy_handler, caller_id_privacy_to_str, 0, 0);
+ ast_sorcery_object_field_register_custom(sip_sorcery, "endpoint", "callerid_tag", "", caller_id_tag_handler, caller_id_tag_to_str, 0, 0);
ast_sorcery_object_field_register(sip_sorcery, "endpoint", "trust_id_inbound", "no", OPT_BOOL_T, 1, FLDSET(struct ast_sip_endpoint, id.trust_inbound));
ast_sorcery_object_field_register(sip_sorcery, "endpoint", "trust_id_outbound", "no", OPT_BOOL_T, 1, FLDSET(struct ast_sip_endpoint, id.trust_outbound));
ast_sorcery_object_field_register(sip_sorcery, "endpoint", "send_pai", "no", OPT_BOOL_T, 1, FLDSET(struct ast_sip_endpoint, id.send_pai));
@@ -706,17 +1312,17 @@ int ast_res_pjsip_initialize_configuration(void)
ast_sorcery_object_field_register(sip_sorcery, "endpoint", "send_diversion", "yes", OPT_BOOL_T, 1, FLDSET(struct ast_sip_endpoint, id.send_diversion));
ast_sorcery_object_field_register(sip_sorcery, "endpoint", "mailboxes", "", OPT_STRINGFIELD_T, 0, STRFLDSET(struct ast_sip_endpoint, subscription.mwi.mailboxes));
ast_sorcery_object_field_register(sip_sorcery, "endpoint", "aggregate_mwi", "yes", OPT_BOOL_T, 1, FLDSET(struct ast_sip_endpoint, subscription.mwi.aggregate));
- ast_sorcery_object_field_register_custom(sip_sorcery, "endpoint", "media_encryption", "no", media_encryption_handler, NULL, 0, 0);
+ ast_sorcery_object_field_register_custom(sip_sorcery, "endpoint", "media_encryption", "no", media_encryption_handler, media_encryption_to_str, 0, 0);
ast_sorcery_object_field_register(sip_sorcery, "endpoint", "use_avpf", "no", OPT_BOOL_T, 1, FLDSET(struct ast_sip_endpoint, media.rtp.use_avpf));
ast_sorcery_object_field_register(sip_sorcery, "endpoint", "one_touch_recording", "no", OPT_BOOL_T, 1, FLDSET(struct ast_sip_endpoint, info.recording.enabled));
ast_sorcery_object_field_register(sip_sorcery, "endpoint", "inband_progress", "no", OPT_BOOL_T, 1, FLDSET(struct ast_sip_endpoint, inband_progress));
- ast_sorcery_object_field_register_custom(sip_sorcery, "endpoint", "call_group", "", group_handler, NULL, 0, 0);
- ast_sorcery_object_field_register_custom(sip_sorcery, "endpoint", "pickup_group", "", group_handler, NULL, 0, 0);
- ast_sorcery_object_field_register_custom(sip_sorcery, "endpoint", "named_call_group", "", named_groups_handler, NULL, 0, 0);
- ast_sorcery_object_field_register_custom(sip_sorcery, "endpoint", "named_pickup_group", "", named_groups_handler, NULL, 0, 0);
+ ast_sorcery_object_field_register_custom(sip_sorcery, "endpoint", "call_group", "", group_handler, callgroup_to_str, 0, 0);
+ ast_sorcery_object_field_register_custom(sip_sorcery, "endpoint", "pickup_group", "", group_handler, pickupgroup_to_str, 0, 0);
+ ast_sorcery_object_field_register_custom(sip_sorcery, "endpoint", "named_call_group", "", named_groups_handler, named_callgroups_to_str, 0, 0);
+ ast_sorcery_object_field_register_custom(sip_sorcery, "endpoint", "named_pickup_group", "", named_groups_handler, named_pickupgroups_to_str, 0, 0);
ast_sorcery_object_field_register(sip_sorcery, "endpoint", "device_state_busy_at", "0", OPT_UINT_T, 0, FLDSET(struct ast_sip_endpoint, devicestate_busy_at));
ast_sorcery_object_field_register(sip_sorcery, "endpoint", "t38_udptl", "no", OPT_BOOL_T, 1, FLDSET(struct ast_sip_endpoint, media.t38.enabled));
- ast_sorcery_object_field_register_custom(sip_sorcery, "endpoint", "t38_udptl_ec", "none", t38udptl_ec_handler, NULL, 0, 0);
+ ast_sorcery_object_field_register_custom(sip_sorcery, "endpoint", "t38_udptl_ec", "none", t38udptl_ec_handler, t38udptl_ec_to_str, 0, 0);
ast_sorcery_object_field_register(sip_sorcery, "endpoint", "t38_udptl_maxdatagram", "0", OPT_UINT_T, 0, FLDSET(struct ast_sip_endpoint, media.t38.maxdatagram));
ast_sorcery_object_field_register(sip_sorcery, "endpoint", "fax_detect", "no", OPT_BOOL_T, 1, FLDSET(struct ast_sip_endpoint, faxdetect));
ast_sorcery_object_field_register(sip_sorcery, "endpoint", "t38_udptl_nat", "no", OPT_BOOL_T, 1, FLDSET(struct ast_sip_endpoint, media.t38.nat));
@@ -738,14 +1344,14 @@ int ast_res_pjsip_initialize_configuration(void)
ast_sorcery_object_field_register(sip_sorcery, "endpoint", "from_domain", "", OPT_STRINGFIELD_T, 0, STRFLDSET(struct ast_sip_endpoint, fromdomain));
ast_sorcery_object_field_register(sip_sorcery, "endpoint", "mwi_from_user", "", OPT_STRINGFIELD_T, 0, STRFLDSET(struct ast_sip_endpoint, subscription.mwi.fromuser));
ast_sorcery_object_field_register(sip_sorcery, "endpoint", "rtp_engine", "asterisk", OPT_STRINGFIELD_T, 0, STRFLDSET(struct ast_sip_endpoint, media.rtp.engine));
- ast_sorcery_object_field_register_custom(sip_sorcery, "endpoint", "dtls_verify", "", dtls_handler, NULL, 0, 0);
- ast_sorcery_object_field_register_custom(sip_sorcery, "endpoint", "dtls_rekey", "", dtls_handler, NULL, 0, 0);
- ast_sorcery_object_field_register_custom(sip_sorcery, "endpoint", "dtls_cert_file", "", dtls_handler, NULL, 0, 0);
- ast_sorcery_object_field_register_custom(sip_sorcery, "endpoint", "dtls_private_key", "", dtls_handler, NULL, 0, 0);
- ast_sorcery_object_field_register_custom(sip_sorcery, "endpoint", "dtls_cipher", "", dtls_handler, NULL, 0, 0);
- ast_sorcery_object_field_register_custom(sip_sorcery, "endpoint", "dtls_ca_file", "", dtls_handler, NULL, 0, 0);
- ast_sorcery_object_field_register_custom(sip_sorcery, "endpoint", "dtls_ca_path", "", dtls_handler, NULL, 0, 0);
- ast_sorcery_object_field_register_custom(sip_sorcery, "endpoint", "dtls_setup", "", dtls_handler, NULL, 0, 0);
+ ast_sorcery_object_field_register_custom(sip_sorcery, "endpoint", "dtls_verify", "", dtls_handler, dtlsverify_to_str, 0, 0);
+ ast_sorcery_object_field_register_custom(sip_sorcery, "endpoint", "dtls_rekey", "", dtls_handler, dtlsrekey_to_str, 0, 0);
+ ast_sorcery_object_field_register_custom(sip_sorcery, "endpoint", "dtls_cert_file", "", dtls_handler, dtlscertfile_to_str, 0, 0);
+ ast_sorcery_object_field_register_custom(sip_sorcery, "endpoint", "dtls_private_key", "", dtls_handler, dtlsprivatekey_to_str, 0, 0);
+ ast_sorcery_object_field_register_custom(sip_sorcery, "endpoint", "dtls_cipher", "", dtls_handler, dtlscipher_to_str, 0, 0);
+ ast_sorcery_object_field_register_custom(sip_sorcery, "endpoint", "dtls_ca_file", "", dtls_handler, dtlscafile_to_str, 0, 0);
+ ast_sorcery_object_field_register_custom(sip_sorcery, "endpoint", "dtls_ca_path", "", dtls_handler, dtlscapath_to_str, 0, 0);
+ ast_sorcery_object_field_register_custom(sip_sorcery, "endpoint", "dtls_setup", "", dtls_handler, dtlssetup_to_str, 0, 0);
ast_sorcery_object_field_register(sip_sorcery, "endpoint", "srtp_tag_32", "no", OPT_BOOL_T, 1, FLDSET(struct ast_sip_endpoint, media.rtp.srtp_tag_32));
if (ast_sip_initialize_sorcery_transport(sip_sorcery)) {
@@ -793,6 +1399,8 @@ int ast_res_pjsip_initialize_configuration(void)
void ast_res_pjsip_destroy_configuration(void)
{
ast_cli_unregister_multiple(cli_commands, ARRAY_LEN(cli_commands));
+ ast_manager_unregister(AMI_SHOW_ENDPOINT);
+ ast_manager_unregister(AMI_SHOW_ENDPOINTS);
ast_sorcery_unref(sip_sorcery);
}