#include "asterisk.h"
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>
#include <sys/ioctl.h>
#include <zaptel/zaptel.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/cli.h"
#include "asterisk/say.h"
#include "asterisk/utils.h"
Include dependency graph for app_zapbarge.c:
Go to the source code of this file.
Defines | |
#define | CONF_SIZE 160 |
Functions | |
AST_MODULE_INFO_STANDARD (ASTERISK_GPL_KEY,"Barge in on Zap channel 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_run (struct ast_channel *chan, int confno, int confflags) |
static int | load_module (void) |
static int | unload_module (void) |
Variables | |
static char * | app = "ZapBarge" |
static char * | descrip |
static char * | synopsis = "Barge in (monitor) Zap channel" |
Definition in file app_zapbarge.c.
#define CONF_SIZE 160 |
Definition at line 74 of file app_zapbarge.c.
AST_MODULE_INFO_STANDARD | ( | ASTERISK_GPL_KEY | , | |
"Barge in on Zap channel application" | ||||
) |
static int careful_write | ( | int | fd, | |
unsigned char * | data, | |||
int | len | |||
) | [static] |
Definition at line 76 of file app_zapbarge.c.
References ast_log(), errno, and LOG_WARNING.
00077 { 00078 int res; 00079 while(len) { 00080 res = write(fd, data, len); 00081 if (res < 1) { 00082 if (errno != EAGAIN) { 00083 ast_log(LOG_WARNING, "Failed to write audio data to conference: %s\n", strerror(errno)); 00084 return -1; 00085 } else 00086 return 0; 00087 } 00088 len -= res; 00089 data += res; 00090 } 00091 return 0; 00092 }
static int conf_exec | ( | struct ast_channel * | chan, | |
void * | data | |||
) | [static] |
Definition at line 260 of file app_zapbarge.c.
References ast_channel::_state, ast_answer(), ast_app_getdata(), ast_log(), ast_module_user_add, ast_module_user_remove, AST_STATE_UP, ast_strlen_zero(), ast_module_user::chan, conf_run(), and LOG_WARNING.
00261 { 00262 int res=-1; 00263 struct ast_module_user *u; 00264 int retrycnt = 0; 00265 int confflags = 0; 00266 int confno = 0; 00267 char confstr[80] = ""; 00268 00269 u = ast_module_user_add(chan); 00270 00271 if (!ast_strlen_zero(data)) { 00272 if ((sscanf(data, "Zap/%d", &confno) != 1) && 00273 (sscanf(data, "%d", &confno) != 1)) { 00274 ast_log(LOG_WARNING, "ZapBarge Argument (if specified) must be a channel number, not '%s'\n", (char *)data); 00275 ast_module_user_remove(u); 00276 return 0; 00277 } 00278 } 00279 00280 if (chan->_state != AST_STATE_UP) 00281 ast_answer(chan); 00282 00283 while(!confno && (++retrycnt < 4)) { 00284 /* Prompt user for conference number */ 00285 confstr[0] = '\0'; 00286 res = ast_app_getdata(chan, "conf-getchannel",confstr, sizeof(confstr) - 1, 0); 00287 if (res <0) goto out; 00288 if (sscanf(confstr, "%d", &confno) != 1) 00289 confno = 0; 00290 } 00291 if (confno) { 00292 /* XXX Should prompt user for pin if pin is required XXX */ 00293 /* Run the conference */ 00294 res = conf_run(chan, confno, confflags); 00295 } 00296 out: 00297 /* Do the conference */ 00298 ast_module_user_remove(u); 00299 return res; 00300 }
static int conf_run | ( | struct ast_channel * | chan, | |
int | confno, | |||
int | confflags | |||
) | [static] |
Definition at line 94 of file app_zapbarge.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_waitfor_nandfds(), ast_write(), careful_write(), CONF_SIZE, errno, f, ast_channel::fds, ast_frame::flags, LOG_DEBUG, LOG_WARNING, ast_channel::tech, and ast_channel_tech::type.
00095 { 00096 int fd; 00097 struct zt_confinfo ztc; 00098 struct ast_frame *f; 00099 struct ast_channel *c; 00100 struct ast_frame fr; 00101 int outfd; 00102 int ms; 00103 int nfds; 00104 int res; 00105 int flags; 00106 int retryzap; 00107 int origfd; 00108 int ret = -1; 00109 00110 ZT_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 retryzap = strcasecmp(chan->tech->type, "Zap"); 00127 zapretry: 00128 origfd = chan->fds[0]; 00129 if (retryzap) { 00130 fd = open("/dev/zap/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 = ZT_POLICY_IMMEDIATE; 00151 bi.rxbufpolicy = ZT_POLICY_IMMEDIATE; 00152 bi.numbufs = 4; 00153 if (ioctl(fd, ZT_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(&ztc, 0, sizeof(ztc)); 00165 /* Check to see if we're in a conference... */ 00166 ztc.chan = 0; 00167 if (ioctl(fd, ZT_GETCONF, &ztc)) { 00168 ast_log(LOG_WARNING, "Error getting conference\n"); 00169 close(fd); 00170 goto outrun; 00171 } 00172 if (ztc.confmode) { 00173 /* Whoa, already in a conference... Retry... */ 00174 if (!retryzap) { 00175 ast_log(LOG_DEBUG, "Zap channel is in a conference already, retrying with pseudo\n"); 00176 retryzap = 1; 00177 goto zapretry; 00178 } 00179 } 00180 memset(&ztc, 0, sizeof(ztc)); 00181 /* Add us to the conference */ 00182 ztc.chan = 0; 00183 ztc.confno = confno; 00184 ztc.confmode = ZT_CONF_MONITORBOTH; 00185 00186 if (ioctl(fd, ZT_SETCONF, &ztc)) { 00187 ast_log(LOG_WARNING, "Error setting conference\n"); 00188 close(fd); 00189 goto outrun; 00190 } 00191 ast_log(LOG_DEBUG, "Placed channel %s in ZAP 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 (retryzap) { 00200 /* Kill old pseudo */ 00201 close(fd); 00202 } 00203 ast_log(LOG_DEBUG, "Ooh, something swapped out under us, starting over\n"); 00204 retryzap = 0; 00205 goto zapretry; 00206 } 00207 f = ast_read(c); 00208 if (!f) 00209 break; 00210 if ((f->frametype == AST_FRAME_DTMF) && (f->subclass == '#')) { 00211 ret = 0; 00212 ast_frfree(f); 00213 break; 00214 } else if (fd != chan->fds[0]) { 00215 if (f->frametype == AST_FRAME_VOICE) { 00216 if (f->subclass == AST_FORMAT_ULAW) { 00217 /* Carefully write */ 00218 careful_write(fd, f->data, f->datalen); 00219 } else 00220 ast_log(LOG_WARNING, "Huh? Got a non-ulaw (%d) frame in the conference\n", f->subclass); 00221 } 00222 } 00223 ast_frfree(f); 00224 } else if (outfd > -1) { 00225 res = read(outfd, buf, CONF_SIZE); 00226 if (res > 0) { 00227 memset(&fr, 0, sizeof(fr)); 00228 fr.frametype = AST_FRAME_VOICE; 00229 fr.subclass = AST_FORMAT_ULAW; 00230 fr.datalen = res; 00231 fr.samples = res; 00232 fr.data = buf; 00233 fr.offset = AST_FRIENDLY_OFFSET; 00234 if (ast_write(chan, &fr) < 0) { 00235 ast_log(LOG_WARNING, "Unable to write frame to channel: %s\n", strerror(errno)); 00236 /* break; */ 00237 } 00238 } else 00239 ast_log(LOG_WARNING, "Failed to read frame: %s\n", strerror(errno)); 00240 } 00241 } 00242 if (fd != chan->fds[0]) 00243 close(fd); 00244 else { 00245 /* Take out of conference */ 00246 /* Add us to the conference */ 00247 ztc.chan = 0; 00248 ztc.confno = 0; 00249 ztc.confmode = 0; 00250 if (ioctl(fd, ZT_SETCONF, &ztc)) { 00251 ast_log(LOG_WARNING, "Error setting conference\n"); 00252 } 00253 } 00254 00255 outrun: 00256 00257 return ret; 00258 }
static int load_module | ( | void | ) | [static] |
Definition at line 313 of file app_zapbarge.c.
References ast_register_application(), and conf_exec().
00314 { 00315 return ast_register_application(app, conf_exec, synopsis, descrip); 00316 }
static int unload_module | ( | void | ) | [static] |
Definition at line 302 of file app_zapbarge.c.
References ast_module_user_hangup_all, and ast_unregister_application().
00303 { 00304 int res; 00305 00306 res = ast_unregister_application(app); 00307 00308 ast_module_user_hangup_all(); 00309 00310 return res; 00311 }
char* app = "ZapBarge" [static] |
Definition at line 63 of file app_zapbarge.c.
char* descrip [static] |
Initial value:
" ZapBarge([channel]): Barges in on a specified zap\n" "channel or prompts if one is not specified. Returns\n" "-1 when caller user hangs up and is independent of the\n" "state of the channel being monitored."
Definition at line 67 of file app_zapbarge.c.
Definition at line 65 of file app_zapbarge.c.