00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039 #include "asterisk.h"
00040
00041 ASTERISK_FILE_VERSION(__FILE__, "$Revision: 284597 $");
00042
00043 #include <stdlib.h>
00044 #include <stdio.h>
00045 #include <string.h>
00046 #include <unistd.h>
00047 #include <errno.h>
00048 #include <signal.h>
00049 #include <pthread.h>
00050
00051 #include "ais/ais.h"
00052
00053 #include "asterisk/module.h"
00054 #include "asterisk/options.h"
00055 #include "asterisk/logger.h"
00056 #include "asterisk/channel.h"
00057 #include "asterisk/utils.h"
00058 #include "asterisk/cli.h"
00059
00060 static struct {
00061 pthread_t id;
00062 unsigned int stop:1;
00063 } dispatch_thread = {
00064 .id = AST_PTHREADT_NULL,
00065 };
00066
00067 SaVersionT ais_version = { 'B', 1, 1 };
00068
00069 static const struct ais_error {
00070 SaAisErrorT error;
00071 const char *desc;
00072 } ais_errors[] = {
00073 { SA_AIS_OK, "OK" },
00074 { SA_AIS_ERR_LIBRARY, "Library Error" },
00075 { SA_AIS_ERR_VERSION, "Version Not Compatible" },
00076 { SA_AIS_ERR_INIT, "Callback Not Registered" },
00077 { SA_AIS_ERR_TIMEOUT, "Timeout" },
00078 { SA_AIS_ERR_TRY_AGAIN , "Try Again" },
00079 { SA_AIS_ERR_INVALID_PARAM, "Invalid Parameter" },
00080 { SA_AIS_ERR_NO_MEMORY, "No Memory" },
00081 { SA_AIS_ERR_BAD_HANDLE, "Invalid Handle" },
00082 { SA_AIS_ERR_BUSY, "Resource Already In Use" },
00083 { SA_AIS_ERR_ACCESS, "Access Denied" },
00084 { SA_AIS_ERR_NOT_EXIST, "Does Not Exist" },
00085 { SA_AIS_ERR_NAME_TOO_LONG, "Name Too Long" },
00086 { SA_AIS_ERR_EXIST, "Already Exists" },
00087 { SA_AIS_ERR_NO_SPACE, "Buffer Too Small" },
00088 { SA_AIS_ERR_INTERRUPT, "Request Interrupted" },
00089 { SA_AIS_ERR_NAME_NOT_FOUND, "Name Not Found" },
00090 { SA_AIS_ERR_NO_RESOURCES, "Not Enough Resources" },
00091 { SA_AIS_ERR_NOT_SUPPORTED, "Requested Function Not Supported" },
00092 { SA_AIS_ERR_BAD_OPERATION, "Operation Not Allowed" },
00093 { SA_AIS_ERR_FAILED_OPERATION, "Operation Failed" },
00094 { SA_AIS_ERR_MESSAGE_ERROR, "Communication Error" },
00095 { SA_AIS_ERR_QUEUE_FULL, "Destination Queue Full" },
00096 { SA_AIS_ERR_QUEUE_NOT_AVAILABLE, "Destination Queue Not Available" },
00097 { SA_AIS_ERR_BAD_FLAGS, "Invalid Flags" },
00098 { SA_AIS_ERR_TOO_BIG, "Value Too Large" },
00099 { SA_AIS_ERR_NO_SECTIONS, "No More Sections to Initialize" },
00100 };
00101
00102 const char *ais_err2str(SaAisErrorT error)
00103 {
00104 int x;
00105
00106 for (x = 0; x < ARRAY_LEN(ais_errors); x++) {
00107 if (ais_errors[x].error == error)
00108 return ais_errors[x].desc;
00109 }
00110
00111 return "Unknown";
00112 }
00113
00114 static void *dispatch_thread_handler(void *data)
00115 {
00116 SaSelectionObjectT clm_fd, evt_fd;
00117 int res;
00118 struct pollfd pfd[2] = { { .events = POLLIN, }, { .events = POLLIN, } };
00119 SaAisErrorT ais_res;
00120
00121 ais_res = saClmSelectionObjectGet(clm_handle, &clm_fd);
00122 if (ais_res != SA_AIS_OK) {
00123 ast_log(LOG_ERROR, "Failed to retrieve select fd for CLM service. "
00124 "This module will not operate.\n");
00125 return NULL;
00126 }
00127
00128 ais_res = saEvtSelectionObjectGet(evt_handle, &evt_fd);
00129 if (ais_res != SA_AIS_OK) {
00130 ast_log(LOG_ERROR, "Failed to retrieve select fd for EVT service. "
00131 "This module will not operate.\n");
00132 return NULL;
00133 }
00134
00135 pfd[0].fd = clm_fd;
00136 pfd[1].fd = evt_fd;
00137
00138 while (!dispatch_thread.stop) {
00139 pfd[0].revents = 0;
00140 pfd[1].revents = 0;
00141
00142 res = ast_poll(pfd, 2, -1);
00143 if (res == -1 && errno != EINTR && errno != EAGAIN) {
00144 ast_log(LOG_ERROR, "Select error (%s) dispatch thread going away now, "
00145 "and the module will no longer operate.\n", strerror(errno));
00146 break;
00147 }
00148
00149 if (pfd[0].revents & POLLIN) {
00150 saClmDispatch(clm_handle, SA_DISPATCH_ALL);
00151 }
00152 if (pfd[1].revents & POLLIN) {
00153 saEvtDispatch(evt_handle, SA_DISPATCH_ALL);
00154 }
00155 }
00156
00157 return NULL;
00158 }
00159
00160 static int load_module(void)
00161 {
00162 if (ast_ais_clm_load_module())
00163 goto return_error;
00164
00165 if (ast_ais_evt_load_module())
00166 goto evt_failed;
00167
00168 if (ast_pthread_create_background(&dispatch_thread.id, NULL,
00169 dispatch_thread_handler, NULL)) {
00170 ast_log(LOG_ERROR, "Error starting AIS dispatch thread.\n");
00171 goto dispatch_failed;
00172 }
00173
00174 return AST_MODULE_LOAD_SUCCESS;
00175
00176 dispatch_failed:
00177 ast_ais_evt_unload_module();
00178 evt_failed:
00179 ast_ais_clm_unload_module();
00180 return_error:
00181 return AST_MODULE_LOAD_DECLINE;
00182 }
00183
00184 static int unload_module(void)
00185 {
00186 ast_ais_clm_unload_module();
00187 ast_ais_evt_unload_module();
00188
00189 if (dispatch_thread.id != AST_PTHREADT_NULL) {
00190 dispatch_thread.stop = 1;
00191 pthread_kill(dispatch_thread.id, SIGURG);
00192 pthread_join(dispatch_thread.id, NULL);
00193 }
00194
00195 return 0;
00196 }
00197
00198 AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "SAForum AIS");