summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMark Michelson <mmichelson@digium.com>2012-10-11 15:49:02 +0000
committerMark Michelson <mmichelson@digium.com>2012-10-11 15:49:02 +0000
commit825607e09b022ce56f7b5ccac03cd0dbf042396c (patch)
treedeec60920ba118bd06d2fdcd18f84853900e15c6
parent5ac43a08ad199d25d50198c0bb15826c346db9d2 (diff)
Don't make chan_sip export global symbols.
During testing, it was discovered that having chan_sip export global symbols was problematic. The biggest problem was that load order was affected. Trying to use realtime could be problematic since in all likelihood the necessary realtime driver(s) would not be loaded before chan_sip. In addition, it was found that it was impossible to use the Digium Phone Module for Asterisk since it must be loaded before chan_sip since it must hook into chan_sip's configuration parsing. The solution is to use a virtual table in the same manner that other modules in Asterisk do, like app_voicemail. (closes issue ASTERISK-20545) Reported by: kmoore ........ Merged revisions 374842 from http://svn.asterisk.org/svn/asterisk/branches/11 git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@374849 65c4cc65-6c06-0410-ace0-fbb531ad65f3
-rw-r--r--channels/chan_sip.c17
-rw-r--r--channels/chan_sip.exports.in6
-rw-r--r--include/asterisk/sip_api.h27
-rw-r--r--main/sip_api.c60
4 files changed, 102 insertions, 8 deletions
diff --git a/channels/chan_sip.c b/channels/chan_sip.c
index 09fef2c99..4b86ab384 100644
--- a/channels/chan_sip.c
+++ b/channels/chan_sip.c
@@ -7342,7 +7342,8 @@ static int initialize_udptl(struct sip_pvt *p)
return 0;
}
-int ast_sipinfo_send(
+
+static int sipinfo_send(
struct ast_channel *chan,
struct ast_variable *headers,
const char *content_type,
@@ -33298,6 +33299,12 @@ static const struct ast_data_entry sip_data_providers[] = {
AST_DATA_ENTRY("asterisk/channel/sip/peers", &peers_data_provider),
};
+static const struct ast_sip_api_tech chan_sip_api_provider = {
+ .version = AST_SIP_API_VERSION,
+ .name = "chan_sip",
+ .sipinfo_send = sipinfo_send,
+};
+
/*!
* \brief Load the module
*
@@ -33316,6 +33323,10 @@ static int load_module(void)
return AST_MODULE_LOAD_FAILURE;
}
+ if (ast_sip_api_provider_register(&chan_sip_api_provider)) {
+ return AST_MODULE_LOAD_FAILURE;
+ }
+
/* the fact that ao2_containers can't resize automatically is a major worry! */
/* if the number of objects gets above MAX_XXX_BUCKETS, things will slow down */
peers = ao2_t_container_alloc(HASH_PEER_SIZE, peer_hash_cb, peer_cmp_cb, "allocate peers");
@@ -33477,6 +33488,8 @@ static int unload_module(void)
struct ao2_iterator i;
int wait_count;
+ ast_sip_api_provider_unregister();
+
ast_websocket_remove_protocol("sip", sip_websocket_callback);
network_change_event_unsubscribe();
@@ -33652,7 +33665,7 @@ static int unload_module(void)
return 0;
}
-AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_GLOBAL_SYMBOLS | AST_MODFLAG_LOAD_ORDER, "Session Initiation Protocol (SIP)",
+AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_LOAD_ORDER, "Session Initiation Protocol (SIP)",
.load = load_module,
.unload = unload_module,
.reload = reload,
diff --git a/channels/chan_sip.exports.in b/channels/chan_sip.exports.in
deleted file mode 100644
index 1e9972a72..000000000
--- a/channels/chan_sip.exports.in
+++ /dev/null
@@ -1,6 +0,0 @@
-{
- global:
- LINKER_SYMBOL_PREFIX*ast_sipinfo_send;
- local:
- *;
-};
diff --git a/include/asterisk/sip_api.h b/include/asterisk/sip_api.h
index 392456758..2b8a3f2a1 100644
--- a/include/asterisk/sip_api.h
+++ b/include/asterisk/sip_api.h
@@ -26,6 +26,16 @@ extern "C" {
#include "asterisk/optional_api.h"
#include "asterisk/config.h"
+#define AST_SIP_API_VERSION 1
+
+struct ast_sip_api_tech {
+ const int version;
+ const char *name;
+ int (*sipinfo_send)(struct ast_channel *chan,
+ struct ast_variable *headers, const char *content_type,
+ const char *content, const char *useragent_filter);
+};
+
/*!
* \brief Send a customized SIP INFO request
*
@@ -45,6 +55,23 @@ int ast_sipinfo_send(struct ast_channel *chan,
const char *content,
const char *useragent_filter);
+/*!
+ * \brief Register a SIP API provider
+ *
+ * This will fail if a provider has already registered or if the
+ * provider is using an incorrect version.
+ *
+ * \param provider The provider to register
+ * \retval 0 Success
+ * \retval -1 Failure
+ */
+int ast_sip_api_provider_register(const struct ast_sip_api_tech *provider);
+
+/*!
+ * \brief Unregister a SIP API provider
+ */
+void ast_sip_api_provider_unregister(void);
+
#if defined(__cplusplus) || defined(c_plusplus)
}
#endif
diff --git a/main/sip_api.c b/main/sip_api.c
new file mode 100644
index 000000000..b87a7fdbb
--- /dev/null
+++ b/main/sip_api.c
@@ -0,0 +1,60 @@
+/*
+ * Asterisk -- An open source telephony toolkit.
+ *
+ * Copyright (C) 2012, Digium, Inc.
+ *
+ * Mark Michelson <mmichelson@digium.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 "asterisk/sip_api.h"
+#include "asterisk/logger.h"
+
+static const struct ast_sip_api_tech *api_provider;
+
+int ast_sipinfo_send(struct ast_channel *chan,
+ struct ast_variable *headers,
+ const char *content_type,
+ const char *content,
+ const char *useragent_filter)
+{
+ if (!api_provider) {
+ ast_log(LOG_WARNING, "Unable to send custom SIP INFO. No API provider registered\n");
+ return -1;
+ }
+
+ return api_provider->sipinfo_send(chan, headers, content_type, content, useragent_filter);
+}
+
+int ast_sip_api_provider_register(const struct ast_sip_api_tech *provider)
+{
+ if (api_provider) {
+ ast_log(LOG_WARNING, "SIP provider %s has already registered. Not registering provider %s\n",
+ api_provider->name, provider->name);
+ return -1;
+ }
+
+ if (provider->version != AST_SIP_API_VERSION) {
+ ast_log(LOG_WARNING, "SIP API provider version mismatch: Current version is %d but provider "
+ "uses version %d\n", AST_SIP_API_VERSION, provider->version);
+ return -1;
+ }
+
+ api_provider = provider;
+ return 0;
+}
+
+void ast_sip_api_provider_unregister(void)
+{
+ api_provider = NULL;
+}