summaryrefslogtreecommitdiff
path: root/include/asterisk
diff options
context:
space:
mode:
Diffstat (limited to 'include/asterisk')
-rw-r--r--include/asterisk/ari.h11
-rw-r--r--include/asterisk/autoconfig.h.in21
-rw-r--r--include/asterisk/compiler.h6
-rw-r--r--include/asterisk/http_websocket.h18
-rw-r--r--include/asterisk/optional_api.h293
5 files changed, 188 insertions, 161 deletions
diff --git a/include/asterisk/ari.h b/include/asterisk/ari.h
index 4f2954000..dfeef513c 100644
--- a/include/asterisk/ari.h
+++ b/include/asterisk/ari.h
@@ -21,7 +21,7 @@
/*! \file
*
- * \brief Stasis RESTful API hooks.
+ * \brief Asterisk RESTful API hooks.
*
* This header file is used mostly as glue code between generated declarations
* and res_ari.c.
@@ -31,7 +31,14 @@
#include "asterisk/http.h"
#include "asterisk/json.h"
-#include "asterisk/http_websocket.h"
+
+/* Forward-declare websocket structs. This avoids including http_websocket.h,
+ * which causes optional_api stuff to happen, which makes optional_api more
+ * difficult to debug. */
+
+struct ast_websocket_server;
+
+struct ast_websocket;
/*!
* \brief Configured encoding format for JSON output.
diff --git a/include/asterisk/autoconfig.h.in b/include/asterisk/autoconfig.h.in
index 1796a3f68..87a769ed0 100644
--- a/include/asterisk/autoconfig.h.in
+++ b/include/asterisk/autoconfig.h.in
@@ -82,12 +82,21 @@
/* Define to 1 if your GCC C compiler supports the 'const' attribute. */
#undef HAVE_ATTRIBUTE_const
+/* Define to 1 if your GCC C compiler supports the 'constructor' attribute. */
+#undef HAVE_ATTRIBUTE_constructor
+
/* Define to 1 if your GCC C compiler supports the 'deprecated' attribute. */
#undef HAVE_ATTRIBUTE_deprecated
+/* Define to 1 if your GCC C compiler supports the 'destructor' attribute. */
+#undef HAVE_ATTRIBUTE_destructor
+
/* Define to 1 if your GCC C compiler supports the 'malloc' attribute. */
#undef HAVE_ATTRIBUTE_malloc
+/* Define to 1 if your GCC C compiler supports the 'may_alias' attribute. */
+#undef HAVE_ATTRIBUTE_may_alias
+
/* Define to 1 if your GCC C compiler supports the 'pure' attribute. */
#undef HAVE_ATTRIBUTE_pure
@@ -101,15 +110,6 @@
attribute. */
#undef HAVE_ATTRIBUTE_warn_unused_result
-/* Define to 1 if your GCC C compiler supports the 'weak' attribute. */
-#undef HAVE_ATTRIBUTE_weak
-
-/* Define to 1 if your GCC C compiler supports the 'weak_import' attribute. */
-#undef HAVE_ATTRIBUTE_weak_import
-
-/* Define to 1 if your GCC C compiler supports the 'weakref' attribute. */
-#undef HAVE_ATTRIBUTE_weakref
-
/* Define to 1 if you have the Debug symbol decoding library. */
#undef HAVE_BFD
@@ -720,6 +720,9 @@
/* Define to 1 if you have the `roundl' function. */
#undef HAVE_ROUNDL
+/* Define if your system has the RTLD_NOLOAD headers. */
+#undef HAVE_RTLD_NOLOAD
+
/* Define to 1 if your system has /sbin/launchd. */
#undef HAVE_SBIN_LAUNCHD
diff --git a/include/asterisk/compiler.h b/include/asterisk/compiler.h
index 91112dbfe..77b5de40e 100644
--- a/include/asterisk/compiler.h
+++ b/include/asterisk/compiler.h
@@ -71,6 +71,12 @@
#define attribute_warn_unused_result
#endif
+#ifdef HAVE_ATTRIBUTE_may_alias
+#define attribute_may_alias __attribute__((may_alias))
+#else
+#define attribute_may_alias
+#endif
+
/* Some older version of GNU gcc (3.3.5 on OpenBSD 4.3 for example) dont like 'NULL' as sentinel */
#define SENTINEL ((char *)NULL)
diff --git a/include/asterisk/http_websocket.h b/include/asterisk/http_websocket.h
index 82c7ad8b6..10cb9a023 100644
--- a/include/asterisk/http_websocket.h
+++ b/include/asterisk/http_websocket.h
@@ -22,6 +22,8 @@
#include "asterisk/http.h"
#include "asterisk/optional_api.h"
+#include <errno.h>
+
/*!
* \file http_websocket.h
* \brief Support for WebSocket connections within the Asterisk HTTP server.
@@ -71,7 +73,7 @@ typedef void (*ast_websocket_callback)(struct ast_websocket *session, struct ast
* \retval \c NULL on error
* \since 12
*/
-struct ast_websocket_server *ast_websocket_server_create(void);
+AST_OPTIONAL_API(struct ast_websocket_server *, ast_websocket_server_create, (void), { return NULL; });
/*!
* \brief Callback suitable for use with a \ref ast_http_uri.
@@ -79,7 +81,7 @@ struct ast_websocket_server *ast_websocket_server_create(void);
* Set the data field of the ast_http_uri to \ref ast_websocket_server.
* \since 12
*/
-int ast_websocket_uri_cb(struct ast_tcptls_session_instance *ser, const struct ast_http_uri *urih, const char *uri, enum ast_http_method method, struct ast_variable *get_vars, struct ast_variable *headers);
+AST_OPTIONAL_API(int, ast_websocket_uri_cb, (struct ast_tcptls_session_instance *ser, const struct ast_http_uri *urih, const char *uri, enum ast_http_method method, struct ast_variable *get_vars, struct ast_variable *headers), { return -1; });
/*!
* \brief Add a sub-protocol handler to the default /ws server
@@ -141,7 +143,7 @@ AST_OPTIONAL_API(int, ast_websocket_server_remove_protocol, (struct ast_websocke
*
* \note Once an AST_WEBSOCKET_OPCODE_CLOSE opcode is received the socket will be closed
*/
-AST_OPTIONAL_API(int, ast_websocket_read, (struct ast_websocket *session, char **payload, uint64_t *payload_len, enum ast_websocket_opcode *opcode, int *fragmented), {return -1;});
+AST_OPTIONAL_API(int, ast_websocket_read, (struct ast_websocket *session, char **payload, uint64_t *payload_len, enum ast_websocket_opcode *opcode, int *fragmented), { errno = ENOSYS; return -1;});
/*!
* \brief Construct and transmit a WebSocket frame
@@ -154,7 +156,7 @@ AST_OPTIONAL_API(int, ast_websocket_read, (struct ast_websocket *session, char *
* \retval 0 if successfully written
* \retval -1 if error occurred
*/
-AST_OPTIONAL_API(int, ast_websocket_write, (struct ast_websocket *session, enum ast_websocket_opcode opcode, char *payload, uint64_t actual_length), {return -1;});
+AST_OPTIONAL_API(int, ast_websocket_write, (struct ast_websocket *session, enum ast_websocket_opcode opcode, char *payload, uint64_t actual_length), { errno = ENOSYS; return -1;});
/*!
* \brief Close a WebSocket session by sending a message with the CLOSE opcode and an optional code
@@ -165,7 +167,7 @@ AST_OPTIONAL_API(int, ast_websocket_write, (struct ast_websocket *session, enum
* \retval 0 if successfully written
* \retval -1 if error occurred
*/
-AST_OPTIONAL_API(int, ast_websocket_close, (struct ast_websocket *session, uint16_t reason), {return -1;});
+AST_OPTIONAL_API(int, ast_websocket_close, (struct ast_websocket *session, uint16_t reason), { errno = ENOSYS; return -1;});
/*!
* \brief Enable multi-frame reconstruction up to a certain number of bytes
@@ -207,7 +209,7 @@ AST_OPTIONAL_API(void, ast_websocket_unref, (struct ast_websocket *session), {re
*
* \note You must *not* directly read from or write to this file descriptor. It should only be used for polling.
*/
-AST_OPTIONAL_API(int, ast_websocket_fd, (struct ast_websocket *session), {return -1;});
+AST_OPTIONAL_API(int, ast_websocket_fd, (struct ast_websocket *session), { errno = ENOSYS; return -1;});
/*!
* \brief Get the remote address for a WebSocket connected session.
@@ -222,7 +224,7 @@ AST_OPTIONAL_API(struct ast_sockaddr *, ast_websocket_remote_address, (struct as
* \retval 0 if unsecure
* \retval 1 if secure
*/
-AST_OPTIONAL_API(int, ast_websocket_is_secure, (struct ast_websocket *session), {return -1;});
+AST_OPTIONAL_API(int, ast_websocket_is_secure, (struct ast_websocket *session), { errno = ENOSYS; return -1;});
/*!
* \brief Set the socket of a WebSocket session to be non-blocking.
@@ -230,6 +232,6 @@ AST_OPTIONAL_API(int, ast_websocket_is_secure, (struct ast_websocket *session),
* \retval 0 on success
* \retval -1 on failure
*/
-AST_OPTIONAL_API(int, ast_websocket_set_nonblock, (struct ast_websocket *session), {return -1;});
+AST_OPTIONAL_API(int, ast_websocket_set_nonblock, (struct ast_websocket *session), { errno = ENOSYS; return -1;});
#endif
diff --git a/include/asterisk/optional_api.h b/include/asterisk/optional_api.h
index cc31ce0a6..7d66d2e47 100644
--- a/include/asterisk/optional_api.h
+++ b/include/asterisk/optional_api.h
@@ -1,7 +1,7 @@
/*
* Asterisk -- An open source telephony toolkit.
*
- * Copyright (C) 2008, Digium, Inc.
+ * Copyright (C) 2008-2013, Digium, Inc.
*
* Kevin P. Fleming <kpfleming@digium.com>
*
@@ -30,19 +30,6 @@
* have only a part of their functionality dependent on the APIs, and can
* provide the remainder even if the APIs are not available.
*
- * To accomodate this situation, the AST_OPTIONAL_API macro allows an API
- * function to be declared in a special way, if Asterisk being built on a
- * platform that supports special compiler and dynamic linker attributes.
- * If so the API function will actually be a weak symbol, which means if the
- * provider of the API is not loaded, the symbol can still be referenced (unlike a
- * strong symbol, which would cause an immediate fault if not defined when
- * referenced), but it will return NULL signifying the linker/loader was
- * not able to resolve the symbol. In addition, the macro defines a hidden
- * 'stub' version of the API call, using a provided function body, and uses
- * various methods to make the API function symbol actually resolve to
- * that hidden stub, but only when the *real* provider of the symbol has
- * not been found.
- *
* An example can be found in agi.h:
*
* \code
@@ -74,19 +61,6 @@
* apply special aliases to the function prototype; this can be done
* by defining AST_API_MODULE just before including the header file
* containing the AST_OPTIONAL_API macro calls.
- *
- * \note If the platform does not provide adequate resources,
- * then the AST_OPTIONAL_API macro will result in a non-optional function
- * definition; this means that any consumers of the API functions so
- * defined will require that the provider of the API functions be
- * loaded before they can reference the symbols.
- *
- * WARNING WARNING WARNING WARNING WARNING
- *
- * You MUST add the AST_MODFLAG_GLOBAL_SYMBOLS to the module for which you
- * are enabling optional_api functionality, or it will fail to work.
- *
- * WARNING WARNING WARNING WARNING WARNING
*/
/*!
@@ -99,150 +73,185 @@
*/
#define AST_OPTIONAL_API_UNAVAILABLE INT_MIN
-
-#if defined(HAVE_ATTRIBUTE_weak_import) || defined(HAVE_ATTRIBUTE_weak)
-
-/*
- * This is the Darwin (Mac OS/X) implementation, that only provides the 'weak'
- * or 'weak_import' compiler attribute for weak symbols. On this platform,
- *
- * - The module providing the API will only provide a '__' prefixed version
- * of the API function to other modules (this will be hidden from the other
- * modules by the macros), so any modules compiled against older versions
- * of the module that provided a non-prefixed version of the API function
- * will fail to link at runtime.
- * - In the API module itself, access to the API function without using a
- * prefixed name is provided by a static pointer variable that holds the
- * function address.
- * - 'Consumer' modules of the API will use a combination of a weak_import or
- * weak symbol, a local stub function, a pointer variable and a constructor
- * function (which initializes that pointer variable as the module is being
- * loaded) to provide safe, optional access to the API function without any
- * special code being required.
+/*!
+ * \def AST_OPTIONAL_API_NAME(name)
+ * \brief Expands to the name of the implementation function.
*/
-#if defined(HAVE_ATTRIBUTE_weak_import)
-#define __default_attribute weak_import /* pre-Lion */
-#else
-#define __default_attribute weak /* Lion-onwards */
-#endif
-
-#define AST_OPTIONAL_API_NAME(name) __##name
-
-#if defined(AST_API_MODULE)
+/*!
+ * \def AST_OPTIONAL_API(result, name, proto, stub)
+ * \brief Declare an optional API function
+ *
+ * \param result The type of result the function returns
+ * \param name The name of the function
+ * \param proto The prototype (arguments) of the function
+ * \param stub The code block that will be used by the hidden stub when needed
+ *
+ * Example usage:
+ * \code
+ * AST_OPTIONAL_API(int, ast_agi_register, (struct ast_module *mod, agi_command *cmd),
+ * { return AST_OPTIONAL_API_UNAVAILABLE; });
+ * \endcode
+ */
-#define AST_OPTIONAL_API(result, name, proto, stub) \
- result AST_OPTIONAL_API_NAME(name) proto; \
- static attribute_unused typeof(AST_OPTIONAL_API_NAME(name)) * const name = AST_OPTIONAL_API_NAME(name);
+/*!
+ * \def AST_OPTIONAL_API_ATTR(result, attr, name, proto, stub)
+ * \brief Declare an optional API function with compiler attributes
+ *
+ * \param result The type of result the function returns
+ * \param attr Any compiler attributes to be applied to the function (without the __attribute__ wrapper)
+ * \param name The name of the function
+ * \param proto The prototype (arguments) of the function
+ * \param stub The code block that will be used by the hidden stub when needed
+ */
-#define AST_OPTIONAL_API_ATTR(result, attr, name, proto, stub) \
- result __attribute__((attr)) AST_OPTIONAL_API_NAME(name) proto; \
- static attribute_unused typeof(AST_OPTIONAL_API_NAME(name)) * const name = AST_OPTIONAL_API_NAME(name);
+#if defined(OPTIONAL_API)
-#else
+#if !defined(HAVE_ATTRIBUTE_constructor) || !defined(HAVE_ATTRIBUTE_constructor)
+#error OPTIONAL_API requires compiler constructor/destructor support
+#endif
-#define AST_OPTIONAL_API(result, name, proto, stub) \
- static result __stub__##name proto stub; \
- __attribute__((__default_attribute)) typeof(__stub__##name) AST_OPTIONAL_API_NAME(name); \
- static attribute_unused typeof(__stub__##name) * name; \
- static void __attribute__((constructor)) __init__##name(void) { name = AST_OPTIONAL_API_NAME(name) ? : __stub__##name; }
+/*!
+ * \internal
+ * \brief Function pointer to an optional API function.
+ *
+ * Functions that are declared as optional may have any signature they want;
+ * they are cast to this type as needed. We don't use a \c void pointer, because
+ * technically data and function pointers are incompatible.
+ *
+ * \note
+ * The may_alias attribute is to avoid type punning/strict aliasing warnings
+ * with older GCC's.
+ */
+typedef void (*ast_optional_fn)(void) attribute_may_alias;
-#define AST_OPTIONAL_API_ATTR(result, attr, name, proto, stub) \
- static __attribute__((attr)) result __stub__##name proto stub; \
- __attribute__((attr, __default_attribute)) typeof(__stub__##name) AST_OPTIONAL_API_NAME(name); \
- static attribute_unused __attribute__((attr)) typeof(__stub__##name) * name; \
- static void __attribute__((constructor)) __init__##name(void) { name = AST_OPTIONAL_API_NAME(name) ? : __stub__##name; }
+/*!
+ * \internal
+ * \brief Provide an implementation of an optional API.
+ *
+ * Any declared usages of this function are linked.
+ *
+ * \param symname Name of the provided function.
+ * \param impl Function pointer to the implementation function.
+ */
+void ast_optional_api_provide(const char *symname, ast_optional_fn impl);
-#endif
+/*!
+ * \internal
+ * \brief Remove an implementation of an optional API.
+ *
+ * Any declared usages of this function are unlinked.
+ *
+ * \param symname Name of the provided function.
+ * \param impl Function pointer to the implementation function.
+ */
+void ast_optional_api_unprovide(const char *symname, ast_optional_fn impl);
-/* End of Darwin (Mac OS/X) implementation */
+/*!
+ * \internal
+ * \brief Define a usage of an optional API.
+ *
+ * If the API has been provided, it will be linked into \a optional_ref.
+ * Otherwise, it will be linked to \a stub until an implementation is provided.
+ *
+ * \param symname Name of the function to use.
+ * \param optional_ref Pointer-to-function-pointer to link to impl/stub.
+ * \param stub Stub function to link to when impl is not available.
+ * \param module Name of the module requesting the API.
+ */
+void ast_optional_api_use(const char *symname, ast_optional_fn *optional_ref,
+ ast_optional_fn stub, const char *module);
-#elif defined(HAVE_ATTRIBUTE_weakref)
+/*!
+ * \internal
+ * \brief Remove a usage of an optional API.
+ *
+ * The \a optional_ref will be linked to the \a stub provided at use time,
+ * will no longer be updated if the API is provided/removed.
+ *
+ * \param symname Name of the function to use.
+ * \param optional_ref Pointer-to-function-pointer to link to impl/stub.
+ * \param module Name of the module requesting the API.
+ */
+void ast_optional_api_unuse(const char *symname, ast_optional_fn *optional_ref,
+ const char *module);
-/*
- * This is the generic GCC implementation, used when the 'weakref'
- * compiler attribute is available. On these platforms:
- *
- * - The module providing the API will provide a '__' prefixed version
- * of the API function to other modules (this will be hidden from the other
- * modules by the macros), and also a non-prefixed alias so that modules
- * compiled against older versions of the module that provided a non-prefixed
- * version of the API function will continue to link properly.
- * - In the API module itself, access to the API function without using a
- * prefixed name is provided by the non-prefixed alias described above.
- * - 'Consumer' modules of the API will use a combination of a weakref
- * symbol, a local stub function, a pointer variable and a constructor function
- * (which initializes that pointer variable as the module is being loaded)
- * to provide safe, optional access to the API function without any special
- * code being required.
+/*!
+ * \brief Call at exit to clean up optional_api internals.
+ *
+ * Since the optional_api code might run before main() starts, it can't safely
+ * register its own cleanup handlers. That has to be done within main().
*/
+void optional_api_cleanup(void);
#define AST_OPTIONAL_API_NAME(name) __##name
#if defined(AST_API_MODULE)
-
-#define AST_OPTIONAL_API(result, name, proto, stub) \
- result AST_OPTIONAL_API_NAME(name) proto; \
- static __attribute__((alias(__stringify(AST_OPTIONAL_API_NAME(name))))) typeof(AST_OPTIONAL_API_NAME(name)) name;
-
-#define AST_OPTIONAL_API_ATTR(result, attr, name, proto, stub) \
- result __attribute__((attr)) AST_OPTIONAL_API_NAME(name) proto; \
- static __attribute__((alias(__stringify(AST_OPTIONAL_API_NAME(name))))) typeof(AST_OPTIONAL_API_NAME(name)) name;
+/* Module defining the API */
+
+#define AST_OPTIONAL_API_IMPL_INIT(name) \
+ static void __attribute__((constructor)) __init__##name##_impl(void) { \
+ ast_optional_api_provide(#name, \
+ (ast_optional_fn)AST_OPTIONAL_API_NAME(name)); \
+ } \
+ static void __attribute__((destructor)) __dtor__##name##_impl(void) { \
+ ast_optional_api_unprovide(#name, \
+ (ast_optional_fn)AST_OPTIONAL_API_NAME(name)); \
+ }
+
+#define AST_OPTIONAL_API(result, name, proto, stub) \
+ result AST_OPTIONAL_API_NAME(name) proto; \
+ static attribute_unused typeof(AST_OPTIONAL_API_NAME(name)) * const \
+ name = AST_OPTIONAL_API_NAME(name); \
+ AST_OPTIONAL_API_IMPL_INIT(name)
+
+#define AST_OPTIONAL_API_ATTR(result, attr, name, proto, stub) \
+ result __attribute__((attr)) AST_OPTIONAL_API_NAME(name) proto; \
+ static attribute_unused typeof(AST_OPTIONAL_API_NAME(name)) * const \
+ name = AST_OPTIONAL_API_NAME(name); \
+ AST_OPTIONAL_API_IMPL_INIT(name)
#else
+/* Module using the API */
-#define AST_OPTIONAL_API(result, name, proto, stub) \
- static result __stub__##name proto stub; \
- static __attribute__((weakref(__stringify(AST_OPTIONAL_API_NAME(name))))) typeof(__stub__##name) __ref__##name; \
- static attribute_unused typeof(__stub__##name) * name; \
- static void __attribute__((constructor)) __init__##name(void) { name = __ref__##name ? : __stub__##name; }
+#define AST_OPTIONAL_API_INIT(name) \
+ static void __attribute__((constructor)) __init__##name(void) { \
+ ast_optional_api_use(#name, (ast_optional_fn *)&name, \
+ (ast_optional_fn)__stub__##name, \
+ AST_MODULE); \
+ } \
+ static void __attribute__((destructor)) __dtor__##name(void) { \
+ ast_optional_api_unuse(#name, (ast_optional_fn *)&name, \
+ AST_MODULE); \
+ }
-#define AST_OPTIONAL_API_ATTR(result, attr, name, proto, stub) \
- static __attribute__((attr)) result __stub__##name proto stub; \
- static __attribute__((attr, weakref(__stringify(AST_OPTIONAL_API_NAME(name))))) typeof(__stub__##name) __ref__##name; \
- static attribute_unused __attribute__((attr)) typeof(__stub__##name) * name; \
- static void __attribute__((constructor)) __init__##name(void) { name = __ref__##name ? : __stub__##name; }
+#define AST_OPTIONAL_API(result, name, proto, stub) \
+ static result __stub__##name proto stub; \
+ static attribute_unused \
+ typeof(__stub__##name) * name; \
+ AST_OPTIONAL_API_INIT(name)
-#endif
+#define AST_OPTIONAL_API_ATTR(result, attr, name, proto, stub) \
+ static __attribute__((attr)) result __stub__##name proto stub; \
+ static attribute_unused __attribute__((attr)) \
+ typeof(__stub__##name) * name; \
+ AST_OPTIONAL_API_INIT(name)
-/* End of GCC implementation */
+#endif /* defined(AST_API_MODULE) */
-#else
+#else /* defined(OPTIONAL_API) */
-/* This is the non-optional implementation. */
+/* Non-optional API */
#define AST_OPTIONAL_API_NAME(name) name
-/*!
- * \brief Define an optional API function
- *
- * \param result The type of result the function returns
- * \param name The name of the function
- * \param proto The prototype (arguments) of the function
- * \param stub The code block that will be used by the hidden stub when needed
- *
- * Example usage:
- * \code
- * AST_OPTIONAL_API(int, ast_agi_register, (struct ast_module *mod, agi_command *cmd),
- * { return AST_OPTIONAL_API_UNAVAILABLE; });
- * \endcode
- */
-#define AST_OPTIONAL_API(result, name, proto, stub) result AST_OPTIONAL_API_NAME(name) proto
+#define AST_OPTIONAL_API(result, name, proto, stub) \
+ result AST_OPTIONAL_API_NAME(name) proto
-/*!
- * \brief Define an optional API function with compiler attributes
- *
- * \param result The type of result the function returns
- * \param attr Any compiler attributes to be applied to the function (without the __attribute__ wrapper)
- * \param name The name of the function
- * \param proto The prototype (arguments) of the function
- * \param stub The code block that will be used by the hidden stub when needed
- */
-#define AST_OPTIONAL_API_ATTR(result, attr, name, proto, stub) result __attribute__((attr)) AST_OPTIONAL_API_NAME(name) proto
-
-/* End of non-optional implementation */
+#define AST_OPTIONAL_API_ATTR(result, attr, name, proto, stub) \
+ result __attribute__((attr)) AST_OPTIONAL_API_NAME(name) proto
-#endif
+#endif /* defined(OPTIONAL_API) */
#undef AST_API_MODULE