DAHDI Scanner. More...
#include "asterisk.h"#include <dahdi/user.h>#include "asterisk/lock.h"#include "asterisk/file.h"#include "asterisk/channel.h"#include "asterisk/pbx.h"#include "asterisk/module.h"#include "asterisk/config.h"#include "asterisk/app.h"#include "asterisk/utils.h"#include "asterisk/cli.h"#include "asterisk/say.h"#include "asterisk/options.h"
Go to the source code of this file.
Defines | |
| #define | CONF_SIZE 160 |
Functions | |
| static void | __reg_module (void) |
| static void | __unreg_module (void) |
| static int | careful_write (int fd, unsigned char *data, int len) |
| static int | conf_exec (struct ast_channel *chan, void *data) |
| static int | conf_run (struct ast_channel *chan, int confno, int confflags) |
| static struct ast_channel * | get_dahdi_channel_locked (int num) |
| static int | load_module (void) |
| static int | unload_module (void) |
Variables | |
| static struct ast_module_info | __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_DEFAULT , .description = "Scan DAHDI channels application" , .key = "This paragraph is copyright (c) 2006 by Digium, Inc. \In order for your module to load, it must return this \key via a function called \"key\". Any code which \includes this paragraph must be licensed under the GNU \General Public License version 2 or later (at your \option). In addition to Digium's general reservations \of rights, Digium expressly reserves the right to \allow other parties to license this paragraph under \different terms. Any use of Digium, Inc. trademarks or \logos (including \"Asterisk\" or \"Digium\") without \express written permission of Digium, Inc. is prohibited.\n" , .buildopt_sum = "0901e4e500243c855563a2d78b0c03e4" , .load = load_module, .unload = unload_module, } |
| static char * | app = "DAHDIScan" |
| static struct ast_module_info * | ast_module_info = &__mod_info |
DAHDI Scanner.
Definition in file app_dahdiscan.c.
| #define CONF_SIZE 160 |
Definition at line 73 of file app_dahdiscan.c.
| static void __reg_module | ( | void | ) | [static] |
Definition at line 377 of file app_dahdiscan.c.
| static void __unreg_module | ( | void | ) | [static] |
Definition at line 377 of file app_dahdiscan.c.
| static int careful_write | ( | int | fd, | |
| unsigned char * | data, | |||
| int | len | |||
| ) | [static] |
Definition at line 82 of file app_dahdiscan.c.
References ast_log(), errno, and LOG_WARNING.
Referenced by conf_run().
00083 { 00084 int res; 00085 while (len) { 00086 res = write(fd, data, len); 00087 if (res < 1) { 00088 if (errno != EAGAIN) { 00089 ast_log(LOG_WARNING, "Failed to write audio data to conference: %s\n", strerror(errno)); 00090 return -1; 00091 } else { 00092 return 0; 00093 } 00094 } 00095 len -= res; 00096 data += res; 00097 } 00098 return 0; 00099 }
| static int conf_exec | ( | struct ast_channel * | chan, | |
| void * | data | |||
| ) | [static] |
Definition at line 290 of file app_dahdiscan.c.
References ast_channel::_state, ast_answer(), ast_channel_unlock, ast_channel_walk_locked(), ast_copy_string(), AST_DIGIT_ANY, AST_FRAME_DTMF, ast_frfree, ast_read(), ast_say_number(), AST_STATE_UP, ast_stopstream(), ast_strlen_zero(), ast_verb, ast_waitfor(), conf_run(), f, ast_frame::frametype, get_dahdi_channel_locked(), input(), ast_channel::language, ast_channel::name, pbx_builtin_getvar_helper(), ast_frame::subclass, ast_channel::tech, and ast_channel_tech::type.
Referenced by load_module().
00291 { 00292 int res=-1; 00293 int confflags = 0; 00294 int confno = 0; 00295 char confnostr[80] = "", *tmp = NULL; 00296 struct ast_channel *tempchan = NULL, *lastchan = NULL, *ichan = NULL; 00297 struct ast_frame *f; 00298 char *desired_group; 00299 int input = 0, search_group = 0; 00300 00301 if (chan->_state != AST_STATE_UP) 00302 ast_answer(chan); 00303 00304 desired_group = ast_strdupa(data); 00305 if (!ast_strlen_zero(desired_group)) { 00306 ast_verb(3, "Scanning for group %s\n", desired_group); 00307 search_group = 1; 00308 } 00309 00310 for (;;) { 00311 if (ast_waitfor(chan, 100) < 0) 00312 break; 00313 00314 f = ast_read(chan); 00315 if (!f) 00316 break; 00317 if ((f->frametype == AST_FRAME_DTMF) && (f->subclass == '*')) { 00318 ast_frfree(f); 00319 break; 00320 } 00321 ast_frfree(f); 00322 ichan = NULL; 00323 if(input) { 00324 ichan = get_dahdi_channel_locked(input); 00325 input = 0; 00326 } 00327 00328 tempchan = ichan ? ichan : ast_channel_walk_locked(tempchan); 00329 00330 if (!tempchan && !lastchan) { 00331 break; 00332 } 00333 00334 if (tempchan && search_group) { 00335 const char *mygroup; 00336 if ((mygroup = pbx_builtin_getvar_helper(tempchan, "GROUP")) && (!strcmp(mygroup, desired_group))) { 00337 ast_verb(3, "Found Matching Channel %s in group %s\n", tempchan->name, desired_group); 00338 } else { 00339 ast_channel_unlock(tempchan); 00340 lastchan = tempchan; 00341 continue; 00342 } 00343 } 00344 if (tempchan && (!strcmp(tempchan->tech->type, "DAHDI")) && (tempchan != chan)) { 00345 ast_verb(3, "DAHDI channel %s is in-use, monitoring...\n", tempchan->name); 00346 ast_copy_string(confnostr, tempchan->name, sizeof(confnostr)); 00347 ast_channel_unlock(tempchan); 00348 if ((tmp = strchr(confnostr, '-'))) { 00349 *tmp = '\0'; 00350 } 00351 confno = atoi(strchr(confnostr, '/') + 1); 00352 ast_stopstream(chan); 00353 ast_say_number(chan, confno, AST_DIGIT_ANY, chan->language, (char *) NULL); 00354 res = conf_run(chan, confno, confflags); 00355 if (res < 0) { 00356 break; 00357 } 00358 input = res; 00359 } else if (tempchan) { 00360 ast_channel_unlock(tempchan); 00361 } 00362 lastchan = tempchan; 00363 } 00364 return res; 00365 }
| static int conf_run | ( | struct ast_channel * | chan, | |
| int | confno, | |||
| int | confflags | |||
| ) | [static] |
Definition at line 101 of file app_dahdiscan.c.
References ast_debug, AST_FORMAT_ULAW, AST_FRAME_DTMF, AST_FRAME_VOICE, ast_frfree, AST_FRIENDLY_OFFSET, ast_indicate(), ast_log(), ast_read(), ast_set_read_format(), ast_set_write_format(), ast_verb, ast_waitfor_nandfds(), ast_write(), buf, careful_write(), CONF_SIZE, ast_frame::data, ast_frame::datalen, errno, f, ast_channel::fds, ast_frame::flags, ast_frame::frametype, input(), LOG_WARNING, ast_channel::name, ast_frame::offset, ast_frame::ptr, ast_frame::samples, ast_frame::subclass, ast_channel::tech, and ast_channel_tech::type.
Referenced by conf_exec().
00102 { 00103 int fd; 00104 struct dahdi_confinfo dahdic; 00105 struct ast_frame *f; 00106 struct ast_channel *c; 00107 struct ast_frame fr; 00108 int outfd; 00109 int ms; 00110 int nfds; 00111 int res; 00112 int flags; 00113 int retrydahdi; 00114 int origfd; 00115 int ret = -1; 00116 char input[4]; 00117 int ic = 0; 00118 00119 struct dahdi_bufferinfo bi; 00120 char __buf[CONF_SIZE + AST_FRIENDLY_OFFSET]; 00121 char *buf = __buf + AST_FRIENDLY_OFFSET; 00122 00123 /* Set it into U-law mode (write) */ 00124 if (ast_set_write_format(chan, AST_FORMAT_ULAW) < 0) { 00125 ast_log(LOG_WARNING, "Unable to set '%s' to write ulaw mode\n", chan->name); 00126 goto outrun; 00127 } 00128 00129 /* Set it into U-law mode (read) */ 00130 if (ast_set_read_format(chan, AST_FORMAT_ULAW) < 0) { 00131 ast_log(LOG_WARNING, "Unable to set '%s' to read ulaw mode\n", chan->name); 00132 goto outrun; 00133 } 00134 ast_indicate(chan, -1); 00135 retrydahdi = strcasecmp(chan->tech->type, "DAHDI"); 00136 dahdiretry: 00137 origfd = chan->fds[0]; 00138 if (retrydahdi) { 00139 fd = open("/dev/dahdi/pseudo", O_RDWR); 00140 if (fd < 0) { 00141 ast_log(LOG_WARNING, "Unable to open pseudo channel: %s\n", strerror(errno)); 00142 goto outrun; 00143 } 00144 /* Make non-blocking */ 00145 flags = fcntl(fd, F_GETFL); 00146 if (flags < 0) { 00147 ast_log(LOG_WARNING, "Unable to get flags: %s\n", strerror(errno)); 00148 close(fd); 00149 goto outrun; 00150 } 00151 if (fcntl(fd, F_SETFL, flags | O_NONBLOCK)) { 00152 ast_log(LOG_WARNING, "Unable to set flags: %s\n", strerror(errno)); 00153 close(fd); 00154 goto outrun; 00155 } 00156 /* Setup buffering information */ 00157 memset(&bi, 0, sizeof(bi)); 00158 bi.bufsize = CONF_SIZE; 00159 bi.txbufpolicy = DAHDI_POLICY_IMMEDIATE; 00160 bi.rxbufpolicy = DAHDI_POLICY_IMMEDIATE; 00161 bi.numbufs = 4; 00162 if (ioctl(fd, DAHDI_SET_BUFINFO, &bi)) { 00163 ast_log(LOG_WARNING, "Unable to set buffering information: %s\n", strerror(errno)); 00164 close(fd); 00165 goto outrun; 00166 } 00167 nfds = 1; 00168 } else { 00169 /* XXX Make sure we're not running on a pseudo channel XXX */ 00170 fd = chan->fds[0]; 00171 nfds = 0; 00172 } 00173 memset(&dahdic, 0, sizeof(dahdic)); 00174 /* Check to see if we're in a conference... */ 00175 dahdic.chan = 0; 00176 if (ioctl(fd, DAHDI_GETCONF, &dahdic)) { 00177 ast_log(LOG_WARNING, "Error getting conference\n"); 00178 close(fd); 00179 goto outrun; 00180 } 00181 if (dahdic.confmode) { 00182 /* Whoa, already in a conference... Retry... */ 00183 if (!retrydahdi) { 00184 ast_debug(1, "DAHDI channel is in a conference already, retrying with pseudo\n"); 00185 retrydahdi = 1; 00186 goto dahdiretry; 00187 } 00188 } 00189 memset(&dahdic, 0, sizeof(dahdic)); 00190 /* Add us to the conference */ 00191 dahdic.chan = 0; 00192 dahdic.confno = confno; 00193 dahdic.confmode = DAHDI_CONF_MONITORBOTH; 00194 00195 if (ioctl(fd, DAHDI_SETCONF, &dahdic)) { 00196 ast_log(LOG_WARNING, "Error setting conference\n"); 00197 close(fd); 00198 goto outrun; 00199 } 00200 ast_debug(1, "Placed channel %s in DAHDI channel %d monitor\n", chan->name, confno); 00201 00202 for (;;) { 00203 outfd = -1; 00204 ms = -1; 00205 c = ast_waitfor_nandfds(&chan, 1, &fd, nfds, NULL, &outfd, &ms); 00206 if (c) { 00207 if (c->fds[0] != origfd) { 00208 if (retrydahdi) { 00209 /* Kill old pseudo */ 00210 close(fd); 00211 } 00212 ast_debug(1, "Ooh, something swapped out under us, starting over\n"); 00213 retrydahdi = 0; 00214 goto dahdiretry; 00215 } 00216 f = ast_read(c); 00217 if (!f) { 00218 break; 00219 } 00220 if (f->frametype == AST_FRAME_DTMF) { 00221 if (f->subclass == '#') { 00222 ret = 0; 00223 break; 00224 } else if (f->subclass == '*') { 00225 ret = -1; 00226 break; 00227 } else { 00228 input[ic++] = f->subclass; 00229 } 00230 if (ic == 3) { 00231 input[ic++] = '\0'; 00232 ic = 0; 00233 ret = atoi(input); 00234 ast_verb(3, "DAHDIScan: change channel to %d\n", ret); 00235 break; 00236 } 00237 } 00238 00239 if (fd != chan->fds[0]) { 00240 if (f->frametype == AST_FRAME_VOICE) { 00241 if (f->subclass == AST_FORMAT_ULAW) { 00242 /* Carefully write */ 00243 careful_write(fd, f->data.ptr, f->datalen); 00244 } else { 00245 ast_log(LOG_WARNING, "Huh? Got a non-ulaw (%d) frame in the conference\n", f->subclass); 00246 } 00247 } 00248 } 00249 ast_frfree(f); 00250 } else if (outfd > -1) { 00251 res = read(outfd, buf, CONF_SIZE); 00252 if (res > 0) { 00253 memset(&fr, 0, sizeof(fr)); 00254 fr.frametype = AST_FRAME_VOICE; 00255 fr.subclass = AST_FORMAT_ULAW; 00256 fr.datalen = res; 00257 fr.samples = res; 00258 fr.data.ptr = buf; 00259 fr.offset = AST_FRIENDLY_OFFSET; 00260 if (ast_write(chan, &fr) < 0) { 00261 ast_log(LOG_WARNING, "Unable to write frame to channel: %s\n", strerror(errno)); 00262 /* break; */ 00263 } 00264 } else { 00265 ast_log(LOG_WARNING, "Failed to read frame: %s\n", strerror(errno)); 00266 } 00267 } 00268 } 00269 if (f) { 00270 ast_frfree(f); 00271 } 00272 if (fd != chan->fds[0]) { 00273 close(fd); 00274 } else { 00275 /* Take out of conference */ 00276 /* Add us to the conference */ 00277 dahdic.chan = 0; 00278 dahdic.confno = 0; 00279 dahdic.confmode = 0; 00280 if (ioctl(fd, DAHDI_SETCONF, &dahdic)) { 00281 ast_log(LOG_WARNING, "Error setting conference\n"); 00282 } 00283 } 00284 00285 outrun: 00286 00287 return ret; 00288 }
| static struct ast_channel* get_dahdi_channel_locked | ( | int | num | ) | [static, read] |
Definition at line 75 of file app_dahdiscan.c.
References ast_get_channel_by_name_locked(), and name.
Referenced by conf_exec().
00075 { 00076 char name[80]; 00077 00078 snprintf(name, sizeof(name), "DAHDI/%d-1", num); 00079 return ast_get_channel_by_name_locked(name); 00080 }
| static int load_module | ( | void | ) | [static] |
Definition at line 372 of file app_dahdiscan.c.
References AST_MODULE_LOAD_FAILURE, AST_MODULE_LOAD_SUCCESS, ast_register_application_xml, and conf_exec().
00373 { 00374 return ((ast_register_application_xml(app, conf_exec)) ? AST_MODULE_LOAD_FAILURE : AST_MODULE_LOAD_SUCCESS); 00375 }
| static int unload_module | ( | void | ) | [static] |
Definition at line 367 of file app_dahdiscan.c.
References ast_unregister_application().
00368 { 00369 return ast_unregister_application(app); 00370 }
struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_DEFAULT , .description = "Scan DAHDI channels application" , .key = "This paragraph is copyright (c) 2006 by Digium, Inc. \In order for your module to load, it must return this \key via a function called \"key\". Any code which \includes this paragraph must be licensed under the GNU \General Public License version 2 or later (at your \option). In addition to Digium's general reservations \of rights, Digium expressly reserves the right to \allow other parties to license this paragraph under \different terms. Any use of Digium, Inc. trademarks or \logos (including \"Asterisk\" or \"Digium\") without \express written permission of Digium, Inc. is prohibited.\n" , .buildopt_sum = "0901e4e500243c855563a2d78b0c03e4" , .load = load_module, .unload = unload_module, } [static] |
Definition at line 377 of file app_dahdiscan.c.
char* app = "DAHDIScan" [static] |
Definition at line 71 of file app_dahdiscan.c.
struct ast_module_info* ast_module_info = &__mod_info [static] |
Definition at line 377 of file app_dahdiscan.c.
1.6.2