diff options
-rw-r--r-- | cel/cel_custom.c | 15 | ||||
-rw-r--r-- | cel/cel_manager.c | 17 | ||||
-rw-r--r-- | cel/cel_odbc.c | 23 | ||||
-rw-r--r-- | cel/cel_pgsql.c | 14 | ||||
-rw-r--r-- | cel/cel_radius.c | 12 | ||||
-rw-r--r-- | cel/cel_sqlite3_custom.c | 12 | ||||
-rw-r--r-- | cel/cel_tds.c | 13 | ||||
-rw-r--r-- | include/asterisk/_private.h | 1 | ||||
-rw-r--r-- | include/asterisk/cel.h | 29 | ||||
-rw-r--r-- | include/asterisk/event.h | 221 | ||||
-rw-r--r-- | include/asterisk/event_defs.h | 1 | ||||
-rw-r--r-- | main/asterisk.c | 5 | ||||
-rw-r--r-- | main/cel.c | 132 | ||||
-rw-r--r-- | main/event.c | 658 | ||||
-rw-r--r-- | tests/test_cel.c | 69 | ||||
-rw-r--r-- | tests/test_event.c | 548 |
16 files changed, 192 insertions, 1578 deletions
diff --git a/cel/cel_custom.c b/cel/cel_custom.c index 871408716..0f72bd6ce 100644 --- a/cel/cel_custom.c +++ b/cel/cel_custom.c @@ -64,7 +64,7 @@ struct cel_config { AST_RWLIST_ENTRY(cel_config) list; }; -static struct ast_event_sub *event_sub = NULL; +#define CUSTOM_BACKEND_NAME "CEL Custom CSV Logging" static AST_RWLIST_HEAD_STATIC(sinks, cel_config); @@ -116,7 +116,7 @@ static int load_config(void) return res; } -static void custom_log(const struct ast_event *event, void *userdata) +static void custom_log(struct ast_event *event) { struct ast_channel *dummy; struct ast_str *str; @@ -167,19 +167,15 @@ static void custom_log(const struct ast_event *event, void *userdata) static int unload_module(void) { - if (event_sub) { - event_sub = ast_event_unsubscribe(event_sub); - } if (AST_RWLIST_WRLOCK(&sinks)) { - event_sub = ast_event_subscribe(AST_EVENT_CEL, custom_log, "CEL Custom CSV Logging", - NULL, AST_EVENT_IE_END); ast_log(LOG_ERROR, "Unable to lock sink list. Unload failed.\n"); return -1; } free_config(); AST_RWLIST_UNLOCK(&sinks); + ast_cel_backend_unregister(CUSTOM_BACKEND_NAME); return 0; } @@ -193,8 +189,9 @@ static enum ast_module_load_result load_module(void) load_config(); AST_RWLIST_UNLOCK(&sinks); - event_sub = ast_event_subscribe(AST_EVENT_CEL, custom_log, "CEL Custom CSV Logging", - NULL, AST_EVENT_IE_END); + if (ast_cel_backend_register(CUSTOM_BACKEND_NAME, custom_log)) { + return AST_MODULE_LOAD_FAILURE; + } return AST_MODULE_LOAD_SUCCESS; } diff --git a/cel/cel_manager.c b/cel/cel_manager.c index 245c7800d..2fc001fe1 100644 --- a/cel/cel_manager.c +++ b/cel/cel_manager.c @@ -57,12 +57,12 @@ static int enablecel; /*! \brief show_user_def is off by default */ #define CEL_SHOW_USERDEF_DEFAULT 0 +#define MANAGER_BACKEND_NAME "Manager Event Logging" + /*! TRUE if we should set the EventName header to USER_DEFINED on user events. */ static unsigned char cel_show_user_def; -static struct ast_event_sub *event_sub; - -static void manager_log(const struct ast_event *event, void *userdata) +static void manager_log(struct ast_event *event) { struct ast_tm timeresult; char start_time[80] = ""; @@ -180,12 +180,9 @@ static int load_config(int reload) cel_show_user_def = new_cel_show_user_def; if (enablecel && !newenablecel) { - if (event_sub) { - event_sub = ast_event_unsubscribe(event_sub); - } + ast_cel_backend_unregister(MANAGER_BACKEND_NAME); } else if (!enablecel && newenablecel) { - event_sub = ast_event_subscribe(AST_EVENT_CEL, manager_log, "Manager Event Logging", NULL, AST_EVENT_IE_END); - if (!event_sub) { + if (ast_cel_backend_register(MANAGER_BACKEND_NAME, manager_log)) { ast_log(LOG_ERROR, "Unable to register Asterisk Call Manager CEL handling\n"); } } @@ -196,9 +193,7 @@ static int load_config(int reload) static int unload_module(void) { - if (event_sub) { - event_sub = ast_event_unsubscribe(event_sub); - } + ast_cel_backend_unregister(MANAGER_BACKEND_NAME); return 0; } diff --git a/cel/cel_odbc.c b/cel/cel_odbc.c index 933d9e344..69066c162 100644 --- a/cel/cel_odbc.c +++ b/cel/cel_odbc.c @@ -51,7 +51,8 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$") #include "asterisk/module.h" #define CONFIG "cel_odbc.conf" -static struct ast_event_sub *event_sub = NULL; + +#define ODBC_BACKEND_NAME "ODBC CEL backend" /*! \brief show_user_def is off by default */ #define CEL_SHOW_USERDEF_DEFAULT 0 @@ -367,7 +368,7 @@ static SQLHSTMT generic_prepare(struct odbc_obj *obj, void *data) } \ } while (0) -static void odbc_log(const struct ast_event *event, void *userdata) +static void odbc_log(struct ast_event *event) { struct tables *tableptr; struct columns *entry; @@ -789,18 +790,12 @@ early_release: static int unload_module(void) { - if (event_sub) { - event_sub = ast_event_unsubscribe(event_sub); - } if (AST_RWLIST_WRLOCK(&odbc_tables)) { - event_sub = ast_event_subscribe(AST_EVENT_CEL, odbc_log, "ODBC CEL backend", NULL, AST_EVENT_IE_END); - if (!event_sub) { - ast_log(LOG_ERROR, "Unable to subscribe to CEL events\n"); - } ast_log(LOG_ERROR, "Unable to lock column list. Unload failed.\n"); return -1; } + ast_cel_backend_unregister(ODBC_BACKEND_NAME); free_config(); AST_RWLIST_UNLOCK(&odbc_tables); AST_RWLIST_HEAD_DESTROY(&odbc_tables); @@ -814,13 +809,13 @@ static int load_module(void) if (AST_RWLIST_WRLOCK(&odbc_tables)) { ast_log(LOG_ERROR, "Unable to lock column list. Load failed.\n"); - return 0; + return AST_MODULE_LOAD_FAILURE; } load_config(); AST_RWLIST_UNLOCK(&odbc_tables); - event_sub = ast_event_subscribe(AST_EVENT_CEL, odbc_log, "ODBC CEL backend", NULL, AST_EVENT_IE_END); - if (!event_sub) { + if (ast_cel_backend_register(ODBC_BACKEND_NAME, odbc_log)) { ast_log(LOG_ERROR, "Unable to subscribe to CEL events\n"); + return AST_MODULE_LOAD_FAILURE; } return AST_MODULE_LOAD_SUCCESS; } @@ -829,7 +824,7 @@ static int reload(void) { if (AST_RWLIST_WRLOCK(&odbc_tables)) { ast_log(LOG_ERROR, "Unable to lock column list. Reload failed.\n"); - return -1; + return AST_MODULE_LOAD_FAILURE; } free_config(); @@ -838,7 +833,7 @@ static int reload(void) return AST_MODULE_LOAD_SUCCESS; } -AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_LOAD_ORDER, "ODBC CEL backend", +AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_LOAD_ORDER, ODBC_BACKEND_NAME, .load = load_module, .unload = unload_module, .reload = reload, diff --git a/cel/cel_pgsql.c b/cel/cel_pgsql.c index 0a393a6ca..5ba5b9972 100644 --- a/cel/cel_pgsql.c +++ b/cel/cel_pgsql.c @@ -58,6 +58,8 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$") #define DATE_FORMAT "%Y-%m-%d %T.%6q" +#define PGSQL_BACKEND_NAME "CEL PGSQL backend" + static char *config = "cel_pgsql.conf"; static char *pghostname = NULL, *pgdbname = NULL, *pgdbuser = NULL, *pgpassword = NULL, *pgdbport = NULL, *table = NULL; static int connected = 0; @@ -73,7 +75,6 @@ AST_MUTEX_DEFINE_STATIC(pgsql_lock); static PGconn *conn = NULL; static PGresult *result = NULL; -static struct ast_event_sub *event_sub = NULL; struct columns { char *name; @@ -113,7 +114,7 @@ static AST_RWLIST_HEAD_STATIC(psql_columns, columns); } \ } while (0) -static void pgsql_log(const struct ast_event *event, void *userdata) +static void pgsql_log(struct ast_event *event) { struct ast_tm tm; char timestr[128]; @@ -346,10 +347,7 @@ static int my_unload_module(void) { struct columns *current; AST_RWLIST_WRLOCK(&psql_columns); - if (event_sub) { - event_sub = ast_event_unsubscribe(event_sub); - event_sub = NULL; - } + ast_cel_backend_unregister(PGSQL_BACKEND_NAME); if (conn) { PQfinish(conn); conn = NULL; @@ -561,9 +559,7 @@ static int my_load_module(int reload) process_my_load_module(cfg); ast_config_destroy(cfg); - event_sub = ast_event_subscribe(AST_EVENT_CEL, pgsql_log, "CEL PGSQL backend", NULL, AST_EVENT_IE_END); - - if (!event_sub) { + if (ast_cel_backend_register(PGSQL_BACKEND_NAME, pgsql_log)) { ast_log(LOG_WARNING, "Unable to subscribe to CEL events for pgsql\n"); return AST_MODULE_LOAD_DECLINE; } diff --git a/cel/cel_radius.c b/cel/cel_radius.c index 9067a0491..be5a9e66f 100644 --- a/cel/cel_radius.c +++ b/cel/cel_radius.c @@ -84,7 +84,8 @@ static char radiuscfg[PATH_MAX] = "/etc/radiusclient-ng/radiusclient.conf"; static struct ast_flags global_flags = { RADIUS_FLAG_USEGMTIME | RADIUS_FLAG_LOGUNIQUEID | RADIUS_FLAG_LOGUSERFIELD }; static rc_handle *rh = NULL; -static struct ast_event_sub *event_sub = NULL; + +#define RADIUS_BACKEND_NAME "CEL Radius Logging" #define ADD_VENDOR_CODE(x,y) (rc_avpair_add(rh, send, x, &y, strlen(y), VENDOR_CODE)) @@ -174,7 +175,7 @@ static int build_radius_record(VALUE_PAIR **send, struct ast_cel_event_record *r return 0; } -static void radius_log(const struct ast_event *event, void *userdata) +static void radius_log(struct ast_event *event) { int result = ERROR_RC; VALUE_PAIR *send = NULL; @@ -204,9 +205,7 @@ return_cleanup: static int unload_module(void) { - if (event_sub) { - event_sub = ast_event_unsubscribe(event_sub); - } + ast_cel_backend_unregister(RADIUS_BACKEND_NAME); if (rh) { rc_destroy(rh); rh = NULL; @@ -256,8 +255,7 @@ static int load_module(void) return AST_MODULE_LOAD_DECLINE; } - event_sub = ast_event_subscribe(AST_EVENT_CEL, radius_log, "CEL Radius Logging", NULL, AST_EVENT_IE_END); - if (!event_sub) { + if (ast_cel_backend_register(RADIUS_BACKEND_NAME, radius_log)) { rc_destroy(rh); rh = NULL; return AST_MODULE_LOAD_DECLINE; diff --git a/cel/cel_sqlite3_custom.c b/cel/cel_sqlite3_custom.c index 6c4a82226..8ff3bd702 100644 --- a/cel/cel_sqlite3_custom.c +++ b/cel/cel_sqlite3_custom.c @@ -57,6 +57,8 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$") #include "asterisk/options.h" #include "asterisk/stringfields.h" +#define SQLITE_BACKEND_NAME "CEL sqlite3 custom backend" + AST_MUTEX_DEFINE_STATIC(lock); static const char config_file[] = "cel_sqlite3_custom.conf"; @@ -69,7 +71,6 @@ static char table[80]; * \bug Handling of this var is crash prone on reloads */ static char *columns; -static struct ast_event_sub *event_sub = NULL; struct values { char *expression; @@ -229,7 +230,7 @@ static void free_config(void) } } -static void write_cel(const struct ast_event *event, void *userdata) +static void write_cel(struct ast_event *event) { char *error = NULL; char *sql = NULL; @@ -293,9 +294,7 @@ static void write_cel(const struct ast_event *event, void *userdata) static int unload_module(void) { - if (event_sub) { - event_sub = ast_event_unsubscribe(event_sub); - } + ast_cel_backend_unregister(SQLITE_BACKEND_NAME); free_config(); @@ -339,8 +338,7 @@ static int load_module(void) } } - event_sub = ast_event_subscribe(AST_EVENT_CEL, write_cel, "CEL sqlite3 custom backend", NULL, AST_EVENT_IE_END); - if (!event_sub) { + if (ast_cel_backend_register(SQLITE_BACKEND_NAME, write_cel)) { ast_log(LOG_ERROR, "Unable to register custom SQLite3 CEL handling\n"); free_config(); return AST_MODULE_LOAD_DECLINE; diff --git a/cel/cel_tds.c b/cel/cel_tds.c index 1bb4d517e..0f8c8ad9a 100644 --- a/cel/cel_tds.c +++ b/cel/cel_tds.c @@ -81,9 +81,9 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$") #define DATE_FORMAT "%Y/%m/%d %T" -static char *config = "cel_tds.conf"; +#define TDS_BACKEND_NAME "CEL TDS logging backend" -static struct ast_event_sub *event_sub = NULL; +static char *config = "cel_tds.conf"; struct cel_tds_config { AST_DECLARE_STRING_FIELDS( @@ -112,7 +112,7 @@ static int execute_and_consume(DBPROCESS *dbproc, const char *fmt, ...) static int mssql_connect(void); static int mssql_disconnect(void); -static void tds_log(const struct ast_event *event, void *userdata) +static void tds_log(struct ast_event *event) { char start[80]; char *accountcode_ai, *clidnum_ai, *exten_ai, *context_ai, *clid_ai, *channel_ai, *app_ai, *appdata_ai, *uniqueid_ai, *linkedid_ai, *cidani_ai, *cidrdnis_ai, *ciddnid_ai, *peer_ai, *userfield_ai; @@ -397,9 +397,7 @@ failed: static int tds_unload_module(void) { - if (event_sub) { - event_sub = ast_event_unsubscribe(event_sub); - } + ast_cel_backend_unregister(TDS_BACKEND_NAME); if (settings) { ast_mutex_lock(&tds_lock); @@ -561,8 +559,7 @@ static int load_module(void) } /* Register MSSQL CEL handler */ - event_sub = ast_event_subscribe(AST_EVENT_CEL, tds_log, "CEL TDS logging backend", NULL, AST_EVENT_IE_END); - if (!event_sub) { + if (ast_cel_backend_register(TDS_BACKEND_NAME, tds_log)) { ast_log(LOG_ERROR, "Unable to register MSSQL CEL handling\n"); ast_string_field_free_memory(settings); ast_free(settings); diff --git a/include/asterisk/_private.h b/include/asterisk/_private.h index b1f6bd471..19ec1be92 100644 --- a/include/asterisk/_private.h +++ b/include/asterisk/_private.h @@ -29,7 +29,6 @@ int dnsmgr_init(void); /*!< Provided by dnsmgr.c */ void dnsmgr_start_refresh(void); /*!< Provided by dnsmgr.c */ int dnsmgr_reload(void); /*!< Provided by dnsmgr.c */ void threadstorage_init(void); /*!< Provided by threadstorage.c */ -int ast_event_init(void); /*!< Provided by event.c */ int ast_device_state_engine_init(void); /*!< Provided by devicestate.c */ int astobj2_init(void); /*!< Provided by astobj2.c */ int ast_file_init(void); /*!< Provided by file.c */ diff --git a/include/asterisk/cel.h b/include/asterisk/cel.h index 394c0667d..62644d2fb 100644 --- a/include/asterisk/cel.h +++ b/include/asterisk/cel.h @@ -300,6 +300,35 @@ struct ast_event *ast_cel_create_event(struct ast_channel_snapshot *snapshot, enum ast_cel_event_type event_type, const char *userdefevname, struct ast_json *extra, const char *peer_name); +/*! + * \brief CEL backend callback + */ +/*typedef int (*ast_cel_backend_cb)(struct ast_cel_event_record *cel);*/ +typedef void (*ast_cel_backend_cb)(struct ast_event *event); + +/*! + * \brief Register a CEL backend + * + * \param name Name of backend to register + * \param backend_callback Callback to register + * + * \retval zero on success + * \retval non-zero on failure + * \since 12 + */ +int ast_cel_backend_register(const char *name, ast_cel_backend_cb backend_callback); + +/*! + * \brief Unregister a CEL backend + * + * \param name Name of backend to unregister + * + * \retval zero on success + * \retval non-zero on failure + * \since 12 + */ +int ast_cel_backend_unregister(const char *name); + #if defined(__cplusplus) || defined(c_plusplus) } #endif diff --git a/include/asterisk/event.h b/include/asterisk/event.h index 7d7820720..3178de5c2 100644 --- a/include/asterisk/event.h +++ b/include/asterisk/event.h @@ -64,211 +64,6 @@ extern "C" { #include "asterisk/event_defs.h" /*! - * \brief Subscriber event callback type - * - * \param event the event being passed to the subscriber - * \param userdata the data provider in the call to ast_event_subscribe() - * - * \return The event callbacks do not return anything. - */ -typedef void (*ast_event_cb_t)(const struct ast_event *event, void *userdata); - -/*! - * \brief Subscribe to events - * - * \param event_type The type of events to subscribe to - * \param cb The function to be called with events - * \param description Description of the subscription. - * \param userdata data to be passed to the event callback - * - * The rest of the arguments to this function specify additional parameters for - * the subscription to filter which events are passed to this subscriber. The - * arguments must be in sets of: - * \code - * <enum ast_event_ie_type>, [enum ast_event_ie_pltype, [payload] ] - * \endcode - * and must end with AST_EVENT_IE_END. - * - * If the ie_type specified is *not* AST_EVENT_IE_END, then it must be followed - * by a valid IE payload type. A payload must also be specified. - * - * \return This returns a reference to the subscription for use with - * un-subscribing later. If there is a failure in creating the - * subscription, NULL will be returned. - * - * Example usage: - * - * \code - * peer->mwi_event_sub = ast_event_subscribe(AST_EVENT_MWI, mwi_event_cb, peer, - * AST_EVENT_IE_MAILBOX, AST_EVENT_IE_PLTYPE_STR, peer->mailbox, - * AST_EVENT_IE_END); - * \endcode - * - * This creates a subscription to AST_EVENT_MWI events that contain an - * information element, AST_EVENT_IE_MAILBOX, with the same string value - * contained in peer->mailbox. Also, the event callback will be passed a - * pointer to the peer. - * - * \note A NULL description will cause this function to crash, so watch out! - */ -struct ast_event_sub *ast_event_subscribe(enum ast_event_type event_type, - ast_event_cb_t cb, const char *description, void *userdata, ...); - -/*! - * \brief Allocate a subscription, but do not activate it - * - * \param type the event type to subscribe to - * \param cb the function to call when an event matches this subscription - * \param userdata data to pass to the provided callback - * - * This function should be used when you want to dynamically build a - * subscription. - * - * \return the allocated subscription, or NULL on failure - * \since 1.6.1 - */ -struct ast_event_sub *ast_event_subscribe_new(enum ast_event_type type, - ast_event_cb_t cb, void *userdata); - -/*! - * \brief Destroy an allocated subscription - * - * \param sub the subscription to destroy - * - * This function should be used when a subscription is allocated with - * ast_event_subscribe_new(), but for some reason, you want to destroy it - * instead of activating it. This could be because of an error when - * reading in the configuration for the dynamically built subscription. - * \since 1.6.1 - */ -void ast_event_sub_destroy(struct ast_event_sub *sub); - -/*! - * \brief Append a uint parameter to a subscription - * - * \param sub the dynamic subscription allocated with ast_event_subscribe_new() - * \param ie_type the information element type for the parameter - * \param uint the value that must be present in the event to match this subscription - * - * \retval 0 success - * \retval non-zero failure - * \since 1.6.1 - */ -int ast_event_sub_append_ie_uint(struct ast_event_sub *sub, - enum ast_event_ie_type ie_type, uint32_t uint); - -/*! - * \brief Append a string parameter to a subscription - * - * \param sub the dynamic subscription allocated with ast_event_subscribe_new() - * \param ie_type the information element type for the parameter - * \param str the string that must be present in the event to match this subscription - * - * \retval 0 success - * \retval non-zero failure - * \since 1.6.1 - */ -int ast_event_sub_append_ie_str(struct ast_event_sub *sub, - enum ast_event_ie_type ie_type, const char *str); - -/*! - * \brief Append a raw parameter to a subscription - * - * \param sub the dynamic subscription allocated with ast_event_subscribe_new() - * \param ie_type the information element type for the parameter - * \param data the data that must be present in the event to match this subscription - * \param raw_datalen length of data - * - * \retval 0 success - * \retval non-zero failure - * \since 1.6.1 - */ -int ast_event_sub_append_ie_raw(struct ast_event_sub *sub, - enum ast_event_ie_type ie_type, void *data, size_t raw_datalen); - -/*! - * \brief Activate a dynamically built subscription - * - * \param sub the subscription to activate that was allocated using - * ast_event_subscribe_new() - * - * Once a dynamically built subscription has had all of the parameters added - * to it, it should be activated using this function. - * - * \retval 0 success - * \retval non-zero failure - * \since 1.6.1 - */ -int ast_event_sub_activate(struct ast_event_sub *sub); - -/*! - * \brief Un-subscribe from events - * - * \param event_sub This is the reference to the subscription returned by - * ast_event_subscribe. - * - * This function will remove a subscription and free the associated data - * structures. - * - * \return NULL for convenience. - * \version 1.6.1 return changed to NULL - */ -struct ast_event_sub *ast_event_unsubscribe(struct ast_event_sub *event_sub); - -/*! - * \brief Check if subscribers exist - * - * \param event_type This is the type of event that the caller would like to - * check for subscribers to. - * - * The rest of the arguments to this function specify additional parameters for - * checking for subscriptions to subsets of an event type. The arguments must - * in sets of: - * \code - * <enum ast_event_ie_type>, [enum ast_event_ie_pltype, [payload] ] - * \endcode - * and must end with AST_EVENT_IE_END. - * - * If the ie_type specified is *not* AST_EVENT_IE_END, then it must be followed - * by a valid IE payload type. A payload must also be specified. - * - * \return This returns one of the values defined in the ast_event_subscriber_res - * enum which will indicate if subscribers exist that match the given - * criteria. - * - * Example usage: - * - * \code - * if (ast_event_check_subscriber(AST_EVENT_MWI, - * AST_EVENT_IE_MAILBOX, AST_EVENT_IE_PLTYPE_STR, mailbox, - * AST_EVENT_IE_END) == AST_EVENT_SUB_NONE) { - * return; - * } - * \endcode - * - * This example will check if there are any subscribers to MWI events for the - * mailbox defined in the "mailbox" variable. - */ -enum ast_event_subscriber_res ast_event_check_subscriber(enum ast_event_type event_type, ...); - -/*! - * \brief Report current subscriptions to a subscription subscriber - * - * \arg sub the subscription subscriber - * - * \return nothing - * - * This reports all of the current subscribers to a subscriber of - * subscribers to a specific event type. (Try saying that a few times fast). - * - * The idea here is that it is sometimes very useful for a module to know when - * someone subscribes to events. However, when they first subscribe, this - * provides that module the ability to request the event core report to them - * all of the subscriptions to that event type that already exist. - */ -void ast_event_report_subs(const struct ast_event_sub *sub); - -/*! * \brief Create a new event * * \param event_type The type of event to create @@ -321,22 +116,6 @@ struct ast_event *ast_event_new(enum ast_event_type event_type, ...); void ast_event_destroy(struct ast_event *event); /*! - * \brief Queue an event - * - * \param event the event to be queued - * - * \retval zero success - * \retval non-zero failure. Note that the caller of this function is - * responsible for destroying the event in the case of a failure. - * - * This function queues an event to be dispatched to all of the appropriate - * subscribers. This function will not block while the event is being - * dispatched because the event is queued up for a dispatching thread - * to handle. - */ -int ast_event_queue(struct ast_event *event); - -/*! * \brief Append an information element that has a string payload * * \param event the event that the IE will be appended to diff --git a/include/asterisk/event_defs.h b/include/asterisk/event_defs.h index e25908e29..f8f98ace0 100644 --- a/include/asterisk/event_defs.h +++ b/include/asterisk/event_defs.h @@ -271,7 +271,6 @@ enum ast_event_subscriber_res { struct ast_event; struct ast_event_ie; -struct ast_event_sub; struct ast_event_iterator; /*! diff --git a/main/asterisk.c b/main/asterisk.c index 07186f655..d6a454e8b 100644 --- a/main/asterisk.c +++ b/main/asterisk.c @@ -4149,11 +4149,6 @@ int main(int argc, char *argv[]) exit(1); } - if (ast_event_init()) { - printf("%s", term_quit()); - exit(1); - } - #ifdef TEST_FRAMEWORK if (ast_test_init()) { printf("%s", term_quit()); diff --git a/main/cel.c b/main/cel.c index d9e1d81df..a613b7c2e 100644 --- a/main/cel.c +++ b/main/cel.c @@ -147,11 +147,17 @@ static struct stasis_subscription *cel_cel_forwarder; /*! Container for primary channel/bridge ID listing for 2 party bridges */ static struct ao2_container *bridge_primaries; +/*! The number of buckets into which bridge primary structs will be hashed */ +#define BRIDGE_PRIMARY_BUCKETS 251 + struct stasis_message_type *cel_generic_type(void); STASIS_MESSAGE_TYPE_DEFN(cel_generic_type); -/*! The number of buckets into which primary channel uniqueids will be hashed */ -#define BRIDGE_PRIMARY_BUCKETS 251 +/*! Container for CEL backend information */ +static struct ao2_container *cel_backends; + +/*! The number of buckets into which backend names will be hashed */ +#define BACKEND_BUCKETS 13 /*! Container for dial end multichannel blobs for holding on to dial statuses */ static struct ao2_container *cel_dialstatus_store; @@ -323,6 +329,57 @@ static const char * const cel_event_types[CEL_MAX_EVENT_IDS] = { [AST_CEL_LOCAL_OPTIMIZE] = "LOCAL_OPTIMIZE", }; +struct cel_backend { + ast_cel_backend_cb callback; /*!< Callback for this backend */ + char name[0]; /*!< Name of this backend */ +}; + +/*! \brief Hashing function for cel_backend */ +static int cel_backend_hash(const void *obj, int flags) +{ + const struct cel_backend *backend; + const char *name; + + switch (flags & (OBJ_POINTER | OBJ_KEY | OBJ_PARTIAL_KEY)) { + case OBJ_POINTER: + backend = obj; + name = backend->name; + break; + case OBJ_KEY: + name = obj; + break; + default: + /* Hash can only work on something with a full key. */ + ast_assert(0); + return 0; + } + + return ast_str_hash(name); +} + +/*! \brief Comparator function for cel_backend */ +static int cel_backend_cmp(void *obj, void *arg, int flags) +{ + struct cel_backend *backend2, *backend1 = obj; + const char *backend2_id, *backend1_id = backend1->name; + + switch (flags & (OBJ_POINTER | OBJ_KEY | OBJ_PARTIAL_KEY)) { + case OBJ_POINTER: + backend2 = arg; + backend2_id = backend2->name; + break; + case OBJ_KEY: + backend2_id = arg; + break; + default: + /* Hash can only work on something with a full key. */ + ast_assert(0); + return 0; + } + + return !strcmp(backend1_id, backend2_id) ? CMP_MATCH | CMP_STOP : 0; +} + struct bridge_assoc { AST_DECLARE_STRING_FIELDS( AST_STRING_FIELD(bridge_id); /*!< UniqueID of the bridge */ @@ -451,18 +508,18 @@ static int print_app(void *obj, void *arg, int flags) return 0; } -static void print_cel_sub(const struct ast_event *event, void *data) +static int event_desc_cb(void *obj, void *arg, int flags) { - struct ast_cli_args *a = data; + struct ast_cli_args *a = arg; + struct cel_backend *backend = obj; - ast_cli(a->fd, "CEL Event Subscriber: %s\n", - ast_event_get_ie_str(event, AST_EVENT_IE_DESCRIPTION)); + ast_cli(a->fd, "CEL Event Subscriber: %s\n", backend->name); + return 0; } static char *handle_cli_status(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) { unsigned int i; - struct ast_event_sub *sub; RAII_VAR(struct cel_config *, cfg, ao2_global_obj_ref(cel_configs), ao2_cleanup); switch (cmd) { @@ -506,14 +563,7 @@ static char *handle_cli_status(struct ast_cli_entry *e, int cmd, struct ast_cli_ } ao2_callback(cfg->general->apps, OBJ_NODATA, print_app, a); - - if (!(sub = ast_event_subscribe_new(AST_EVENT_SUB, print_cel_sub, a))) { - return CLI_FAILURE; - } - ast_event_sub_append_ie_uint(sub, AST_EVENT_IE_EVENTTYPE, AST_EVENT_CEL); - ast_event_report_subs(sub); - ast_event_sub_destroy(sub); - sub = NULL; + ao2_callback(cel_backends, OBJ_MULTIPLE | OBJ_NODATA, event_desc_cb, a); return CLI_SUCCESS; } @@ -668,6 +718,14 @@ struct ast_event *ast_cel_create_event(struct ast_channel_snapshot *snapshot, AST_EVENT_IE_END); } +static int cel_backend_send_cb(void *obj, void *arg, int flags) +{ + struct cel_backend *backend = obj; + + backend->callback(arg); + return 0; +} + static int cel_report_event(struct ast_channel_snapshot *snapshot, enum ast_cel_event_type event_type, const char *userdefevname, struct ast_json *extra, const char *peer2_name) @@ -711,11 +769,14 @@ static int cel_report_event(struct ast_channel_snapshot *snapshot, } ev = ast_cel_create_event(snapshot, event_type, userdefevname, extra, peer_name); - if (ev && ast_event_queue(ev)) { - ast_event_destroy(ev); + if (!ev) { return -1; } + /* Distribute event to backends */ + ao2_callback(cel_backends, OBJ_MULTIPLE | OBJ_NODATA, cel_backend_send_cb, ev); + ast_event_destroy(ev); + return 0; } @@ -1543,6 +1604,11 @@ int ast_cel_engine_init(void) return -1; } + cel_backends = ao2_container_alloc(BACKEND_BUCKETS, cel_backend_hash, cel_backend_cmp); + if (!cel_backends) { + return -1; + } + cel_aggregation_topic = stasis_topic_create("cel_aggregation_topic"); if (!cel_aggregation_topic) { return -1; @@ -1702,3 +1768,35 @@ void ast_cel_set_config(struct ast_cel_general_config *config) ao2_ref(mod_cfg->general, +1); } +int ast_cel_backend_unregister(const char *name) +{ + RAII_VAR(struct cel_backend *, backend, NULL, ao2_cleanup); + + backend = ao2_find(cel_backends, name, OBJ_KEY | OBJ_UNLINK); + if (!backend) { + return -1; + } + + return 0; +} + +int ast_cel_backend_register(const char *name, ast_cel_backend_cb backend_callback) +{ + RAII_VAR(struct cel_backend *, backend, NULL, ao2_cleanup); + + if (ast_strlen_zero(name)) { + return -1; + } + + backend = ao2_alloc(sizeof(*backend) + 1 + strlen(name), NULL); + if (!backend) { + return -1; + } + + /* safe strcpy */ + strcpy(backend->name, name); + backend->callback = backend_callback; + ao2_link(cel_backends, backend); + + return 0; +} diff --git a/main/event.c b/main/event.c index 787f3bc51..0f0406f55 100644 --- a/main/event.c +++ b/main/event.c @@ -44,12 +44,9 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$") #include "asterisk/astobj2.h" #include "asterisk/cli.h" -static struct ast_taskprocessor *event_dispatcher; static int event_append_ie_raw(struct ast_event **event, enum ast_event_ie_type ie_type, const void *data, size_t data_len); static const void *event_get_ie_raw(const struct ast_event *event, enum ast_event_ie_type ie_type); -static uint16_t event_get_ie_raw_payload_len(const struct ast_event *event, enum ast_event_ie_type ie_type); -static uint32_t event_get_ie_str_hash(const struct ast_event *event, enum ast_event_ie_type ie_type); /*! * \brief An event information element @@ -112,23 +109,6 @@ struct ast_event_ie_val { size_t raw_datalen; }; -/*! \brief Event subscription */ -struct ast_event_sub { - enum ast_event_type type; - ast_event_cb_t cb; - char description[64]; - void *userdata; - uint32_t uniqueid; - AST_LIST_HEAD_NOLOCK(, ast_event_ie_val) ie_vals; - AST_RWDLLIST_ENTRY(ast_event_sub) entry; -}; - -static uint32_t sub_uniqueid; - -/*! \brief Event subscriptions - * The event subscribers are indexed by which event they are subscribed to */ -static AST_RWDLLIST_HEAD(ast_event_sub_list, ast_event_sub) ast_event_subs[AST_EVENT_TOTAL]; - struct ie_map { enum ast_event_ie_pltype ie_pltype; const char *name; @@ -217,513 +197,11 @@ size_t ast_event_get_size(const struct ast_event *event) return res; } -static void ast_event_ie_val_destroy(struct ast_event_ie_val *ie_val) -{ - switch (ie_val->ie_pltype) { - case AST_EVENT_IE_PLTYPE_STR: - ast_free((char *) ie_val->payload.str); - break; - case AST_EVENT_IE_PLTYPE_RAW: - ast_free(ie_val->payload.raw); - break; - case AST_EVENT_IE_PLTYPE_UINT: - case AST_EVENT_IE_PLTYPE_UNKNOWN: - break; - } - - ast_free(ie_val); -} - /*! \brief Subscription event check list. */ struct ast_ev_check_list { AST_LIST_HEAD_NOLOCK(, ast_event_ie_val) ie_vals; }; -/*! - * \internal - * \brief Check if a subscription ie_val matches an event. - * - * \param sub_ie_val Subscripton IE value to check - * \param check_ie_vals event list to check against - * - * \retval 0 not matched - * \retval non-zero matched - */ -static int match_sub_ie_val_to_event(const struct ast_event_ie_val *sub_ie_val, const struct ast_ev_check_list *check_ie_vals) -{ - const struct ast_event_ie_val *event_ie_val; - int res = 0; - - AST_LIST_TRAVERSE(&check_ie_vals->ie_vals, event_ie_val, entry) { - if (sub_ie_val->ie_type == event_ie_val->ie_type) { - break; - } - } - if (!event_ie_val) { - /* We did not find the event ie the subscriber cares about. */ - return 0; - } - - if (sub_ie_val->ie_pltype != event_ie_val->ie_pltype) { - /* Payload types do not match. */ - return 0; - } - - switch (sub_ie_val->ie_pltype) { - case AST_EVENT_IE_PLTYPE_UINT: - res = (sub_ie_val->payload.uint == event_ie_val->payload.uint); - break; - case AST_EVENT_IE_PLTYPE_STR: - { - const char *substr = sub_ie_val->payload.str; - const char *estr = event_ie_val->payload.str; - res = !strcmp(substr, estr); - break; - } - case AST_EVENT_IE_PLTYPE_RAW: - res = (sub_ie_val->raw_datalen == event_ie_val->raw_datalen - && !memcmp(sub_ie_val->payload.raw, event_ie_val->payload.raw, - sub_ie_val->raw_datalen)); - break; - case AST_EVENT_IE_PLTYPE_UNKNOWN: - /* - * Should never be in a subscription event ie val list and - * check_ie_vals cannot have this type either. - */ - break; - } - - return res; -} - -enum ast_event_subscriber_res ast_event_check_subscriber(enum ast_event_type type, ...) -{ - va_list ap; - enum ast_event_ie_type ie_type; - enum ast_event_subscriber_res res = AST_EVENT_SUB_NONE; - struct ast_event_ie_val *ie_val; - struct ast_event_sub *sub; - struct ast_ev_check_list check_ie_vals = { - .ie_vals = AST_LIST_HEAD_NOLOCK_INIT_VALUE - }; - const enum ast_event_type event_types[] = { type, AST_EVENT_ALL }; - int i; - int want_specific_event;/* TRUE if looking for subscribers wanting specific parameters. */ - - if (type >= AST_EVENT_TOTAL) { - ast_log(LOG_ERROR, "%u is an invalid type!\n", type); - return res; - } - - want_specific_event = 0; - va_start(ap, type); - for (ie_type = va_arg(ap, enum ast_event_ie_type); - ie_type != AST_EVENT_IE_END; - ie_type = va_arg(ap, enum ast_event_ie_type)) - { - struct ast_event_ie_val *ie_value = ast_alloca(sizeof(*ie_value)); - int insert = 0; - - memset(ie_value, 0, sizeof(*ie_value)); - ie_value->ie_type = ie_type; - ie_value->ie_pltype = va_arg(ap, enum ast_event_ie_pltype); - switch (ie_value->ie_pltype) { - case AST_EVENT_IE_PLTYPE_UINT: - ie_value->payload.uint = va_arg(ap, uint32_t); - insert = 1; - break; - case AST_EVENT_IE_PLTYPE_STR: - ie_value->payload.str = va_arg(ap, const char *); - insert = 1; - break; - case AST_EVENT_IE_PLTYPE_RAW: - { - void *data = va_arg(ap, void *); - size_t datalen = va_arg(ap, size_t); - - ie_value->payload.raw = ast_alloca(datalen); - memcpy(ie_value->payload.raw, data, datalen); - ie_value->raw_datalen = datalen; - insert = 1; - break; - } - case AST_EVENT_IE_PLTYPE_UNKNOWN: - /* Unsupported payload type. */ - break; - } - - if (insert) { - want_specific_event = 1; - AST_LIST_INSERT_TAIL(&check_ie_vals.ie_vals, ie_value, entry); - } else { - ast_log(LOG_WARNING, "Unsupported PLTYPE(%d)\n", ie_value->ie_pltype); - } - } - va_end(ap); - - for (i = 0; i < ARRAY_LEN(event_types); i++) { - AST_RWDLLIST_RDLOCK(&ast_event_subs[event_types[i]]); - if (want_specific_event) { - AST_RWDLLIST_TRAVERSE(&ast_event_subs[event_types[i]], sub, entry) { - AST_LIST_TRAVERSE(&sub->ie_vals, ie_val, entry) { - if (!match_sub_ie_val_to_event(ie_val, &check_ie_vals)) { - /* The current subscription ie did not match an event ie. */ - break; - } - } - if (!ie_val) { - /* Everything matched. A subscriber is looking for this event. */ - break; - } - } - } else { - /* Just looking to see if there are ANY subscribers to the event type. */ - sub = AST_RWLIST_FIRST(&ast_event_subs[event_types[i]]); - } - AST_RWDLLIST_UNLOCK(&ast_event_subs[event_types[i]]); - if (sub) { - break; - } - } - - return sub ? AST_EVENT_SUB_EXISTS : AST_EVENT_SUB_NONE; -} - -/*! - * \internal - * \brief Check if an ie_val matches an event - * - * \param event event to check against - * \param ie_val IE value to check - * \param event2 optional event, if specified, the value to compare against will be pulled - * from this event instead of from the ie_val structure. In this case, only the IE - * type and payload type will be pulled from ie_val. - * - * \retval 0 not matched - * \retval non-zero matched - */ -static int match_ie_val(const struct ast_event *event, - const struct ast_event_ie_val *ie_val, const struct ast_event *event2) -{ - switch (ie_val->ie_pltype) { - case AST_EVENT_IE_PLTYPE_UINT: - { - uint32_t val = event2 ? ast_event_get_ie_uint(event2, ie_val->ie_type) : ie_val->payload.uint; - - return (val == ast_event_get_ie_uint(event, ie_val->ie_type)) ? 1 : 0; - } - - case AST_EVENT_IE_PLTYPE_STR: - { - const char *str; - uint32_t hash; - - hash = event2 ? event_get_ie_str_hash(event2, ie_val->ie_type) : ie_val->payload.hash; - if (hash != event_get_ie_str_hash(event, ie_val->ie_type)) { - return 0; - } - - str = event2 ? ast_event_get_ie_str(event2, ie_val->ie_type) : ie_val->payload.str; - if (str) { - const char *e1str, *e2str; - e1str = ast_event_get_ie_str(event, ie_val->ie_type); - e2str = str; - - if (!strcmp(e1str, e2str)) { - return 1; - } - } - - return 0; - } - - case AST_EVENT_IE_PLTYPE_RAW: - { - const void *buf = event2 ? event_get_ie_raw(event2, ie_val->ie_type) : ie_val->payload.raw; - uint16_t ie_payload_len = event2 ? event_get_ie_raw_payload_len(event2, ie_val->ie_type) : ie_val->raw_datalen; - - return (buf - && ie_payload_len == event_get_ie_raw_payload_len(event, ie_val->ie_type) - && !memcmp(buf, event_get_ie_raw(event, ie_val->ie_type), ie_payload_len)) ? 1 : 0; - } - - case AST_EVENT_IE_PLTYPE_UNKNOWN: - return 0; - } - - return 0; -} - -static struct ast_event *gen_sub_event(struct ast_event_sub *sub) -{ - struct ast_event_ie_val *ie_val; - struct ast_event *event; - - event = ast_event_new(AST_EVENT_SUB, - AST_EVENT_IE_UNIQUEID, AST_EVENT_IE_PLTYPE_UINT, sub->uniqueid, - AST_EVENT_IE_EVENTTYPE, AST_EVENT_IE_PLTYPE_UINT, sub->type, - AST_EVENT_IE_DESCRIPTION, AST_EVENT_IE_PLTYPE_STR, sub->description, - AST_EVENT_IE_END); - if (!event) - return NULL; - - AST_LIST_TRAVERSE(&sub->ie_vals, ie_val, entry) { - switch (ie_val->ie_pltype) { - case AST_EVENT_IE_PLTYPE_UNKNOWN: - break; - case AST_EVENT_IE_PLTYPE_UINT: - ast_event_append_ie_uint(&event, ie_val->ie_type, ie_val->payload.uint); - break; - case AST_EVENT_IE_PLTYPE_STR: - ast_event_append_ie_str(&event, ie_val->ie_type, ie_val->payload.str); - break; - case AST_EVENT_IE_PLTYPE_RAW: - event_append_ie_raw(&event, ie_val->ie_type, ie_val->payload.raw, ie_val->raw_datalen); - break; - } - if (!event) - break; - } - - return event; -} - -/*! \brief Send AST_EVENT_SUB events to this subscriber of ... subscriber events */ -void ast_event_report_subs(const struct ast_event_sub *event_sub) -{ - struct ast_event *event; - struct ast_event_sub *sub; - enum ast_event_type event_type = -1; - struct ast_event_ie_val *ie_val; - - if (event_sub->type != AST_EVENT_SUB) - return; - - AST_LIST_TRAVERSE(&event_sub->ie_vals, ie_val, entry) { - if (ie_val->ie_type == AST_EVENT_IE_EVENTTYPE) { - event_type = ie_val->payload.uint; - break; - } - } - - if (event_type == -1) - return; - - AST_RWDLLIST_RDLOCK(&ast_event_subs[event_type]); - AST_RWDLLIST_TRAVERSE(&ast_event_subs[event_type], sub, entry) { - if (event_sub == sub) { - continue; - } - - event = gen_sub_event(sub); - if (!event) { - continue; - } - - event_sub->cb(event, event_sub->userdata); - - ast_event_destroy(event); - } - AST_RWDLLIST_UNLOCK(&ast_event_subs[event_type]); -} - -struct ast_event_sub *ast_event_subscribe_new(enum ast_event_type type, - ast_event_cb_t cb, void *userdata) -{ - struct ast_event_sub *sub; - - if (type < 0 || type >= AST_EVENT_TOTAL) { - ast_log(LOG_ERROR, "%u is an invalid type!\n", type); - return NULL; - } - - if (!(sub = ast_calloc(1, sizeof(*sub)))) { - return NULL; - } - - sub->type = type; - sub->cb = cb; - sub->userdata = userdata; - sub->uniqueid = ast_atomic_fetchadd_int((int *) &sub_uniqueid, 1); - - return sub; -} - -int ast_event_sub_append_ie_uint(struct ast_event_sub *sub, - enum ast_event_ie_type ie_type, uint32_t unsigned_int) -{ - struct ast_event_ie_val *ie_val; - - if (ie_type <= 0 || ie_type >= AST_EVENT_IE_TOTAL) { - return -1; - } - - if (!(ie_val = ast_calloc(1, sizeof(*ie_val)))) { - return -1; - } - - ie_val->ie_type = ie_type; - ie_val->payload.uint = unsigned_int; - ie_val->ie_pltype = AST_EVENT_IE_PLTYPE_UINT; - - AST_LIST_INSERT_TAIL(&sub->ie_vals, ie_val, entry); - - return 0; -} - -int ast_event_sub_append_ie_str(struct ast_event_sub *sub, - enum ast_event_ie_type ie_type, const char *str) -{ - struct ast_event_ie_val *ie_val; - - if (ie_type <= 0 || ie_type >= AST_EVENT_IE_TOTAL) { - return -1; - } - - if (!(ie_val = ast_calloc(1, sizeof(*ie_val)))) { - return -1; - } - - ie_val->ie_type = ie_type; - ie_val->ie_pltype = AST_EVENT_IE_PLTYPE_STR; - - if (!(ie_val->payload.str = ast_strdup(str))) { - ast_free(ie_val); - return -1; - } - - ie_val->payload.hash = ast_str_hash(str); - - AST_LIST_INSERT_TAIL(&sub->ie_vals, ie_val, entry); - - return 0; -} - -int ast_event_sub_append_ie_raw(struct ast_event_sub *sub, - enum ast_event_ie_type ie_type, void *data, size_t raw_datalen) -{ - struct ast_event_ie_val *ie_val; - - if (ie_type <= 0 || ie_type >= AST_EVENT_IE_TOTAL) { - return -1; - } - - if (!(ie_val = ast_calloc(1, sizeof(*ie_val)))) { - return -1; - } - - ie_val->ie_type = ie_type; - ie_val->ie_pltype = AST_EVENT_IE_PLTYPE_RAW; - ie_val->raw_datalen = raw_datalen; - - if (!(ie_val->payload.raw = ast_malloc(raw_datalen))) { - ast_free(ie_val); - return -1; - } - - memcpy(ie_val->payload.raw, data, raw_datalen); - - AST_LIST_INSERT_TAIL(&sub->ie_vals, ie_val, entry); - - return 0; -} - -int ast_event_sub_activate(struct ast_event_sub *sub) -{ - if (ast_event_check_subscriber(AST_EVENT_SUB, - AST_EVENT_IE_EVENTTYPE, AST_EVENT_IE_PLTYPE_UINT, sub->type, - AST_EVENT_IE_END) != AST_EVENT_SUB_NONE) { - struct ast_event *event; - - event = gen_sub_event(sub); - if (event && ast_event_queue(event)) { - ast_event_destroy(event); - } - } - - AST_RWDLLIST_WRLOCK(&ast_event_subs[sub->type]); - AST_RWDLLIST_INSERT_TAIL(&ast_event_subs[sub->type], sub, entry); - AST_RWDLLIST_UNLOCK(&ast_event_subs[sub->type]); - - return 0; -} - -struct ast_event_sub *ast_event_subscribe(enum ast_event_type type, ast_event_cb_t cb, - const char *description, void *userdata, ...) -{ - va_list ap; - enum ast_event_ie_type ie_type; - struct ast_event_sub *sub; - - if (!(sub = ast_event_subscribe_new(type, cb, userdata))) { - return NULL; - } - - ast_copy_string(sub->description, description, sizeof(sub->description)); - - va_start(ap, userdata); - for (ie_type = va_arg(ap, enum ast_event_ie_type); - ie_type != AST_EVENT_IE_END; - ie_type = va_arg(ap, enum ast_event_ie_type)) - { - enum ast_event_ie_pltype ie_pltype; - - ie_pltype = va_arg(ap, enum ast_event_ie_pltype); - - switch (ie_pltype) { - case AST_EVENT_IE_PLTYPE_UNKNOWN: - break; - case AST_EVENT_IE_PLTYPE_UINT: - { - uint32_t unsigned_int = va_arg(ap, uint32_t); - ast_event_sub_append_ie_uint(sub, ie_type, unsigned_int); - break; - } - case AST_EVENT_IE_PLTYPE_STR: - { - const char *str = va_arg(ap, const char *); - ast_event_sub_append_ie_str(sub, ie_type, str); - break; - } - case AST_EVENT_IE_PLTYPE_RAW: - { - void *data = va_arg(ap, void *); - size_t data_len = va_arg(ap, size_t); - ast_event_sub_append_ie_raw(sub, ie_type, data, data_len); - break; - } - } - } - va_end(ap); - - ast_event_sub_activate(sub); - - return sub; -} - -void ast_event_sub_destroy(struct ast_event_sub *sub) -{ - struct ast_event_ie_val *ie_val; - - while ((ie_val = AST_LIST_REMOVE_HEAD(&sub->ie_vals, entry))) { - ast_event_ie_val_destroy(ie_val); - } - - ast_free(sub); -} - -struct ast_event_sub *ast_event_unsubscribe(struct ast_event_sub *sub) -{ - - AST_RWDLLIST_WRLOCK(&ast_event_subs[sub->type]); - AST_DLLIST_REMOVE(&ast_event_subs[sub->type], sub, entry); - AST_RWDLLIST_UNLOCK(&ast_event_subs[sub->type]); - - ast_event_sub_destroy(sub); - - return NULL; -} - int ast_event_iterator_init(struct ast_event_iterator *iterator, const struct ast_event *event) { int res = 0; @@ -770,11 +248,6 @@ static void *event_iterator_get_ie_raw(struct ast_event_iterator *iterator) return iterator->ie->ie_payload; } -static uint16_t event_iterator_get_ie_raw_payload_len(struct ast_event_iterator *iterator) -{ - return ntohs(iterator->ie->ie_payload_len); -} - enum ast_event_type ast_event_get_type(const struct ast_event *event) { return ntohs(event->type); @@ -789,15 +262,6 @@ uint32_t ast_event_get_ie_uint(const struct ast_event *event, enum ast_event_ie_ return ie_val ? ntohl(get_unaligned_uint32(ie_val)) : 0; } -static uint32_t event_get_ie_str_hash(const struct ast_event *event, enum ast_event_ie_type ie_type) -{ - const struct ast_event_ie_str_payload *str_payload; - - str_payload = event_get_ie_raw(event, ie_type); - - return str_payload ? str_payload->hash : 0; -} - const char *ast_event_get_ie_str(const struct ast_event *event, enum ast_event_ie_type ie_type) { const struct ast_event_ie_str_payload *str_payload; @@ -821,20 +285,6 @@ static const void *event_get_ie_raw(const struct ast_event *event, enum ast_even return NULL; } -static uint16_t event_get_ie_raw_payload_len(const struct ast_event *event, enum ast_event_ie_type ie_type) -{ - struct ast_event_iterator iterator; - int res; - - for (res = ast_event_iterator_init(&iterator, event); !res; res = ast_event_iterator_next(&iterator)) { - if (ast_event_iterator_get_ie_type(&iterator) == ie_type) { - return event_iterator_get_ie_raw_payload_len(&iterator); - } - } - - return 0; -} - int ast_event_append_ie_str(struct ast_event **event, enum ast_event_ie_type ie_type, const char *str) { @@ -974,111 +424,3 @@ void ast_event_destroy(struct ast_event *event) { ast_free(event); } - -static int handle_event(void *data) -{ - struct ast_event *event = data; - struct ast_event_sub *sub; - const enum ast_event_type event_types[] = { - ntohs(event->type), - AST_EVENT_ALL - }; - int i; - - for (i = 0; i < ARRAY_LEN(event_types); i++) { - AST_RWDLLIST_RDLOCK(&ast_event_subs[event_types[i]]); - AST_RWDLLIST_TRAVERSE(&ast_event_subs[event_types[i]], sub, entry) { - struct ast_event_ie_val *ie_val; - - AST_LIST_TRAVERSE(&sub->ie_vals, ie_val, entry) { - if (!match_ie_val(event, ie_val, NULL)) { - /* The current subscription ie did not match an event ie. */ - break; - } - } - if (ie_val) { - /* The event did not match this subscription. */ - continue; - } - sub->cb(event, sub->userdata); - } - AST_RWDLLIST_UNLOCK(&ast_event_subs[event_types[i]]); - } - - ast_event_destroy(event); - - return 0; -} - -int ast_event_queue(struct ast_event *event) -{ - uint16_t host_event_type; - int res; - - host_event_type = ntohs(event->type); - - /* Invalid type */ - if (host_event_type >= AST_EVENT_TOTAL) { - ast_log(LOG_WARNING, "Someone tried to queue an event of invalid " - "type '%d'!\n", host_event_type); - return -1; - } - - /* If nobody has subscribed to this event type, throw it away now */ - if (ast_event_check_subscriber(host_event_type, AST_EVENT_IE_END) - == AST_EVENT_SUB_NONE) { - ast_event_destroy(event); - return 0; - } - - res = ast_taskprocessor_push(event_dispatcher, handle_event, event); - if (res) { - ast_event_destroy(event); - } - return res; -} - -/*! \internal \brief Clean up resources on Asterisk shutdown */ -static void event_shutdown(void) -{ - struct ast_event_sub *sub; - int i; - - if (event_dispatcher) { - event_dispatcher = ast_taskprocessor_unreference(event_dispatcher); - } - - /* Remove any remaining subscriptions. Note that we can't just call - * unsubscribe, as it will attempt to lock the subscription list - * as well */ - for (i = 0; i < AST_EVENT_TOTAL; i++) { - AST_RWDLLIST_WRLOCK(&ast_event_subs[i]); - while ((sub = AST_RWDLLIST_REMOVE_HEAD(&ast_event_subs[i], entry))) { - ast_event_sub_destroy(sub); - } - AST_RWDLLIST_UNLOCK(&ast_event_subs[i]); - AST_RWDLLIST_HEAD_DESTROY(&ast_event_subs[i]); - } -} - -int ast_event_init(void) -{ - int i; - - for (i = 0; i < AST_EVENT_TOTAL; i++) { - AST_RWDLLIST_HEAD_INIT(&ast_event_subs[i]); - } - - if (!(event_dispatcher = ast_taskprocessor_get("core_event_dispatcher", 0))) { - goto event_init_cleanup; - } - - ast_register_atexit(event_shutdown); - - return 0; - -event_init_cleanup: - event_shutdown(); - return -1; -} - diff --git a/tests/test_cel.c b/tests/test_cel.c index 2bf4f29e5..0ad92f475 100644 --- a/tests/test_cel.c +++ b/tests/test_cel.c @@ -56,6 +56,8 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$") #define CHANNEL_TECH_NAME "CELTestChannel" +#define TEST_BACKEND_NAME "CEL Test Logging" + /*! \brief A placeholder for Asterisk's 'real' CEL configuration */ static struct ast_cel_general_config *saved_config; @@ -1544,9 +1546,6 @@ AST_TEST_DEFINE(test_cel_local_optimize) return AST_TEST_PASS; } -/*! Subscription for CEL events */ -static struct ast_event_sub *event_sub = NULL; - /*! Container for astobj2 duplicated ast_events */ static struct ao2_container *cel_received_events = NULL; @@ -1648,26 +1647,15 @@ static int append_expected_event( return append_expected_event_snapshot(snapshot, type, userdefevname, extra, peer); } -static void test_sub(const struct ast_event *event, void *data) +static void test_sub(struct ast_event *event) { struct ast_event *event_dup = ao2_dup_event(event); - const char *sync_tag; SCOPED_MUTEX(mid_test_lock, &mid_test_sync_lock); if (!event_dup) { return; } - sync_tag = ast_event_get_ie_str(event, AST_EVENT_IE_SERVICE); - if (sync_tag) { - if (!strcmp(sync_tag, "SYNC")) { - /* trigger things */ - SCOPED_MUTEX(lock, &sync_lock); - ast_cond_signal(&sync_out); - return; - } - } - /* save the event for later processing */ ao2_link(cel_received_events, event_dup); @@ -1690,7 +1678,6 @@ static void test_sub(const struct ast_event *event, void *data) */ static int test_cel_init_cb(struct ast_test_info *info, struct ast_test *test) { - ast_assert(event_sub == NULL); ast_assert(cel_received_events == NULL); ast_assert(cel_expected_events == NULL); @@ -1707,8 +1694,9 @@ static int test_cel_init_cb(struct ast_test_info *info, struct ast_test *test) cel_expected_events = ao2_container_alloc(1, NULL, NULL); /* start the CEL event callback */ - event_sub = ast_event_subscribe(AST_EVENT_CEL, test_sub, "CEL Test Logging", - NULL, AST_EVENT_IE_END); + if (ast_cel_backend_register(TEST_BACKEND_NAME, test_sub)) { + return -1; + } return 0; } @@ -1866,29 +1854,6 @@ static int check_events(struct ast_test *test, struct ao2_container *local_expec return 0; } -static struct ast_event *create_sync_event(void) -{ - struct ast_event *event_dup; - RAII_VAR(struct ast_event *, event, ao2_callback(cel_expected_events, 0, NULL, NULL), ao2_cleanup); - uint16_t event_len; - - if (!event) { - return NULL; - } - - event_len = ast_event_get_size(event); - - event_dup = ast_calloc(1, event_len); - if (!event_dup) { - return NULL; - } - - memcpy(event_dup, event, event_len); - ast_event_append_ie_str(&event_dup, AST_EVENT_IE_SERVICE, "SYNC"); - - return event_dup; -} - /*! * \internal * \brief Callback function called after each test executes. @@ -1900,35 +1865,15 @@ static struct ast_event *create_sync_event(void) */ static int cel_verify_and_cleanup_cb(struct ast_test_info *info, struct ast_test *test) { - struct ast_event *sync; RAII_VAR(struct ao2_container *, local_expected, cel_expected_events, ao2_cleanup); RAII_VAR(struct ao2_container *, local_received, cel_received_events, ao2_cleanup); - ast_assert(event_sub != NULL); ast_assert(cel_received_events != NULL); ast_assert(cel_expected_events != NULL); do_sleep(); - /* sync with the event system */ - sync = create_sync_event(); - ast_test_validate(test, sync != NULL); - if (ast_event_queue(sync)) { - ast_event_destroy(sync); - ast_test_validate(test, NULL); - } else { - struct timeval start = ast_tvnow(); - struct timespec end = { - .tv_sec = start.tv_sec + 15, - .tv_nsec = start.tv_usec * 1000 - }; - - SCOPED_MUTEX(lock, &sync_lock); - ast_cond_timedwait(&sync_out, &sync_lock, &end); - } - /* stop the CEL event callback and clean up storage structures*/ - ast_event_unsubscribe(event_sub); - event_sub = NULL; + ast_cel_backend_unregister(TEST_BACKEND_NAME); /* cleaned up by RAII_VAR's */ cel_expected_events = NULL; diff --git a/tests/test_event.c b/tests/test_event.c index 10282b5cc..a7279e585 100644 --- a/tests/test_event.c +++ b/tests/test_event.c @@ -25,7 +25,6 @@ * \ingroup tests * * \todo API Calls not yet touched by a test: XXX TODO - * - ast_event_report_subs() * - ast_event_get_ie_type_name() * - ast_event_get_ie_pltype() * - ast_event_iterator_init() @@ -194,555 +193,9 @@ struct event_sub_data { unsigned int count; }; -static void event_sub_cb(const struct ast_event *event, void *d) -{ - struct event_sub_data *data = d; - - data->count++; -} - -enum test_subs_class_type { - TEST_SUBS_ALL_STR, - TEST_SUBS_CUSTOM_STR, - TEST_SUBS_CUSTOM_RAW, - TEST_SUBS_CUSTOM_UINT, - TEST_SUBS_CUSTOM_EXISTS, - TEST_SUBS_CUSTOM_DYNAMIC, - TEST_SUBS_CUSTOM_ANY, - - /* Must be last. */ - TEST_SUBS_TOTAL, -}; - -/*! - * \internal - * \brief Convert enum test_subs_class_type to string. - * - * \param val Enum value to convert to string. - * - * \return String equivalent of enum value. - */ -static const char *test_subs_class_type_str(enum test_subs_class_type val) -{ - switch (val) { - case TEST_SUBS_ALL_STR: - return "TEST_SUBS_ALL_STR"; - case TEST_SUBS_CUSTOM_STR: - return "TEST_SUBS_CUSTOM_STR"; - case TEST_SUBS_CUSTOM_RAW: - return "TEST_SUBS_CUSTOM_RAW"; - case TEST_SUBS_CUSTOM_UINT: - return "TEST_SUBS_CUSTOM_UINT"; - case TEST_SUBS_CUSTOM_EXISTS: - return "TEST_SUBS_CUSTOM_EXISTS"; - case TEST_SUBS_CUSTOM_DYNAMIC: - return "TEST_SUBS_CUSTOM_DYNAMIC"; - case TEST_SUBS_CUSTOM_ANY: - return "TEST_SUBS_CUSTOM_ANY"; - case TEST_SUBS_TOTAL: - break; - } - return "Unknown"; -} - -/*! - * \internal - * \brief Test event subscriptions - * - * - Query for existing Subscriptions: - * - ast_event_check_subscriber() - */ -AST_TEST_DEFINE(event_sub_test) -{ - enum ast_test_result_state res = AST_TEST_PASS; - struct ast_event *event; - int i; - enum ast_event_subscriber_res sub_res; - struct { - struct ast_event_sub *sub; - struct event_sub_data data; - const unsigned int expected_count; - } test_subs[TEST_SUBS_TOTAL] = { - [TEST_SUBS_ALL_STR] = { - .expected_count = 2, - }, - [TEST_SUBS_CUSTOM_STR] = { - .expected_count = 2, - }, - [TEST_SUBS_CUSTOM_RAW] = { - .expected_count = 2, - }, - [TEST_SUBS_CUSTOM_UINT] = { - .expected_count = 1, - }, - [TEST_SUBS_CUSTOM_EXISTS] = { - .expected_count = 2, - }, - [TEST_SUBS_CUSTOM_DYNAMIC] = { - .expected_count = 1, - }, - [TEST_SUBS_CUSTOM_ANY] = { - .expected_count = 5, - }, - }; - - switch (cmd) { - case TEST_INIT: - info->name = "ast_event_subscribe_test"; - info->category = "/main/event/"; - info->summary = "Test event subscriptions"; - info->description = - "This test exercises the API calls that allow subscriptions " - "to events."; - return AST_TEST_NOT_RUN; - case TEST_EXECUTE: - break; - } - - ast_test_status_update(test, "Check that NO CUSTOM subscribers exist\n"); - sub_res = ast_event_check_subscriber(AST_EVENT_CUSTOM, - AST_EVENT_IE_END); - if (sub_res != AST_EVENT_SUB_NONE) { - ast_test_status_update(test, "CUSTOM subscriptions should not exist! (%d)\n", - sub_res); - res = AST_TEST_FAIL; - } - - /* - * Subscription TEST_SUBS_CUSTOM_STR: - * - allocate normally - * - subscribe to CUSTOM events with a CEL_CIDNAME STR IE check - */ - ast_test_status_update(test, "Adding TEST_SUBS_CUSTOM_STR subscription\n"); - test_subs[TEST_SUBS_CUSTOM_STR].sub = ast_event_subscribe(AST_EVENT_CUSTOM, event_sub_cb, - test_subs_class_type_str(TEST_SUBS_CUSTOM_STR), &test_subs[TEST_SUBS_CUSTOM_STR].data, - AST_EVENT_IE_CEL_CIDNAME, AST_EVENT_IE_PLTYPE_STR, "FOO/bar", - AST_EVENT_IE_END); - if (!test_subs[TEST_SUBS_CUSTOM_STR].sub) { - ast_test_status_update(test, "Failed to create TEST_SUBS_CUSTOM_STR subscription\n"); - res = AST_TEST_FAIL; - goto return_cleanup; - } - - ast_test_status_update(test, "Check that a CUSTOM subscriber exists\n"); - sub_res = ast_event_check_subscriber(AST_EVENT_CUSTOM, - AST_EVENT_IE_END); - if (sub_res != AST_EVENT_SUB_EXISTS) { - ast_test_status_update(test, "A CUSTOM subscription should exist! (%d)\n", - sub_res); - res = AST_TEST_FAIL; - } - - /* - * Subscription TEST_SUBS_ALL_STR: - * - allocate normally - * - subscribe to ALL events with a CEL_CIDNAME STR IE check - */ - ast_test_status_update(test, "Adding TEST_SUBS_ALL_STR subscription\n"); - test_subs[TEST_SUBS_ALL_STR].sub = ast_event_subscribe(AST_EVENT_ALL, event_sub_cb, - test_subs_class_type_str(TEST_SUBS_ALL_STR), &test_subs[TEST_SUBS_ALL_STR].data, - AST_EVENT_IE_CEL_CIDNAME, AST_EVENT_IE_PLTYPE_STR, "FOO/bar", - AST_EVENT_IE_END); - if (!test_subs[TEST_SUBS_ALL_STR].sub) { - ast_test_status_update(test, "Failed to create TEST_SUBS_ALL_STR subscription\n"); - res = AST_TEST_FAIL; - goto return_cleanup; - } - - /* - * Subscription TEST_SUBS_CUSTOM_RAW: - * - allocate normally - * - subscribe to CUSTOM events with a CEL_USEREVENT_NAME RAW IE check - */ - ast_test_status_update(test, "Adding TEST_SUBS_CUSTOM_RAW subscription\n"); - test_subs[TEST_SUBS_CUSTOM_RAW].sub = ast_event_subscribe(AST_EVENT_CUSTOM, event_sub_cb, - test_subs_class_type_str(TEST_SUBS_CUSTOM_RAW), &test_subs[TEST_SUBS_CUSTOM_RAW].data, - AST_EVENT_IE_CEL_USEREVENT_NAME, AST_EVENT_IE_PLTYPE_RAW, "FOO/bar", sizeof("FOO/bar"), - AST_EVENT_IE_END); - if (!test_subs[TEST_SUBS_CUSTOM_RAW].sub) { - ast_test_status_update(test, "Failed to create TEST_SUBS_CUSTOM_RAW subscription\n"); - res = AST_TEST_FAIL; - goto return_cleanup; - } - - /* - * Subscription TEST_SUBS_CUSTOM_UINT: - * - allocate normally - * - subscribe to CUSTOM events with a CEL_AMAFLAGS UINT IE check - */ - ast_test_status_update(test, "Adding TEST_SUBS_CUSTOM_UINT subscription\n"); - test_subs[TEST_SUBS_CUSTOM_UINT].sub = ast_event_subscribe(AST_EVENT_CUSTOM, event_sub_cb, - test_subs_class_type_str(TEST_SUBS_CUSTOM_UINT), &test_subs[TEST_SUBS_CUSTOM_UINT].data, - AST_EVENT_IE_CEL_AMAFLAGS, AST_EVENT_IE_PLTYPE_UINT, 5, - AST_EVENT_IE_END); - if (!test_subs[TEST_SUBS_CUSTOM_UINT].sub) { - ast_test_status_update(test, "Failed to create TEST_SUBS_CUSTOM_UINT subscription\n"); - res = AST_TEST_FAIL; - goto return_cleanup; - } - - /* - * Subscription TEST_SUBS_CUSTOM_EXISTS: - * - allocate normally - * - subscribe to CUSTOM events with a CEL_AMAFLAGS UINT and UNIQUEID EXISTS IE check - */ - ast_test_status_update(test, "Adding TEST_SUBS_CUSTOM_EXISTS subscription\n"); - test_subs[TEST_SUBS_CUSTOM_EXISTS].sub = ast_event_subscribe(AST_EVENT_CUSTOM, event_sub_cb, - test_subs_class_type_str(TEST_SUBS_CUSTOM_EXISTS), &test_subs[TEST_SUBS_CUSTOM_EXISTS].data, - AST_EVENT_IE_CEL_AMAFLAGS, AST_EVENT_IE_PLTYPE_UINT, 4, - AST_EVENT_IE_END); - if (!test_subs[TEST_SUBS_CUSTOM_EXISTS].sub) { - ast_test_status_update(test, "Failed to create TEST_SUBS_CUSTOM_EXISTS subscription\n"); - res = AST_TEST_FAIL; - goto return_cleanup; - } - - /* For the sake of exercising destruction before activation */ - test_subs[TEST_SUBS_CUSTOM_DYNAMIC].sub = ast_event_subscribe_new(AST_EVENT_CUSTOM, - event_sub_cb, &test_subs[TEST_SUBS_CUSTOM_DYNAMIC].data); - if (!test_subs[TEST_SUBS_CUSTOM_DYNAMIC].sub) { - ast_test_status_update(test, "Failed to create TEST_SUBS_CUSTOM_DYNAMIC subscription\n"); - res = AST_TEST_FAIL; - goto return_cleanup; - } - ast_event_sub_destroy(test_subs[TEST_SUBS_CUSTOM_DYNAMIC].sub); - - /* - * Subscription TEST_SUBS_CUSTOM_DYNAMIC: - * - allocate dynamically - * - subscribe to all CUSTOM events - * - add IE checks for all types - */ - ast_test_status_update(test, "Adding TEST_SUBS_CUSTOM_DYNAMIC subscription\n"); - test_subs[TEST_SUBS_CUSTOM_DYNAMIC].sub = ast_event_subscribe_new(AST_EVENT_CUSTOM, - event_sub_cb, &test_subs[TEST_SUBS_CUSTOM_DYNAMIC].data); - if (!test_subs[TEST_SUBS_CUSTOM_DYNAMIC].sub) { - ast_test_status_update(test, "Failed to create TEST_SUBS_CUSTOM_DYNAMIC subscription\n"); - res = AST_TEST_FAIL; - goto return_cleanup; - } - - if (ast_event_sub_append_ie_uint(test_subs[TEST_SUBS_CUSTOM_DYNAMIC].sub, AST_EVENT_IE_CEL_AMAFLAGS, 4)) { - ast_event_sub_destroy(test_subs[TEST_SUBS_CUSTOM_DYNAMIC].sub); - test_subs[TEST_SUBS_CUSTOM_DYNAMIC].sub = NULL; - ast_test_status_update(test, "Failed to append UINT IE to TEST_SUBS_CUSTOM_DYNAMIC subscription\n"); - res = AST_TEST_FAIL; - goto return_cleanup; - } - - if (ast_event_sub_append_ie_str(test_subs[TEST_SUBS_CUSTOM_DYNAMIC].sub, AST_EVENT_IE_CEL_CIDNAME, "FOO/bar")) { - ast_event_sub_destroy(test_subs[TEST_SUBS_CUSTOM_DYNAMIC].sub); - test_subs[TEST_SUBS_CUSTOM_DYNAMIC].sub = NULL; - ast_test_status_update(test, "Failed to append STR IE to TEST_SUBS_CUSTOM_DYNAMIC subscription\n"); - res = AST_TEST_FAIL; - goto return_cleanup; - } - - if (ast_event_sub_append_ie_raw(test_subs[TEST_SUBS_CUSTOM_DYNAMIC].sub, AST_EVENT_IE_CEL_USEREVENT_NAME, "800 km", - strlen("800 km"))) { - ast_event_sub_destroy(test_subs[TEST_SUBS_CUSTOM_DYNAMIC].sub); - test_subs[TEST_SUBS_CUSTOM_DYNAMIC].sub = NULL; - ast_test_status_update(test, "Failed to append RAW IE to TEST_SUBS_CUSTOM_DYNAMIC subscription\n"); - res = AST_TEST_FAIL; - goto return_cleanup; - } - - if (ast_event_sub_activate(test_subs[TEST_SUBS_CUSTOM_DYNAMIC].sub)) { - ast_event_sub_destroy(test_subs[TEST_SUBS_CUSTOM_DYNAMIC].sub); - test_subs[TEST_SUBS_CUSTOM_DYNAMIC].sub = NULL; - ast_test_status_update(test, "Failed to activate TEST_SUBS_CUSTOM_DYNAMIC subscription\n"); - res = AST_TEST_FAIL; - goto return_cleanup; - } - - /* - * Exercise the API call to check for existing subscriptions. - */ - ast_test_status_update(test, "Checking for subscribers to specific events\n"); - - /* Check STR matching. */ - sub_res = ast_event_check_subscriber(AST_EVENT_CUSTOM, - AST_EVENT_IE_CEL_CIDNAME, AST_EVENT_IE_PLTYPE_STR, "FOO/bar", - AST_EVENT_IE_END); - if (sub_res != AST_EVENT_SUB_EXISTS) { - ast_test_status_update(test, "Str FOO/bar subscription did not exist\n"); - res = AST_TEST_FAIL; - } - - sub_res = ast_event_check_subscriber(AST_EVENT_CUSTOM, - AST_EVENT_IE_CEL_CIDNAME, AST_EVENT_IE_PLTYPE_STR, "Money", - AST_EVENT_IE_END); - if (sub_res != AST_EVENT_SUB_NONE) { - ast_test_status_update(test, "Str Money subscription should not exist! (%d)\n", - sub_res); - res = AST_TEST_FAIL; - } - - /* Check RAW matching. */ - sub_res = ast_event_check_subscriber(AST_EVENT_CUSTOM, - AST_EVENT_IE_CEL_USEREVENT_NAME, AST_EVENT_IE_PLTYPE_RAW, "FOO/bar", sizeof("FOO/bar"), - AST_EVENT_IE_END); - if (sub_res != AST_EVENT_SUB_EXISTS) { - ast_test_status_update(test, "Raw FOO/bar subscription did not exist\n"); - res = AST_TEST_FAIL; - } - - sub_res = ast_event_check_subscriber(AST_EVENT_CUSTOM, - AST_EVENT_IE_CEL_USEREVENT_NAME, AST_EVENT_IE_PLTYPE_RAW, "FOO/bar", sizeof("FOO/bar") - 1, - AST_EVENT_IE_END); - if (sub_res != AST_EVENT_SUB_NONE) { - ast_test_status_update(test, "Raw FOO/bar-1 subscription should not exist! (%d)\n", - sub_res); - res = AST_TEST_FAIL; - } - - sub_res = ast_event_check_subscriber(AST_EVENT_CUSTOM, - AST_EVENT_IE_CEL_USEREVENT_NAME, AST_EVENT_IE_PLTYPE_RAW, "Monkeys", sizeof("Monkeys"), - AST_EVENT_IE_END); - if (sub_res != AST_EVENT_SUB_NONE) { - ast_test_status_update(test, "Raw Monkeys subscription should not exist! (%d)\n", - sub_res); - res = AST_TEST_FAIL; - } - - /* Check UINT matching. */ - sub_res = ast_event_check_subscriber(AST_EVENT_CUSTOM, - AST_EVENT_IE_CEL_AMAFLAGS, AST_EVENT_IE_PLTYPE_UINT, 5, - AST_EVENT_IE_END); - if (sub_res != AST_EVENT_SUB_EXISTS) { - ast_test_status_update(test, "UINT=5 subscription did not exist\n"); - res = AST_TEST_FAIL; - } - - sub_res = ast_event_check_subscriber(AST_EVENT_CUSTOM, - AST_EVENT_IE_CEL_AMAFLAGS, AST_EVENT_IE_PLTYPE_UINT, 1, - AST_EVENT_IE_END); - if (sub_res != AST_EVENT_SUB_NONE) { - ast_test_status_update(test, "UINT=1 subscription should not exist! (%d)\n", - sub_res); - res = AST_TEST_FAIL; - } - - ast_test_status_update(test, "Special event posting test\n"); - - /* - * Event to check if event is even posted. - * - * Matching subscriptions: - * TEST_SUBS_CUSTOM_RAW - */ - event = ast_event_new(AST_EVENT_CUSTOM, - AST_EVENT_IE_CEL_CIDNAME, AST_EVENT_IE_PLTYPE_STR, "Mula", - AST_EVENT_IE_CEL_USEREVENT_NAME, AST_EVENT_IE_PLTYPE_RAW, "FOO/bar", sizeof("FOO/bar"), - AST_EVENT_IE_END); - if (!event) { - ast_test_status_update(test, "Failed to create event\n"); - res = AST_TEST_FAIL; - goto return_cleanup; - } - if (ast_event_queue(event)) { - ast_event_destroy(event); - event = NULL; - ast_test_status_update(test, "Failed to queue event\n"); - res = AST_TEST_FAIL; - goto return_cleanup; - } - - ast_test_status_update(test, "Sleeping a few seconds to allow event propagation...\n"); - sleep(3); - - /* - * Subscription TEST_SUBS_CUSTOM_ANY: - * - allocate normally - * - subscribe to all CUSTOM events - */ - ast_test_status_update(test, "Adding TEST_SUBS_CUSTOM_ANY subscription\n"); - test_subs[TEST_SUBS_CUSTOM_ANY].sub = ast_event_subscribe(AST_EVENT_CUSTOM, event_sub_cb, - test_subs_class_type_str(TEST_SUBS_CUSTOM_ANY), &test_subs[TEST_SUBS_CUSTOM_ANY].data, - AST_EVENT_IE_END); - if (!test_subs[TEST_SUBS_CUSTOM_ANY].sub) { - ast_test_status_update(test, "Failed to create TEST_SUBS_CUSTOM_ANY subscription\n"); - res = AST_TEST_FAIL; - goto return_cleanup; - } - - /* - * Fire off some events and track what was received in the callback - */ - ast_test_status_update(test, "Posting test events\n"); - - /* - * Event to check STR matching. - * - * Matching subscriptions: - * TEST_SUBS_ALL_STR - * TEST_SUBS_CUSTOM_STR - * TEST_SUBS_CUSTOM_ANY - */ - event = ast_event_new(AST_EVENT_CUSTOM, - AST_EVENT_IE_CEL_USEREVENT_NAME, AST_EVENT_IE_PLTYPE_RAW, "FOO/bar", sizeof("FOO/bar") - 1, - AST_EVENT_IE_CEL_CIDNAME, AST_EVENT_IE_PLTYPE_STR, "FOO/bar", - AST_EVENT_IE_END); - if (!event) { - ast_test_status_update(test, "Failed to create event\n"); - res = AST_TEST_FAIL; - goto return_cleanup; - } - if (ast_event_queue(event)) { - ast_event_destroy(event); - event = NULL; - ast_test_status_update(test, "Failed to queue event\n"); - res = AST_TEST_FAIL; - goto return_cleanup; - } - - /* - * Event to check RAW matching. - * - * Matching subscriptions: - * TEST_SUBS_CUSTOM_RAW - * TEST_SUBS_CUSTOM_ANY - */ - event = ast_event_new(AST_EVENT_CUSTOM, - AST_EVENT_IE_CEL_CIDNAME, AST_EVENT_IE_PLTYPE_STR, "Misery", - AST_EVENT_IE_CEL_USEREVENT_NAME, AST_EVENT_IE_PLTYPE_RAW, "FOO/bar", sizeof("FOO/bar"), - AST_EVENT_IE_END); - if (!event) { - ast_test_status_update(test, "Failed to create event\n"); - res = AST_TEST_FAIL; - goto return_cleanup; - } - if (ast_event_queue(event)) { - ast_event_destroy(event); - event = NULL; - ast_test_status_update(test, "Failed to queue event\n"); - res = AST_TEST_FAIL; - goto return_cleanup; - } - - /* - * Event to check UINT matching. - * - * Matching subscriptions: - * TEST_SUBS_CUSTOM_UINT - * TEST_SUBS_CUSTOM_ANY - */ - event = ast_event_new(AST_EVENT_CUSTOM, - AST_EVENT_IE_CEL_AMAFLAGS, AST_EVENT_IE_PLTYPE_UINT, 5, - AST_EVENT_IE_END); - if (!event) { - ast_test_status_update(test, "Failed to create event\n"); - res = AST_TEST_FAIL; - goto return_cleanup; - } - if (ast_event_queue(event)) { - ast_event_destroy(event); - event = NULL; - ast_test_status_update(test, "Failed to queue event\n"); - res = AST_TEST_FAIL; - goto return_cleanup; - } - - /* - * Event to check EXISTS matching. - * - * Matching subscriptions: - * TEST_SUBS_CUSTOM_EXISTS - * TEST_SUBS_CUSTOM_ANY - */ - event = ast_event_new(AST_EVENT_CUSTOM, - AST_EVENT_IE_CEL_AMAFLAGS, AST_EVENT_IE_PLTYPE_UINT, 4, - AST_EVENT_IE_UNIQUEID, AST_EVENT_IE_PLTYPE_UINT, 4, - AST_EVENT_IE_END); - if (!event) { - ast_test_status_update(test, "Failed to create event\n"); - res = AST_TEST_FAIL; - goto return_cleanup; - } - if (ast_event_queue(event)) { - ast_event_destroy(event); - event = NULL; - ast_test_status_update(test, "Failed to queue event\n"); - res = AST_TEST_FAIL; - goto return_cleanup; - } - - /* - * Event to get dynamic subscription to have an event. - * - * Matching subscriptions: - * TEST_SUBS_CUSTOM_DYNAMIC - * TEST_SUBS_CUSTOM_EXISTS - * TEST_SUBS_ALL_STR - * TEST_SUBS_CUSTOM_STR - * TEST_SUBS_CUSTOM_ANY - */ - event = ast_event_new(AST_EVENT_CUSTOM, - AST_EVENT_IE_CEL_AMAFLAGS, AST_EVENT_IE_PLTYPE_UINT, 4, - AST_EVENT_IE_UNIQUEID, AST_EVENT_IE_PLTYPE_UINT, 5, - AST_EVENT_IE_CEL_USEREVENT_NAME, AST_EVENT_IE_PLTYPE_RAW, "800 km", strlen("800 km"), - AST_EVENT_IE_CEL_CIDNAME, AST_EVENT_IE_PLTYPE_STR, "FOO/bar", - AST_EVENT_IE_CEL_EVENT_TIME_USEC, AST_EVENT_IE_PLTYPE_UINT, 5, - AST_EVENT_IE_END); - if (!event) { - ast_test_status_update(test, "Failed to create event\n"); - res = AST_TEST_FAIL; - goto return_cleanup; - } - if (ast_event_queue(event)) { - ast_event_destroy(event); - event = NULL; - ast_test_status_update(test, "Failed to queue event\n"); - res = AST_TEST_FAIL; - goto return_cleanup; - } - - event = NULL; - - /* - * Check the results of the test. - * - * First of all, event distribution is asynchronous from the event producer, - * so knowing when to continue from here and check results is an instance of - * the halting problem. A few seconds really should be more than enough time. - * If something was actually blocking event distribution that long, I would call - * it a bug. - * - * See test_subs[] initialization for expected results. - */ - - ast_test_status_update(test, "Sleeping a few seconds to allow event propagation...\n"); - sleep(3); - - for (i = 0; i < ARRAY_LEN(test_subs); i++) { - if (!test_subs[i].sub) { - ast_test_status_update(test, "Missing a test subscription for %s\n", - test_subs_class_type_str(i)); - res = AST_TEST_FAIL; - } - if (test_subs[i].data.count != test_subs[i].expected_count) { - ast_test_status_update(test, - "Unexpected callback count, got %u expected %u for %s\n", - test_subs[i].data.count, test_subs[i].expected_count, - test_subs_class_type_str(i)); - res = AST_TEST_FAIL; - } - } - -return_cleanup: - for (i = 0; i < ARRAY_LEN(test_subs); i++) { - if (test_subs[i].sub) { - test_subs[i].sub = ast_event_unsubscribe(test_subs[i].sub); - } - } - - return res; -} - static int unload_module(void) { AST_TEST_UNREGISTER(event_new_test); - AST_TEST_UNREGISTER(event_sub_test); return 0; } @@ -750,7 +203,6 @@ static int unload_module(void) static int load_module(void) { AST_TEST_REGISTER(event_new_test); - AST_TEST_REGISTER(event_sub_test); return AST_MODULE_LOAD_SUCCESS; } |