Version 0.1.3 from FTP
[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                                 /* See if they need servicing */
179                                 f = ast_read(pu->chan);
180                                 if (!f || ((f->frametype == AST_FRAME_CONTROL) && (f->subclass ==  AST_CONTROL_HANGUP))) {
181                                         /* There's a problem, hang them up*/
182                                         if (option_verbose > 1) 
183                                                 ast_verbose(VERBOSE_PREFIX_2 "%s got tired of being parked\n", pu->chan->name);
184                                         ast_hangup(pu->chan);
185                                         /* And take them out of the parking lot */
186                                         if (pl) 
187                                                 pl->next = pu->next;
188                                         else
189                                                 parkinglot = pu->next;
190                                         pt = pu;
191                                         pu = pu->next;
192                                         free(pt);
193                                 } else {
194                                         /* XXX Maybe we could do something with packets, like dial "0" for operator or something XXX */
195                                         ast_frfree(f);
196                                         goto std;       /* XXX Ick: jumping into an else statement??? XXX */
197                                 }
198                         } else  {
199                                 /* Keep this one for next one */
200 std:                    FD_SET(pu->chan->fd, &nrfds);
201                                 FD_SET(pu->chan->fd, &nefds);
202                                 /* Keep track of our longest wait */
203                                 if ((tms < ms) || (ms < 0))
204                                         ms = tms;
205                                 if (pu->chan->fd > max)
206                                         max = pu->chan->fd;
207                                 pl = pu;
208                                 pu = pu->next;
209                         }
210                 }
211                 pthread_mutex_unlock(&parking_lock);
212                 rfds = nrfds;
213                 efds = nefds;
214                 tv.tv_sec = ms / 1000;
215                 tv.tv_usec = (ms % 1000) * 1000;
216                 /* Wait for something to happen */
217                 select(max + 1, &rfds, NULL, &efds, (ms > -1) ? &tv : NULL);
218                 pthread_testcancel();
219         }
220         return NULL;    /* Never reached */
221 }
222
223 static void hanguptree(struct localuser *outgoing, struct ast_channel *exception)
224 {
225         /* Hang up a tree of stuff */
226         struct localuser *oo;
227         while(outgoing) {
228                 /* Hangup any existing lines we have open */
229                 if (outgoing->chan != exception)
230                         ast_hangup(outgoing->chan);
231                 oo = outgoing;
232                 outgoing=outgoing->next;
233                 free(oo);
234         }
235 }
236
237 static struct ast_channel *wait_for_answer(struct ast_channel *in, struct localuser *outgoing, int *to, int *allowredir)
238 {
239         fd_set rfds, efds;
240         struct localuser *o;
241         int found;
242         int numlines;
243         int numbusies = 0;
244         int orig = *to;
245         struct timeval tv;
246         struct ast_frame *f;
247         struct ast_channel *peer = NULL;
248         /* Watch all outgoing channels looking for an answer of some sort.  */
249         tv.tv_sec = *to / 1000;
250         tv.tv_usec = (*to % 1000) * 1000;
251         while((tv.tv_sec || tv.tv_usec) && !peer) {
252                 FD_ZERO(&rfds);
253                 FD_ZERO(&efds);
254                 /* Always watch the input fd */
255                 FD_SET(in->fd, &rfds);
256                 FD_SET(in->fd, &efds);
257                 o = outgoing;
258                 found = -1;
259                 numlines = 0;
260                 while(o) {
261                         if (o->stillgoing) {
262                                 /* Pay attention to this one */
263                                 CHECK_BLOCKING(o->chan);
264                                 FD_SET(o->chan->fd, &rfds);
265                                 FD_SET(o->chan->fd, &efds);
266                                 if (o->chan->fd > found)
267                                         found = o->chan->fd;
268                         }
269                         numlines++;
270                         o = o->next;
271                 }
272                 /* If nobody is left, just go ahead and stop */
273                 if (found<0) {
274                         if (numlines == numbusies) {
275                                 if (option_verbose > 2)
276                                         ast_verbose( VERBOSE_PREFIX_2 "Everyone is busy at this time\n");
277                                 /* See if there is a special busy message */
278                                 if (ast_exists_extension(in, in->context, in->exten, in->priority + 101)) 
279                                         in->priority+=100;
280                         } else {
281                                 if (option_verbose > 2)
282                                         ast_verbose( VERBOSE_PREFIX_2 "No one is available to answer at this time\n");
283                         }
284                         break;
285                 }
286                 if (in->fd > found)
287                         found = in->fd;
288                 if (*to > -1) 
289                         found = select(found + 1, &rfds, NULL, &efds, &tv);
290                 else
291                         found = select(found + 1, &rfds, NULL, &efds, NULL);
292                 if (found < 0) {
293                         ast_log(LOG_WARNING, "select failed, returned %d (%s)\n", errno, strerror(errno));
294                         *to = -1;
295                         o = outgoing;
296                         while(o) {
297                                 if (o->stillgoing) {
298                                         o->chan->blocking = 0;
299                                 }
300                                 o = o->next;
301                         }
302                         return NULL;
303                 }
304                 o = outgoing;
305                 while(o) {
306                         if (o->stillgoing) {
307                                 o->chan->blocking = 0;
308                                 if (FD_ISSET(o->chan->fd, &rfds) || FD_ISSET(o->chan->fd, &efds)) {
309                                         f = ast_read(o->chan);
310                                         if (f) {
311                                                 if (f->frametype == AST_FRAME_CONTROL) {
312                                                         switch(f->subclass) {
313                                                     case AST_CONTROL_ANSWER:
314                                                                 /* This is our guy if someone answered. */
315                                                                 if (!peer) {
316                                                                         if (option_verbose > 2)
317                                                                                 ast_verbose( VERBOSE_PREFIX_3 "%s answered %s\n", o->chan->name, in->name);
318                                                                         peer = o->chan;
319                                                                         *allowredir = o->allowredirect;
320                                                                 }
321                                                                 break;
322                                                         case AST_CONTROL_BUSY:
323                                                                 if (option_verbose > 2)
324                                                                         ast_verbose( VERBOSE_PREFIX_3 "%s is busy\n", o->chan->name);
325                                                                 o->stillgoing = 0;
326                                                                 numbusies++;
327                                                                 break;
328                                                         case AST_CONTROL_RINGING:
329                                                                 if (option_verbose > 2)
330                                                                         ast_verbose( VERBOSE_PREFIX_3 "%s is ringing\n", o->chan->name);
331                                                                 break;
332                                                         case AST_CONTROL_OFFHOOK:
333                                                                 /* Ignore going off hook */
334                                                                 break;
335                                                         default:
336                                                                 ast_log(LOG_DEBUG, "Dunno what to do with control type %d\n", f->subclass);
337                                                         }
338                                                 }
339                                                 ast_frfree(f);
340                                         } else {
341                                                 o->stillgoing = 0;
342                                         }
343                                         
344                                 }
345                         }
346                         o = o->next;
347                 }
348                 if (FD_ISSET(in->fd, &rfds) || FD_ISSET(in->fd, &efds)) {
349                         /* After unblocking the entirity of the list, check for the main channel */
350                         f = ast_read(in);
351 #if 0
352                         if (f && (f->frametype != AST_FRAME_VOICE))
353                                         printf("Frame type: %d, %d\n", f->frametype, f->subclass);
354 #endif
355                         if (!f || ((f->frametype == AST_FRAME_CONTROL) && (f->subclass = AST_CONTROL_HANGUP))) {
356                                 /* Got hung up */
357                                 *to=-1;
358                                 return NULL;
359                         }
360                 }
361                 
362         }
363         if (!(tv.tv_sec || tv.tv_usec) && (option_verbose > 2))
364                 ast_verbose( VERBOSE_PREFIX_3 "Nobody picked up in %d ms\n", orig);
365         *to = 0;
366         return peer;
367 }
368
369 static int bridge_call(struct ast_channel *chan, struct ast_channel *peer, int allowredirect)
370 {
371         /* Copy voice back and forth between the two channels.  Give the peer
372            the ability to transfer calls with '#<extension' syntax. */
373         struct ast_channel *cs[3];
374         int to = -1, len;
375         struct ast_frame *f;
376         struct ast_channel *who;
377         char newext[256], *ptr;
378         int res;
379         /* Answer if need be */
380         if (chan->state != AST_STATE_UP)
381                 if (ast_answer(chan))
382                         return -1;
383         peer->appl = "Bridged Call";
384         peer->data = chan->name;
385         cs[0] = chan;
386         cs[1] = peer;
387         for (/* ever */;;) {
388                 who = ast_waitfor_n(cs, 2, &to);
389                 if (!who) {
390                         ast_log(LOG_WARNING, "Nobody there??\n");
391                         continue;
392                 }
393                 f = ast_read(who);
394                 if (!f || ((f->frametype == AST_FRAME_CONTROL) && 
395                                         ((f->subclass == AST_CONTROL_HANGUP) ||
396                                          (f->subclass == AST_CONTROL_BUSY)))) 
397                         return -1;
398                 if ((f->frametype == AST_FRAME_VOICE) ||
399                     (f->frametype == AST_FRAME_DTMF) ||
400                         (f->frametype == AST_FRAME_TEXT)) {
401                         if ((f->frametype == AST_FRAME_DTMF) && (who == peer) && allowredirect &&
402                              (f->subclass == '#')) {
403                                 if (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
410                                         /* Transfer */
411                                         if ((res=ast_streamfile(peer, "pbx-transfer", chan->language)))
412                                                 break;
413                                         if ((res=ast_waitstream(peer, AST_DIGIT_ANY)) < 0)
414                                                 break;
415                                         ast_stopstream(peer);
416                                         if (res > 0) {
417                                                 /* If they've typed a digit already, handle it */
418                                                 newext[0] = res;
419                                                 ptr++;
420                                                 len --;
421                                         }
422                                         res = ast_readstring(peer, ptr, len, 3000, 2000, "#");
423                                         if (res)
424                                                 break;
425                                         if (!strcmp(newext, parking_ext)) {
426                                                 if (!park_call(chan, peer)) {
427                                                         /* We return non-zero, but tell the PBX not to hang the channel when
428                                                            the thread dies -- We have to be careful now though.  We are responsible for 
429                                                            hanging up the channel, else it will never be hung up! */
430                                                         res=AST_PBX_KEEPALIVE;
431                                                         break;
432                                                 } else {
433                                                         ast_log(LOG_WARNING, "Unable to park call %s\n", chan->name);
434                                                 }
435                                                 /* XXX Maybe we should have another message here instead of invalid extension XXX */
436                                         } else if (ast_exists_extension(chan, peer->context, newext, 1)) {
437                                                 /* Set the channel's new extension, since it exists, using peer context */
438                                                 strncpy(chan->exten, newext, sizeof(chan->exten));
439                                                 strncpy(chan->context, peer->context, sizeof(chan->context));
440                                                 chan->priority = 0;
441                                                 ast_frfree(f);
442                                                 res=0;
443                                                 break;
444                                         } else if (ast_exists_extension(chan, "default", newext, 1)) {
445                                                 /* Set the channel's new extension, since it exists, using peer context */
446                                                 strncpy(chan->exten, newext, sizeof(chan->exten));
447                                                 strncpy(chan->context, "default", sizeof(chan->context));
448                                                 chan->priority = 0;
449                                                 ast_frfree(f);
450                                                 res=0;
451                                                 break;
452                                         }
453                                         res = ast_streamfile(peer, "pbx-invalid", chan->language);
454                                         if (res)
455                                                 break;
456                                         res = ast_waitstream(peer, AST_DIGIT_ANY);
457                                         ast_stopstream(peer);
458                                         res = 0;
459                                 }
460                         } else {
461 #if 0
462                                 ast_log(LOG_DEBUG, "Read from %s\n", who->name);
463 #endif
464                                 if (who == chan) 
465                                         ast_write(peer, f);
466                                 else 
467                                         ast_write(chan, f);
468                         }
469                         ast_frfree(f);
470                         
471                 } else
472                         ast_frfree(f);
473                 /* Swap who gets priority */
474                 cs[2] = cs[0];
475                 cs[0] = cs[1];
476                 cs[1] = cs[2];
477         }
478         return res;
479 }
480
481 static int park_exec(struct ast_channel *chan, void *data)
482 {
483         int res=0;
484         struct localuser *u;
485         struct ast_channel *peer=NULL, *nchan;
486         struct parkeduser *pu, *pl=NULL;
487         int park;
488         if (!data) {
489                 ast_log(LOG_WARNING, "Park requires an argument (extension number)\n");
490                 return -1;
491         }
492         LOCAL_USER_ADD(u);
493         park = atoi((char *)data);
494         pthread_mutex_lock(&parking_lock);
495         pu = parkinglot;
496         while(pu) {
497                 if (pu->parkingnum == park) {
498                         if (pl)
499                                 pl->next = pu->next;
500                         else
501                                 parkinglot = pu->next;
502                         break;
503                 }
504                 pu = pu->next;
505         }
506         pthread_mutex_unlock(&parking_lock);
507         if (pu) {
508                 peer = pu->chan;
509                 free(pu);
510         }
511         if (peer) {
512                 /* Build a translator if necessary */
513                 if (peer->format & chan->format) 
514                         nchan = chan;
515                 else
516                         nchan = ast_translator_create(chan, peer->format, AST_DIRECTION_BOTH);
517                 /* This runs sorta backwards, since we give the incoming channel control, as if it
518                    were the person called. */
519                 if (option_verbose > 2) 
520                         ast_verbose(VERBOSE_PREFIX_3 "Channel %s connected to parked call %d\n", chan->name, park);
521                 res = bridge_call(peer, nchan, 1);
522                 if (nchan != chan)
523                         ast_translator_destroy(nchan);
524                 /* Simulate the PBX hanging up */
525                 if (res != AST_PBX_KEEPALIVE)
526                         ast_hangup(peer);
527                 return -1;
528         } else {
529                 /* XXX Play a message XXX */
530                 if (option_verbose > 2) 
531                         ast_verbose(VERBOSE_PREFIX_3 "Channel %s tried to talk to non-existant parked call %d\n", chan->name, park);
532                 res = -1;
533         }
534         LOCAL_USER_REMOVE(u);
535         return res;
536 }
537
538 static int dial_exec(struct ast_channel *chan, void *data)
539 {
540         int res=-1;
541         struct localuser *u;
542         char *info, *peers, *timeout, *tech, *number, *rest, *cur;
543         struct localuser *outgoing=NULL, *tmp;
544         struct ast_channel *peer, *npeer;
545         int to;
546         int allowredir=0;
547         char numsubst[AST_MAX_EXTENSION];
548         char restofit[AST_MAX_EXTENSION];
549         char *newnum;
550         
551         if (!data) {
552                 ast_log(LOG_WARNING, "Dial requires an argument (technology1/number1&technology2/number2...|optional timeout)\n");
553                 return -1;
554         }
555         
556         LOCAL_USER_ADD(u);
557         
558         /* Parse our arguments XXX Check for failure XXX */
559         info = malloc(strlen((char *)data) + AST_MAX_EXTENSION);
560         strncpy(info, (char *)data, strlen((char *)data) + AST_MAX_EXTENSION);
561         peers = strtok(info, "|");
562         if (!peers) {
563                 ast_log(LOG_WARNING, "Dial argument takes format (technology1/number1&technology2/number2...|optional timeout)\n");
564                 goto out;
565         }
566         timeout = strtok(NULL, "|");
567         rest = peers;
568         do {
569                 cur = strtok(rest, "&");
570                 /* Remember where to start next time */
571                 rest = strtok(NULL, "\128");
572                 /* Get a technology/[device:]number pair */
573                 tech = strtok(cur, "/");
574                 number = strtok(NULL, "&");
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                 tmp = malloc(sizeof(struct localuser));
580                 if (!tmp) {
581                         ast_log(LOG_WARNING, "Out of memory\n");
582                         goto out;
583                 }
584                 tmp->allowredirect = 1;
585                 strncpy(numsubst, number, sizeof(numsubst));
586                 /* If we're dialing by extension, look at the extension to know what to dial */
587                 if ((newnum = strstr(numsubst, "BYEXTENSION"))) {
588                         strncpy(restofit, newnum + strlen("BYEXTENSION"), sizeof(restofit));
589                         snprintf(newnum, sizeof(numsubst) - (newnum - numsubst), "%s%s", chan->exten,restofit);
590                         /* By default, if we're dialing by extension, don't permit redirecting */
591                         tmp->allowredirect = 0;
592                         if (option_debug)
593                                 ast_log(LOG_DEBUG, "Dialing by extension %s\n", numsubst);
594                 }
595                 /* Request the peer */
596                 tmp->chan = ast_request(tech, chan->format, numsubst);
597                 if (!tmp->chan) {
598                         /* If we can't, just go on to the next call */
599                         ast_log(LOG_WARNING, "Unable to create channel of type '%s'\n", tech);
600                         free(tmp);
601                         continue;
602                 }
603                 tmp->chan->appl = "AppDial";
604                 tmp->chan->data = "(Outgoing Line)";
605                 /* Place the call, but don't wait on the answer */
606                 res = ast_call(tmp->chan, numsubst, 0);
607                 if (res) {
608                         /* Again, keep going even if there's an error */
609                         if (option_debug)
610                                 ast_log(LOG_DEBUG, "ast call on peer returned %d\n", res);
611                         else if (option_verbose > 2)
612                                 ast_verbose(VERBOSE_PREFIX_3 "Couldn't call %s\n", numsubst);
613                         ast_hangup(tmp->chan);
614                         free(tmp);
615                         continue;
616                 } else
617                         if (option_verbose > 2)
618                                 ast_verbose(VERBOSE_PREFIX_3 "Called %s\n", numsubst);
619                 /* Put them in the list of outgoing thingies...  We're ready now. 
620                    XXX If we're forcibly removed, these outgoing calls won't get
621                    hung up XXX */
622                 tmp->stillgoing = -1;
623                 tmp->next = outgoing;
624                 outgoing = tmp;
625         } while(rest);
626         if (timeout)
627                 to = atoi(timeout) * 1000;
628         else
629                 to = -1;
630         peer = wait_for_answer(chan, outgoing, &to, &allowredir);
631         if (!peer) {
632                 if (to) 
633                         /* Musta gotten hung up */
634                         res = -1;
635                  else 
636                         /* Nobody answered, next please? */
637                         res=0;
638                 
639                 goto out;
640         }
641         if (peer) {
642                 /* Ah ha!  Someone answered within the desired timeframe.  Of course after this
643                    we will always return with -1 so that it is hung up properly after the 
644                    conversation.  */
645                 hanguptree(outgoing, peer);
646                 outgoing = NULL;
647                 /* Build a translator if necessary */
648                 if (peer->format & chan->format) 
649                         npeer = peer;
650                 else
651                         npeer = ast_translator_create(peer, chan->format, AST_DIRECTION_BOTH);
652                 res = bridge_call(chan, npeer, allowredir);
653                 if (npeer != peer)
654                         ast_translator_destroy(npeer);
655                 ast_hangup(peer);
656         }       
657 out:
658         hanguptree(outgoing, NULL);
659         free(info);
660         LOCAL_USER_REMOVE(u);
661         return res;
662 }
663
664 int unload_module(void)
665 {
666         STANDARD_HANGUP_LOCALUSERS;
667         return ast_unregister_application(app);
668 }
669
670 int load_module(void)
671 {
672         int res;
673         int x;
674         struct ast_context *con;
675         char exten[AST_MAX_EXTENSION];
676         con = ast_context_find(parking_con);
677         if (!con) {
678                 ast_log(LOG_ERROR, "Parking context '%s' does not exist\n", parking_con);
679                 return -1;
680         }
681         for(x=parking_start; x<=parking_stop;x++) {
682                 snprintf(exten, sizeof(exten), "%d", x);
683                 ast_add_extension2(con, 1, exten, 1, parkedcall, strdup(exten), free);
684         }
685         pthread_create(&parking_thread, NULL, do_parking_thread, NULL);
686         res = ast_register_application(parkedcall, park_exec);
687         if (!res)
688                 res = ast_register_application(app, dial_exec);
689         return res;
690 }
691
692 char *description(void)
693 {
694         return tdesc;
695 }
696
697 int usecount(void)
698 {
699         int res;
700         STANDARD_USECOUNT(res);
701         return res;
702 }