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: 37419 $")
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 if (option_highpriority)
00101 ast_set_priority(0);
00102
00103
00104 for (x=STDERR_FILENO + 1;x<1024;x++)
00105 close(x);
00106
00107
00108 for (x=0;x<NSIG;x++)
00109 signal(x, SIG_DFL);
00110
00111
00112 memset(argv, 0, sizeof(argv));
00113
00114
00115
00116 argv[argc++] = PPP_EXEC;
00117 argv[argc++] = "nodetach";
00118
00119
00120 stringp=args;
00121 c = strsep(&stringp, "|");
00122 while(c && strlen(c) && (argc < (PPP_MAX_ARGS - 4))) {
00123 argv[argc++] = c;
00124 c = strsep(&stringp, "|");
00125 }
00126
00127 argv[argc++] = "plugin";
00128 argv[argc++] = "zaptel.so";
00129 argv[argc++] = "stdin";
00130
00131
00132 execv(PPP_EXEC, argv);
00133 fprintf(stderr, "Failed to exec PPPD!\n");
00134 exit(1);
00135 }
00136
00137 static void run_ras(struct ast_channel *chan, char *args)
00138 {
00139 pid_t pid;
00140 int status;
00141 int res;
00142 int signalled = 0;
00143 struct zt_bufferinfo savebi;
00144 int x;
00145
00146 res = ioctl(chan->fds[0], ZT_GET_BUFINFO, &savebi);
00147 if(res) {
00148 ast_log(LOG_WARNING, "Unable to check buffer policy on channel %s\n", chan->name);
00149 return;
00150 }
00151
00152 pid = spawn_ras(chan, args);
00153 if (pid < 0) {
00154 ast_log(LOG_WARNING, "Failed to spawn RAS\n");
00155 } else {
00156 for (;;) {
00157 res = wait4(pid, &status, WNOHANG, NULL);
00158 if (!res) {
00159
00160 if (chan->_softhangup && !signalled) {
00161 ast_log(LOG_DEBUG, "Channel '%s' hungup. Signalling RAS at %d to die...\n", chan->name, pid);
00162 kill(pid, SIGTERM);
00163 signalled=1;
00164 }
00165
00166 sleep(1);
00167 continue;
00168 }
00169 if (res < 0) {
00170 ast_log(LOG_WARNING, "wait4 returned %d: %s\n", res, strerror(errno));
00171 }
00172 if (option_verbose > 2) {
00173 if (WIFEXITED(status)) {
00174 ast_verbose(VERBOSE_PREFIX_3 "RAS on %s terminated with status %d\n", chan->name, WEXITSTATUS(status));
00175 } else if (WIFSIGNALED(status)) {
00176 ast_verbose(VERBOSE_PREFIX_3 "RAS on %s terminated with signal %d\n",
00177 chan->name, WTERMSIG(status));
00178 } else {
00179 ast_verbose(VERBOSE_PREFIX_3 "RAS on %s terminated weirdly.\n", chan->name);
00180 }
00181 }
00182
00183 x = 1;
00184 ioctl(chan->fds[0], ZT_AUDIOMODE, &x);
00185
00186
00187 res = ioctl(chan->fds[0], ZT_SET_BUFINFO, &savebi);
00188 if (res < 0) {
00189 ast_log(LOG_WARNING, "Unable to set buffer policy on channel %s\n", chan->name);
00190 }
00191 break;
00192 }
00193 }
00194 }
00195
00196 static int zapras_exec(struct ast_channel *chan, void *data)
00197 {
00198 int res=-1;
00199 char *args;
00200 struct localuser *u;
00201 ZT_PARAMS ztp;
00202
00203 if (!data)
00204 data = "";
00205
00206 LOCAL_USER_ADD(u);
00207
00208 args = ast_strdupa(data);
00209 if (!args) {
00210 ast_log(LOG_ERROR, "Out of memory\n");
00211 LOCAL_USER_REMOVE(u);
00212 return -1;
00213 }
00214
00215
00216 if (chan->_state != AST_STATE_UP)
00217 ast_answer(chan);
00218 if (strcasecmp(chan->type, "Zap")) {
00219
00220
00221 if (option_verbose > 1)
00222 ast_verbose(VERBOSE_PREFIX_2 "Channel %s is not a Zap channel\n", chan->name);
00223 sleep(2);
00224 } else {
00225 memset(&ztp, 0, sizeof(ztp));
00226 if (ioctl(chan->fds[0], ZT_GET_PARAMS, &ztp)) {
00227 ast_log(LOG_WARNING, "Unable to get zaptel parameters\n");
00228 } else if (ztp.sigtype != ZT_SIG_CLEAR) {
00229 if (option_verbose > 1)
00230 ast_verbose(VERBOSE_PREFIX_2 "Channel %s is not a clear channel\n", chan->name);
00231 } else {
00232
00233 if (option_verbose > 2)
00234 ast_verbose(VERBOSE_PREFIX_3 "Starting RAS on %s\n", chan->name);
00235
00236 run_ras(chan, args);
00237 }
00238 }
00239 LOCAL_USER_REMOVE(u);
00240 return res;
00241 }
00242
00243 int unload_module(void)
00244 {
00245 int res;
00246
00247 res = ast_unregister_application(app);
00248
00249 STANDARD_HANGUP_LOCALUSERS;
00250
00251 return res;
00252 }
00253
00254 int load_module(void)
00255 {
00256 return ast_register_application(app, zapras_exec, synopsis, descrip);
00257 }
00258
00259 char *description(void)
00260 {
00261 return tdesc;
00262 }
00263
00264 int usecount(void)
00265 {
00266 int res;
00267 STANDARD_USECOUNT(res);
00268 return res;
00269 }
00270
00271 char *key()
00272 {
00273 return ASTERISK_GPL_KEY;
00274 }