#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 | |
AST_MODULE_INFO_STANDARD (ASTERISK_GPL_KEY,"Scan Zap channels application") | |
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 char * | app = "DAHDIScan" |
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.
AST_MODULE_INFO_STANDARD | ( | ASTERISK_GPL_KEY | , | |
"Scan Zap channels application" | ||||
) |
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_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, 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, errno, f, ast_channel::fds, ast_frame::flags, input(), LOG_DEBUG, LOG_WARNING, 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("/dev/zap/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 }
char* app = "DAHDIScan" [static] |
Definition at line 63 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.