#include "asterisk.h"
#include <sys/ioctl.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"
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 = "068e67f60f50dd9ee86464c05884a49d" , .load = load_module, .unload = unload_module, } |
static char * | app = "DAHDIScan" |
static const struct ast_module_info * | ast_module_info = &__mod_info |
static char * | descrip |
static char * | synopsis = "Scan DAHDI channels to monitor calls" |
Definition in file app_dahdiscan.c.
#define CONF_SIZE 160 |
Definition at line 65 of file app_dahdiscan.c.
static void __reg_module | ( | void | ) | [static] |
Definition at line 363 of file app_dahdiscan.c.
static void __unreg_module | ( | void | ) | [static] |
Definition at line 363 of file app_dahdiscan.c.
static int careful_write | ( | int | fd, | |
unsigned char * | data, | |||
int | len | |||
) | [static] |
Definition at line 74 of file app_dahdiscan.c.
References ast_log(), errno, and LOG_WARNING.
00075 { 00076 int res; 00077 while(len) { 00078 res = write(fd, data, len); 00079 if (res < 1) { 00080 if (errno != EAGAIN) { 00081 ast_log(LOG_WARNING, "Failed to write audio data to conference: %s\n", strerror(errno)); 00082 return -1; 00083 } else 00084 return 0; 00085 } 00086 len -= res; 00087 data += res; 00088 } 00089 return 0; 00090 }
static int conf_exec | ( | struct ast_channel * | chan, | |
void * | data | |||
) | [static] |
Definition at line 280 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_strdupa, ast_strlen_zero(), ast_verb, ast_waitfor(), chan, conf_run(), f, get_dahdi_channel_locked(), input(), ast_channel::name, pbx_builtin_getvar_helper(), ast_channel::tech, and ast_channel_tech::type.
00281 { 00282 int res=-1; 00283 int confflags = 0; 00284 int confno = 0; 00285 char confstr[80] = "", *tmp = NULL; 00286 struct ast_channel *tempchan = NULL, *lastchan = NULL,*ichan = NULL; 00287 struct ast_frame *f; 00288 char *desired_group; 00289 int input=0,search_group=0; 00290 00291 if (chan->_state != AST_STATE_UP) 00292 ast_answer(chan); 00293 00294 desired_group = ast_strdupa(data); 00295 if(!ast_strlen_zero(desired_group)) { 00296 ast_verb(3, "Scanning for group %s\n", desired_group); 00297 search_group = 1; 00298 } 00299 00300 for (;;) { 00301 if (ast_waitfor(chan, 100) < 0) 00302 break; 00303 00304 f = ast_read(chan); 00305 if (!f) 00306 break; 00307 if ((f->frametype == AST_FRAME_DTMF) && (f->subclass == '*')) { 00308 ast_frfree(f); 00309 break; 00310 } 00311 ast_frfree(f); 00312 ichan = NULL; 00313 if(input) { 00314 ichan = get_dahdi_channel_locked(input); 00315 input = 0; 00316 } 00317 00318 tempchan = ichan ? ichan : ast_channel_walk_locked(tempchan); 00319 00320 if ( !tempchan && !lastchan ) 00321 break; 00322 00323 if (tempchan && search_group) { 00324 const char *mygroup; 00325 if((mygroup = pbx_builtin_getvar_helper(tempchan, "GROUP")) && (!strcmp(mygroup, desired_group))) { 00326 ast_verb(3, "Found Matching Channel %s in group %s\n", tempchan->name, desired_group); 00327 } else { 00328 ast_channel_unlock(tempchan); 00329 lastchan = tempchan; 00330 continue; 00331 } 00332 } 00333 if (tempchan && (!strcmp(tempchan->tech->type, "DAHDI")) && (tempchan != chan) ) { 00334 ast_verb(3, "DAHDI channel %s is in-use, monitoring...\n", tempchan->name); 00335 ast_copy_string(confstr, tempchan->name, sizeof(confstr)); 00336 ast_channel_unlock(tempchan); 00337 if ((tmp = strchr(confstr,'-'))) { 00338 *tmp = '\0'; 00339 } 00340 confno = atoi(strchr(confstr,'/') + 1); 00341 ast_stopstream(chan); 00342 ast_say_number(chan, confno, AST_DIGIT_ANY, chan->language, (char *) NULL); 00343 res = conf_run(chan, confno, confflags); 00344 if (res<0) break; 00345 input = res; 00346 } else if (tempchan) 00347 ast_channel_unlock(tempchan); 00348 lastchan = tempchan; 00349 } 00350 return res; 00351 }
static int conf_run | ( | struct ast_channel * | chan, | |
int | confno, | |||
int | confflags | |||
) | [static] |
Definition at line 92 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(), chan, CONF_SIZE, errno, f, ast_channel::fds, ast_frame::flags, input(), LOG_WARNING, ast_channel::name, ast_channel::tech, and ast_channel_tech::type.
00093 { 00094 int fd; 00095 struct dahdi_confinfo dahdic; 00096 struct ast_frame *f; 00097 struct ast_channel *c; 00098 struct ast_frame fr; 00099 int outfd; 00100 int ms; 00101 int nfds; 00102 int res; 00103 int flags; 00104 int retrydahdi; 00105 int origfd; 00106 int ret = -1; 00107 char input[4]; 00108 int ic=0; 00109 00110 struct dahdi_bufferinfo bi; 00111 char __buf[CONF_SIZE + AST_FRIENDLY_OFFSET]; 00112 char *buf = __buf + AST_FRIENDLY_OFFSET; 00113 00114 /* Set it into U-law mode (write) */ 00115 if (ast_set_write_format(chan, AST_FORMAT_ULAW) < 0) { 00116 ast_log(LOG_WARNING, "Unable to set '%s' to write ulaw mode\n", chan->name); 00117 goto outrun; 00118 } 00119 00120 /* Set it into U-law mode (read) */ 00121 if (ast_set_read_format(chan, AST_FORMAT_ULAW) < 0) { 00122 ast_log(LOG_WARNING, "Unable to set '%s' to read ulaw mode\n", chan->name); 00123 goto outrun; 00124 } 00125 ast_indicate(chan, -1); 00126 retrydahdi = strcasecmp(chan->tech->type, "DAHDI"); 00127 dahdiretry: 00128 origfd = chan->fds[0]; 00129 if (retrydahdi) { 00130 fd = open("/dev/dahdi/pseudo", O_RDWR); 00131 if (fd < 0) { 00132 ast_log(LOG_WARNING, "Unable to open pseudo channel: %s\n", strerror(errno)); 00133 goto outrun; 00134 } 00135 /* Make non-blocking */ 00136 flags = fcntl(fd, F_GETFL); 00137 if (flags < 0) { 00138 ast_log(LOG_WARNING, "Unable to get flags: %s\n", strerror(errno)); 00139 close(fd); 00140 goto outrun; 00141 } 00142 if (fcntl(fd, F_SETFL, flags | O_NONBLOCK)) { 00143 ast_log(LOG_WARNING, "Unable to set flags: %s\n", strerror(errno)); 00144 close(fd); 00145 goto outrun; 00146 } 00147 /* Setup buffering information */ 00148 memset(&bi, 0, sizeof(bi)); 00149 bi.bufsize = CONF_SIZE; 00150 bi.txbufpolicy = DAHDI_POLICY_IMMEDIATE; 00151 bi.rxbufpolicy = DAHDI_POLICY_IMMEDIATE; 00152 bi.numbufs = 4; 00153 if (ioctl(fd, DAHDI_SET_BUFINFO, &bi)) { 00154 ast_log(LOG_WARNING, "Unable to set buffering information: %s\n", strerror(errno)); 00155 close(fd); 00156 goto outrun; 00157 } 00158 nfds = 1; 00159 } else { 00160 /* XXX Make sure we're not running on a pseudo channel XXX */ 00161 fd = chan->fds[0]; 00162 nfds = 0; 00163 } 00164 memset(&dahdic, 0, sizeof(dahdic)); 00165 /* Check to see if we're in a conference... */ 00166 dahdic.chan = 0; 00167 if (ioctl(fd, DAHDI_GETCONF, &dahdic)) { 00168 ast_log(LOG_WARNING, "Error getting conference\n"); 00169 close(fd); 00170 goto outrun; 00171 } 00172 if (dahdic.confmode) { 00173 /* Whoa, already in a conference... Retry... */ 00174 if (!retrydahdi) { 00175 ast_debug(1, "DAHDI channel is in a conference already, retrying with pseudo\n"); 00176 retrydahdi = 1; 00177 goto dahdiretry; 00178 } 00179 } 00180 memset(&dahdic, 0, sizeof(dahdic)); 00181 /* Add us to the conference */ 00182 dahdic.chan = 0; 00183 dahdic.confno = confno; 00184 dahdic.confmode = DAHDI_CONF_MONITORBOTH; 00185 00186 if (ioctl(fd, DAHDI_SETCONF, &dahdic)) { 00187 ast_log(LOG_WARNING, "Error setting conference\n"); 00188 close(fd); 00189 goto outrun; 00190 } 00191 ast_debug(1, "Placed channel %s in DAHDI channel %d monitor\n", chan->name, confno); 00192 00193 for(;;) { 00194 outfd = -1; 00195 ms = -1; 00196 c = ast_waitfor_nandfds(&chan, 1, &fd, nfds, NULL, &outfd, &ms); 00197 if (c) { 00198 if (c->fds[0] != origfd) { 00199 if (retrydahdi) { 00200 /* Kill old pseudo */ 00201 close(fd); 00202 } 00203 ast_debug(1, "Ooh, something swapped out under us, starting over\n"); 00204 retrydahdi = 0; 00205 goto dahdiretry; 00206 } 00207 f = ast_read(c); 00208 if (!f) 00209 break; 00210 if(f->frametype == AST_FRAME_DTMF) { 00211 if(f->subclass == '#') { 00212 ret = 0; 00213 break; 00214 } 00215 else if (f->subclass == '*') { 00216 ret = -1; 00217 break; 00218 00219 } 00220 else { 00221 input[ic++] = f->subclass; 00222 } 00223 if(ic == 3) { 00224 input[ic++] = '\0'; 00225 ic=0; 00226 ret = atoi(input); 00227 ast_verb(3, "DAHDIscan: change channel to %d\n",ret); 00228 break; 00229 } 00230 } 00231 00232 if (fd != chan->fds[0]) { 00233 if (f->frametype == AST_FRAME_VOICE) { 00234 if (f->subclass == AST_FORMAT_ULAW) { 00235 /* Carefully write */ 00236 careful_write(fd, f->data, f->datalen); 00237 } else 00238 ast_log(LOG_WARNING, "Huh? Got a non-ulaw (%d) frame in the conference\n", f->subclass); 00239 } 00240 } 00241 ast_frfree(f); 00242 } else if (outfd > -1) { 00243 res = read(outfd, buf, CONF_SIZE); 00244 if (res > 0) { 00245 memset(&fr, 0, sizeof(fr)); 00246 fr.frametype = AST_FRAME_VOICE; 00247 fr.subclass = AST_FORMAT_ULAW; 00248 fr.datalen = res; 00249 fr.samples = res; 00250 fr.data = buf; 00251 fr.offset = AST_FRIENDLY_OFFSET; 00252 if (ast_write(chan, &fr) < 0) { 00253 ast_log(LOG_WARNING, "Unable to write frame to channel: %s\n", strerror(errno)); 00254 /* break; */ 00255 } 00256 } else 00257 ast_log(LOG_WARNING, "Failed to read frame: %s\n", strerror(errno)); 00258 } 00259 } 00260 if (f) 00261 ast_frfree(f); 00262 if (fd != chan->fds[0]) 00263 close(fd); 00264 else { 00265 /* Take out of conference */ 00266 /* Add us to the conference */ 00267 dahdic.chan = 0; 00268 dahdic.confno = 0; 00269 dahdic.confmode = 0; 00270 if (ioctl(fd, DAHDI_SETCONF, &dahdic)) { 00271 ast_log(LOG_WARNING, "Error setting conference\n"); 00272 } 00273 } 00274 00275 outrun: 00276 00277 return ret; 00278 }
static struct ast_channel* get_dahdi_channel_locked | ( | int | num | ) | [static] |
Definition at line 67 of file app_dahdiscan.c.
References ast_get_channel_by_name_locked(), and name.
Referenced by conf_exec().
00067 { 00068 char name[80]; 00069 00070 snprintf(name, sizeof(name), "DAHDI/%d-1", num); 00071 return ast_get_channel_by_name_locked(name); 00072 }
static int load_module | ( | void | ) | [static] |
Definition at line 358 of file app_dahdiscan.c.
References AST_MODULE_LOAD_FAILURE, AST_MODULE_LOAD_SUCCESS, ast_register_application, and conf_exec().
00359 { 00360 return ((ast_register_application(app, conf_exec, synopsis, descrip)) ? AST_MODULE_LOAD_FAILURE : AST_MODULE_LOAD_SUCCESS); 00361 }
static int unload_module | ( | void | ) | [static] |
Definition at line 353 of file app_dahdiscan.c.
References ast_unregister_application().
00354 { 00355 return ast_unregister_application(app); 00356 }
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 = "068e67f60f50dd9ee86464c05884a49d" , .load = load_module, .unload = unload_module, } [static] |
Definition at line 363 of file app_dahdiscan.c.
char* app = "DAHDIScan" [static] |
Definition at line 55 of file app_dahdiscan.c.
const struct ast_module_info* ast_module_info = &__mod_info [static] |
Definition at line 363 of file app_dahdiscan.c.
char* descrip [static] |
Initial value:
" DAHDIScan([group]) allows a call center manager to monitor DAHDI 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 59 of file app_dahdiscan.c.
Definition at line 57 of file app_dahdiscan.c.