Wed Jan 8 2020 09:49:49

Asterisk developer's documentation


res_ais.c
Go to the documentation of this file.
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  <support_level>extended</support_level>
38  ***/
39 
40 #include "asterisk.h"
41 
42 ASTERISK_FILE_VERSION(__FILE__, "$Revision: 359053 $");
43 
44 #include <stdlib.h>
45 #include <stdio.h>
46 #include <string.h>
47 #include <unistd.h>
48 #include <errno.h>
49 #include <signal.h>
50 #include <pthread.h>
51 
52 #include "ais/ais.h"
53 
54 #include "asterisk/module.h"
55 #include "asterisk/options.h"
56 #include "asterisk/logger.h"
57 #include "asterisk/channel.h"
58 #include "asterisk/utils.h"
59 #include "asterisk/cli.h"
60 
61 static struct {
62  pthread_t id;
63  int alert_pipe[2];
64  unsigned int stop:1;
65 } dispatch_thread = {
66  .id = AST_PTHREADT_NULL,
67  .alert_pipe = { -1, -1 },
68 };
69 
70 SaVersionT ais_version = { 'B', 1, 1 };
71 
72 static const struct ais_error {
73  SaAisErrorT error;
74  const char *desc;
75 } ais_errors[] = {
76  { SA_AIS_OK, "OK" },
77  { SA_AIS_ERR_LIBRARY, "Library Error" },
78  { SA_AIS_ERR_VERSION, "Version Not Compatible" },
79  { SA_AIS_ERR_INIT, "Callback Not Registered" },
80  { SA_AIS_ERR_TIMEOUT, "Timeout" },
81  { SA_AIS_ERR_TRY_AGAIN , "Try Again" },
82  { SA_AIS_ERR_INVALID_PARAM, "Invalid Parameter" },
83  { SA_AIS_ERR_NO_MEMORY, "No Memory" },
84  { SA_AIS_ERR_BAD_HANDLE, "Invalid Handle" },
85  { SA_AIS_ERR_BUSY, "Resource Already In Use" },
86  { SA_AIS_ERR_ACCESS, "Access Denied" },
87  { SA_AIS_ERR_NOT_EXIST, "Does Not Exist" },
88  { SA_AIS_ERR_NAME_TOO_LONG, "Name Too Long" },
89  { SA_AIS_ERR_EXIST, "Already Exists" },
90  { SA_AIS_ERR_NO_SPACE, "Buffer Too Small" },
91  { SA_AIS_ERR_INTERRUPT, "Request Interrupted" },
92  { SA_AIS_ERR_NAME_NOT_FOUND, "Name Not Found" },
93  { SA_AIS_ERR_NO_RESOURCES, "Not Enough Resources" },
94  { SA_AIS_ERR_NOT_SUPPORTED, "Requested Function Not Supported" },
95  { SA_AIS_ERR_BAD_OPERATION, "Operation Not Allowed" },
96  { SA_AIS_ERR_FAILED_OPERATION, "Operation Failed" },
97  { SA_AIS_ERR_MESSAGE_ERROR, "Communication Error" },
98  { SA_AIS_ERR_QUEUE_FULL, "Destination Queue Full" },
99  { SA_AIS_ERR_QUEUE_NOT_AVAILABLE, "Destination Queue Not Available" },
100  { SA_AIS_ERR_BAD_FLAGS, "Invalid Flags" },
101  { SA_AIS_ERR_TOO_BIG, "Value Too Large" },
102  { SA_AIS_ERR_NO_SECTIONS, "No More Sections to Initialize" },
103 };
104 
105 const char *ais_err2str(SaAisErrorT error)
106 {
107  int x;
108 
109  for (x = 0; x < ARRAY_LEN(ais_errors); x++) {
110  if (ais_errors[x].error == error)
111  return ais_errors[x].desc;
112  }
113 
114  return "Unknown";
115 }
116 
117 static void *dispatch_thread_handler(void *data)
118 {
119  SaSelectionObjectT clm_fd, evt_fd;
120  int res;
121  struct pollfd pfd[3] = {
122  { .events = POLLIN, },
123  { .events = POLLIN, },
124  { .events = POLLIN, },
125  };
126  SaAisErrorT ais_res;
127 
128  ais_res = saClmSelectionObjectGet(clm_handle, &clm_fd);
129  if (ais_res != SA_AIS_OK) {
130  ast_log(LOG_ERROR, "Failed to retrieve select fd for CLM service. "
131  "This module will not operate.\n");
132  return NULL;
133  }
134 
135  ais_res = saEvtSelectionObjectGet(evt_handle, &evt_fd);
136  if (ais_res != SA_AIS_OK) {
137  ast_log(LOG_ERROR, "Failed to retrieve select fd for EVT service. "
138  "This module will not operate.\n");
139  return NULL;
140  }
141 
142  pfd[0].fd = clm_fd;
143  pfd[1].fd = evt_fd;
144  pfd[2].fd = dispatch_thread.alert_pipe[0];
145 
146  while (!dispatch_thread.stop) {
147  pfd[0].revents = 0;
148  pfd[1].revents = 0;
149  pfd[2].revents = 0;
150 
151  res = ast_poll(pfd, ARRAY_LEN(pfd), -1);
152  if (res == -1 && errno != EINTR && errno != EAGAIN) {
153  ast_log(LOG_ERROR, "Select error (%s) dispatch thread going away now, "
154  "and the module will no longer operate.\n", strerror(errno));
155  break;
156  }
157 
158  if (pfd[0].revents & POLLIN) {
159  saClmDispatch(clm_handle, SA_DISPATCH_ALL);
160  }
161  if (pfd[1].revents & POLLIN) {
162  saEvtDispatch(evt_handle, SA_DISPATCH_ALL);
163  }
164  if (pfd[2].revents & POLLIN) {
165  enum ast_ais_cmd cmd;
166  ast_debug(1, "Got a command in the poll() loop\n");
167  if (read(dispatch_thread.alert_pipe[0], &cmd, sizeof(cmd)) != -1) {
168  switch (cmd) {
171  break;
172  case AST_AIS_CMD_EXIT:
173  break;
174  }
175  }
176  }
177  }
178 
179  return NULL;
180 }
181 
183 {
184  int res;
185 
186  res = write(dispatch_thread.alert_pipe[1], (char *) &cmd, sizeof(cmd));
187 
188  ast_debug(1, "AIS cmd: %d, res: %d\n", cmd, res);
189 
190  return res;
191 }
192 
193 static int load_module(void)
194 {
195  if (pipe(dispatch_thread.alert_pipe) == -1) {
196  ast_log(LOG_ERROR, "Failed to create alert pipe: %s (%d)\n",
197  strerror(errno), errno);
198  goto return_error;
199  }
200 
202  goto clm_failed;
203 
205  goto evt_failed;
206 
208  dispatch_thread_handler, NULL)) {
209  ast_log(LOG_ERROR, "Error starting AIS dispatch thread.\n");
210  goto dispatch_failed;
211  }
212 
214 
215 dispatch_failed:
217 evt_failed:
219 clm_failed:
220  close(dispatch_thread.alert_pipe[0]);
221  close(dispatch_thread.alert_pipe[1]);
222 return_error:
224 }
225 
226 static int unload_module(void)
227 {
230 
232  dispatch_thread.stop = 1;
233  if (ast_ais_cmd(AST_AIS_CMD_EXIT) == -1) {
234  ast_log(LOG_ERROR, "Failed to write to pipe: %s (%d)\n",
235  strerror(errno), errno);
236  }
237  pthread_join(dispatch_thread.id, NULL);
238  }
239 
240  if (dispatch_thread.alert_pipe[0] != -1) {
241  close(dispatch_thread.alert_pipe[0]);
242  dispatch_thread.alert_pipe[0] = -1;
243  }
244 
245  if (dispatch_thread.alert_pipe[1] != -1) {
246  close(dispatch_thread.alert_pipe[1]);
247  dispatch_thread.alert_pipe[1] = -1;
248  }
249 
250  return 0;
251 }
252 
#define AST_MODULE_INFO_STANDARD(keystr, desc)
Definition: module.h:396
Asterisk main include file. File version handling, generic pbx functions.
#define ARRAY_LEN(a)
Definition: isdn_lib.c:42
int ast_ais_evt_load_module(void)
Definition: evt.c:576
void ast_ais_evt_membership_changed(void)
Definition: evt.c:319
SaEvtHandleT evt_handle
Definition: evt.c:61
SaAisErrorT error
Definition: res_ais.c:73
const char * desc
Definition: res_ais.c:74
unsigned int stop
Definition: app_meetme.c:969
ast_ais_cmd
Definition: ais.h:50
SaVersionT ais_version
Definition: res_ais.c:70
Utility functions.
#define ast_pthread_create_background(a, b, c, d)
Definition: utils.h:426
int ast_ais_clm_load_module(void)
Definition: clm.c:157
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:236
General Asterisk PBX channel definitions.
#define AST_PTHREADT_NULL
Definition: lock.h:65
#define ast_poll(a, b, c)
Definition: poll-compat.h:88
Usage of the SAForum AIS (Application Interface Specification)
int alert_pipe[2]
Definition: res_ais.c:63
#define LOG_ERROR
Definition: logger.h:155
static int unload_module(void)
Definition: res_ais.c:226
SaClmHandleT clm_handle
Definition: clm.c:52
void ast_log(int level, const char *file, int line, const char *function, const char *fmt,...)
Used for sending a log message This is the standard logger function. Probably the only way you will i...
Definition: logger.c:1207
static struct ais_error ais_errors[]
int ast_ais_evt_unload_module(void)
Definition: evt.c:592
int errno
static struct @322 dispatch_thread
Support for logging to various files, console and syslog Configuration in file logger.conf.
static int load_module(void)
Definition: res_ais.c:193
Standard Command Line Interface.
const char * ais_err2str(SaAisErrorT error)
Definition: res_ais.c:105
static void * dispatch_thread_handler(void *data)
Definition: res_ais.c:117
Options provided by main asterisk program.
enum queue_result id
Definition: app_queue.c:1090
int ast_ais_clm_unload_module(void)
Definition: clm.c:178
#define ASTERISK_GPL_KEY
The text the key() function should return.
Definition: module.h:38
Asterisk module definitions.
#define ASTERISK_FILE_VERSION(file, version)
Register/unregister a source code file with the core.
Definition: asterisk.h:180