[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