#include "asterisk.h"
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>
#include <sys/ioctl.h>
#include "asterisk/lock.h"
#include "asterisk/file.h"
#include "asterisk/logger.h"
#include "asterisk/channel.h"
#include "asterisk/pbx.h"
#include "asterisk/module.h"
#include "asterisk/config.h"
#include "asterisk/app.h"
#include "asterisk/options.h"
#include "asterisk/utils.h"
#include "asterisk/cli.h"
#include "asterisk/say.h"
#include "asterisk/dahdi_compat.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_exec_warn (struct ast_channel *chan, void *data) |
static int | conf_run (struct ast_channel *chan, int confno, int confflags) |
static struct ast_channel * | get_zap_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 | AST_MODFLAG_BUILDSUM, .description = "Scan Zap 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 = "361d7bb937402d51e4658efb5b4d76e4" , .load = load_module, .unload = unload_module, } |
static char * | app = "DAHDIScan" |
static const struct ast_module_info * | ast_module_info = &__mod_info |
static char * | deprecated_app = "ZapScan" |
static char * | descrip |
static char * | synopsis = "Scan Zap channels to monitor calls" |
Definition in file app_dahdiscan.c.
#define CONF_SIZE 160 |
Definition at line 74 of file app_dahdiscan.c.
static void __reg_module | ( | void | ) | [static] |
Definition at line 388 of file app_dahdiscan.c.
static void __unreg_module | ( | void | ) | [static] |
Definition at line 388 of file app_dahdiscan.c.
static int careful_write | ( | int | fd, | |
unsigned char * | data, | |||
int | len | |||
) | [static] |
Definition at line 83 of file app_dahdiscan.c.
References ast_log(), errno, and LOG_WARNING.
00084 { 00085 int res; 00086 while(len) { 00087 res = write(fd, data, len); 00088 if (res < 1) { 00089 if (errno != EAGAIN) { 00090 ast_log(LOG_WARNING, "Failed to write audio data to conference: %s\n", strerror(errno)); 00091 return -1; 00092 } else 00093 return 0; 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 288 of file app_dahdiscan.c.
References ast_channel::_state, ast_answer(), ast_channel_walk_locked(), ast_copy_string(), AST_DIGIT_ANY, AST_FRAME_DTMF, ast_frfree, ast_module_user_add, ast_module_user_remove, ast_mutex_unlock(), ast_read(), ast_say_number(), AST_STATE_UP, ast_stopstream(), ast_strdupa, ast_strlen_zero(), ast_verbose(), ast_waitfor(), conf_run(), f, get_zap_channel_locked(), input(), ast_channel::lock, ast_channel::name, pbx_builtin_getvar_helper(), ast_channel::tech, ast_channel_tech::type, and VERBOSE_PREFIX_3.
Referenced by conf_exec_warn(), and load_module().
00289 { 00290 int res=-1; 00291 struct ast_module_user *u; 00292 int confflags = 0; 00293 int confno = 0; 00294 char confstr[80] = "", *tmp = NULL; 00295 struct ast_channel *tempchan = NULL, *lastchan = NULL,*ichan = NULL; 00296 struct ast_frame *f; 00297 char *desired_group; 00298 int input=0,search_group=0; 00299 00300 u = ast_module_user_add(chan); 00301 00302 if (chan->_state != AST_STATE_UP) 00303 ast_answer(chan); 00304 00305 desired_group = ast_strdupa(data); 00306 if(!ast_strlen_zero(desired_group)) { 00307 ast_verbose(VERBOSE_PREFIX_3 "Scanning for group %s\n", desired_group); 00308 search_group = 1; 00309 } 00310 00311 for (;;) { 00312 if (ast_waitfor(chan, 100) < 0) 00313 break; 00314 00315 f = ast_read(chan); 00316 if (!f) 00317 break; 00318 if ((f->frametype == AST_FRAME_DTMF) && (f->subclass == '*')) { 00319 ast_frfree(f); 00320 break; 00321 } 00322 ast_frfree(f); 00323 ichan = NULL; 00324 if(input) { 00325 ichan = get_zap_channel_locked(input); 00326 input = 0; 00327 } 00328 00329 tempchan = ichan ? ichan : ast_channel_walk_locked(tempchan); 00330 00331 if ( !tempchan && !lastchan ) 00332 break; 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_verbose(VERBOSE_PREFIX_3 "Found Matching Channel %s in group %s\n", tempchan->name, desired_group); 00338 } else { 00339 ast_mutex_unlock(&tempchan->lock); 00340 lastchan = tempchan; 00341 continue; 00342 } 00343 } 00344 if (tempchan && (!strcmp(tempchan->tech->type, "Zap")) && (tempchan != chan) ) { 00345 ast_verbose(VERBOSE_PREFIX_3 "Zap channel %s is in-use, monitoring...\n", tempchan->name); 00346 ast_copy_string(confstr, tempchan->name, sizeof(confstr)); 00347 ast_mutex_unlock(&tempchan->lock); 00348 if ((tmp = strchr(confstr,'-'))) { 00349 *tmp = '\0'; 00350 } 00351 confno = atoi(strchr(confstr,'/') + 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) break; 00356 input = res; 00357 } else if (tempchan) 00358 ast_mutex_unlock(&tempchan->lock); 00359 lastchan = tempchan; 00360 } 00361 ast_module_user_remove(u); 00362 return res; 00363 }
static int conf_exec_warn | ( | struct ast_channel * | chan, | |
void * | data | |||
) | [static] |
Definition at line 365 of file app_dahdiscan.c.
References ast_log(), conf_exec(), and LOG_WARNING.
Referenced by load_module().
00366 { 00367 ast_log(LOG_WARNING, "Use of the command %s is deprecated, please use %s instead.\n", deprecated_app, app); 00368 return conf_exec(chan, data); 00369 }
static int conf_run | ( | struct ast_channel * | chan, | |
int | confno, | |||
int | confflags | |||
) | [static] |
Definition at line 101 of file app_dahdiscan.c.
References 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_verbose(), ast_waitfor_nandfds(), ast_write(), careful_write(), CONF_SIZE, DAHDI_FILE_PSEUDO, errno, f, ast_channel::fds, ast_frame::flags, input(), LOG_DEBUG, LOG_WARNING, ast_channel::name, ast_channel::tech, ast_channel_tech::type, and VERBOSE_PREFIX_3.
00102 { 00103 int fd; 00104 struct dahdi_confinfo ztc; 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 retryzap; 00114 int origfd; 00115 int ret = -1; 00116 char input[4]; 00117 int ic=0; 00118 struct dahdi_bufferinfo bi; 00119 char __buf[CONF_SIZE + AST_FRIENDLY_OFFSET]; 00120 char *buf = __buf + AST_FRIENDLY_OFFSET; 00121 00122 /* Set it into U-law mode (write) */ 00123 if (ast_set_write_format(chan, AST_FORMAT_ULAW) < 0) { 00124 ast_log(LOG_WARNING, "Unable to set '%s' to write ulaw mode\n", chan->name); 00125 goto outrun; 00126 } 00127 00128 /* Set it into U-law mode (read) */ 00129 if (ast_set_read_format(chan, AST_FORMAT_ULAW) < 0) { 00130 ast_log(LOG_WARNING, "Unable to set '%s' to read ulaw mode\n", chan->name); 00131 goto outrun; 00132 } 00133 ast_indicate(chan, -1); 00134 retryzap = strcasecmp(chan->tech->type, "Zap"); 00135 zapretry: 00136 origfd = chan->fds[0]; 00137 if (retryzap) { 00138 fd = open(DAHDI_FILE_PSEUDO, O_RDWR); 00139 if (fd < 0) { 00140 ast_log(LOG_WARNING, "Unable to open pseudo channel: %s\n", strerror(errno)); 00141 goto outrun; 00142 } 00143 /* Make non-blocking */ 00144 flags = fcntl(fd, F_GETFL); 00145 if (flags < 0) { 00146 ast_log(LOG_WARNING, "Unable to get flags: %s\n", strerror(errno)); 00147 close(fd); 00148 goto outrun; 00149 } 00150 if (fcntl(fd, F_SETFL, flags | O_NONBLOCK)) { 00151 ast_log(LOG_WARNING, "Unable to set flags: %s\n", strerror(errno)); 00152 close(fd); 00153 goto outrun; 00154 } 00155 /* Setup buffering information */ 00156 memset(&bi, 0, sizeof(bi)); 00157 bi.bufsize = CONF_SIZE; 00158 bi.txbufpolicy = DAHDI_POLICY_IMMEDIATE; 00159 bi.rxbufpolicy = DAHDI_POLICY_IMMEDIATE; 00160 bi.numbufs = 4; 00161 if (ioctl(fd, DAHDI_SET_BUFINFO, &bi)) { 00162 ast_log(LOG_WARNING, "Unable to set buffering information: %s\n", strerror(errno)); 00163 close(fd); 00164 goto outrun; 00165 } 00166 nfds = 1; 00167 } else { 00168 /* XXX Make sure we're not running on a pseudo channel XXX */ 00169 fd = chan->fds[0]; 00170 nfds = 0; 00171 } 00172 memset(&ztc, 0, sizeof(ztc)); 00173 /* Check to see if we're in a conference... */ 00174 ztc.chan = 0; 00175 if (ioctl(fd, DAHDI_GETCONF, &ztc)) { 00176 ast_log(LOG_WARNING, "Error getting conference\n"); 00177 close(fd); 00178 goto outrun; 00179 } 00180 if (ztc.confmode) { 00181 /* Whoa, already in a conference... Retry... */ 00182 if (!retryzap) { 00183 ast_log(LOG_DEBUG, "Zap channel is in a conference already, retrying with pseudo\n"); 00184 retryzap = 1; 00185 goto zapretry; 00186 } 00187 } 00188 memset(&ztc, 0, sizeof(ztc)); 00189 /* Add us to the conference */ 00190 ztc.chan = 0; 00191 ztc.confno = confno; 00192 ztc.confmode = DAHDI_CONF_MONITORBOTH; 00193 00194 if (ioctl(fd, DAHDI_SETCONF, &ztc)) { 00195 ast_log(LOG_WARNING, "Error setting conference\n"); 00196 close(fd); 00197 goto outrun; 00198 } 00199 ast_log(LOG_DEBUG, "Placed channel %s in ZAP channel %d monitor\n", chan->name, confno); 00200 00201 for(;;) { 00202 outfd = -1; 00203 ms = -1; 00204 c = ast_waitfor_nandfds(&chan, 1, &fd, nfds, NULL, &outfd, &ms); 00205 if (c) { 00206 if (c->fds[0] != origfd) { 00207 if (retryzap) { 00208 /* Kill old pseudo */ 00209 close(fd); 00210 } 00211 ast_log(LOG_DEBUG, "Ooh, something swapped out under us, starting over\n"); 00212 retryzap = 0; 00213 goto zapretry; 00214 } 00215 f = ast_read(c); 00216 if (!f) 00217 break; 00218 if(f->frametype == AST_FRAME_DTMF) { 00219 if(f->subclass == '#') { 00220 ret = 0; 00221 break; 00222 } 00223 else if (f->subclass == '*') { 00224 ret = -1; 00225 break; 00226 00227 } 00228 else { 00229 input[ic++] = f->subclass; 00230 } 00231 if(ic == 3) { 00232 input[ic++] = '\0'; 00233 ic=0; 00234 ret = atoi(input); 00235 ast_verbose(VERBOSE_PREFIX_3 "Zapscan: change channel to %d\n",ret); 00236 break; 00237 } 00238 } 00239 00240 if (fd != chan->fds[0]) { 00241 if (f->frametype == AST_FRAME_VOICE) { 00242 if (f->subclass == AST_FORMAT_ULAW) { 00243 /* Carefully write */ 00244 careful_write(fd, f->data, f->datalen); 00245 } else 00246 ast_log(LOG_WARNING, "Huh? Got a non-ulaw (%d) frame in the conference\n", f->subclass); 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 = 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 if (f) 00269 ast_frfree(f); 00270 if (fd != chan->fds[0]) 00271 close(fd); 00272 else { 00273 /* Take out of conference */ 00274 /* Add us to the conference */ 00275 ztc.chan = 0; 00276 ztc.confno = 0; 00277 ztc.confmode = 0; 00278 if (ioctl(fd, DAHDI_SETCONF, &ztc)) { 00279 ast_log(LOG_WARNING, "Error setting conference\n"); 00280 } 00281 } 00282 00283 outrun: 00284 00285 return ret; 00286 }
static struct ast_channel* get_zap_channel_locked | ( | int | num | ) | [static] |
Definition at line 76 of file app_dahdiscan.c.
References ast_get_channel_by_name_locked(), dahdi_chan_name, and name.
Referenced by conf_exec().
00076 { 00077 char name[80]; 00078 00079 snprintf(name,sizeof(name),"%s/%d-1", dahdi_chan_name, num); 00080 return ast_get_channel_by_name_locked(name); 00081 }
static int load_module | ( | void | ) | [static] |
Definition at line 382 of file app_dahdiscan.c.
References ast_register_application(), conf_exec(), and conf_exec_warn().
00383 { 00384 ast_register_application(deprecated_app, conf_exec_warn, synopsis, descrip); 00385 return ast_register_application(app, conf_exec, synopsis, descrip); 00386 }
static int unload_module | ( | void | ) | [static] |
Definition at line 371 of file app_dahdiscan.c.
References ast_module_user_hangup_all, and ast_unregister_application().
00372 { 00373 int res; 00374 00375 res = ast_unregister_application(app); 00376 00377 ast_module_user_hangup_all(); 00378 00379 return res; 00380 }
struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_DEFAULT | AST_MODFLAG_BUILDSUM, .description = "Scan Zap 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 = "361d7bb937402d51e4658efb5b4d76e4" , .load = load_module, .unload = unload_module, } [static] |
Definition at line 388 of file app_dahdiscan.c.
char* app = "DAHDIScan" [static] |
Definition at line 63 of file app_dahdiscan.c.
const struct ast_module_info* ast_module_info = &__mod_info [static] |
Definition at line 388 of file app_dahdiscan.c.
char* deprecated_app = "ZapScan" [static] |
Definition at line 64 of file app_dahdiscan.c.
char* descrip [static] |
Initial value:
" ZapScan([group]) allows a call center manager to monitor Zap channels in\n" "a convenient way. Use '#' to select the next channel and use '*' to exit\n" "Limit scanning to a channel GROUP by setting the option group argument.\n"
Definition at line 68 of file app_dahdiscan.c.
Definition at line 66 of file app_dahdiscan.c.