[svn-commits] file: branch file/chan_jingle2 r368694 - /team/file/chan_jingle2/channels/
SVN commits to the Digium repositories
svn-commits at lists.digium.com
Fri Jun 8 09:44:50 CDT 2012
Author: file
Date: Fri Jun 8 09:44:47 2012
New Revision: 368694
URL: http://svnview.digium.com/svn/asterisk?view=rev&rev=368694
Log:
Use the new config options API from twilson since this is a new module.
Modified:
team/file/chan_jingle2/channels/chan_jingle2.c
Modified: team/file/chan_jingle2/channels/chan_jingle2.c
URL: http://svnview.digium.com/svn/asterisk/team/file/chan_jingle2/channels/chan_jingle2.c?view=diff&rev=368694&r1=368693&r2=368694
==============================================================================
--- team/file/chan_jingle2/channels/chan_jingle2.c (original)
+++ team/file/chan_jingle2/channels/chan_jingle2.c Fri Jun 8 09:44:47 2012
@@ -50,7 +50,7 @@
#include "asterisk/lock.h"
#include "asterisk/channel.h"
-#include "asterisk/config.h"
+#include "asterisk/config_options.h"
#include "asterisk/module.h"
#include "asterisk/pbx.h"
#include "asterisk/sched.h"
@@ -74,10 +74,10 @@
#define JINGLE_CONFIG "jingle2.conf"
/*! \brief Default maximum number of ICE candidates we will offer */
-#define DEFAULT_MAX_ICE_CANDIDATES 10
+#define DEFAULT_MAX_ICE_CANDIDATES "10"
/*! \brief Default maximum number of payloads we will offer */
-#define DEFAULT_MAX_PAYLOADS 30
+#define DEFAULT_MAX_PAYLOADS "30"
/*! \brief Number of buckets for endpoints */
#define ENDPOINT_BUCKETS 37
@@ -123,28 +123,31 @@
JINGLE_TRANSPORT_NONE = 0, /*!< No transport specified */
};
+/*! \brief Endpoint state information */
+struct jingle_endpoint_state {
+ struct ao2_container *sessions; /*!< Active sessions to or from the endpoint */
+};
+
/*! \brief Endpoint which contains configuration information and active sessions */
struct jingle_endpoint {
AST_DECLARE_STRING_FIELDS(
- AST_STRING_FIELD(name); /*!< Name of the endpoint */
+ AST_STRING_FIELD(name); /*!< Name of the endpoint */
+ AST_STRING_FIELD(context); /*!< Context to place incoming calls into */
+ AST_STRING_FIELD(accountcode); /*!< Account code */
+ AST_STRING_FIELD(language); /*!< Default language for prompts */
+ AST_STRING_FIELD(musicclass); /*!< Configured music on hold class */
+ AST_STRING_FIELD(parkinglot); /*!< Configured parking lot */
);
struct aji_client *connection; /*!< Connection to use for traffic */
- iksrule *rule; /*!< Action matching rule */
+ iksrule *rule; /*!< Active matching rule */
unsigned int maxicecandidates; /*!< Maximum number of ICE candidates we will offer */
unsigned int maxpayloads; /*!< Maximum number of payloads we will offer */
struct ast_codec_pref prefs; /*!< Codec preferences */
- char context[AST_MAX_CONTEXT]; /*!< Context to place incoming calls into */
- char accountcode[AST_MAX_ACCOUNT_CODE]; /*!< Account code */
struct ast_format_cap *cap; /*!< Formats to use */
ast_group_t callgroup; /*!< Call group */
ast_group_t pickupgroup; /*!< Pickup group */
- char language[MAX_LANGUAGE]; /*!< Default language for prompts */
- char musicclass[MAX_MUSICCLASS]; /*!< Configured music on hold class */
- char parkinglot[AST_MAX_CONTEXT]; /*!< Configured parking lot */
enum jingle_transport transport; /*!< Default transport to use on outgoing sessions */
- struct ao2_container *sessions; /*!< Active sessions to or from the endpoint */
- unsigned int destroy:1; /*!< Bit to indicate that the endpoint should be destroyed */
- unsigned int destroyed:1; /*!< Bit to indicate this endpoint is effectively destroyed */
+ struct jingle_endpoint_state *state; /*!< Endpoint state information */
};
/*! \brief Session which contains information about an active session */
@@ -154,7 +157,7 @@
AST_STRING_FIELD(audio_name); /*!< Name of the audio content */
AST_STRING_FIELD(video_name); /*!< Name of the video content */
);
- struct jingle_endpoint *endpoint; /*!< Endpoint we are associated with */
+ struct jingle_endpoint_state *state; /*!< Endpoint we are associated with */
struct aji_client *connection; /*!< Connection to use for traffic */
enum jingle_transport transport; /*!< Transport type to use for this session */
unsigned int maxicecandidates; /*!< Maximum number of ICE candidates we will offer */
@@ -176,7 +179,12 @@
static const char desc[] = "Jingle Channel";
static const char channel_type[] = "Jingle2";
-static struct ao2_container *endpoints; /*!< Configured endpoints */
+struct jingle_config {
+ struct ao2_container *endpoints; /*!< Configured endpoints */
+};
+
+static AO2_GLOBAL_OBJ_STATIC(globals);
+
static struct ast_sched_context *sched; /*!< Scheduling context for RTCP */
/* \brief Asterisk core interaction functions */
@@ -263,6 +271,32 @@
{ "unsupported-transports", AST_CAUSE_FACILITY_NOT_IMPLEMENTED, },
};
+/*! \brief Hashing function for Jingle sessions */
+static int jingle_session_hash(const void *obj, const int flags)
+{
+ const struct jingle_session *session = obj;
+ const char *sid = obj;
+
+ return ast_str_hash(flags & OBJ_KEY ? sid : session->sid);
+}
+
+/*! \brief Comparator function for Jingle sessions */
+static int jingle_session_cmp(void *obj, void *arg, int flags)
+{
+ struct jingle_session *session1 = obj, *session2 = arg;
+ const char *sid = arg;
+
+ return !strcmp(session1->sid, flags & OBJ_KEY ? sid : session2->sid) ? CMP_MATCH | CMP_STOP : 0;
+}
+
+/*! \brief Destructor for Jingle endpoint state */
+static void jingle_endpoint_state_destructor(void *obj)
+{
+ struct jingle_endpoint_state *state = obj;
+
+ ao2_ref(state->sessions, -1);
+}
+
/*! \brief Destructor for Jingle endpoints */
static void jingle_endpoint_destructor(void *obj)
{
@@ -278,9 +312,67 @@
ast_format_cap_destroy(endpoint->cap);
- ao2_ref(endpoint->sessions, -1);
+ ao2_ref(endpoint->state, -1);
ast_string_field_free_memory(endpoint);
+}
+
+/*! \brief Allocator function for Jingle endpoint state */
+static struct jingle_endpoint_state *jingle_endpoint_state_create(void)
+{
+ struct jingle_endpoint_state *state;
+
+ if (!(state = ao2_alloc(sizeof(*state), jingle_endpoint_state_destructor))) {
+ return NULL;
+ }
+
+ if (!(state->sessions = ao2_container_alloc(SESSION_BUCKETS, jingle_session_hash, jingle_session_cmp))) {
+ ao2_ref(state, -1);
+ return NULL;
+ }
+
+ return state;
+}
+
+/*! \brief State find/create function */
+static struct jingle_endpoint_state *jingle_endpoint_state_find_or_create(const char *category)
+{
+ RAII_VAR(struct jingle_config *, cfg, ao2_global_obj_ref(globals), ao2_cleanup);
+ RAII_VAR(struct jingle_endpoint *, endpoint, NULL, ao2_cleanup);
+
+ if (!cfg || !cfg->endpoints || !(endpoint = ao2_find(cfg->endpoints, category, OBJ_KEY))) {
+ return jingle_endpoint_state_create();
+ }
+
+ ao2_ref(endpoint->state, +1);
+ return endpoint->state;
+}
+
+/*! \brief Allocator function for Jingle endpoints */
+static void *jingle_endpoint_alloc(const char *cat)
+{
+ struct jingle_endpoint *endpoint;
+
+ if (!(endpoint = ao2_alloc(sizeof(*endpoint), jingle_endpoint_destructor))) {
+ return NULL;
+ }
+
+ if (ast_string_field_init(endpoint, 512)) {
+ ao2_ref(endpoint, -1);
+ return NULL;
+ }
+
+ if (!(endpoint->state = jingle_endpoint_state_find_or_create(cat))) {
+ ao2_ref(endpoint, -1);
+ return NULL;
+ }
+
+ ast_string_field_set(endpoint, name, cat);
+
+ endpoint->cap = ast_format_cap_alloc_nolock();
+ endpoint->transport = JINGLE_TRANSPORT_ICE_UDP;
+
+ return endpoint;
}
/*! \brief Hashing function for Jingle endpoints */
@@ -300,6 +392,28 @@
return !strcmp(endpoint1->name, flags & OBJ_KEY ? name : endpoint2->name) ? CMP_MATCH | CMP_STOP : 0;
}
+
+/*! \brief Find function for Jingle endpoints */
+static void *jingle_endpoint_find(struct ao2_container *tmp_container, const char *category)
+{
+ return ao2_find(tmp_container, category, OBJ_KEY);
+}
+
+static struct aco_type endpoint_option = {
+ .type = ACO_ITEM,
+ .category_match = ACO_BLACKLIST,
+ .category = "^general$",
+ .item_alloc = jingle_endpoint_alloc,
+ .item_find = jingle_endpoint_find,
+ .item_offset = offsetof(struct jingle_config, endpoints),
+};
+
+struct aco_type *endpoint_options[] = ACO_TYPES(&endpoint_option);
+
+struct aco_file jingle_conf = {
+ .filename = "jingle2.conf",
+ .types = ACO_TYPES(&endpoint_option),
+};
/*! \brief Destructor for Jingle sessions */
static void jingle_session_destructor(void *obj)
@@ -329,23 +443,33 @@
ast_string_field_free_memory(session);
}
-/*! \brief Hashing function for Jingle sessions */
-static int jingle_session_hash(const void *obj, const int flags)
-{
- const struct jingle_session *session = obj;
- const char *sid = obj;
-
- return ast_str_hash(flags & OBJ_KEY ? sid : session->sid);
-}
-
-/*! \brief Comparator function for Jingle sessions */
-static int jingle_session_cmp(void *obj, void *arg, int flags)
-{
- struct jingle_session *session1 = obj, *session2 = arg;
- const char *sid = arg;
-
- return !strcmp(session1->sid, flags & OBJ_KEY ? sid : session2->sid) ? CMP_MATCH | CMP_STOP : 0;
-}
+/*! \brief Destructor called when module configuration goes away */
+static void jingle_config_destructor(void *obj)
+{
+ struct jingle_config *cfg = obj;
+ ao2_cleanup(cfg->endpoints);
+}
+
+/*! \brief Allocator called when module configuration should appear */
+static void *jingle_config_alloc(void)
+{
+ struct jingle_config *cfg;
+
+ if (!(cfg = ao2_alloc(sizeof(*cfg), jingle_config_destructor))) {
+ return NULL;
+ }
+
+ if (!(cfg->endpoints = ao2_container_alloc(ENDPOINT_BUCKETS, jingle_endpoint_hash, jingle_endpoint_cmp))) {
+ ao2_ref(cfg, -1);
+ return NULL;
+ }
+
+ return cfg;
+}
+
+CONFIG_INFO_STANDARD(cfg_info, globals, jingle_config_alloc,
+ .files = ACO_FILES(&jingle_conf),
+ );
/*! \brief Function called by RTP engine to get local RTP peer */
static enum ast_rtp_glue_result jingle_get_rtp_peer(struct ast_channel *chan, struct ast_rtp_instance **instance)
@@ -444,25 +568,14 @@
ast_string_field_set(session, sid, sid);
}
- ao2_lock(endpoint);
-
- /* If the endpoint is effectively destroyed it is not acceptable to create a session on it */
- if (endpoint->destroyed) {
- ao2_unlock(endpoint);
- ao2_ref(session, -1);
- return NULL;
- }
-
- ao2_ref(endpoint, +1);
- session->endpoint = endpoint;
+ ao2_ref(endpoint->state, +1);
+ session->state = endpoint->state;
session->connection = ASTOBJ_REF(endpoint->connection);
session->transport = endpoint->transport;
if (!(session->cap = ast_format_cap_alloc_nolock()) ||
!(session->jointcap = ast_format_cap_alloc_nolock()) ||
!(session->peercap = ast_format_cap_alloc_nolock())) {
- ao2_unlock(endpoint);
- ao2_ref(endpoint, -1);
ao2_ref(session, -1);
return NULL;
}
@@ -475,8 +588,6 @@
/* Sessions always carry audio, but video is optional so don't enable it here */
if (!(session->rtp = ast_rtp_instance_new("asterisk", sched, &tmp, NULL))) {
- ao2_unlock(endpoint);
- ao2_ref(endpoint, -1);
ao2_ref(session, -1);
return NULL;
}
@@ -487,8 +598,6 @@
session->maxicecandidates = endpoint->maxicecandidates;
session->maxpayloads = endpoint->maxpayloads;
-
- ao2_unlock(endpoint);
return session;
}
@@ -1553,8 +1662,8 @@
ast_channel_tech_pvt_set(ast, NULL);
session->owner = NULL;
- ao2_unlink(session->endpoint->sessions, session);
- ao2_ref(session->endpoint, -1);
+ ao2_unlink(session->state->sessions, session);
+ ao2_ref(session->state, -1);
ao2_unlock(session);
ao2_ref(session, -1);
@@ -1565,8 +1674,9 @@
/*! \brief Function called by core to create a new outgoing Jingle session */
static struct ast_channel *jingle_request(const char *type, struct ast_format_cap *cap, const struct ast_channel *requestor, const char *data, int *cause)
{
+ RAII_VAR(struct jingle_config *, cfg, ao2_global_obj_ref(globals), ao2_cleanup);
+ RAII_VAR(struct jingle_endpoint *, endpoint, NULL, ao2_cleanup);
char *dialed, target[200] = "";
- struct jingle_endpoint *endpoint;
struct aji_buddy *buddy;
struct jingle_session *session;
struct ast_channel *chan;
@@ -1598,20 +1708,19 @@
return NULL;
}
- if (!(endpoint = ao2_find(endpoints, args.name, OBJ_KEY))) {
+ if (!(endpoint = ao2_find(cfg->endpoints, args.name, OBJ_KEY))) {
ast_log(LOG_ERROR, "Endpoint '%s' does not exist.\n", args.name);
*cause = AST_CAUSE_CHANNEL_UNACCEPTABLE;
return NULL;
}
- ao2_lock(endpoint);
+ ao2_lock(endpoint->state);
/* If we don't have a connection for the endpoint we can't exactly start a session on it */
if (!endpoint->connection) {
ast_log(LOG_ERROR, "Unable to create Jingle session on endpoint '%s' as no valid connection exists\n", args.name);
*cause = AST_CAUSE_SWITCH_CONGESTION;
- ao2_unlock(endpoint);
- ao2_ref(endpoint, -1);
+ ao2_unlock(endpoint->state);
return NULL;
}
@@ -1638,20 +1747,18 @@
ast_copy_string(target, args.target, sizeof(target));
}
- ao2_unlock(endpoint);
+ ao2_unlock(endpoint->state);
/* If no target was found we can't set up a session */
if (ast_strlen_zero(target)) {
ast_log(LOG_ERROR, "Unable to create Jingle session on endpoint '%s' as no capable resource for target '%s' was found\n", args.name, args.target);
*cause = AST_CAUSE_SWITCH_CONGESTION;
- ao2_ref(endpoint, -1);
return NULL;
}
if (!(session = jingle_alloc(endpoint, target, NULL))) {
ast_log(LOG_ERROR, "Unable to create Jingle session on endpoint '%s'\n", args.name);
*cause = AST_CAUSE_SWITCH_CONGESTION;
- ao2_ref(endpoint, -1);
return NULL;
}
@@ -1665,7 +1772,6 @@
ast_log(LOG_ERROR, "Unable to create Jingle channel on endpoint '%s'\n", args.name);
*cause = AST_CAUSE_SWITCH_CONGESTION;
ao2_ref(session, -1);
- ao2_ref(endpoint, -1);
return NULL;
}
@@ -1675,8 +1781,7 @@
}
/* We purposely don't decrement the session here as there is a reference on the channel */
- ao2_link(endpoint->sessions, session);
- ao2_ref(endpoint, -1);
+ ao2_link(endpoint->state->sessions, session);
return chan;
}
@@ -2056,7 +2161,7 @@
return;
}
- ao2_link(endpoint->sessions, session);
+ ao2_link(endpoint->state->sessions, session);
ast_setstate(chan, AST_STATE_RING);
res = ast_pbx_start(chan);
@@ -2221,7 +2326,7 @@
/* If a session identifier was present in the message attempt to find the session, it is up to the action handler whether
* this is required or not */
if (!ast_strlen_zero(sid)) {
- session = ao2_find(endpoint->sessions, sid, OBJ_KEY);
+ session = ao2_find(endpoint->state->sessions, sid, OBJ_KEY);
}
/* Iterate through supported action handlers looking for one that is able to handle this */
@@ -2248,176 +2353,62 @@
return IKS_FILTER_EAT;
}
-/*! \brief Internal configuration function for storing connection information */
-static void store_config_connection(struct jingle_endpoint *endpoint, const char *value)
-{
- struct aji_client *client;
-
- if (!(client = ast_aji_get_client(value))) {
- ast_log(LOG_ERROR, "Connection '%s' configured on endpoint '%s' could not be found\n", value, endpoint->name);
- return;
- }
-
- if (endpoint->rule) {
- iks_filter_remove_rule(endpoint->connection->f, endpoint->rule);
- }
-
- if (endpoint->connection) {
- ASTOBJ_UNREF(endpoint->connection, ast_aji_client_destroy);
- }
-
- endpoint->connection = client;
-
- endpoint->rule = iks_filter_add_rule(client->f, jingle_action_hook, endpoint,
- IKS_RULE_TYPE, IKS_PAK_IQ,
- IKS_RULE_NS, JINGLE_NS,
- IKS_RULE_NS, GOOGLE_SESSION_NS,
- IKS_RULE_DONE);
-}
-
-/*! \brief Internal configuration function for storing transport information */
-static void store_config_transport(struct jingle_endpoint *endpoint, const char *value)
-{
- if (!strcasecmp(value, "ice-udp")) {
+/*! \brief Custom handler for groups */
+static int custom_group_handler(const struct aco_option *opt, struct ast_variable *var, void *obj)
+{
+ struct jingle_endpoint *endpoint = obj;
+
+ if (!strcasecmp(var->name, "callgroup")) {
+ endpoint->callgroup = ast_get_group(var->value);
+ } else if (!strcasecmp(var->name, "pickupgroup")) {
+ endpoint->pickupgroup = ast_get_group(var->value);
+ } else {
+ return -1;
+ }
+
+ return 0;
+}
+
+/*! \brief Custom handler for connection */
+static int custom_connection_handler(const struct aco_option *opt, struct ast_variable *var, void *obj)
+{
+ struct jingle_endpoint *endpoint = obj;
+
+ /* You might think... but Josh, shouldn't you do this in a prelink callback? Well I *could* but until the original is destroyed
+ * this will not actually get called, so even if the config turns out to be bogus this is harmless.
+ */
+ if (!(endpoint->connection = ast_aji_get_client(var->value))) {
+ ast_log(LOG_ERROR, "Connection '%s' configured on endpoint '%s' could not be found\n", var->value, endpoint->name);
+ return -1;
+ }
+
+ if (!(endpoint->rule = iks_filter_add_rule(endpoint->connection->f, jingle_action_hook, endpoint,
+ IKS_RULE_TYPE, IKS_PAK_IQ,
+ IKS_RULE_NS, JINGLE_NS,
+ IKS_RULE_NS, GOOGLE_SESSION_NS,
+ IKS_RULE_DONE))) {
+ ast_log(LOG_ERROR, "Action hook could not be added to connection '%s' on endpoint '%s'\n", var->value, endpoint->name);
+ return -1;
+ }
+
+ return 0;
+}
+
+/*! \brief Custom handler for transport */
+static int custom_transport_handler(const struct aco_option *opt, struct ast_variable *var, void *obj)
+{
+ struct jingle_endpoint *endpoint = obj;
+
+ if (!strcasecmp(var->value, "ice-udp")) {
endpoint->transport = JINGLE_TRANSPORT_ICE_UDP;
- } else if (!strcasecmp(value, "google")) {
+ } else if (!strcasecmp(var->value, "google")) {
endpoint->transport = JINGLE_TRANSPORT_GOOGLE_V2;
- } else if (!strcasecmp(value, "google-v1")) {
+ } else if (!strcasecmp(var->value, "google-v1")) {
endpoint->transport = JINGLE_TRANSPORT_GOOGLE_V1;
} else {
- ast_log(LOG_WARNING, "Unknown transport type '%s' on endpoint '%s', defaulting to 'ice-udp'\n", value, endpoint->name);
+ ast_log(LOG_WARNING, "Unknown transport type '%s' on endpoint '%s', defaulting to 'ice-udp'\n", var->value, endpoint->name);
endpoint->transport = JINGLE_TRANSPORT_ICE_UDP;
}
-}
-
-/*! \brief Internal function used to store general configuration information */
-static void store_config_general(struct ast_config *cfg)
-{
- /* This is purposely left empty in case general options are indeed required in the future */
-}
-
-/*! \brief Internal function used to store endpoint configuration information */
-static void store_config_endpoint(struct ast_config *cfg, const char *category)
-{
- struct jingle_endpoint *endpoint;
- struct ast_variable *v;
-
- ao2_lock(endpoints);
-
- /* Find the existing endpoint if present and if not, create a new one */
- if (!(endpoint = ao2_find(endpoints, category, OBJ_KEY | OBJ_NOLOCK))) {
- if (!(endpoint = ao2_alloc(sizeof(*endpoint), jingle_endpoint_destructor))) {
- ao2_unlock(endpoints);
- return;
- }
-
- if (ast_string_field_init(endpoint, 512)) {
- ao2_ref(endpoint, -1);
- ao2_unlock(endpoints);
- return;
- }
-
- ast_string_field_set(endpoint, name, category);
-
- if (!(endpoint->sessions = ao2_container_alloc(SESSION_BUCKETS, jingle_session_hash, jingle_session_cmp))) {
- ao2_ref(endpoint, -1);
- ao2_unlock(endpoints);
- return;
- }
-
- endpoint->cap = ast_format_cap_alloc_nolock();
- endpoint->transport = JINGLE_TRANSPORT_ICE_UDP;
-
- ao2_link(endpoints, endpoint);
- }
-
- ao2_unlock(endpoints);
-
- ao2_lock(endpoint);
-
- endpoint->destroy = 0;
- endpoint->maxicecandidates = DEFAULT_MAX_ICE_CANDIDATES;
- endpoint->maxpayloads = DEFAULT_MAX_PAYLOADS;
-
- for (v = ast_variable_browse(cfg, category); v; v = v->next) {
- CV_START(v->name, v->value);
-
- CV_STR("context", endpoint->context);
- CV_F("callgroup", endpoint->callgroup = ast_get_group(v->value));
- CV_F("pickupgroup", endpoint->pickupgroup = ast_get_group(v->value));
- CV_STR("language", endpoint->language);
- CV_STR("musicclass", endpoint->musicclass);
- CV_STR("parkinglot", endpoint->parkinglot);
- CV_STR("accountcode", endpoint->accountcode);
- CV_F("allow", ast_parse_allow_disallow(&endpoint->prefs, endpoint->cap, v->value, 1));
- CV_F("disallow", ast_parse_allow_disallow(&endpoint->prefs, endpoint->cap, v->value, 0));
- CV_F("connection", store_config_connection(endpoint, v->value));
- CV_F("transport", store_config_transport(endpoint, v->value));
- CV_UINT("maxicecandidates", endpoint->maxicecandidates);
- CV_UINT("maxpayloads", endpoint->maxpayloads);
-
- CV_END;
- }
-
- ao2_unlock(endpoint);
- ao2_ref(endpoint, -1);
-}
-
-/*! \brief Callback function that sets the endpoint to be destroyed */
-static int jingle_endpoint_set_destroy(void *obj, void *arg, int flags)
-{
- struct jingle_endpoint *endpoint = obj;
-
- endpoint->destroy = 1;
-
- return 0;
-}
-
-/*! \brief Callback function that returns true if an endpoint should be destroyed */
-static int jingle_endpoint_remove_destroyed(void *obj, void *arg, int flags)
-{
- struct jingle_endpoint *endpoint = obj;
-
- /* If this endpoint is set to be destroyed mark is as such, this will stop incoming sessions from it as
- * being accepted if there are outstanding sessions still using it */
- if (endpoint->destroy) {
- endpoint->destroyed = 1;
- return CMP_MATCH;
- }
-
- return 0;
-}
-
-/*! \brief Internal function which loads and parses the configuration */
-static int jingle_load_config(int reload)
-{
- struct ast_config *cfg;
- struct ast_flags config_flags = { reload ? CONFIG_FLAG_FILEUNCHANGED : 0 };
- char *cat;
-
- if (!(cfg = ast_config_load(JINGLE_CONFIG, config_flags))) {
- ast_log(LOG_ERROR, "Could not load Jingle2 configuration file '%s'\n", JINGLE_CONFIG);
- return -1;
- } else if (cfg == CONFIG_STATUS_FILEINVALID) {
- ast_log(LOG_ERROR, "Jingle2 configuration file '%s' invalid\n", JINGLE_CONFIG);
- return -1;
- } else if (cfg == CONFIG_STATUS_FILEUNCHANGED) {
- return 0;
- }
-
- ao2_callback(endpoints, OBJ_NODATA | OBJ_MULTIPLE, jingle_endpoint_set_destroy, NULL);
-
- for (cat = ast_category_browse(cfg, NULL); cat; cat = ast_category_browse(cfg, cat)) {
- if (!strcasecmp(cat, "general")) {
- store_config_general(cfg);
- } else {
- store_config_endpoint(cfg, cat);
- }
- }
-
- ao2_callback(endpoints, OBJ_NODATA | OBJ_UNLINK | OBJ_MULTIPLE, jingle_endpoint_remove_destroyed, NULL);
-
- ast_config_destroy(cfg);
return 0;
}
@@ -2429,14 +2420,30 @@
return AST_MODULE_LOAD_DECLINE;
}
+ if (aco_info_init(&cfg_info)) {
+ ast_log(LOG_ERROR, "Unable to intialize configuration for chan_jingle2.\n");
+ goto end;
+ }
+
+ aco_option_register(&cfg_info, "context", ACO_EXACT, endpoint_options, "default", OPT_STRINGFIELD_T, 0, STRFLDSET(struct jingle_endpoint, context));
+ aco_option_register_custom(&cfg_info, "callgroup", ACO_EXACT, endpoint_options, NULL, custom_group_handler, 0);
+ aco_option_register_custom(&cfg_info, "pickupgroup", ACO_EXACT, endpoint_options, NULL, custom_group_handler, 0);
+ aco_option_register(&cfg_info, "language", ACO_EXACT, endpoint_options, NULL, OPT_STRINGFIELD_T, 0, STRFLDSET(struct jingle_endpoint, language));
+ aco_option_register(&cfg_info, "musicclass", ACO_EXACT, endpoint_options, NULL, OPT_STRINGFIELD_T, 0, STRFLDSET(struct jingle_endpoint, musicclass));
+ aco_option_register(&cfg_info, "parkinglot", ACO_EXACT, endpoint_options, NULL, OPT_STRINGFIELD_T, 0, STRFLDSET(struct jingle_endpoint, parkinglot));
+ aco_option_register(&cfg_info, "accountcode", ACO_EXACT, endpoint_options, NULL, OPT_STRINGFIELD_T, 0, STRFLDSET(struct jingle_endpoint, accountcode));
+ aco_option_register(&cfg_info, "allow", ACO_EXACT, endpoint_options, "ulaw,alaw", OPT_CODEC_T, 1, FLDSET(struct jingle_endpoint, prefs, cap));
+ aco_option_register(&cfg_info, "disallow", ACO_EXACT, endpoint_options, "all", OPT_CODEC_T, 0, FLDSET(struct jingle_endpoint, prefs, cap));
+ aco_option_register_custom(&cfg_info, "connection", ACO_EXACT, endpoint_options, NULL, custom_connection_handler, 0);
+ aco_option_register_custom(&cfg_info, "transport", ACO_EXACT, endpoint_options, NULL, custom_transport_handler, 0);
+ aco_option_register(&cfg_info, "maxicecandidates", ACO_EXACT, endpoint_options, DEFAULT_MAX_ICE_CANDIDATES, OPT_UINT_T, PARSE_DEFAULT,
+ FLDSET(struct jingle_endpoint, maxicecandidates));
+ aco_option_register(&cfg_info, "maxpayloads", ACO_EXACT, endpoint_options, DEFAULT_MAX_PAYLOADS, OPT_UINT_T, PARSE_DEFAULT,
+ FLDSET(struct jingle_endpoint, maxpayloads));
+
ast_format_cap_add_all_by_type(jingle_tech.capabilities, AST_FORMAT_TYPE_AUDIO);
- if (!(endpoints = ao2_container_alloc(ENDPOINT_BUCKETS, jingle_endpoint_hash, jingle_endpoint_cmp))) {
- ast_log(LOG_ERROR, "Unable to create container for endpoints.\n");
- goto end;
- }
-
- if (jingle_load_config(0)) {
+ if (aco_process_config(&cfg_info, 0)) {
ast_log(LOG_ERROR, "Unable to read config file %s. Not loading module.\n", JINGLE_CONFIG);
goto end;
}
@@ -2466,9 +2473,8 @@
if (sched) {
ast_sched_context_destroy(sched);
}
- if (endpoints) {
- ao2_ref(endpoints, -1);
- }
+
+ aco_info_destroy(&cfg_info);
return AST_MODULE_LOAD_FAILURE;
}
@@ -2476,7 +2482,7 @@
/*! \brief Reload module */
static int reload(void)
{
- return jingle_load_config(1);
+ return aco_process_config(&cfg_info, 1);
}
/*! \brief Unload the jingle channel from Asterisk */
@@ -2485,7 +2491,8 @@
ast_channel_unregister(&jingle_tech);
ast_rtp_glue_unregister(&jingle_rtp_glue);
ast_sched_context_destroy(sched);
- ao2_ref(endpoints, -1);
+ aco_info_destroy(&cfg_info);
+ ao2_global_obj_release(globals);
return 0;
}
More information about the svn-commits
mailing list