Media Project Phase2: SILK 8khz-24khz, SLINEAR 8khz-192khz, SPEEX 32khz, hd audio...
[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  * \note This module is still considered experimental, as it exposes the
31  * internal binary format of events between Asterisk servers over a network.
32  * However, this format is still subject to change between 1.6.X releases.
33  */
34
35 /*** MODULEINFO
36         <depend>ais</depend>
37  ***/
38
39 #include "asterisk.h"
40
41 ASTERISK_FILE_VERSION(__FILE__, "$Revision$");
42
43 #include <stdlib.h>
44 #include <stdio.h>
45 #include <string.h>
46 #include <unistd.h>
47 #include <errno.h>
48 #include <signal.h>
49 #include <pthread.h>
50
51 #include "ais/ais.h"
52
53 #include "asterisk/module.h"
54 #include "asterisk/options.h"
55 #include "asterisk/logger.h"
56 #include "asterisk/channel.h"
57 #include "asterisk/utils.h"
58 #include "asterisk/cli.h"
59
60 static struct {
61         pthread_t id;
62         unsigned int stop:1;
63 } dispatch_thread = {
64         .id = AST_PTHREADT_NULL,
65 };
66
67 SaVersionT ais_version = { 'B', 1, 1 };
68
69 static const struct ais_error {
70         SaAisErrorT error;
71         const char *desc;
72 } ais_errors[] = {
73         { SA_AIS_OK, "OK" },
74         { SA_AIS_ERR_LIBRARY, "Library Error" },
75         { SA_AIS_ERR_VERSION, "Version Not Compatible" },
76         { SA_AIS_ERR_INIT, "Callback Not Registered" },
77         { SA_AIS_ERR_TIMEOUT, "Timeout" },
78         { SA_AIS_ERR_TRY_AGAIN , "Try Again" },
79         { SA_AIS_ERR_INVALID_PARAM, "Invalid Parameter" },
80         { SA_AIS_ERR_NO_MEMORY, "No Memory" },
81         { SA_AIS_ERR_BAD_HANDLE, "Invalid Handle" },
82         { SA_AIS_ERR_BUSY, "Resource Already In Use" },
83         { SA_AIS_ERR_ACCESS, "Access Denied" },
84         { SA_AIS_ERR_NOT_EXIST, "Does Not Exist" },
85         { SA_AIS_ERR_NAME_TOO_LONG, "Name Too Long" },
86         { SA_AIS_ERR_EXIST, "Already Exists" },
87         { SA_AIS_ERR_NO_SPACE, "Buffer Too Small" },
88         { SA_AIS_ERR_INTERRUPT, "Request Interrupted" },
89         { SA_AIS_ERR_NAME_NOT_FOUND, "Name Not Found" },
90         { SA_AIS_ERR_NO_RESOURCES, "Not Enough Resources" },
91         { SA_AIS_ERR_NOT_SUPPORTED, "Requested Function Not Supported" },
92         { SA_AIS_ERR_BAD_OPERATION, "Operation Not Allowed" },
93         { SA_AIS_ERR_FAILED_OPERATION, "Operation Failed" },
94         { SA_AIS_ERR_MESSAGE_ERROR, "Communication Error" },
95         { SA_AIS_ERR_QUEUE_FULL, "Destination Queue Full" },
96         { SA_AIS_ERR_QUEUE_NOT_AVAILABLE, "Destination Queue Not Available" },
97         { SA_AIS_ERR_BAD_FLAGS, "Invalid Flags" },
98         { SA_AIS_ERR_TOO_BIG, "Value Too Large" },
99         { SA_AIS_ERR_NO_SECTIONS, "No More Sections to Initialize" },
100 };
101
102 const char *ais_err2str(SaAisErrorT error)
103 {
104         int x;
105
106         for (x = 0; x < ARRAY_LEN(ais_errors); x++) {
107                 if (ais_errors[x].error == error)
108                         return ais_errors[x].desc;
109         }
110
111         return "Unknown";
112 }
113
114 static void *dispatch_thread_handler(void *data)
115 {
116         SaSelectionObjectT clm_fd, evt_fd;
117         int res;
118         struct pollfd pfd[2] = { { .events = POLLIN, }, { .events = POLLIN, } };
119         SaAisErrorT ais_res;
120
121         ais_res = saClmSelectionObjectGet(clm_handle, &clm_fd);
122         if (ais_res != SA_AIS_OK) {
123                 ast_log(LOG_ERROR, "Failed to retrieve select fd for CLM service.  "
124                         "This module will not operate.\n");
125                 return NULL;
126         }
127
128         ais_res = saEvtSelectionObjectGet(evt_handle, &evt_fd);
129         if (ais_res != SA_AIS_OK) {
130                 ast_log(LOG_ERROR, "Failed to retrieve select fd for EVT service.  "
131                         "This module will not operate.\n");
132                 return NULL;
133         }
134
135         pfd[0].fd = clm_fd;
136         pfd[1].fd = evt_fd;
137
138         while (!dispatch_thread.stop) {
139                 pfd[0].revents = 0;
140                 pfd[1].revents = 0;
141
142                 res = ast_poll(pfd, 2, -1);
143                 if (res == -1 && errno != EINTR && errno != EAGAIN) {
144                         ast_log(LOG_ERROR, "Select error (%s) dispatch thread going away now, "
145                                 "and the module will no longer operate.\n", strerror(errno));
146                         break;
147                 }
148
149                 if (pfd[0].revents & POLLIN) {
150                         saClmDispatch(clm_handle,   SA_DISPATCH_ALL);
151                 }
152                 if (pfd[1].revents & POLLIN) {
153                         saEvtDispatch(evt_handle,   SA_DISPATCH_ALL);
154                 }
155         }
156
157         return NULL;
158 }
159
160 static int load_module(void)
161 {
162         if (ast_ais_clm_load_module())
163                 goto return_error;
164
165         if (ast_ais_evt_load_module())
166                 goto evt_failed;
167
168         if (ast_pthread_create_background(&dispatch_thread.id, NULL, 
169                 dispatch_thread_handler, NULL)) {
170                 ast_log(LOG_ERROR, "Error starting AIS dispatch thread.\n");
171                 goto dispatch_failed;
172         }
173
174         return AST_MODULE_LOAD_SUCCESS;
175
176 dispatch_failed:
177         ast_ais_evt_unload_module();
178 evt_failed:
179         ast_ais_clm_unload_module();
180 return_error:
181         return AST_MODULE_LOAD_DECLINE;
182 }
183
184 static int unload_module(void)
185 {
186         ast_ais_clm_unload_module();
187         ast_ais_evt_unload_module();
188
189         if (dispatch_thread.id != AST_PTHREADT_NULL) {
190                 dispatch_thread.stop = 1;
191                 pthread_kill(dispatch_thread.id, SIGURG); /* poke! */
192                 pthread_join(dispatch_thread.id, NULL);
193         }
194
195         return 0;
196 }
197
198 AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "SAForum AIS");