[Asterisk-Users] app_valetparking.c
Terry Wilson
otherwiseguy at gmail.com
Fri Jun 24 12:57:40 MST 2005
Actually, anthm is now hosting this at http://www.pbxfeeware.org.
On 6/20/05, Paul Zimm <pbzinc at dejazzd.com> wrote:
> Try this
>
> > Since www.bkw.org seems not to exist anymore (getting response from
> > some hosting provider), does anyone happend to have a copy of
> > app_valetparking.c from www.bkw.org - the one that should work with *
> > stable 1.0.X ? If so please contact me.
> >
> > One that can be downloaded from www.loligo.com dosn't compile with
> > 1.0.X, and SuperValletParking (www.asterlink.com/svp/) seems to be for
> > * HEAD (1.1.X), so it wont do me any good.
> >
>
>
>
> /*
> * Asterisk -- A telephony toolkit for Linux.
> *
> * Routines implementing call valetparking
> *
> * Copyright (C) 1999, Mark Spencer
> *
> * Mark Spencer <markster at linux-support.net>
> *
> * This program is free software, distributed under the terms of
> * the GNU General Public License
> */
>
> #include <asterisk/lock.h>
> #include <asterisk/file.h>
> #include <asterisk/logger.h>
> #include <asterisk/channel.h>
> #include <asterisk/pbx.h>
> #include <asterisk/options.h>
> #include <asterisk/module.h>
> #include <asterisk/translate.h>
> #include <asterisk/say.h>
> #include <asterisk/callerid.h>
> #include <asterisk/channel_pvt.h>
> #include <asterisk/parking.h>
> #include <asterisk/musiconhold.h>
> #include <asterisk/config.h>
> #include <asterisk/cli.h>
> #include <asterisk/app.h>
> #include <asterisk/manager.h>
> #include <stdlib.h>
> #include <errno.h>
> #include <unistd.h>
> #include <string.h>
> #include <stdlib.h>
> #include <stdio.h>
> #include <sys/time.h>
> #include <sys/signal.h>
> #include <netinet/in.h>
>
> #include <pthread.h>
>
> #define DEFAULT_VALETPARK_TIME 45000
>
> static char *valetparking = "ValetParking";
> static char *valetparkedcall = "ValetParkCall";
> static char *valetunparkedcall = "ValetUnparkCall";
> static char *valetparklist = "ValetParkList";
>
> /* No more than 45 seconds valetparked before you do something with them */
> static int valetparkingtime = DEFAULT_VALETPARK_TIME;
>
> /* First available extension for valetparking */
> static int valetparking_start = 1;
>
> /* Last available extension for valetparking */
> static int valetparking_stop = 10000;
>
> static char *vpsynopsis = "Valet Parking";
>
> static char *vpcsynopsis = "Valet Park Call";
>
> static char *vupsynopsis = "Valet UnPark Call";
>
> static char *vlsynopsis = "ValetParkList";
>
> static char *vpdesc =
> "ValetParking(<exten>|<lotname>|<timeout>[|<return_ext>][|<return_pri>][|<return_context>])\n"
> "Auto-Sense Valet Parking: if <exten> is not occupied, park it, if it is already parked, bridge to it.\n\n";
>
> static char *vpcdesc =
> "ValetParkCall(<exten>|<lotname>|<timeout>[|<return_ext>][|<return_pri>][|<return_context>])\n"
> "Park Call at <exten> in <lotname> until someone calls ValetUnparkCall on the same <exten> + <lotname>\n"
> "set <exten> to 'auto' to auto-choose the slot.\n\n";
>
> static char *vupdesc =
> "ValetUnparkCall(<exten>|<lotname>)\n"
> "Un-Park the call at <exten> in lot <lotname> use 'fifo' or 'filo' for auto-ordered Un-Park.\n\n";
>
> static char *vldesc =
> "ValetParkList(<lotname>)\n"
> "Audibly list the slot number of all the calls in <lotname> press * to unpark it.\n\n";
>
> struct valetparkeduser {
> struct ast_channel *chan;
> struct timeval start;
> int valetparkingnum;
> /* Where to go if our valetparking time expires */
> char context[AST_MAX_EXTENSION];
> char exten[AST_MAX_EXTENSION];
> char lotname[AST_MAX_EXTENSION];
> int priority;
> int valetparkingtime;
> struct valetparkeduser *next;
> };
>
> static struct valetparkeduser *valetparkinglot;
>
> static ast_mutex_t valetparking_lock = AST_MUTEX_INITIALIZER;
>
> static pthread_t valetparking_thread;
>
> STANDARD_LOCAL_USER;
>
> LOCAL_USER_DECL;
>
> static int valetparking_count(void)
> {
> struct valetparkeduser *cur;
> int x=0;
> ast_mutex_lock(&valetparking_lock);
> for(cur = valetparkinglot;cur;cur = cur->next)
> x++;
> ast_mutex_unlock(&valetparking_lock);
> return x;
> }
>
> static int valetparking_say(struct ast_channel *chan,char *lotname)
> {
> struct valetparkeduser *cur;
> int x=0,y=0,res=0;
> int list[1024];
> if(!lotname)
> return 0;
> ast_mutex_lock(&valetparking_lock);
> for(cur = valetparkinglot;cur;cur = cur->next)
> if(cur->lotname && !strcmp(lotname,cur->lotname))
> list[y++] = cur->valetparkingnum;
> ast_mutex_unlock(&valetparking_lock);
> for(x=0;x<y;x++) {
> ast_say_digits(chan,list[x], "", chan->language);
> res = ast_waitfordigit(chan,1500);
> if(res != 0) {
> res = list[x];
> break;
> }
> }
> return res;
> }
>
> static int ast_pop_valetparking_top(char *lotname)
> {
> struct valetparkeduser *cur;
>
> ast_mutex_lock(&valetparking_lock);
> for(cur = valetparkinglot;cur;cur = cur->next)
> if(cur->lotname && !strcmp(lotname,cur->lotname))
> break;
>
> ast_mutex_unlock(&valetparking_lock);
> return cur ? cur->valetparkingnum : 0;
> }
>
> static int ast_pop_valetparking_bot(char *lotname)
> {
> struct valetparkeduser *cur,*last=NULL;
> ast_mutex_lock(&valetparking_lock);
> for(cur = valetparkinglot;cur;cur = cur->next) {
> if(cur->lotname && !strcmp(lotname,cur->lotname)) {
> last = cur;
> }
> }
> ast_mutex_unlock(&valetparking_lock);
> return last ? last->valetparkingnum : 0;
> }
>
> static int ast_is_valetparked(char *exten,char *lotname)
> {
> struct valetparkeduser *cur;
> int ext=0;
> int ret = 0;
> ext = atoi(exten);
> if(! ext > 0) {
> return ret;
> }
> ast_mutex_lock(&valetparking_lock);
> cur = valetparkinglot;
> while(cur) {
> if (cur->valetparkingnum == ext && lotname && cur->lotname && !strcmp(lotname,cur->lotname)) {
> ret = 1;
> break;
> }
> cur = cur->next;
> }
> ast_mutex_unlock(&valetparking_lock);
> return ret;
> }
>
> static int ast_valetpark_call(struct ast_channel *chan, int timeout, int *extout,char *lotname)
> {
> /* We put the user in the valetparking list, then wake up the valetparking thread to be sure it looks
> after these channels too */
> struct valetparkeduser *pu, *cur;
> int x;
>
> x = *extout;
> pu = malloc(sizeof(struct valetparkeduser));
> if (pu) {
> memset(pu,0,sizeof(struct valetparkeduser));
> ast_mutex_lock(&valetparking_lock);
> if(lotname) {
> strncpy(pu->lotname,lotname,sizeof(pu->lotname));
> if(chan->exten)
> strncpy(pu->exten,chan->exten,sizeof(pu->exten)-1);
> if(chan->context)
> strncpy(pu->context,chan->context,sizeof(pu->context)-1);
>
> pu->priority = chan->priority;
>
> x = *extout;
> if(x == -1) {
> for (x=valetparking_start;x<=valetparking_stop;x++) {
> for(cur = valetparkinglot;cur;cur=cur->next) {
> if (cur->valetparkingnum == x && cur->lotname && !strcmp(cur->lotname,lotname))
> break;
> }
> if (!cur)
> break;
> }
> }
> }
> if (x <= valetparking_stop) {
> chan->appl = "Valet Parked Call";
> chan->data = NULL;
>
> pu->chan = chan;
> /* Start music on hold */
> ast_moh_start(pu->chan, NULL);
> gettimeofday(&pu->start, NULL);
> pu->valetparkingnum = x;
> if (timeout >= 0)
> pu->valetparkingtime = timeout;
> else
> pu->valetparkingtime = valetparkingtime;
>
> *extout = x;
> /* Remember what had been dialed, so that if the valetparking
> expires, we try to come back to the same place */
> if (strlen(chan->macrocontext))
> strncpy(pu->context, chan->macrocontext, sizeof(pu->context)-1);
> else
> strncpy(pu->context, chan->context, sizeof(pu->context)-1);
> if (strlen(chan->macroexten))
> strncpy(pu->exten, chan->macroexten, sizeof(pu->exten)-1);
> else
> strncpy(pu->exten, chan->exten, sizeof(pu->exten)-1);
> if (chan->macropriority)
> pu->priority = chan->macropriority;
> else
> pu->priority = chan->priority;
> pu->next = valetparkinglot;
> valetparkinglot = pu;
> ast_mutex_unlock(&valetparking_lock);
> /* Wake up the (presumably select()ing) thread */
> pthread_kill(valetparking_thread, SIGURG);
> if (option_verbose > 1)
> ast_verbose(VERBOSE_PREFIX_2 "Valet Parked %s on slot %d\n", pu->chan->name, pu->valetparkingnum);
>
> manager_event(EVENT_FLAG_CALL, "VirtualValetparkedCall",
> "Exten: %d\r\n"
> "Channel: %s\r\n"
> "LotName: %s\r\n"
> "Timeout: %ld\r\n"
> "CallerID: %s\r\n"
> ,pu->valetparkingnum, pu->chan->name, lotname
> ,(long)pu->start.tv_sec + (long)(pu->valetparkingtime/1000) - (long)time(NULL)
> ,(pu->chan->callerid ? pu->chan->callerid : "")
> );
> return 0;
> } else {
> ast_log(LOG_WARNING, "No more valetparking spaces\n");
> free(pu);
> ast_mutex_unlock(&valetparking_lock);
> return -1;
> }
> } else {
> ast_log(LOG_WARNING, "Out of memory\n");
> return -1;
> }
> return 0;
> }
>
> static int ast_masq_valetpark_call(struct ast_channel *rchan,int timeout, int *extout,char *lotname)
> {
> struct ast_channel *chan;
> struct ast_frame *f;
>
> /* Make a new, fake channel that we'll use to masquerade in the real one */
> chan = ast_channel_alloc(0);
> if (chan) {
> /* Let us keep track of the channel name */
> snprintf(chan->name, sizeof (chan->name), "ValetParked/%s",rchan->name);
> /* Make formats okay */
> chan->readformat = rchan->readformat;
> chan->writeformat = rchan->writeformat;
> ast_channel_masquerade(chan, rchan);
> /* Setup the extensions and such */
> strncpy(chan->context, rchan->context, sizeof(chan->context) - 1);
> strncpy(chan->exten, rchan->exten, sizeof(chan->exten) - 1);
> chan->priority = rchan->priority;
> /* Make the masq execute */
> f = ast_read(chan);
> if (f)
> ast_frfree(f);
> ast_valetpark_call(chan, timeout, extout,lotname);
> } else {
> ast_log(LOG_WARNING, "Unable to create Valet Parked channel\n");
> return -1;
> }
> return 0;
> }
>
> static void *do_valetparking_thread(void *ignore)
> {
> int ms, tms, max;
> struct valetparkeduser *pu, *pl, *pt = NULL;
> struct timeval tv;
> struct ast_frame *f;
> int x;
> int gc=0;
> fd_set rfds, efds;
> fd_set nrfds, nefds;
> FD_ZERO(&rfds);
> FD_ZERO(&efds);
> for (;;) {
> ms = -1;
> max = -1;
> ast_mutex_lock(&valetparking_lock);
> pl = NULL;
> pu = valetparkinglot;
> gettimeofday(&tv, NULL);
> FD_ZERO(&nrfds);
> FD_ZERO(&nefds);
> while(pu) {
> tms = (tv.tv_sec - pu->start.tv_sec) * 1000 + (tv.tv_usec - pu->start.tv_usec) / 1000;
>
> if(gc < 5 && !pu->chan->generator) {
> gc++;
> ast_moh_start(pu->chan,NULL);
> }
> if(pu->valetparkingtime > 0 && tms > pu->valetparkingtime) {
> /* They've been waiting too long, send them back to where they came. Theoretically they
> should have their original extensions and such, but we copy to be on the safe side */
> strncpy(pu->chan->exten, pu->exten, sizeof(pu->chan->exten)-1);
> strncpy(pu->chan->context, pu->context, sizeof(pu->chan->context)-1);
> pu->chan->priority = pu->priority;
> /* Stop music on hold */
> ast_moh_stop(pu->chan);
> /* Start up the PBX, or hang them up */
> if (ast_pbx_start(pu->chan)) {
> ast_log(LOG_WARNING, "Unable to restart the PBX for user on '%s', hanging them up...\n", pu->chan->name);
> ast_hangup(pu->chan);
> }
> /* And take them out of the valetparking lot */
> if (pl)
> pl->next = pu->next;
> else
> valetparkinglot = pu->next;
> pt = pu;
> pu = pu->next;
> free(pt);
> } else {
> for (x=0;x<AST_MAX_FDS;x++) {
> if ((pu->chan->fds[x] > -1) && (FD_ISSET(pu->chan->fds[x], &rfds) || FD_ISSET(pu->chan->fds[x], &efds))) {
> if (FD_ISSET(pu->chan->fds[x], &efds))
> pu->chan->exception = 1;
> pu->chan->fdno = x;
> /* See if they need servicing */
> f = ast_read(pu->chan);
> if (!f || ((f->frametype == AST_FRAME_CONTROL) && (f->subclass == AST_CONTROL_HANGUP))) {
> /* There's a problem, hang them up*/
> if (option_verbose > 1)
> ast_verbose(VERBOSE_PREFIX_2 "%s got tired of being Valet Parked\n", pu->chan->name);
> ast_hangup(pu->chan);
> /* And take them out of the valetparking lot */
> if (pl)
> pl->next = pu->next;
> else
> valetparkinglot = pu->next;
> pt = pu;
> pu = pu->next;
> free(pt);
> break;
> } else {
> /* XXX Maybe we could do something with packets, like dial "0" for operator or something XXX */
> ast_frfree(f);
> goto std; /* XXX Ick: jumping into an else statement??? XXX */
> }
> }
> }
> if (x >= AST_MAX_FDS) {
> std: for (x=0;x<AST_MAX_FDS;x++) {
> /* Keep this one for next one */
> if (pu->chan->fds[x] > -1) {
> FD_SET(pu->chan->fds[x], &nrfds);
> FD_SET(pu->chan->fds[x], &nefds);
> if (pu->chan->fds[x] > max)
> max = pu->chan->fds[x];
> }
> }
> /* Keep track of our longest wait */
> if ((tms < ms) || (ms < 0))
> ms = tms;
> pl = pu;
> pu = pu->next;
> }
> }
> }
> ast_mutex_unlock(&valetparking_lock);
> rfds = nrfds;
> efds = nefds;
> tv.tv_sec = ms / 1000;
> tv.tv_usec = (ms % 1000) * 1000;
> /* Wait for something to happen */
> ast_select(max + 1, &rfds, NULL, &efds, (ms > -1) ? &tv : NULL);
> pthread_testcancel();
> }
> return NULL; /* Never reached */
> }
>
> static int ast_valetparking(struct ast_channel *chan, void *data)
> {
> struct localuser *u;
> char *appname;
> char buf[512],*exten,*lotname,*to;
> struct ast_app *app;
> int res=0;
>
> if (!data) {
> ast_log(LOG_WARNING, "ValetParking requires an argument (extension number)\n");
> return -1;
> }
>
> exten=lotname=to=NULL;
> strncpy(buf,data,512);
> exten = buf;
> if((lotname=strchr(exten,'|'))) {
> *lotname = '\0';
> *lotname++;
> if((to=strchr(lotname,'|'))) {
> *to = '\0';
> *to++;
> }
> }
> if(exten[0] >= 97) {
> ast_log(LOG_WARNING, "ValetParking requires a numeric extension.\n");
> return -1;
> }
> appname = ast_is_valetparked(exten,lotname) ? "ValetParkCall" : "ValetUnparkCall";
> app = pbx_findapp(appname);
> LOCAL_USER_ADD(u);
> if(app) {
> res = pbx_exec(chan,app,data,1);
> } else {
> ast_log(LOG_WARNING, "Error: Can't find app %s\n",appname);
> res = -1;
> }
> LOCAL_USER_REMOVE(u);
> return res;
> }
>
> static int valetpark_call(struct ast_channel *chan, void *data)
> {
> struct localuser *u;
> int timeout = DEFAULT_VALETPARK_TIME;
> int ext = 0,res = 0;
> char buf[512],*exten,*lotname,*to,*findme,*context,*priority=NULL,tmp[80];
> if (!data) {
> ast_log(LOG_WARNING, "ValetParkCall requires an argument (extension number)\n");
> return -1;
> }
> exten=lotname=to=findme=context=NULL;
> strncpy(buf,data,512);
> exten = buf;
> if((lotname=strchr(exten,'|'))) {
> *lotname = '\0';
> *lotname++;
> if((to=strchr(lotname,'|'))) {
> *to = '\0';
> *to++;
> timeout = atoi(to) * 1000;
> if((findme=strchr(to,'|'))) {
> *findme = '\0';
> *findme++;
> if((priority=strchr(findme,'|'))) {
> *priority = '\0';
> *priority++;
> if((context=strchr(priority,'|'))) {
> *context = '\0';
> *context++;
> }
> }
> }
> }
> }
> if(!lotname) {
> ast_log(LOG_WARNING,"Please specify a lotname in the dialplan.");
> return -1;
> }
> if(ast_is_valetparked(exten,lotname)) {
> ast_log(LOG_WARNING,"Call is already Valet Parked Here [%s]\n",exten);
> return -1;
> }
> LOCAL_USER_ADD(u);
> ast_answer(chan);
> if(exten && lotname) {
> if(!strcmp(exten,"auto"))
> ext = -1;
> else if(!strcmp(exten,"query")) {
> ast_waitfor(chan,-1);
> memset(&tmp,0,80);
> ast_streamfile(chan, "vm-extension", chan->language);
> res = ast_waitstream(chan, AST_DIGIT_ANY);
> if(res)
> return -1;
>
> ast_app_getdata(chan,"vm-then-pound",tmp,80,5000);
> if(tmp[0])
> ext = atoi(tmp);
> } else {
> ext = atoi(exten);
> }
> if(ext == 0)
> ext = -1;
> if(findme)
> strncpy(chan->exten,findme,sizeof(chan->exten)-1);
> if (context)
> strncpy(chan->context, context, sizeof(chan->context)-1);
> if(priority) {
> chan->priority = atoi(priority);
> if(!chan->priority)
> chan->priority = 1;
> }
> ast_masq_valetpark_call(chan,timeout,&ext,lotname);
> }
> LOCAL_USER_REMOVE(u);
> return 1;
> }
>
> static int valetpark_list(struct ast_channel *chan, void *data)
> {
> struct localuser *u;
> int res=0;
> struct ast_app *app;
> char buf[512];
> if(!data) {
> ast_log(LOG_WARNING,"Parameter 'lotname' is required.\n");
> return -1;
> }
> LOCAL_USER_ADD(u);
> res = valetparking_say(chan,data);
> if(res > 0) {
> app = pbx_findapp("ValetUnparkCall");
> if(app) {
> snprintf(buf,512,"%d|%s",res,(char *)data);
> res = pbx_exec(chan,app,buf,1);
> }
> }
> LOCAL_USER_REMOVE(u);
> return 1;
> }
>
> static int valetunpark_call(struct ast_channel *chan, void *data)
> {
> int res=0;
> struct localuser *u;
> struct ast_channel *peer=NULL;
> struct valetparkeduser *pu, *pl=NULL;
> int valetpark=-1;
> int dres;
> struct ast_bridge_config config;
> char buf[512],tmp[80],*exten,*lotname;
> if (!data) {
> ast_log(LOG_WARNING, "Valetpark requires an argument (extension number)\n");
> return -1;
> }
> exten=lotname=NULL;
> strncpy(buf,data,512);
> exten = buf;
> if((lotname=strchr(exten,'|'))) {
> *lotname = '\0';
> *lotname++;
> }
> if(!lotname) {
> ast_log(LOG_WARNING,"Please specify a lotname in the dialplan.");
> return -1;
> }
> LOCAL_USER_ADD(u);
> ast_answer(chan);
> if(exten) {
> if(!strcmp(exten,"fifo")) {
> valetpark = ast_pop_valetparking_top(lotname);
> }
> else if(!strcmp(exten,"filo")) {
> valetpark = ast_pop_valetparking_bot(lotname);
> }
> else if(!strcmp(exten,"query")) {
> ast_waitfor(chan,-1);
> memset(&tmp,0,80);
> ast_streamfile(chan, "vm-extension", chan->language);
> res = ast_waitstream(chan, AST_DIGIT_ANY);
> if(res)
> return -1;
> ast_app_getdata(chan,"vm-then-pound",tmp,80,5000);
> if(tmp[0])
> valetpark = atoi(tmp);
> }
> else {
> valetpark = atoi(exten);
> }
>
> if(valetpark == 0) {
> ast_log(LOG_WARNING, "Nobody Valet Parked in %s",lotname);
> LOCAL_USER_REMOVE(u);
> return -1;
> }
>
> }
> else
> valetpark = atoi((char *)data);
> ast_mutex_lock(&valetparking_lock);
> pu = valetparkinglot;
> while(pu) {
> if ((lotname && pu->valetparkingnum == valetpark && pu->lotname && !strcmp(pu->lotname,lotname))
> || (! lotname && pu->valetparkingnum == valetpark)) {
> if (pl)
> pl->next = pu->next;
> else
> valetparkinglot = pu->next;
> break;
> }
> pl = pu;
> pu = pu->next;
> }
> ast_mutex_unlock(&valetparking_lock);
> if (pu) {
> peer = pu->chan;
> free(pu);
> }
> /* JK02: it helps to answer the channel if not already up */
> if (chan->_state != AST_STATE_UP) {
> ast_answer(chan);
> }
>
> if (peer) {
> ast_moh_stop(peer);
> res = ast_channel_make_compatible(chan, peer);
> if (res < 0) {
> ast_log(LOG_WARNING, "Could not make channels %s and %s compatible for bridge\n", chan->name, peer->name);
> ast_hangup(peer);
> LOCAL_USER_REMOVE(u);
> return -1;
> }
> /* This runs sorta backwards, since we give the incoming channel control, as if it
> were the person called. */
>
> if (option_verbose > 2)
> ast_verbose(VERBOSE_PREFIX_3 "Channel %s connected to Valet Parked call %d in lot %s\n", chan->name, valetpark,lotname);
>
> memset(&config,0,sizeof(struct ast_bridge_config));
> config.allowredirect_in = 1;
> config.allowredirect_out = 1;
> config.allowdisconnect = 0;
> config.timelimit = 0;
> config.play_warning = 0;
> config.warning_freq = 0;
> config.warning_sound=NULL;
> res = ast_bridge_call(chan,peer,&config);
>
> /* Simulate the PBX hanging up */
> if (res != AST_PBX_NO_HANGUP_PEER)
> ast_hangup(peer);
> LOCAL_USER_REMOVE(u);
> return res;
> } else {
> /* XXX Play a message XXX */
> dres = ast_streamfile(chan, "pbx-invalidpark", chan->language);
> if (!dres) {
> dres = ast_waitstream(chan, "");
> } else {
> ast_log(LOG_WARNING, "ast_streamfile of %s failed on %s\n", "pbx-invalidpark", chan->name);
> res = 0;
> }
> if (option_verbose > 2)
> ast_verbose(VERBOSE_PREFIX_3 "Channel %s tried to talk to non-existant Valet Parked call %d\n", chan->name, valetpark);
> res = -1;
> }
> LOCAL_USER_REMOVE(u);
> return res;
> }
>
> static int handle_valetparkedcalls(int fd, int argc, char *argv[])
> {
> struct valetparkeduser *cur;
>
> ast_cli(fd, "%4s %25s (%-15s %-12s %-4s) %-6s %-6s %-15s\n", "Num", "Channel"
> , "Context", "Extension", "Pri", "Elapsed","Timeout","LotName");
>
> ast_mutex_lock(&valetparking_lock);
>
> cur=valetparkinglot;
> while(cur) {
> ast_cli(fd, "%4d %25s (%-15s %-12s %-4d) %6lds %6lds %-15s\n"
> ,cur->valetparkingnum, cur->chan->name, cur->context, cur->exten
> ,cur->priority,(time(NULL) - cur->start.tv_sec),cur->valetparkingtime ? (cur->start.tv_sec + (cur->valetparkingtime/1000) - time(NULL)) : 0,cur->lotname);
>
> cur = cur->next;
> }
>
> ast_mutex_unlock(&valetparking_lock);
>
> return RESULT_SUCCESS;
> }
>
> static char showvaletparked_help[] =
> "Usage: show valetparkedcalls\n"
> " Lists currently Valet Parked calls.\n";
>
> static struct ast_cli_entry showvaletparked =
> { { "show", "valetparkedcalls", NULL }, handle_valetparkedcalls, "Lists valetparked calls", showvaletparked_help };
> /* Dump lot status */
> static int manager_valetparking_status( struct mansession *s, struct message *m )
> {
> struct valetparkeduser *cur;
>
> astman_send_ack(s, m, "Valet Parked calls will follow");
>
> ast_mutex_lock(&valetparking_lock);
>
> cur=valetparkinglot;
> while(cur) {
> ast_cli(s->fd, "Event: ValetParkedCall\r\n"
> "Exten: %d\r\n"
> "Channel: %s\r\n"
> "Timeout: %ld\r\n"
> "CallerID: %s\r\n"
> "\r\n"
> ,cur->valetparkingnum, cur->chan->name
> ,(long)cur->start.tv_sec + (long)(cur->valetparkingtime/1000) - (long)time(NULL)
> ,(cur->chan->callerid ? cur->chan->callerid : "")
> );
>
> cur = cur->next;
> }
>
> ast_mutex_unlock(&valetparking_lock);
>
> return RESULT_SUCCESS;
> }
>
> int load_module(void)
> {
> int res;
>
> ast_cli_register(&showvaletparked);
> valetparkingtime = DEFAULT_VALETPARK_TIME;
> pthread_create(&valetparking_thread, NULL, do_valetparking_thread, NULL);
> res = ast_register_application(valetunparkedcall, valetunpark_call, vupsynopsis, vupdesc);
> res = ast_register_application(valetparkedcall, valetpark_call, vpcsynopsis, vpcdesc);
> res = ast_register_application(valetparking, ast_valetparking, vpsynopsis, vpdesc);
> res = ast_register_application(valetparklist,valetpark_list, vlsynopsis, vldesc);
>
>
>
> if (!res) {
> ast_manager_register( "ValetparkedCalls", 0, manager_valetparking_status, "List valetparked calls" );
> }
>
> return res;
> }
>
> int unload_module(void)
> {
> STANDARD_HANGUP_LOCALUSERS;
>
> if (!ast_mutex_lock(&valetparking_lock)) {
> if (valetparking_thread && (valetparking_thread != AST_PTHREADT_STOP)) {
> pthread_cancel(valetparking_thread);
> pthread_kill(valetparking_thread, SIGURG);
> pthread_join(valetparking_thread, NULL);
> }
> valetparking_thread = AST_PTHREADT_STOP;
> ast_mutex_unlock(&valetparking_lock);
> } else {
> ast_log(LOG_WARNING, "Unable to lock the valet\n");
> return -1;
> }
>
>
> ast_manager_unregister( "ValetparkedCalls" );
> ast_cli_unregister(&showvaletparked);
> ast_unregister_application(valetunparkedcall);
> ast_unregister_application(valetparkedcall);
> ast_unregister_application(valetparking);
> ast_unregister_application(valetparklist);
> return 0;
> }
>
> char *description(void)
> {
> return "Valet Parking Application";
> }
>
> int usecount(void)
> {
> int res;
> STANDARD_USECOUNT(res);
> res += valetparking_count();
> return res;
> }
>
> char *key()
> {
> return ASTERISK_GPL_KEY;
> }
>
>
> _______________________________________________
> Asterisk-Users mailing list
> Asterisk-Users at lists.digium.com
> http://lists.digium.com/mailman/listinfo/asterisk-users
> To UNSUBSCRIBE or update options visit:
> http://lists.digium.com/mailman/listinfo/asterisk-users
>
>
More information about the asterisk-users
mailing list