diff options
Diffstat (limited to 'res/res_ais.c')
-rw-r--r-- | res/res_ais.c | 193 |
1 files changed, 193 insertions, 0 deletions
diff --git a/res/res_ais.c b/res/res_ais.c new file mode 100644 index 000000000..884eb0d23 --- /dev/null +++ b/res/res_ais.c @@ -0,0 +1,193 @@ +/* + * Asterisk -- An open source telephony toolkit. + * + * Copyright (C) 2007 - 2008, Digium, Inc. + * + * Russell Bryant <russell@digium.com> + * + * See http://www.asterisk.org for more information about + * the Asterisk project. Please do not directly contact + * any of the maintainers of this project for assistance; + * the project provides a web site, mailing lists and IRC + * channels for your use. + * + * This program is free software, distributed under the terms of + * the GNU General Public License Version 2. See the LICENSE file + * at the top of the source tree. + */ + +/*! + * \file + * \author Russell Bryant <russell@digium.com> + * + * \brief Usage of the SAForum AIS (Application Interface Specification) + * + * \arg http://www.openais.org/ + * + * This file contains the common code between the uses of the different AIS + * services. + */ + +/*** MODULEINFO + <depend>SaClm</depend> + <depend>SaEvt</depend> + ***/ + +#include "asterisk.h" + +ASTERISK_FILE_VERSION(__FILE__, "$Revision$"); + +#include <stdlib.h> +#include <stdio.h> +#include <string.h> +#include <unistd.h> +#include <errno.h> +#include <signal.h> +#include <pthread.h> + +#include "ais/ais.h" + +#include "asterisk/module.h" +#include "asterisk/options.h" +#include "asterisk/logger.h" +#include "asterisk/channel.h" +#include "asterisk/utils.h" +#include "asterisk/cli.h" + +static struct { + pthread_t id; + unsigned int stop:1; +} dispatch_thread = { + .id = AST_PTHREADT_NULL, +}; + +SaVersionT ais_version = { 'B', 1, 1 }; + +static const struct ais_error { + SaAisErrorT error; + const char *desc; +} ais_errors[] = { + { SA_AIS_OK, "OK" }, + { SA_AIS_ERR_LIBRARY, "Library Error" }, + { SA_AIS_ERR_VERSION, "Version Not Compatible" }, + { SA_AIS_ERR_INIT, "Callback Not Registered" }, + { SA_AIS_ERR_TIMEOUT, "Timeout" }, + { SA_AIS_ERR_TRY_AGAIN , "Try Again" }, + { SA_AIS_ERR_INVALID_PARAM, "Invalid Parameter" }, + { SA_AIS_ERR_NO_MEMORY, "No Memory" }, + { SA_AIS_ERR_BAD_HANDLE, "Invalid Handle" }, + { SA_AIS_ERR_BUSY, "Resource Already In Use" }, + { SA_AIS_ERR_ACCESS, "Access Denied" }, + { SA_AIS_ERR_NOT_EXIST, "Does Not Exist" }, + { SA_AIS_ERR_NAME_TOO_LONG, "Name Too Long" }, + { SA_AIS_ERR_EXIST, "Already Exists" }, + { SA_AIS_ERR_NO_SPACE, "Buffer Too Small" }, + { SA_AIS_ERR_INTERRUPT, "Request Interrupted" }, + { SA_AIS_ERR_NAME_NOT_FOUND, "Name Not Found" }, + { SA_AIS_ERR_NO_RESOURCES, "Not Enough Resources" }, + { SA_AIS_ERR_NOT_SUPPORTED, "Requested Function Not Supported" }, + { SA_AIS_ERR_BAD_OPERATION, "Operation Not Allowed" }, + { SA_AIS_ERR_FAILED_OPERATION, "Operation Failed" }, + { SA_AIS_ERR_MESSAGE_ERROR, "Communication Error" }, + { SA_AIS_ERR_QUEUE_FULL, "Destination Queue Full" }, + { SA_AIS_ERR_QUEUE_NOT_AVAILABLE, "Destination Queue Not Available" }, + { SA_AIS_ERR_BAD_FLAGS, "Invalid Flags" }, + { SA_AIS_ERR_TOO_BIG, "Value Too Large" }, + { SA_AIS_ERR_NO_SECTIONS, "No More Sections to Initialize" }, +}; + +const char *ais_err2str(SaAisErrorT error) +{ + int x; + + for (x = 0; x < ARRAY_LEN(ais_errors); x++) { + if (ais_errors[x].error == error) + return ais_errors[x].desc; + } + + return "Unknown"; +} + +static void *dispatch_thread_handler(void *data) +{ + SaSelectionObjectT clm_fd, evt_fd, max_fd; + int res; + fd_set read_fds; + SaAisErrorT ais_res; + + ais_res = saClmSelectionObjectGet(clm_handle, &clm_fd); + if (ais_res != SA_AIS_OK) { + ast_log(LOG_ERROR, "Failed to retrieve select fd for CLM service. " + "This module will not operate.\n"); + return NULL; + } + + ais_res = saEvtSelectionObjectGet(evt_handle, &evt_fd); + if (ais_res != SA_AIS_OK) { + ast_log(LOG_ERROR, "Failed to retrieve select fd for EVT service. " + "This module will not operate.\n"); + return NULL; + } + + max_fd = clm_fd > evt_fd ? clm_fd : evt_fd; + + while (!dispatch_thread.stop) { + FD_ZERO(&read_fds); + FD_SET(clm_fd, &read_fds); + FD_SET(evt_fd, &read_fds); + + res = ast_select(max_fd + 1, &read_fds, NULL, NULL, NULL); + if (res == -1 && errno != EINTR && errno != EAGAIN) { + ast_log(LOG_ERROR, "Select error (%s) dispatch thread going away now, " + "and the module will no longer operate.\n", strerror(errno)); + break; + } + + if (FD_ISSET(clm_fd, &read_fds)) + saClmDispatch(clm_handle, SA_DISPATCH_ALL); + if (FD_ISSET(evt_fd, &read_fds)) + saEvtDispatch(evt_handle, SA_DISPATCH_ALL); + } + + return NULL; +} + +static int load_module(void) +{ + if (ast_ais_clm_load_module()) + goto return_error; + + if (ast_ais_evt_load_module()) + goto evt_failed; + + if (ast_pthread_create_background(&dispatch_thread.id, NULL, + dispatch_thread_handler, NULL)) { + ast_log(LOG_ERROR, "Error starting AIS dispatch thread.\n"); + goto dispatch_failed; + } + + return AST_MODULE_LOAD_SUCCESS; + +dispatch_failed: + ast_ais_evt_unload_module(); +evt_failed: + ast_ais_clm_unload_module(); +return_error: + return AST_MODULE_LOAD_DECLINE; +} + +static int unload_module(void) +{ + ast_ais_clm_unload_module(); + ast_ais_evt_unload_module(); + + if (dispatch_thread.id != AST_PTHREADT_NULL) { + dispatch_thread.stop = 1; + pthread_kill(dispatch_thread.id, SIGURG); /* poke! */ + pthread_join(dispatch_thread.id, NULL); + } + + return 0; +} + +AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "SAForum AIS"); |