#include <sys/ioctl.h>
#include <sys/wait.h>
#include <signal.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>
#include <stdio.h>
#include <fcntl.h>
#include <zaptel.h>
#include "asterisk.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/options.h"
Go to the source code of this file.
Defines | |
#define | PPP_EXEC "/usr/sbin/pppd" |
#define | PPP_MAX_ARGS 32 |
Functions | |
char * | description (void) |
Provides a description of the module. | |
char * | key () |
Returns the ASTERISK_GPL_KEY. | |
int | load_module (void) |
Initialize the module. | |
static void | run_ras (struct ast_channel *chan, char *args) |
static pid_t | spawn_ras (struct ast_channel *chan, char *args) |
int | unload_module (void) |
Cleanup all module structures, sockets, etc. | |
int | usecount (void) |
Provides a usecount. | |
static int | zapras_exec (struct ast_channel *chan, void *data) |
Variables | |
static char * | app = "ZapRAS" |
static char * | descrip |
LOCAL_USER_DECL | |
STANDARD_LOCAL_USER | |
static char * | synopsis = "Executes Zaptel ISDN RAS application" |
static char * | tdesc = "Zap RAS Application" |
Definition in file app_zapras.c.
#define PPP_EXEC "/usr/sbin/pppd" |
#define PPP_MAX_ARGS 32 |
char* description | ( | void | ) |
Provides a description of the module.
Definition at line 259 of file app_zapras.c.
References tdesc.
00260 { 00261 return tdesc; 00262 }
char* key | ( | void | ) |
Returns the ASTERISK_GPL_KEY.
This returns the ASTERISK_GPL_KEY, signifiying that you agree to the terms of the GPL stated in the ASTERISK_GPL_KEY. Your module will not load if it does not return the EXACT message:
char *key(void) { return ASTERISK_GPL_KEY; }
Definition at line 271 of file app_zapras.c.
References ASTERISK_GPL_KEY.
00272 { 00273 return ASTERISK_GPL_KEY; 00274 }
int load_module | ( | void | ) |
Initialize the module.
Initialize the Agents module. This function is being called by Asterisk when loading the module. Among other thing it registers applications, cli commands and reads the cofiguration file.
Definition at line 254 of file app_zapras.c.
References app, ast_register_application(), descrip, synopsis, and zapras_exec().
00255 { 00256 return ast_register_application(app, zapras_exec, synopsis, descrip); 00257 }
static void run_ras | ( | struct ast_channel * | chan, | |
char * | args | |||
) | [static] |
Definition at line 137 of file app_zapras.c.
References ast_channel::_softhangup, ast_log(), ast_verbose(), ast_channel::fds, LOG_DEBUG, LOG_WARNING, ast_channel::name, option_verbose, spawn_ras(), and VERBOSE_PREFIX_3.
Referenced by zapras_exec().
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 /* Check for hangup */ 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 /* Try again */ 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 /* Throw back into audio mode */ 00183 x = 1; 00184 ioctl(chan->fds[0], ZT_AUDIOMODE, &x); 00185 00186 /* Restore saved values */ 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 }
static pid_t spawn_ras | ( | struct ast_channel * | chan, | |
char * | args | |||
) | [static] |
Definition at line 81 of file app_zapras.c.
References ast_set_priority(), localuser::chan, ast_channel::fds, option_highpriority, PPP_EXEC, PPP_MAX_ARGS, and strsep().
Referenced by run_ras().
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 /* Start by forking */ 00092 pid = fork(); 00093 if (pid) 00094 return pid; 00095 00096 /* Execute RAS on File handles */ 00097 dup2(chan->fds[0], STDIN_FILENO); 00098 00099 /* Drop high priority */ 00100 if (option_highpriority) 00101 ast_set_priority(0); 00102 00103 /* Close other file descriptors */ 00104 for (x=STDERR_FILENO + 1;x<1024;x++) 00105 close(x); 00106 00107 /* Restore original signal handlers */ 00108 for (x=0;x<NSIG;x++) 00109 signal(x, SIG_DFL); 00110 00111 /* Reset all arguments */ 00112 memset(argv, 0, sizeof(argv)); 00113 00114 /* First argument is executable, followed by standard 00115 arguments for zaptel PPP */ 00116 argv[argc++] = PPP_EXEC; 00117 argv[argc++] = "nodetach"; 00118 00119 /* And all the other arguments */ 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 /* Finally launch PPP */ 00132 execv(PPP_EXEC, argv); 00133 fprintf(stderr, "Failed to exec PPPD!\n"); 00134 exit(1); 00135 }
int unload_module | ( | void | ) |
Cleanup all module structures, sockets, etc.
This is called at exit. Any registrations and memory allocations need to be unregistered and free'd here. Nothing else will do these for you (until exit).
Definition at line 243 of file app_zapras.c.
References app, ast_unregister_application(), and STANDARD_HANGUP_LOCALUSERS.
00244 { 00245 int res; 00246 00247 res = ast_unregister_application(app); 00248 00249 STANDARD_HANGUP_LOCALUSERS; 00250 00251 return res; 00252 }
int usecount | ( | void | ) |
Provides a usecount.
This function will be called by various parts of asterisk. Basically, all it has to do is to return a usecount when called. You will need to maintain your usecount within the module somewhere. The usecount should be how many channels provided by this module are in use.
Definition at line 264 of file app_zapras.c.
References STANDARD_USECOUNT.
00265 { 00266 int res; 00267 STANDARD_USECOUNT(res); 00268 return res; 00269 }
static int zapras_exec | ( | struct ast_channel * | chan, | |
void * | data | |||
) | [static] |
Definition at line 196 of file app_zapras.c.
References ast_channel::_state, ast_answer(), ast_log(), AST_STATE_UP, ast_strdupa, ast_verbose(), localuser::chan, LOCAL_USER_ADD, LOCAL_USER_REMOVE, LOG_ERROR, LOG_WARNING, option_verbose, run_ras(), VERBOSE_PREFIX_2, and VERBOSE_PREFIX_3.
Referenced by load_module().
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 /* Answer the channel if it's not up */ 00216 if (chan->_state != AST_STATE_UP) 00217 ast_answer(chan); 00218 if (strcasecmp(chan->type, "Zap")) { 00219 /* If it's not a zap channel, we're done. Wait a couple of 00220 seconds and then hangup... */ 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 /* Everything should be okay. Run PPP. */ 00233 if (option_verbose > 2) 00234 ast_verbose(VERBOSE_PREFIX_3 "Starting RAS on %s\n", chan->name); 00235 /* Execute RAS */ 00236 run_ras(chan, args); 00237 } 00238 } 00239 LOCAL_USER_REMOVE(u); 00240 return res; 00241 }
char* app = "ZapRAS" [static] |
Definition at line 63 of file app_zapras.c.
char* descrip [static] |
Definition at line 67 of file app_zapras.c.
Definition at line 76 of file app_zapras.c.
Definition at line 74 of file app_zapras.c.
char* synopsis = "Executes Zaptel ISDN RAS application" [static] |
Definition at line 65 of file app_zapras.c.
char* tdesc = "Zap RAS Application" [static] |
Definition at line 61 of file app_zapras.c.