mark this revision as merged manually
[asterisk/asterisk.git] / res / res_ais.c
1 /*
2  * Asterisk -- An open source telephony toolkit.
3  *
4  * Copyright (C) 2007 - 2008, Digium, Inc.
5  *
6  * Russell Bryant <russell@digium.com>
7  *
8  * See http://www.asterisk.org for more information about
9  * the Asterisk project. Please do not directly contact
10  * any of the maintainers of this project for assistance;
11  * the project provides a web site, mailing lists and IRC
12  * channels for your use.
13  *
14  * This program is free software, distributed under the terms of
15  * the GNU General Public License Version 2. See the LICENSE file
16  * at the top of the source tree.
17  */
18
19 /*! 
20  * \file
21  * \author Russell Bryant <russell@digium.com>
22  *
23  * \brief Usage of the SAForum AIS (Application Interface Specification)
24  *
25  * \arg http://www.openais.org/
26  *
27  * This file contains the common code between the uses of the different AIS
28  * services.
29  */
30
31 /*** MODULEINFO
32         <depend>ais</depend>
33  ***/
34
35 #include "asterisk.h"
36
37 ASTERISK_FILE_VERSION(__FILE__, "$Revision$");
38
39 #include <stdlib.h>
40 #include <stdio.h>
41 #include <string.h>
42 #include <unistd.h>
43 #include <errno.h>
44 #include <signal.h>
45 #include <pthread.h>
46
47 #include "ais/ais.h"
48
49 #include "asterisk/module.h"
50 #include "asterisk/options.h"
51 #include "asterisk/logger.h"
52 #include "asterisk/channel.h"
53 #include "asterisk/utils.h"
54 #include "asterisk/cli.h"
55
56 static struct {
57         pthread_t id;
58         unsigned int stop:1;
59 } dispatch_thread = {
60         .id = AST_PTHREADT_NULL,
61 };
62
63 SaVersionT ais_version = { 'B', 1, 1 };
64
65 static const struct ais_error {
66         SaAisErrorT error;
67         const char *desc;
68 } ais_errors[] = {
69         { SA_AIS_OK, "OK" },
70         { SA_AIS_ERR_LIBRARY, "Library Error" },
71         { SA_AIS_ERR_VERSION, "Version Not Compatible" },
72         { SA_AIS_ERR_INIT, "Callback Not Registered" },
73         { SA_AIS_ERR_TIMEOUT, "Timeout" },
74         { SA_AIS_ERR_TRY_AGAIN , "Try Again" },
75         { SA_AIS_ERR_INVALID_PARAM, "Invalid Parameter" },
76         { SA_AIS_ERR_NO_MEMORY, "No Memory" },
77         { SA_AIS_ERR_BAD_HANDLE, "Invalid Handle" },
78         { SA_AIS_ERR_BUSY, "Resource Already In Use" },
79         { SA_AIS_ERR_ACCESS, "Access Denied" },
80         { SA_AIS_ERR_NOT_EXIST, "Does Not Exist" },
81         { SA_AIS_ERR_NAME_TOO_LONG, "Name Too Long" },
82         { SA_AIS_ERR_EXIST, "Already Exists" },
83         { SA_AIS_ERR_NO_SPACE, "Buffer Too Small" },
84         { SA_AIS_ERR_INTERRUPT, "Request Interrupted" },
85         { SA_AIS_ERR_NAME_NOT_FOUND, "Name Not Found" },
86         { SA_AIS_ERR_NO_RESOURCES, "Not Enough Resources" },
87         { SA_AIS_ERR_NOT_SUPPORTED, "Requested Function Not Supported" },
88         { SA_AIS_ERR_BAD_OPERATION, "Operation Not Allowed" },
89         { SA_AIS_ERR_FAILED_OPERATION, "Operation Failed" },
90         { SA_AIS_ERR_MESSAGE_ERROR, "Communication Error" },
91         { SA_AIS_ERR_QUEUE_FULL, "Destination Queue Full" },
92         { SA_AIS_ERR_QUEUE_NOT_AVAILABLE, "Destination Queue Not Available" },
93         { SA_AIS_ERR_BAD_FLAGS, "Invalid Flags" },
94         { SA_AIS_ERR_TOO_BIG, "Value Too Large" },
95         { SA_AIS_ERR_NO_SECTIONS, "No More Sections to Initialize" },
96 };
97
98 const char *ais_err2str(SaAisErrorT error)
99 {
100         int x;
101
102         for (x = 0; x < ARRAY_LEN(ais_errors); x++) {
103                 if (ais_errors[x].error == error)
104                         return ais_errors[x].desc;
105         }
106
107         return "Unknown";
108 }
109
110 static void *dispatch_thread_handler(void *data)
111 {
112         SaSelectionObjectT clm_fd, evt_fd, max_fd;
113         int res;
114         fd_set read_fds;
115         SaAisErrorT ais_res;
116
117         ais_res = saClmSelectionObjectGet(clm_handle, &clm_fd);
118         if (ais_res != SA_AIS_OK) {
119                 ast_log(LOG_ERROR, "Failed to retrieve select fd for CLM service.  "
120                         "This module will not operate.\n");
121                 return NULL;
122         }
123
124         ais_res = saEvtSelectionObjectGet(evt_handle, &evt_fd);
125         if (ais_res != SA_AIS_OK) {
126                 ast_log(LOG_ERROR, "Failed to retrieve select fd for EVT service.  "
127                         "This module will not operate.\n");
128                 return NULL;
129         }
130
131         max_fd = clm_fd > evt_fd ? clm_fd : evt_fd;
132
133         while (!dispatch_thread.stop) {
134                 FD_ZERO(&read_fds);
135                 FD_SET(clm_fd,  &read_fds);
136                 FD_SET(evt_fd,  &read_fds);
137
138                 res = ast_select(max_fd + 1, &read_fds, NULL, NULL, NULL);
139                 if (res == -1 && errno != EINTR && errno != EAGAIN) {
140                         ast_log(LOG_ERROR, "Select error (%s) dispatch thread going away now, "
141                                 "and the module will no longer operate.\n", strerror(errno));
142                         break;
143                 }
144
145                 if (FD_ISSET(clm_fd,  &read_fds))
146                         saClmDispatch(clm_handle,   SA_DISPATCH_ALL);
147                 if (FD_ISSET(evt_fd,  &read_fds))
148                         saEvtDispatch(evt_handle,   SA_DISPATCH_ALL);
149         }
150
151         return NULL;
152 }
153
154 static int load_module(void)
155 {
156         if (ast_ais_clm_load_module())
157                 goto return_error;
158
159         if (ast_ais_evt_load_module())
160                 goto evt_failed;
161
162         if (ast_pthread_create_background(&dispatch_thread.id, NULL, 
163                 dispatch_thread_handler, NULL)) {
164                 ast_log(LOG_ERROR, "Error starting AIS dispatch thread.\n");
165                 goto dispatch_failed;
166         }
167
168         return AST_MODULE_LOAD_SUCCESS;
169
170 dispatch_failed:
171         ast_ais_evt_unload_module();
172 evt_failed:
173         ast_ais_clm_unload_module();
174 return_error:
175         return AST_MODULE_LOAD_DECLINE;
176 }
177
178 static int unload_module(void)
179 {
180         ast_ais_clm_unload_module();
181         ast_ais_evt_unload_module();
182
183         if (dispatch_thread.id != AST_PTHREADT_NULL) {
184                 dispatch_thread.stop = 1;
185                 pthread_kill(dispatch_thread.id, SIGURG); /* poke! */
186                 pthread_join(dispatch_thread.id, NULL);
187         }
188
189         return 0;
190 }
191
192 AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "SAForum AIS");