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