#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>
#include <sys/ioctl.h>
#include <zaptel.h>
#include "asterisk.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 dependency graph for app_zapscan.c:
Go to the source code of this file.
Defines | |
#define | CONF_SIZE 160 |
Functions | |
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) |
char * | description (void) |
Provides a description of the module. | |
static struct ast_channel * | get_zap_channel_locked (int num) |
char * | key () |
Returns the ASTERISK_GPL_KEY. | |
int | load_module (void) |
Initialize the module. | |
int | unload_module (void) |
Cleanup all module structures, sockets, etc. | |
int | usecount (void) |
Provides a usecount. | |
Variables | |
static char * | app = "ZapScan" |
static char * | descrip |
LOCAL_USER_DECL | |
STANDARD_LOCAL_USER | |
static char * | synopsis = "Scan Zap channels to monitor calls" |
static char * | tdesc = "Scan Zap channels application" |
Definition in file app_zapscan.c.
|
Definition at line 77 of file app_zapscan.c. |
|
Definition at line 86 of file app_zapscan.c. References ast_log(), and LOG_WARNING. 00087 { 00088 int res; 00089 while(len) { 00090 res = write(fd, data, len); 00091 if (res < 1) { 00092 if (errno != EAGAIN) { 00093 ast_log(LOG_WARNING, "Failed to write audio data to conference: %s\n", strerror(errno)); 00094 return -1; 00095 } else 00096 return 0; 00097 } 00098 len -= res; 00099 data += res; 00100 } 00101 return 0; 00102 }
|
|
Definition at line 290 of file app_zapscan.c. References ast_channel::_state, ast_answer(), ast_channel_walk_locked(), AST_DIGIT_ANY, AST_FRAME_DTMF, ast_frfree(), ast_mutex_unlock(), ast_read(), ast_say_number(), AST_STATE_UP, ast_stopstream(), ast_strdupa, ast_strlen_zero(), ast_verbose(), ast_waitfor(), conf_run(), ast_frame::frametype, get_zap_channel_locked(), input(), LOCAL_USER_ADD, ast_channel::lock, ast_channel::name, pbx_builtin_getvar_helper(), ast_frame::subclass, ast_channel::type, and VERBOSE_PREFIX_3. 00291 { 00292 int res=-1; 00293 struct localuser *u; 00294 int confflags = 0; 00295 int confno = 0; 00296 char confstr[80] = "", *tmp = NULL; 00297 struct ast_channel *tempchan = NULL, *lastchan = NULL,*ichan = NULL; 00298 struct ast_frame *f; 00299 char *mygroup; 00300 char *desired_group; 00301 int input=0,search_group=0; 00302 00303 LOCAL_USER_ADD(u); 00304 00305 if (chan->_state != AST_STATE_UP) 00306 ast_answer(chan); 00307 00308 desired_group = ast_strdupa((char *) data); 00309 if(!ast_strlen_zero(desired_group)) { 00310 ast_verbose(VERBOSE_PREFIX_3 "Scanning for group %s\n", desired_group); 00311 search_group = 1; 00312 } 00313 00314 for (;;) { 00315 if (ast_waitfor(chan, 100) < 0) 00316 break; 00317 00318 f = ast_read(chan); 00319 if (!f) 00320 break; 00321 if ((f->frametype == AST_FRAME_DTMF) && (f->subclass == '*')) { 00322 ast_frfree(f); 00323 break; 00324 } 00325 ast_frfree(f); 00326 ichan = NULL; 00327 if(input) { 00328 ichan = get_zap_channel_locked(input); 00329 input = 0; 00330 } 00331 00332 tempchan = ichan ? ichan : ast_channel_walk_locked(tempchan); 00333 00334 if ( !tempchan && !lastchan ) 00335 break; 00336 00337 if (tempchan && search_group) { 00338 if((mygroup = pbx_builtin_getvar_helper(tempchan, "GROUP")) && (!strcmp(mygroup, desired_group))) { 00339 ast_verbose(VERBOSE_PREFIX_3 "Found Matching Channel %s in group %s\n", tempchan->name, desired_group); 00340 } else { 00341 ast_mutex_unlock(&tempchan->lock); 00342 lastchan = tempchan; 00343 continue; 00344 } 00345 } 00346 if ( tempchan && tempchan->type && (!strcmp(tempchan->type, "Zap")) && (tempchan != chan) ) { 00347 ast_verbose(VERBOSE_PREFIX_3 "Zap channel %s is in-use, monitoring...\n", tempchan->name); 00348 ast_copy_string(confstr, tempchan->name, sizeof(confstr)); 00349 ast_mutex_unlock(&tempchan->lock); 00350 if ((tmp = strchr(confstr,'-'))) { 00351 *tmp = '\0'; 00352 } 00353 confno = atoi(strchr(confstr,'/') + 1); 00354 ast_stopstream(chan); 00355 ast_say_number(chan, confno, AST_DIGIT_ANY, chan->language, (char *) NULL); 00356 res = conf_run(chan, confno, confflags); 00357 if (res<0) break; 00358 input = res; 00359 } else if (tempchan) 00360 ast_mutex_unlock(&tempchan->lock); 00361 lastchan = tempchan; 00362 } 00363 LOCAL_USER_REMOVE(u); 00364 return res; 00365 }
|
|
Definition at line 104 of file app_zapscan.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, ast_frame::data, ast_frame::datalen, ast_channel::fds, ast_frame::frametype, input(), LOG_DEBUG, LOG_WARNING, ast_channel::name, ast_frame::subclass, ast_channel::type, and VERBOSE_PREFIX_3. 00105 { 00106 int fd; 00107 struct zt_confinfo ztc; 00108 struct ast_frame *f; 00109 struct ast_channel *c; 00110 struct ast_frame fr; 00111 int outfd; 00112 int ms; 00113 int nfds; 00114 int res; 00115 int flags; 00116 int retryzap; 00117 int origfd; 00118 int ret = -1; 00119 char input[4]; 00120 int ic=0; 00121 00122 ZT_BUFFERINFO bi; 00123 char __buf[CONF_SIZE + AST_FRIENDLY_OFFSET]; 00124 char *buf = __buf + AST_FRIENDLY_OFFSET; 00125 00126 /* Set it into U-law mode (write) */ 00127 if (ast_set_write_format(chan, AST_FORMAT_ULAW) < 0) { 00128 ast_log(LOG_WARNING, "Unable to set '%s' to write ulaw mode\n", chan->name); 00129 goto outrun; 00130 } 00131 00132 /* Set it into U-law mode (read) */ 00133 if (ast_set_read_format(chan, AST_FORMAT_ULAW) < 0) { 00134 ast_log(LOG_WARNING, "Unable to set '%s' to read ulaw mode\n", chan->name); 00135 goto outrun; 00136 } 00137 ast_indicate(chan, -1); 00138 retryzap = strcasecmp(chan->type, "Zap"); 00139 zapretry: 00140 origfd = chan->fds[0]; 00141 if (retryzap) { 00142 fd = open("/dev/zap/pseudo", O_RDWR); 00143 if (fd < 0) { 00144 ast_log(LOG_WARNING, "Unable to open pseudo channel: %s\n", strerror(errno)); 00145 goto outrun; 00146 } 00147 /* Make non-blocking */ 00148 flags = fcntl(fd, F_GETFL); 00149 if (flags < 0) { 00150 ast_log(LOG_WARNING, "Unable to get flags: %s\n", strerror(errno)); 00151 close(fd); 00152 goto outrun; 00153 } 00154 if (fcntl(fd, F_SETFL, flags | O_NONBLOCK)) { 00155 ast_log(LOG_WARNING, "Unable to set flags: %s\n", strerror(errno)); 00156 close(fd); 00157 goto outrun; 00158 } 00159 /* Setup buffering information */ 00160 memset(&bi, 0, sizeof(bi)); 00161 bi.bufsize = CONF_SIZE; 00162 bi.txbufpolicy = ZT_POLICY_IMMEDIATE; 00163 bi.rxbufpolicy = ZT_POLICY_IMMEDIATE; 00164 bi.numbufs = 4; 00165 if (ioctl(fd, ZT_SET_BUFINFO, &bi)) { 00166 ast_log(LOG_WARNING, "Unable to set buffering information: %s\n", strerror(errno)); 00167 close(fd); 00168 goto outrun; 00169 } 00170 nfds = 1; 00171 } else { 00172 /* XXX Make sure we're not running on a pseudo channel XXX */ 00173 fd = chan->fds[0]; 00174 nfds = 0; 00175 } 00176 memset(&ztc, 0, sizeof(ztc)); 00177 /* Check to see if we're in a conference... */ 00178 ztc.chan = 0; 00179 if (ioctl(fd, ZT_GETCONF, &ztc)) { 00180 ast_log(LOG_WARNING, "Error getting conference\n"); 00181 close(fd); 00182 goto outrun; 00183 } 00184 if (ztc.confmode) { 00185 /* Whoa, already in a conference... Retry... */ 00186 if (!retryzap) { 00187 ast_log(LOG_DEBUG, "Zap channel is in a conference already, retrying with pseudo\n"); 00188 retryzap = 1; 00189 goto zapretry; 00190 } 00191 } 00192 memset(&ztc, 0, sizeof(ztc)); 00193 /* Add us to the conference */ 00194 ztc.chan = 0; 00195 ztc.confno = confno; 00196 ztc.confmode = ZT_CONF_MONITORBOTH; 00197 00198 if (ioctl(fd, ZT_SETCONF, &ztc)) { 00199 ast_log(LOG_WARNING, "Error setting conference\n"); 00200 close(fd); 00201 goto outrun; 00202 } 00203 ast_log(LOG_DEBUG, "Placed channel %s in ZAP channel %d monitor\n", chan->name, confno); 00204 00205 for(;;) { 00206 outfd = -1; 00207 ms = -1; 00208 c = ast_waitfor_nandfds(&chan, 1, &fd, nfds, NULL, &outfd, &ms); 00209 if (c) { 00210 if (c->fds[0] != origfd) { 00211 if (retryzap) { 00212 /* Kill old pseudo */ 00213 close(fd); 00214 } 00215 ast_log(LOG_DEBUG, "Ooh, something swapped out under us, starting over\n"); 00216 retryzap = 0; 00217 goto zapretry; 00218 } 00219 f = ast_read(c); 00220 if (!f) 00221 break; 00222 if(f->frametype == AST_FRAME_DTMF) { 00223 if(f->subclass == '#') { 00224 ret = 0; 00225 break; 00226 } 00227 else if (f->subclass == '*') { 00228 ret = -1; 00229 break; 00230 00231 } 00232 else { 00233 input[ic++] = f->subclass; 00234 } 00235 if(ic == 3) { 00236 input[ic++] = '\0'; 00237 ic=0; 00238 ret = atoi(input); 00239 ast_verbose(VERBOSE_PREFIX_3 "Zapscan: change channel to %d\n",ret); 00240 break; 00241 } 00242 } 00243 00244 if (fd != chan->fds[0]) { 00245 if (f->frametype == AST_FRAME_VOICE) { 00246 if (f->subclass == AST_FORMAT_ULAW) { 00247 /* Carefully write */ 00248 careful_write(fd, f->data, f->datalen); 00249 } else 00250 ast_log(LOG_WARNING, "Huh? Got a non-ulaw (%d) frame in the conference\n", f->subclass); 00251 } 00252 } 00253 ast_frfree(f); 00254 } else if (outfd > -1) { 00255 res = read(outfd, buf, CONF_SIZE); 00256 if (res > 0) { 00257 memset(&fr, 0, sizeof(fr)); 00258 fr.frametype = AST_FRAME_VOICE; 00259 fr.subclass = AST_FORMAT_ULAW; 00260 fr.datalen = res; 00261 fr.samples = res; 00262 fr.data = buf; 00263 fr.offset = AST_FRIENDLY_OFFSET; 00264 if (ast_write(chan, &fr) < 0) { 00265 ast_log(LOG_WARNING, "Unable to write frame to channel: %s\n", strerror(errno)); 00266 /* break; */ 00267 } 00268 } else 00269 ast_log(LOG_WARNING, "Failed to read frame: %s\n", strerror(errno)); 00270 } 00271 } 00272 if (fd != chan->fds[0]) 00273 close(fd); 00274 else { 00275 /* Take out of conference */ 00276 /* Add us to the conference */ 00277 ztc.chan = 0; 00278 ztc.confno = 0; 00279 ztc.confmode = 0; 00280 if (ioctl(fd, ZT_SETCONF, &ztc)) { 00281 ast_log(LOG_WARNING, "Error setting conference\n"); 00282 } 00283 } 00284 00285 outrun: 00286 00287 return ret; 00288 }
|
|
Provides a description of the module.
Definition at line 383 of file app_zapscan.c. 00384 { 00385 return tdesc; 00386 }
|
|
Definition at line 79 of file app_zapscan.c. References ast_get_channel_by_name_locked(), and name. Referenced by conf_exec(). 00079 { 00080 char name[80]; 00081 00082 snprintf(name,sizeof(name),"Zap/%d-1",num); 00083 return ast_get_channel_by_name_locked(name); 00084 }
|
|
Returns the ASTERISK_GPL_KEY. This returns the ASTERISK_GPL_KEY, signifiying that you agree to the terms of the GPL stated in the ASTERISK_GPL_KEY. Your module will not load if it does not return the EXACT message:
char *key(void) { return ASTERISK_GPL_KEY; }
Definition at line 395 of file app_zapscan.c. References ASTERISK_GPL_KEY. 00396 { 00397 return ASTERISK_GPL_KEY; 00398 }
|
|
Initialize the module. Initialize the Agents module. This function is being called by Asterisk when loading the module. Among other thing it registers applications, cli commands and reads the cofiguration file.
Definition at line 378 of file app_zapscan.c. References ast_register_application(), and conf_exec(). 00379 { 00380 return ast_register_application(app, conf_exec, synopsis, descrip); 00381 }
|
|
Cleanup all module structures, sockets, etc. This is called at exit. Any registrations and memory allocations need to be unregistered and free'd here. Nothing else will do these for you (until exit).
Definition at line 367 of file app_zapscan.c. References ast_unregister_application(), and STANDARD_HANGUP_LOCALUSERS. 00368 { 00369 int res; 00370 00371 res = ast_unregister_application(app); 00372 00373 STANDARD_HANGUP_LOCALUSERS; 00374 00375 return res; 00376 }
|
|
Provides a usecount. This function will be called by various parts of asterisk. Basically, all it has to do is to return a usecount when called. You will need to maintain your usecount within the module somewhere. The usecount should be how many channels provided by this module are in use.
Definition at line 388 of file app_zapscan.c. References STANDARD_USECOUNT. 00389 { 00390 int res; 00391 STANDARD_USECOUNT(res); 00392 return res; 00393 }
|
|
Definition at line 63 of file app_zapscan.c. |
|
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 67 of file app_zapscan.c. |
|
Definition at line 74 of file app_zapscan.c. |
|
Definition at line 72 of file app_zapscan.c. |
|
Definition at line 65 of file app_zapscan.c. |
|
Definition at line 61 of file app_zapscan.c. |