abfb2dd374edd2956d143eb6fc2602f6f6419310
[asterisk/asterisk.git] / apps / app_dial.c
1 /*
2  * Asterisk -- A telephony toolkit for Linux.
3  *
4  * Trivial application to dial a channel
5  * 
6  * Copyright (C) 1999, Mark Spencer
7  *
8  * Mark Spencer <markster@linux-support.net>
9  *
10  * This program is free software, distributed under the terms of
11  * the GNU General Public License
12  */
13
14 #include <asterisk/file.h>
15 #include <asterisk/logger.h>
16 #include <asterisk/channel.h>
17 #include <asterisk/pbx.h>
18 #include <asterisk/options.h>
19 #include <asterisk/module.h>
20 #include <asterisk/translate.h>
21 #include <asterisk/say.h>
22 #include <stdlib.h>
23 #include <errno.h>
24 #include <unistd.h>
25 #include <string.h>
26 #include <stdlib.h>
27 #include <stdio.h>
28 #include <sys/time.h>
29 #include <sys/signal.h>
30
31 #include <pthread.h>
32
33 static char *tdesc = "Dialing/Parking Application";
34
35 static char *app = "Dial";
36
37 static char *parkedcall = "ParkedCall";
38
39 /* No more than 90 seconds parked before you do something with them */
40 static int parkingtime = 90000;
41
42 /* Context for which parking is made accessible */
43 static char parking_con[AST_MAX_EXTENSION] = "default";
44
45 /* Extension you type to park the call */
46 static char parking_ext[AST_MAX_EXTENSION] = "700";
47
48 /* First available extension for parking */
49 static int parking_start = 701;
50
51 /* Last available extension for parking */
52 static int parking_stop = 750;
53
54 /* We define a customer "local user" structure because we
55    use it not only for keeping track of what is in use but
56    also for keeping track of who we're dialing. */
57
58 struct localuser {
59         struct ast_channel *chan;
60         int stillgoing;
61         int allowredirect;
62         struct localuser *next;
63 };
64
65 struct parkeduser {
66         struct ast_channel *chan;
67         struct timeval start;
68         int parkingnum;
69         /* Where to go if our parking time expires */
70         char context[AST_MAX_EXTENSION];
71         char exten[AST_MAX_EXTENSION];
72         int priority;
73         struct parkeduser *next;
74 };
75
76 static struct parkeduser *parkinglot;
77
78 static pthread_mutex_t parking_lock = PTHREAD_MUTEX_INITIALIZER;
79
80 static pthread_t parking_thread;
81
82 LOCAL_USER_DECL;
83
84 static int bridge_call(struct ast_channel *chan, struct ast_channel *peer, int allowredirect);
85
86
87 static int park_call(struct ast_channel *chan, struct ast_channel *peer)
88 {
89         /* We put the user in the parking list, then wake up the parking thread to be sure it looks
90            after these channels too */
91         struct parkeduser *pu, *cur;
92         int x;
93         pu = malloc(sizeof(struct parkeduser));
94         if (pu) {
95                 pthread_mutex_lock(&parking_lock);
96                 for (x=parking_start;x<=parking_stop;x++) {
97                         cur = parkinglot;
98                         while(cur) {
99                                 if (cur->parkingnum == x) 
100                                         break;
101                                 cur = cur->next;
102                         }
103                         if (!cur)
104                                 break;
105                 }
106                 if (x <= parking_stop) {
107                         pu->chan = chan;
108                         gettimeofday(&pu->start, NULL);
109                         pu->parkingnum = x;
110                         /* Remember what had been dialed, so that if the parking
111                            expires, we try to come back to the same place */
112                         strncpy(pu->context, chan->context, sizeof(pu->context));
113                         strncpy(pu->exten, chan->exten, sizeof(pu->exten));
114                         pu->priority = chan->priority;
115                         pu->next = parkinglot;
116                         parkinglot = pu;
117                         pthread_mutex_unlock(&parking_lock);
118                         /* Wake up the (presumably select()ing) thread */
119                         pthread_kill(parking_thread, SIGURG);
120                         if (option_verbose > 1) 
121                                 ast_verbose(VERBOSE_PREFIX_2 "Parked %s on %d\n", pu->chan->name, pu->parkingnum);
122                         ast_say_digits(peer, pu->parkingnum, peer->language);
123                         return 0;
124                 } else {
125                         ast_log(LOG_WARNING, "No more parking spaces\n");
126                         free(pu);
127                         pthread_mutex_unlock(&parking_lock);
128                         return -1;
129                 }
130         } else {
131                 ast_log(LOG_WARNING, "Out of memory\n");
132                 return -1;
133         }
134         return 0;
135 }
136
137 static void *do_parking_thread(void *ignore)
138 {
139         int ms, tms, max;
140         struct parkeduser *pu, *pl, *pt = NULL;
141         struct timeval tv;
142         struct ast_frame *f;
143         fd_set rfds, efds;
144         fd_set nrfds, nefds;
145         FD_ZERO(&rfds);
146         FD_ZERO(&efds);
147         for (;;) {
148                 ms = -1;
149                 max = -1;
150                 pthread_mutex_lock(&parking_lock);
151                 pl = NULL;
152                 pu = parkinglot;
153                 gettimeofday(&tv, NULL);
154                 FD_ZERO(&nrfds);
155                 FD_ZERO(&nefds);
156                 while(pu) {
157                         tms = (tv.tv_sec - pu->start.tv_sec) * 1000 + (tv.tv_usec - pu->start.tv_usec) / 1000;
158                         if (tms > parkingtime) {
159                                 /* They've been waiting too long, send them back to where they came.  Theoretically they
160                                    should have their original extensions and such, but we copy to be on the safe side */
161                                 strncpy(pu->chan->exten, pu->exten, sizeof(pu->chan->exten));
162                                 strncpy(pu->chan->context, pu->context, sizeof(pu->chan->context));
163                                 pu->chan->priority = pu->priority;
164                                 /* Start up the PBX, or hang them up */
165                                 if (ast_pbx_start(pu->chan))  {
166                                         ast_log(LOG_WARNING, "Unable to restart the PBX for user on '%s', hanging them up...\n", pu->chan->name);
167                                         ast_hangup(pu->chan);
168                                 }
169                                 /* And take them out of the parking lot */
170                                 if (pl) 
171                                         pl->next = pu->next;
172                                 else
173                                         parkinglot = pu->next;
174                                 pt = pu;
175                                 pu = pu->next;
176                                 free(pt);
177                         } else if (FD_ISSET(pu->chan->fd, &rfds) || FD_ISSET(pu->chan->fd, &efds)) {
178                                 if (FD_ISSET(pu->chan->fd, &efds))
179                                         pu->chan->exception = 1;
180                                 /* See if they need servicing */
181                                 f = ast_read(pu->chan);
182                                 if (!f || ((f->frametype == AST_FRAME_CONTROL) && (f->subclass ==  AST_CONTROL_HANGUP))) {
183                                         /* There's a problem, hang them up*/
184                                         if (option_verbose > 1) 
185                                                 ast_verbose(VERBOSE_PREFIX_2 "%s got tired of being parked\n", pu->chan->name);
186                                         ast_hangup(pu->chan);
187                                         /* And take them out of the parking lot */
188                                         if (pl) 
189                                                 pl->next = pu->next;
190                                         else
191                                                 parkinglot = pu->next;
192                                         pt = pu;
193                                         pu = pu->next;
194                                         free(pt);
195                                 } else {
196                                         /* XXX Maybe we could do something with packets, like dial "0" for operator or something XXX */
197                                         ast_frfree(f);
198                                         goto std;       /* XXX Ick: jumping into an else statement??? XXX */
199                                 }
200                         } else  {
201                                 /* Keep this one for next one */
202 std:                    FD_SET(pu->chan->fd, &nrfds);
203                                 FD_SET(pu->chan->fd, &nefds);
204                                 /* Keep track of our longest wait */
205                                 if ((tms < ms) || (ms < 0))
206                                         ms = tms;
207                                 if (pu->chan->fd > max)
208                                         max = pu->chan->fd;
209                                 pl = pu;
210                                 pu = pu->next;
211                         }
212                 }
213                 pthread_mutex_unlock(&parking_lock);
214                 rfds = nrfds;
215                 efds = nefds;
216                 tv.tv_sec = ms / 1000;
217                 tv.tv_usec = (ms % 1000) * 1000;
218                 /* Wait for something to happen */
219                 select(max + 1, &rfds, NULL, &efds, (ms > -1) ? &tv : NULL);
220                 pthread_testcancel();
221         }
222         return NULL;    /* Never reached */
223 }
224
225 static void hanguptree(struct localuser *outgoing, struct ast_channel *exception)
226 {
227         /* Hang up a tree of stuff */
228         struct localuser *oo;
229         while(outgoing) {
230                 /* Hangup any existing lines we have open */
231                 if (outgoing->chan != exception)
232                         ast_hangup(outgoing->chan);
233                 oo = outgoing;
234                 outgoing=outgoing->next;
235                 free(oo);
236         }
237 }
238
239 static struct ast_channel *wait_for_answer(struct ast_channel *in, struct localuser *outgoing, int *to, int *allowredir)
240 {
241         fd_set rfds, efds;
242         struct localuser *o;
243         int found;
244         int numlines;
245         int numbusies = 0;
246         int orig = *to;
247         struct timeval tv;
248         struct ast_frame *f;
249         struct ast_channel *peer = NULL;
250         /* Watch all outgoing channels looking for an answer of some sort.  */
251         tv.tv_sec = *to / 1000;
252         tv.tv_usec = (*to % 1000) * 1000;
253         while((tv.tv_sec || tv.tv_usec) && !peer) {
254                 FD_ZERO(&rfds);
255                 FD_ZERO(&efds);
256                 /* Always watch the input fd */
257                 FD_SET(in->fd, &rfds);
258                 FD_SET(in->fd, &efds);
259                 o = outgoing;
260                 found = -1;
261                 numlines = 0;
262                 while(o) {
263                         if (o->stillgoing) {
264                                 /* Pay attention to this one */
265                                 CHECK_BLOCKING(o->chan);
266                                 FD_SET(o->chan->fd, &rfds);
267                                 FD_SET(o->chan->fd, &efds);
268                                 if (o->chan->fd > found)
269                                         found = o->chan->fd;
270                         }
271                         numlines++;
272                         o = o->next;
273                 }
274                 /* If nobody is left, just go ahead and stop */
275                 if (found<0) {
276                         if (numlines == numbusies) {
277                                 if (option_verbose > 2)
278                                         ast_verbose( VERBOSE_PREFIX_2 "Everyone is busy at this time\n");
279                                 /* See if there is a special busy message */
280                                 if (ast_exists_extension(in, in->context, in->exten, in->priority + 101)) 
281                                         in->priority+=100;
282                         } else {
283                                 if (option_verbose > 2)
284                                         ast_verbose( VERBOSE_PREFIX_2 "No one is available to answer at this time\n");
285                         }
286                         break;
287                 }
288                 if (in->fd > found)
289                         found = in->fd;
290                 if (*to > -1) 
291                         found = select(found + 1, &rfds, NULL, &efds, &tv);
292                 else
293                         found = select(found + 1, &rfds, NULL, &efds, NULL);
294                 if (found < 0) {
295                         ast_log(LOG_WARNING, "select failed, returned %d (%s)\n", errno, strerror(errno));
296                         *to = -1;
297                         o = outgoing;
298                         while(o) {
299                                 if (o->stillgoing) {
300                                         o->chan->blocking = 0;
301                                 }
302                                 o = o->next;
303                         }
304                         return NULL;
305                 }
306                 o = outgoing;
307                 while(o) {
308                         if (o->stillgoing) {
309                                 o->chan->blocking = 0;
310                                 if (FD_ISSET(o->chan->fd, &rfds) || FD_ISSET(o->chan->fd, &efds)) {
311                                         if (FD_ISSET(o->chan->fd, &efds))
312                                                 o->chan->exception = 1;
313                                         f = ast_read(o->chan);
314                                         if (f) {
315                                                 if (f->frametype == AST_FRAME_CONTROL) {
316                                                         switch(f->subclass) {
317                                                     case AST_CONTROL_ANSWER:
318                                                                 /* This is our guy if someone answered. */
319                                                                 if (!peer) {
320                                                                         if (option_verbose > 2)
321                                                                                 ast_verbose( VERBOSE_PREFIX_3 "%s answered %s\n", o->chan->name, in->name);
322                                                                         peer = o->chan;
323                                                                         *allowredir = o->allowredirect;
324                                                                 }
325                                                                 break;
326                                                         case AST_CONTROL_BUSY:
327                                                                 if (option_verbose > 2)
328                                                                         ast_verbose( VERBOSE_PREFIX_3 "%s is busy\n", o->chan->name);
329                                                                 o->stillgoing = 0;
330                                                                 numbusies++;
331                                                                 break;
332                                                         case AST_CONTROL_RINGING:
333                                                                 if (option_verbose > 2)
334                                                                         ast_verbose( VERBOSE_PREFIX_3 "%s is ringing\n", o->chan->name);
335                                                                 break;
336                                                         case AST_CONTROL_OFFHOOK:
337                                                                 /* Ignore going off hook */
338                                                                 break;
339                                                         default:
340                                                                 ast_log(LOG_DEBUG, "Dunno what to do with control type %d\n", f->subclass);
341                                                         }
342                                                 }
343                                                 ast_frfree(f);
344                                         } else {
345                                                 o->stillgoing = 0;
346                                         }
347                                         
348                                 }
349                         }
350                         o = o->next;
351                 }
352                 if (FD_ISSET(in->fd, &rfds) || FD_ISSET(in->fd, &efds)) {
353                         /* After unblocking the entirity of the list, check for the main channel */
354                         if (FD_ISSET(in->fd, &efds))
355                                 in->exception = 1;
356                         f = ast_read(in);
357 #if 0
358                         if (f && (f->frametype != AST_FRAME_VOICE))
359                                         printf("Frame type: %d, %d\n", f->frametype, f->subclass);
360 #endif
361                         if (!f || ((f->frametype == AST_FRAME_CONTROL) && (f->subclass = AST_CONTROL_HANGUP))) {
362                                 /* Got hung up */
363                                 *to=-1;
364                                 return NULL;
365                         }
366                 }
367                 
368         }
369         if (!(tv.tv_sec || tv.tv_usec) && (option_verbose > 2))
370                 ast_verbose( VERBOSE_PREFIX_3 "Nobody picked up in %d ms\n", orig);
371         *to = 0;
372         return peer;
373 }
374
375 static int bridge_call(struct ast_channel *chan, struct ast_channel *peer, int allowredirect)
376 {
377         /* Copy voice back and forth between the two channels.  Give the peer
378            the ability to transfer calls with '#<extension' syntax. */
379         int len;
380         struct ast_frame *f;
381         struct ast_channel *who;
382         char newext[256], *ptr;
383         int res;
384         /* Answer if need be */
385         if (chan->state != AST_STATE_UP)
386                 if (ast_answer(chan))
387                         return -1;
388         peer->appl = "Bridged Call";
389         peer->data = chan->name;
390         for (;;) {
391                 res = ast_channel_bridge(chan, peer, AST_BRIDGE_DTMF_CHANNEL_1, &f, &who);
392                 if (res < 0) {
393                         ast_log(LOG_WARNING, "Bridge failed on channels %s and %s\n", chan->name, peer->name);
394                         return -1;
395                 }
396                 
397                 if (!f || ((f->frametype == AST_FRAME_CONTROL) && ((f->subclass == AST_CONTROL_HANGUP) || (f->subclass == AST_CONTROL_BUSY) || 
398                         (f->subclass == AST_CONTROL_CONGESTION)))) {
399                                 res = -1;
400                                 break;
401                 }
402                 if ((f->frametype == AST_FRAME_DTMF) && (who == peer) && allowredirect &&
403                      (f->subclass == '#')) {
404                                 memset(newext, 0, sizeof(newext));
405                                 ptr = newext;
406                                 len = ast_pbx_longest_extension(chan->context) + 1;
407                                 if (len < ast_pbx_longest_extension("default") + 1)
408                                         len = ast_pbx_longest_extension("default") + 1;
409                                         /* Transfer */
410                                 if ((res=ast_streamfile(peer, "pbx-transfer", chan->language)))
411                                         break;
412                                 if ((res=ast_waitstream(peer, AST_DIGIT_ANY)) < 0)
413                                         break;
414                                 ast_stopstream(peer);
415                                 if (res > 0) {
416                                         /* If they've typed a digit already, handle it */
417                                         newext[0] = res;
418                                         ptr++;
419                                         len --;
420                                 }
421                                 res = ast_readstring(peer, ptr, len, 3000, 2000, "#");
422                                 if (res)
423                                         break;
424                                 if (!strcmp(newext, parking_ext)) {
425                                         if (!park_call(chan, peer)) {
426                                                 /* We return non-zero, but tell the PBX not to hang the channel when
427                                                    the thread dies -- We have to be careful now though.  We are responsible for 
428                                                    hanging up the channel, else it will never be hung up! */
429                                                 res=AST_PBX_KEEPALIVE;
430                                                 break;
431                                         } else {
432                                                 ast_log(LOG_WARNING, "Unable to park call %s\n", chan->name);
433                                         }
434                                         /* XXX Maybe we should have another message here instead of invalid extension XXX */
435                                 } else if (ast_exists_extension(chan, peer->context, newext, 1)) {
436                                         /* Set the channel's new extension, since it exists, using peer context */
437                                         strncpy(chan->exten, newext, sizeof(chan->exten));
438                                         strncpy(chan->context, peer->context, sizeof(chan->context));
439                                         chan->priority = 0;
440                                         ast_frfree(f);
441                                         res=0;
442                                         break;
443                                 } else if (ast_exists_extension(chan, "default", newext, 1)) {
444                                         /* Set the channel's new extension, since it exists, using peer context */
445                                         strncpy(chan->exten, newext, sizeof(chan->exten));
446                                         strncpy(chan->context, "default", sizeof(chan->context));
447                                         chan->priority = 0;
448                                         ast_frfree(f);
449                                         res=0;
450                                         break;
451                                 }
452                                 res = ast_streamfile(peer, "pbx-invalid", chan->language);
453                                 if (res)
454                                         break;
455                                 res = ast_waitstream(peer, AST_DIGIT_ANY);
456                                 ast_stopstream(peer);
457                                 res = 0;
458                         } else {
459 #if 1
460                                 ast_log(LOG_DEBUG, "Read from %s (%d,%d)\n", who->name, f->frametype, f->subclass);
461 #endif
462                         }
463         }
464         return res;
465 }
466
467 static int park_exec(struct ast_channel *chan, void *data)
468 {
469         int res=0;
470         struct localuser *u;
471         struct ast_channel *peer=NULL;
472         struct parkeduser *pu, *pl=NULL;
473         int park;
474         if (!data) {
475                 ast_log(LOG_WARNING, "Park requires an argument (extension number)\n");
476                 return -1;
477         }
478         LOCAL_USER_ADD(u);
479         park = atoi((char *)data);
480         pthread_mutex_lock(&parking_lock);
481         pu = parkinglot;
482         while(pu) {
483                 if (pu->parkingnum == park) {
484                         if (pl)
485                                 pl->next = pu->next;
486                         else
487                                 parkinglot = pu->next;
488                         break;
489                 }
490                 pu = pu->next;
491         }
492         pthread_mutex_unlock(&parking_lock);
493         if (pu) {
494                 peer = pu->chan;
495                 free(pu);
496         }
497         if (peer) {
498                 res = ast_channel_make_compatible(chan, peer);
499                 if (res < 0) {
500                         ast_log(LOG_WARNING, "Could not make channels %s and %s compatible for bridge\n", chan->name, peer->name);
501                         ast_hangup(peer);
502                         return -1;
503                 }
504                 /* This runs sorta backwards, since we give the incoming channel control, as if it
505                    were the person called. */
506                 if (option_verbose > 2) 
507                         ast_verbose(VERBOSE_PREFIX_3 "Channel %s connected to parked call %d\n", chan->name, park);
508                 res = bridge_call(peer, chan, 1);
509                 /* Simulate the PBX hanging up */
510                 if (res != AST_PBX_KEEPALIVE)
511                         ast_hangup(peer);
512                 return -1;
513         } else {
514                 /* XXX Play a message XXX */
515                 if (option_verbose > 2) 
516                         ast_verbose(VERBOSE_PREFIX_3 "Channel %s tried to talk to non-existant parked call %d\n", chan->name, park);
517                 res = -1;
518         }
519         LOCAL_USER_REMOVE(u);
520         return res;
521 }
522
523 static int dial_exec(struct ast_channel *chan, void *data)
524 {
525         int res=-1;
526         struct localuser *u;
527         char *info, *peers, *timeout, *tech, *number, *rest, *cur;
528         struct localuser *outgoing=NULL, *tmp;
529         struct ast_channel *peer;
530         int to;
531         int allowredir=0;
532         char numsubst[AST_MAX_EXTENSION];
533         char restofit[AST_MAX_EXTENSION];
534         char *newnum;
535         
536         if (!data) {
537                 ast_log(LOG_WARNING, "Dial requires an argument (technology1/number1&technology2/number2...|optional timeout)\n");
538                 return -1;
539         }
540         
541         LOCAL_USER_ADD(u);
542         
543         /* Parse our arguments XXX Check for failure XXX */
544         info = malloc(strlen((char *)data) + AST_MAX_EXTENSION);
545         if (!info) {
546                 ast_log(LOG_WARNING, "Out of memory\n");
547                 return -1;
548         }
549         strncpy(info, (char *)data, strlen((char *)data) + AST_MAX_EXTENSION);
550         peers = info;
551         if (peers) {
552                 timeout = strchr(info, '|');
553                 if (timeout) {
554                         *timeout = '\0';
555                         timeout++;
556                 }
557         } else
558                 timeout = NULL;
559         if (!peers || !strlen(peers)) {
560                 ast_log(LOG_WARNING, "Dial argument takes format (technology1/number1&technology2/number2...|optional timeout)\n");
561                 goto out;
562         }
563         
564         cur = peers;
565         do {
566                 /* Remember where to start next time */
567                 rest = strchr(cur, '&');
568                 if (rest) {
569                         *rest = 0;
570                         rest++;
571                 }
572                 /* Get a technology/[device:]number pair */
573                 tech = cur;
574                 number = strchr(tech, '/');
575                 if (!number) {
576                         ast_log(LOG_WARNING, "Dial argument takes format (technology1/[device:]number1&technology2/[device:]number2...|optional timeout)\n");
577                         goto out;
578                 }
579                 *number = '\0';
580                 number++;
581                 tmp = malloc(sizeof(struct localuser));
582                 if (!tmp) {
583                         ast_log(LOG_WARNING, "Out of memory\n");
584                         goto out;
585                 }
586                 tmp->allowredirect = 1;
587                 strncpy(numsubst, number, sizeof(numsubst));
588                 /* If we're dialing by extension, look at the extension to know what to dial */
589                 if ((newnum = strstr(numsubst, "BYEXTENSION"))) {
590                         strncpy(restofit, newnum + strlen("BYEXTENSION"), sizeof(restofit));
591                         snprintf(newnum, sizeof(numsubst) - (newnum - numsubst), "%s%s", chan->exten,restofit);
592                         /* By default, if we're dialing by extension, don't permit redirecting */
593                         tmp->allowredirect = 0;
594                         if (option_debug)
595                                 ast_log(LOG_DEBUG, "Dialing by extension %s\n", numsubst);
596                 }
597                 /* Request the peer */
598                 tmp->chan = ast_request(tech, chan->nativeformats, numsubst);
599                 if (!tmp->chan) {
600                         /* If we can't, just go on to the next call */
601                         ast_log(LOG_WARNING, "Unable to create channel of type '%s'\n", tech);
602                         free(tmp);
603                         cur = rest;
604                         continue;
605                 }
606                 tmp->chan->appl = "AppDial";
607                 tmp->chan->data = "(Outgoing Line)";
608                 if (chan->callerid)
609                         tmp->chan->callerid = strdup(chan->callerid);
610                 /* Place the call, but don't wait on the answer */
611                 res = ast_call(tmp->chan, numsubst, 0);
612                 if (res) {
613                         /* Again, keep going even if there's an error */
614                         if (option_debug)
615                                 ast_log(LOG_DEBUG, "ast call on peer returned %d\n", res);
616                         else if (option_verbose > 2)
617                                 ast_verbose(VERBOSE_PREFIX_3 "Couldn't call %s\n", numsubst);
618                         ast_hangup(tmp->chan);
619                         free(tmp);
620                         continue;
621                 } else
622                         if (option_verbose > 2)
623                                 ast_verbose(VERBOSE_PREFIX_3 "Called %s\n", numsubst);
624                 /* Put them in the list of outgoing thingies...  We're ready now. 
625                    XXX If we're forcibly removed, these outgoing calls won't get
626                    hung up XXX */
627                 tmp->stillgoing = -1;
628                 tmp->next = outgoing;
629                 outgoing = tmp;
630                 cur = rest;
631         } while(cur);
632         
633         if (timeout)
634                 to = atoi(timeout) * 1000;
635         else
636                 to = -1;
637         peer = wait_for_answer(chan, outgoing, &to, &allowredir);
638         if (!peer) {
639                 if (to) 
640                         /* Musta gotten hung up */
641                         res = -1;
642                  else 
643                         /* Nobody answered, next please? */
644                         res=0;
645                 
646                 goto out;
647         }
648         if (peer) {
649                 /* Ah ha!  Someone answered within the desired timeframe.  Of course after this
650                    we will always return with -1 so that it is hung up properly after the 
651                    conversation.  */
652                 hanguptree(outgoing, peer);
653                 outgoing = NULL;
654                 /* Make sure channels are compatible */
655                 res = ast_channel_make_compatible(chan, peer);
656                 if (res < 0) {
657                         ast_log(LOG_WARNING, "Had to drop call because I couldn't make %s compatible with %s\n", chan->name, peer->name);
658                         ast_hangup(peer);
659                         return -1;
660                 }
661                 res = bridge_call(chan, peer, allowredir);
662                 ast_hangup(peer);
663         }       
664 out:
665         hanguptree(outgoing, NULL);
666         free(info);
667         LOCAL_USER_REMOVE(u);
668         return res;
669 }
670
671 int unload_module(void)
672 {
673         STANDARD_HANGUP_LOCALUSERS;
674         return ast_unregister_application(app);
675 }
676
677 int load_module(void)
678 {
679         int res;
680         int x;
681         struct ast_context *con;
682         char exten[AST_MAX_EXTENSION];
683         con = ast_context_find(parking_con);
684         if (!con) {
685                 ast_log(LOG_ERROR, "Parking context '%s' does not exist\n", parking_con);
686                 return -1;
687         }
688         for(x=parking_start; x<=parking_stop;x++) {
689                 snprintf(exten, sizeof(exten), "%d", x);
690                 ast_add_extension2(con, 1, exten, 1, parkedcall, strdup(exten), free);
691         }
692         pthread_create(&parking_thread, NULL, do_parking_thread, NULL);
693         res = ast_register_application(parkedcall, park_exec);
694         if (!res)
695                 res = ast_register_application(app, dial_exec);
696         return res;
697 }
698
699 char *description(void)
700 {
701         return tdesc;
702 }
703
704 int usecount(void)
705 {
706         int res;
707         STANDARD_USECOUNT(res);
708         return res;
709 }
710
711 char *key()
712 {
713         return ASTERISK_GPL_KEY;
714 }