00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026 #include <sys/ioctl.h>
00027 #include <sys/wait.h>
00028 #ifdef __linux__
00029 #include <sys/signal.h>
00030 #else
00031 #include <signal.h>
00032 #endif
00033
00034 #include <stdlib.h>
00035 #include <unistd.h>
00036 #include <string.h>
00037 #include <stdlib.h>
00038 #include <errno.h>
00039 #include <stdio.h>
00040 #include <fcntl.h>
00041
00042
00043 #ifdef __linux__
00044 #include <linux/zaptel.h>
00045 #else
00046 #include <zaptel.h>
00047 #endif
00048
00049 #include "asterisk.h"
00050
00051 ASTERISK_FILE_VERSION(__FILE__, "$Revision: 7221 $")
00052
00053 #include "asterisk/lock.h"
00054 #include "asterisk/file.h"
00055 #include "asterisk/logger.h"
00056 #include "asterisk/channel.h"
00057 #include "asterisk/pbx.h"
00058 #include "asterisk/module.h"
00059 #include "asterisk/options.h"
00060
00061 static char *tdesc = "Zap RAS Application";
00062
00063 static char *app = "ZapRAS";
00064
00065 static char *synopsis = "Executes Zaptel ISDN RAS application";
00066
00067 static char *descrip =
00068 " ZapRAS(args): Executes a RAS server using pppd on the given channel.\n"
00069 "The channel must be a clear channel (i.e. PRI source) and a Zaptel\n"
00070 "channel to be able to use this function (No modem emulation is included).\n"
00071 "Your pppd must be patched to be zaptel aware. Arguments should be\n"
00072 "separated by | characters.\n";
00073
00074 STANDARD_LOCAL_USER;
00075
00076 LOCAL_USER_DECL;
00077
00078 #define PPP_MAX_ARGS 32
00079 #define PPP_EXEC "/usr/sbin/pppd"
00080
00081 static pid_t spawn_ras(struct ast_channel *chan, char *args)
00082 {
00083 pid_t pid;
00084 int x;
00085 char *c;
00086
00087 char *argv[PPP_MAX_ARGS];
00088 int argc = 0;
00089 char *stringp=NULL;
00090
00091
00092 pid = fork();
00093 if (pid)
00094 return pid;
00095
00096
00097 dup2(chan->fds[0], STDIN_FILENO);
00098
00099
00100 for (x=STDERR_FILENO + 1;x<1024;x++)
00101 close(x);
00102
00103
00104 for (x=0;x<NSIG;x++)
00105 signal(x, SIG_DFL);
00106
00107
00108 memset(argv, 0, sizeof(argv));
00109
00110
00111
00112 argv[argc++] = PPP_EXEC;
00113 argv[argc++] = "nodetach";
00114
00115
00116 stringp=args;
00117 c = strsep(&stringp, "|");
00118 while(c && strlen(c) && (argc < (PPP_MAX_ARGS - 4))) {
00119 argv[argc++] = c;
00120 c = strsep(&stringp, "|");
00121 }
00122
00123 argv[argc++] = "plugin";
00124 argv[argc++] = "zaptel.so";
00125 argv[argc++] = "stdin";
00126
00127 #if 0
00128 for (x=0;x<argc;x++) {
00129 fprintf(stderr, "Arg %d: %s\n", x, argv[x]);
00130 }
00131 #endif
00132
00133
00134 execv(PPP_EXEC, argv);
00135 fprintf(stderr, "Failed to exec PPPD!\n");
00136 exit(1);
00137 }
00138
00139 static void run_ras(struct ast_channel *chan, char *args)
00140 {
00141 pid_t pid;
00142 int status;
00143 int res;
00144 int signalled = 0;
00145 struct zt_bufferinfo savebi;
00146 int x;
00147
00148 res = ioctl(chan->fds[0], ZT_GET_BUFINFO, &savebi);
00149 if(res) {
00150 ast_log(LOG_WARNING, "Unable to check buffer policy on channel %s\n", chan->name);
00151 return;
00152 }
00153
00154 pid = spawn_ras(chan, args);
00155 if (pid < 0) {
00156 ast_log(LOG_WARNING, "Failed to spawn RAS\n");
00157 } else {
00158 for (;;) {
00159 res = wait4(pid, &status, WNOHANG, NULL);
00160 if (!res) {
00161
00162 if (chan->_softhangup && !signalled) {
00163 ast_log(LOG_DEBUG, "Channel '%s' hungup. Signalling RAS at %d to die...\n", chan->name, pid);
00164 kill(pid, SIGTERM);
00165 signalled=1;
00166 }
00167
00168 sleep(1);
00169 continue;
00170 }
00171 if (res < 0) {
00172 ast_log(LOG_WARNING, "wait4 returned %d: %s\n", res, strerror(errno));
00173 }
00174 if (option_verbose > 2) {
00175 if (WIFEXITED(status)) {
00176 ast_verbose(VERBOSE_PREFIX_3 "RAS on %s terminated with status %d\n", chan->name, WEXITSTATUS(status));
00177 } else if (WIFSIGNALED(status)) {
00178 ast_verbose(VERBOSE_PREFIX_3 "RAS on %s terminated with signal %d\n",
00179 chan->name, WTERMSIG(status));
00180 } else {
00181 ast_verbose(VERBOSE_PREFIX_3 "RAS on %s terminated weirdly.\n", chan->name);
00182 }
00183 }
00184
00185 x = 1;
00186 ioctl(chan->fds[0], ZT_AUDIOMODE, &x);
00187
00188
00189 res = ioctl(chan->fds[0], ZT_SET_BUFINFO, &savebi);
00190 if (res < 0) {
00191 ast_log(LOG_WARNING, "Unable to set buffer policy on channel %s\n", chan->name);
00192 }
00193 break;
00194 }
00195 }
00196 }
00197
00198 static int zapras_exec(struct ast_channel *chan, void *data)
00199 {
00200 int res=-1;
00201 char *args;
00202 struct localuser *u;
00203 ZT_PARAMS ztp;
00204
00205 if (!data)
00206 data = "";
00207
00208 LOCAL_USER_ADD(u);
00209
00210 args = ast_strdupa(data);
00211 if (!args) {
00212 ast_log(LOG_ERROR, "Out of memory\n");
00213 LOCAL_USER_REMOVE(u);
00214 return -1;
00215 }
00216
00217
00218 if (chan->_state != AST_STATE_UP)
00219 ast_answer(chan);
00220 if (strcasecmp(chan->type, "Zap")) {
00221
00222
00223 if (option_verbose > 1)
00224 ast_verbose(VERBOSE_PREFIX_2 "Channel %s is not a Zap channel\n", chan->name);
00225 sleep(2);
00226 } else {
00227 memset(&ztp, 0, sizeof(ztp));
00228 if (ioctl(chan->fds[0], ZT_GET_PARAMS, &ztp)) {
00229 ast_log(LOG_WARNING, "Unable to get zaptel parameters\n");
00230 } else if (ztp.sigtype != ZT_SIG_CLEAR) {
00231 if (option_verbose > 1)
00232 ast_verbose(VERBOSE_PREFIX_2 "Channel %s is not a clear channel\n", chan->name);
00233 } else {
00234
00235 if (option_verbose > 2)
00236 ast_verbose(VERBOSE_PREFIX_3 "Starting RAS on %s\n", chan->name);
00237
00238 run_ras(chan, args);
00239 }
00240 }
00241 LOCAL_USER_REMOVE(u);
00242 return res;
00243 }
00244
00245 int unload_module(void)
00246 {
00247 int res;
00248
00249 res = ast_unregister_application(app);
00250
00251 STANDARD_HANGUP_LOCALUSERS;
00252
00253 return res;
00254 }
00255
00256 int load_module(void)
00257 {
00258 return ast_register_application(app, zapras_exec, synopsis, descrip);
00259 }
00260
00261 char *description(void)
00262 {
00263 return tdesc;
00264 }
00265
00266 int usecount(void)
00267 {
00268 int res;
00269 STANDARD_USECOUNT(res);
00270 return res;
00271 }
00272
00273 char *key()
00274 {
00275 return ASTERISK_GPL_KEY;
00276 }