diff --git a/channels/chan_sip.c b/channels/chan_sip.c index eaa19e72bc..5843ddb382 100644 --- a/channels/chan_sip.c +++ b/channels/chan_sip.c @@ -7299,7 +7299,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, @@ -33174,6 +33175,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 PBX load module - initialization */ static int load_module(void) { @@ -33183,6 +33190,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"); @@ -33344,6 +33355,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(); @@ -33519,7 +33532,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 1e9972a723..0000000000 --- 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 018785a8dc..89d7389b5d 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 * @@ -44,6 +54,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 0000000000..b87a7fdbb4 --- /dev/null +++ b/main/sip_api.c @@ -0,0 +1,60 @@ +/* + * Asterisk -- An open source telephony toolkit. + * + * Copyright (C) 2012, Digium, Inc. + * + * Mark Michelson + * + * 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; +}