Fixed bug in remote base part of app_rpt, and updated rpt.conf.sample to
[asterisk/asterisk.git] / apps / app_rpt.c
1 /** @file app_rpt.c 
2  *
3  * Asterisk -- A telephony toolkit for Linux.
4  *
5  * Radio Repeater / Remote Base program 
6  *  version 0.5 6/22/04
7  * 
8  * Copyright (C) 2002-2004, Jim Dixon, WB6NIL
9  *
10  * Jim Dixon, WB6NIL <jim@lambdatel.com>
11  *
12  * This program is free software, distributed under the terms of
13  * the GNU General Public License
14  *
15  * Repeater / Remote Functions:
16  * "Simple" Mode:  * - autopatch access, # - autopatch hangup
17  * Normal mode:
18  *  *0 - autopatch off
19  *  *1XXX - remote link off
20  *  *2XXX - remote link monitor
21  *  *3XXX - remote link tranceive
22  *  *4XXX - remote link command mode
23  *  *6 - autopatch access/send (*)
24  *  *7 - system status
25  *  *8 - force ID
26  *  *9 - system reset
27  *
28  *  To send an asterisk (*) while dialing or talking on phone,
29  *  use the autopatch acess code.
30  */
31  
32 /* number of digits for function after *. Must be at least 1 */
33 #define FUNCTION_LEN 4
34 /* string containing all of the 1 digit functions */
35 #define SHORTFUNCS "056789"
36
37 /* maximum digits in DTMF buffer, and seconds after * for DTMF command timeout */
38
39 #define MAXDTMF 10
40 #define DTMF_TIMEOUT 3
41
42 #define NODES "nodes"
43
44 #define MAXCONNECTTIME 5000
45
46 #define MAXNODESTR 300
47
48 enum {REM_OFF,REM_MONITOR,REM_TX};
49
50 enum{ID,PROC,TERM,COMPLETE,UNKEY,REMDISC,REMALREADY,REMNOTFOUND,REMGO,
51         CONNECTED,CONNFAIL,STATUS};
52
53 #include <asterisk/lock.h>
54 #include <asterisk/file.h>
55 #include <asterisk/logger.h>
56 #include <asterisk/channel.h>
57 #include <asterisk/callerid.h>
58 #include <asterisk/pbx.h>
59 #include <asterisk/module.h>
60 #include <asterisk/translate.h>
61 #include <asterisk/options.h>
62 #include <asterisk/config.h>
63 #include <asterisk/utils.h>
64 #include <asterisk/say.h>
65 #include <stdio.h>
66 #include <unistd.h>
67 #include <string.h>
68 #include <stdlib.h>
69 #include <search.h>
70 #include <sys/types.h>
71 #include <sys/stat.h>
72 #include <errno.h>
73 #include <dirent.h>
74 #include <ctype.h>
75 #include <sys/stat.h>
76 #include <sys/time.h>
77 #include <sys/file.h>
78 #include <sys/ioctl.h>
79 #include <math.h>
80 #include <tonezone.h>
81 #include <linux/zaptel.h>
82
83 static  char *tdesc = "Radio Repeater / Remote Base  version 0.3  06/18/2004";
84 static char *app = "Rpt";
85
86 static char *synopsis = "Radio Repeater/Remote Base Control System";
87
88 static char *descrip = 
89 "  Rpt(sysname):  Radio Remote Link or Remote Base Link Endpoint Process.\n";
90
91 static int debug = 0;
92 static int nrpts = 0;
93
94 struct  ast_config *cfg;
95
96 STANDARD_LOCAL_USER;
97 LOCAL_USER_DECL;
98
99 #define MSWAIT 200
100 #define HANGTIME 5000
101 #define TOTIME 180000
102 #define IDTIME 300000
103 #define MAXRPTS 20
104
105 static  pthread_t rpt_master_thread;
106
107 struct rpt;
108
109 struct rpt_link
110 {
111         struct rpt_link *next;
112         struct rpt_link *prev;
113         char    mode;                   /* 1 if in tx mode */
114         char    isremote;
115         char    name[MAXNODESTR];       /* identifier (routing) string */
116         char    lasttx;
117         char    lastrx;
118         char    connected;
119         char    outbound;
120         long elaptime;
121         struct ast_channel *chan;       
122         struct ast_channel *pchan;      
123 } ;
124
125 struct rpt_tele
126 {
127         struct rpt_tele *next;
128         struct rpt_tele *prev;
129         struct rpt *rpt;
130         int     mode;
131         struct rpt_link mylink;
132         pthread_t threadid;
133 } ;
134
135 static struct rpt
136 {
137         char *name;
138         ast_mutex_t lock;
139         char *rxchanname;
140         char *txchanname;
141         char *ourcontext;
142         char *ourcallerid;
143         char *acctcode;
144         char *ident;
145         char *tonezone;
146         struct rpt_link links;
147         int hangtime;
148         int totime;
149         int idtime;
150         char exttx;
151         char localtx;
152         char remoterx;
153         char remotetx;
154         char remoteon;
155         char simple;
156         char remote;
157         char dtmfbuf[MAXDTMF];
158         char rem_dtmfbuf[MAXDTMF];
159         char cmdnode[50];
160         struct ast_channel *rxchannel,*txchannel;
161         struct ast_channel *pchannel,*txpchannel;
162         struct rpt_tele tele;
163         pthread_t rpt_call_thread,rpt_thread;
164         time_t rem_dtmf_time;
165         int tailtimer,totimer,idtimer,txconf,conf,callmode,cidx;
166         int dtmfidx,rem_dtmfidx;
167         char mydtmf;
168         char exten[AST_MAX_EXTENSION];
169 } rpt_vars[MAXRPTS];            
170
171 static void *rpt_tele_thread(void *this)
172 {
173 ZT_CONFINFO ci;  /* conference info */
174 int     res = 0,hastx,imdone = 0;
175 struct  rpt_tele *mytele = (struct rpt_tele *)this;
176 struct  rpt *myrpt;
177 struct  rpt_link *l,*m,linkbase;
178 struct  ast_channel *mychannel;
179
180         /* get a pointer to myrpt */
181         myrpt = mytele->rpt;
182         /* allocate a pseudo-channel thru asterisk */
183         mychannel = ast_request("zap",AST_FORMAT_SLINEAR,"pseudo");
184         if (!mychannel)
185         {
186                 fprintf(stderr,"rpt:Sorry unable to obtain pseudo channel\n");
187                 ast_mutex_lock(&myrpt->lock);
188                 remque((struct qelem *)mytele);
189                 ast_mutex_unlock(&myrpt->lock);
190                 free(mytele);           
191                 pthread_exit(NULL);
192         }
193         /* make a conference for the tx */
194         ci.chan = 0;
195         ci.confno = myrpt->conf; /* use the tx conference */
196         ci.confmode = ZT_CONF_CONFANN;
197         /* first put the channel on the conference in announce mode */
198         if (ioctl(mychannel->fds[0],ZT_SETCONF,&ci) == -1)
199         {
200                 ast_log(LOG_WARNING, "Unable to set conference mode to Announce\n");
201                 ast_mutex_lock(&myrpt->lock);
202                 remque((struct qelem *)mytele);
203                 ast_mutex_unlock(&myrpt->lock);
204                 free(mytele);           
205                 ast_hangup(mychannel);
206                 pthread_exit(NULL);
207         }
208         ast_stopstream(mychannel);
209         switch(mytele->mode)
210         {
211             case ID:
212                 res = ast_streamfile(mychannel, myrpt->ident, mychannel->language);
213                 break;
214             case PROC:
215                 /* wait a little bit longer */
216                 usleep(1500000);
217                 res = ast_streamfile(mychannel, "rpt/callproceeding", mychannel->language);
218                 break;
219             case TERM:
220                 /* wait a little bit longer */
221                 usleep(1500000);
222                 res = ast_streamfile(mychannel, "rpt/callterminated", mychannel->language);
223                 break;
224             case COMPLETE:
225                 /* wait a little bit */
226                 usleep(1000000);
227                 res = ast_streamfile(mychannel, "rpt/functioncomplete", mychannel->language);
228                 break;
229             case UNKEY:
230                 /* wait a little bit */
231                 usleep(1000000);
232                 hastx = 0;
233                 l = myrpt->links.next;
234                 if (l != &myrpt->links)
235                 {
236                         ast_mutex_lock(&myrpt->lock);
237                         while(l != &myrpt->links)
238                         {
239                                 if (l->mode) hastx++;
240                                 l = l->next;
241                         }
242                         ast_mutex_unlock(&myrpt->lock);
243                         res = ast_streamfile(mychannel, 
244                                 ((!hastx) ? "rpt/remote_monitor" : "rpt/remote_tx"),
245                                         mychannel->language);
246                         if (!res) 
247                                 res = ast_waitstream(mychannel, "");
248                         else
249                                  ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", mychannel->name);
250                         ast_stopstream(mychannel);
251                 } 
252                 /* if in remote cmd mode, indicate it */
253                 if (myrpt->cmdnode[0])
254                 {
255                         ast_safe_sleep(mychannel,200);
256                         res = ast_streamfile(mychannel, "rpt/remote_cmd", mychannel->language);
257                         if (!res) 
258                                 res = ast_waitstream(mychannel, "");
259                         else
260                                  ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", mychannel->name);
261                         ast_stopstream(mychannel);
262                 }
263                 imdone = 1;
264                 break;
265             case REMDISC:
266                 /* wait a little bit */
267                 usleep(1000000);
268                 res = ast_streamfile(mychannel, "rpt/node", mychannel->language);
269                 if (!res) 
270                         res = ast_waitstream(mychannel, "");
271                 else
272                          ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", mychannel->name);
273                 ast_stopstream(mychannel);
274                 ast_say_character_str(mychannel,mytele->mylink.name,NULL,mychannel->language);
275                 res = ast_streamfile(mychannel, ((mytele->mylink.connected) ? 
276                         "rpt/remote_disc" : "rpt/remote_busy"), mychannel->language);
277                 break;
278             case REMALREADY:
279                 /* wait a little bit */
280                 usleep(1000000);
281                 res = ast_streamfile(mychannel, "rpt/remote_already", mychannel->language);
282                 break;
283             case REMNOTFOUND:
284                 /* wait a little bit */
285                 usleep(1000000);
286                 res = ast_streamfile(mychannel, "rpt/remote_notfound", mychannel->language);
287                 break;
288             case REMGO:
289                 /* wait a little bit */
290                 usleep(1000000);
291                 res = ast_streamfile(mychannel, "rpt/remote_go", mychannel->language);
292                 break;
293             case CONNECTED:
294                 /* wait a little bit */
295                 usleep(1000000);
296                 res = ast_streamfile(mychannel, "rpt/node", mychannel->language);
297                 if (!res) 
298                         res = ast_waitstream(mychannel, "");
299                 else
300                          ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", mychannel->name);
301                 ast_stopstream(mychannel);
302                 ast_say_character_str(mychannel,mytele->mylink.name,NULL,mychannel->language);
303                 res = ast_streamfile(mychannel, "rpt/connected", mychannel->language);
304                 break;
305             case CONNFAIL:
306                 res = ast_streamfile(mychannel, "rpt/node", mychannel->language);
307                 if (!res) 
308                         res = ast_waitstream(mychannel, "");
309                 else
310                          ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", mychannel->name);
311                 ast_stopstream(mychannel);
312                 ast_say_character_str(mychannel,mytele->mylink.name,NULL,mychannel->language);
313                 res = ast_streamfile(mychannel, "rpt/connection_failed", mychannel->language);
314                 break;
315             case STATUS:
316                 /* wait a little bit */
317                 usleep(1000000);
318                 hastx = 0;
319                 linkbase.next = &linkbase;
320                 linkbase.prev = &linkbase;
321                 ast_mutex_lock(&myrpt->lock);
322                 /* make our own list of links */
323                 l = myrpt->links.next;
324                 while(l != &myrpt->links)
325                 {
326                         m = malloc(sizeof(struct rpt_link));
327                         if (!m)
328                         {
329                                 ast_log(LOG_WARNING, "Cannot alloc memory on %s\n", mychannel->name);
330                                 pthread_exit(NULL);
331                         }
332                         memcpy(m,l,sizeof(struct rpt_link));
333                         m->next = m->prev = NULL;
334                         insque((struct qelem *)m,(struct qelem *)linkbase.next);
335                         l = l->next;
336                 }
337                 ast_mutex_unlock(&myrpt->lock);
338                 res = ast_streamfile(mychannel, "rpt/node", mychannel->language);
339                 if (!res) 
340                         res = ast_waitstream(mychannel, "");
341                 else
342                          ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", mychannel->name);
343                 ast_stopstream(mychannel);
344                 ast_say_character_str(mychannel,myrpt->name,NULL,mychannel->language);
345                 if (!res) 
346                         res = ast_waitstream(mychannel, "");
347                 else
348                          ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", mychannel->name);
349                 ast_stopstream(mychannel);
350                 if (myrpt->callmode)
351                 {
352                         hastx = 1;
353                         res = ast_streamfile(mychannel, "rpt/autopatch_on", mychannel->language);
354                         if (!res) 
355                                 res = ast_waitstream(mychannel, "");
356                         else
357                                  ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", mychannel->name);
358                         ast_stopstream(mychannel);
359                 }
360                 l = linkbase.next;
361                 while(l != &linkbase)
362                 {
363                         hastx = 1;
364                         res = ast_streamfile(mychannel, "rpt/node", mychannel->language);
365                         if (!res) 
366                                 res = ast_waitstream(mychannel, "");
367                         else
368                                 ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", mychannel->name);
369                         ast_stopstream(mychannel);
370                         ast_say_character_str(mychannel,l->name,NULL,mychannel->language);
371                         if (!res) 
372                                 res = ast_waitstream(mychannel, "");
373                         else
374                                  ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", mychannel->name);
375                         ast_stopstream(mychannel);
376                         res = ast_streamfile(mychannel, ((l->mode) ? 
377                                 "rpt/tranceive" : "rpt/monitor"), mychannel->language);
378                         if (!res) 
379                                 res = ast_waitstream(mychannel, "");
380                         else
381                                 ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", mychannel->name);
382                         ast_stopstream(mychannel);
383                         l = l->next;
384                 }                       
385                 if (!hastx)
386                 {
387                         res = ast_streamfile(mychannel, "rpt/repeat_only", mychannel->language);
388                         if (!res) 
389                                 res = ast_waitstream(mychannel, "");
390                         else
391                                  ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", mychannel->name);
392                         ast_stopstream(mychannel);
393                 }
394                 /* destroy our local link queue */
395                 l = linkbase.next;
396                 while(l != &linkbase)
397                 {
398                         m = l;
399                         l = l->next;
400                         remque((struct qelem *)m);
401                         free(m);
402                 }                       
403                 imdone = 1;
404                 break;
405         }
406         if (!imdone)
407         {
408                 if (!res) 
409                         res = ast_waitstream(mychannel, "");
410                 else {
411                         ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", mychannel->name);
412                         res = 0;
413                 }
414         }
415         ast_stopstream(mychannel);
416         ast_mutex_lock(&myrpt->lock);
417         remque((struct qelem *)mytele);
418         ast_mutex_unlock(&myrpt->lock);
419         free(mytele);           
420         ast_hangup(mychannel);
421         pthread_exit(NULL);
422 }
423
424 static void rpt_telemetry(struct rpt *myrpt,int mode,struct rpt_link *mylink)
425 {
426 struct rpt_tele *tele;
427 pthread_attr_t attr;
428
429         tele = malloc(sizeof(struct rpt_tele));
430         if (!tele)
431         {
432                 ast_log(LOG_WARNING, "Unable to allocate memory\n");
433                 pthread_exit(NULL);
434                 return;
435         }
436         /* zero it out */
437         memset((char *)tele,0,sizeof(struct rpt_tele));
438         tele->rpt = myrpt;
439         tele->mode = mode;
440         ast_mutex_lock(&myrpt->lock);
441         memset(&tele->mylink,0,sizeof(struct rpt_link));
442         if (mylink)
443         {
444                 memcpy(&tele->mylink,mylink,sizeof(struct rpt_link));
445         }               
446         insque((struct qelem *)tele,(struct qelem *)myrpt->tele.next); 
447         ast_mutex_unlock(&myrpt->lock);
448         pthread_attr_init(&attr);
449         pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
450         pthread_create(&tele->threadid,&attr,rpt_tele_thread,(void *) tele);
451         return;
452 }
453
454 static void *rpt_call(void *this)
455 {
456 ZT_CONFINFO ci;  /* conference info */
457 struct  rpt *myrpt = (struct rpt *)this;
458 int     res;
459 struct  ast_frame *f,wf;
460 int stopped,congstarted;
461 struct ast_channel *mychannel,*genchannel;
462
463         myrpt->mydtmf = 0;
464         /* allocate a pseudo-channel thru asterisk */
465         mychannel = ast_request("zap",AST_FORMAT_SLINEAR,"pseudo");
466         if (!mychannel)
467         {
468                 fprintf(stderr,"rpt:Sorry unable to obtain pseudo channel\n");
469                 pthread_exit(NULL);
470         }
471         ci.chan = 0;
472         ci.confno = myrpt->conf; /* use the pseudo conference */
473         ci.confmode = ZT_CONF_REALANDPSEUDO | ZT_CONF_TALKER | ZT_CONF_LISTENER
474                 | ZT_CONF_PSEUDO_TALKER | ZT_CONF_PSEUDO_LISTENER; 
475         /* first put the channel on the conference */
476         if (ioctl(mychannel->fds[0],ZT_SETCONF,&ci) == -1)
477         {
478                 ast_log(LOG_WARNING, "Unable to set conference mode to Announce\n");
479                 ast_hangup(mychannel);
480                 myrpt->callmode = 0;
481                 pthread_exit(NULL);
482         }
483         /* allocate a pseudo-channel thru asterisk */
484         genchannel = ast_request("zap",AST_FORMAT_SLINEAR,"pseudo");
485         if (!genchannel)
486         {
487                 fprintf(stderr,"rpt:Sorry unable to obtain pseudo channel\n");
488                 ast_hangup(mychannel);
489                 pthread_exit(NULL);
490         }
491         ci.chan = 0;
492         ci.confno = myrpt->conf;
493         ci.confmode = ZT_CONF_REALANDPSEUDO | ZT_CONF_TALKER | ZT_CONF_LISTENER
494                 | ZT_CONF_PSEUDO_TALKER | ZT_CONF_PSEUDO_LISTENER; 
495         /* first put the channel on the conference */
496         if (ioctl(genchannel->fds[0],ZT_SETCONF,&ci) == -1)
497         {
498                 ast_log(LOG_WARNING, "Unable to set conference mode to Announce\n");
499                 ast_hangup(mychannel);
500                 ast_hangup(genchannel);
501                 myrpt->callmode = 0;
502                 pthread_exit(NULL);
503         }
504         if (myrpt->tonezone && (tone_zone_set_zone(mychannel->fds[0],myrpt->tonezone) == -1))
505         {
506                 ast_log(LOG_WARNING, "Unable to set tone zone %s\n",myrpt->tonezone);
507                 ast_hangup(mychannel);
508                 ast_hangup(genchannel);
509                 myrpt->callmode = 0;
510                 pthread_exit(NULL);
511         }
512         if (myrpt->tonezone && (tone_zone_set_zone(genchannel->fds[0],myrpt->tonezone) == -1))
513         {
514                 ast_log(LOG_WARNING, "Unable to set tone zone %s\n",myrpt->tonezone);
515                 ast_hangup(mychannel);
516                 ast_hangup(genchannel);
517                 myrpt->callmode = 0;
518                 pthread_exit(NULL);
519         }
520         /* start dialtone */
521         if (tone_zone_play_tone(mychannel->fds[0],ZT_TONE_DIALTONE) < 0)
522         {
523                 ast_log(LOG_WARNING, "Cannot start dialtone\n");
524                 ast_hangup(mychannel);
525                 ast_hangup(genchannel);
526                 myrpt->callmode = 0;
527                 pthread_exit(NULL);
528         }
529         stopped = 0;
530         congstarted = 0;
531         while ((myrpt->callmode == 1) || (myrpt->callmode == 4))
532         {
533
534                 if ((myrpt->callmode == 1) && (myrpt->cidx > 0) && (!stopped))
535                 {
536                         stopped = 1;
537                         /* stop dial tone */
538                         tone_zone_play_tone(mychannel->fds[0],-1);
539                 }
540                 if ((myrpt->callmode == 4) && (!congstarted))
541                 {
542                         congstarted = 1;
543                         /* start congestion tone */
544                         tone_zone_play_tone(mychannel->fds[0],ZT_TONE_CONGESTION);
545                 }
546                 res = ast_waitfor(mychannel, MSWAIT);
547                 if (res < 0)
548                 {
549                         ast_hangup(mychannel);
550                         ast_hangup(genchannel);
551                         ast_mutex_lock(&myrpt->lock);
552                         myrpt->callmode = 0;
553                         ast_mutex_unlock(&myrpt->lock);
554                         pthread_exit(NULL);
555                 }
556                 if (res == 0) continue;
557                 f = ast_read(mychannel);
558                 if (f == NULL) 
559                 {
560                         ast_hangup(mychannel);
561                         ast_hangup(genchannel);
562                         ast_mutex_lock(&myrpt->lock);
563                         myrpt->callmode = 0;
564                         ast_mutex_unlock(&myrpt->lock);
565                         pthread_exit(NULL);                     
566                 }
567                 if ((f->frametype == AST_FRAME_CONTROL) &&
568                     (f->subclass == AST_CONTROL_HANGUP))
569                 {
570                         ast_frfree(f);
571                         ast_hangup(mychannel);
572                         ast_hangup(genchannel);
573                         ast_mutex_lock(&myrpt->lock);
574                         myrpt->callmode = 0;
575                         ast_mutex_unlock(&myrpt->lock);
576                         pthread_exit(NULL);                     
577                 }
578                 ast_frfree(f);
579         }
580         /* stop any tone generation */
581         tone_zone_play_tone(mychannel->fds[0],-1);
582         /* end if done */
583         if (!myrpt->callmode)
584         {
585                 ast_hangup(mychannel);
586                 ast_hangup(genchannel);
587                 ast_mutex_lock(&myrpt->lock);
588                 myrpt->callmode = 0;
589                 ast_mutex_unlock(&myrpt->lock);
590                 pthread_exit(NULL);                     
591         }
592         if (myrpt->ourcallerid && *myrpt->ourcallerid)
593         {
594                 if (mychannel->callerid) free(mychannel->callerid);
595                 mychannel->callerid = strdup(myrpt->ourcallerid);
596         }
597         strcpy(mychannel->exten,myrpt->exten);
598         strcpy(mychannel->context,myrpt->ourcontext);
599         if (myrpt->acctcode)
600                 strcpy(mychannel->accountcode,myrpt->acctcode);
601         mychannel->priority = 1;
602         ast_channel_undefer_dtmf(mychannel);
603         if (ast_pbx_start(mychannel) < 0)
604         {
605                 ast_log(LOG_WARNING, "Unable to start PBX!!\n");
606                 ast_hangup(mychannel);
607                 ast_hangup(genchannel);
608                 ast_mutex_lock(&myrpt->lock);
609                 myrpt->callmode = 0;
610                 ast_mutex_unlock(&myrpt->lock);
611                 pthread_exit(NULL);
612         }
613         ast_mutex_lock(&myrpt->lock);
614         myrpt->callmode = 3;
615         while(myrpt->callmode)
616         {
617                 if ((!mychannel->pvt) && (myrpt->callmode != 4))
618                 {
619                         myrpt->callmode = 4;
620                         ast_mutex_unlock(&myrpt->lock);
621                         /* start congestion tone */
622                         tone_zone_play_tone(genchannel->fds[0],ZT_TONE_CONGESTION);
623                         ast_mutex_lock(&myrpt->lock);
624                 }
625                 if (myrpt->mydtmf)
626                 {
627                         wf.frametype = AST_FRAME_DTMF;
628                         wf.subclass = myrpt->mydtmf;
629                         wf.offset = 0;
630                         wf.mallocd = 0;
631                         wf.data = NULL;
632                         wf.datalen = 0;
633                         wf.samples = 0;
634                         ast_mutex_unlock(&myrpt->lock);
635                         ast_write(genchannel,&wf); 
636                         ast_mutex_lock(&myrpt->lock);
637                         myrpt->mydtmf = 0;
638                 }
639                 ast_mutex_unlock(&myrpt->lock);
640                 usleep(25000);
641                 ast_mutex_lock(&myrpt->lock);
642         }
643         ast_mutex_unlock(&myrpt->lock);
644         tone_zone_play_tone(genchannel->fds[0],-1);
645         if (mychannel->pvt) ast_softhangup(mychannel,AST_SOFTHANGUP_DEV);
646         ast_hangup(genchannel);
647         ast_mutex_lock(&myrpt->lock);
648         myrpt->callmode = 0;
649         ast_mutex_unlock(&myrpt->lock);
650         pthread_exit(NULL);
651 }
652
653 static void send_link_dtmf(struct rpt *myrpt,char c)
654 {
655 char    str[300];
656 struct  ast_frame wf;
657 struct  rpt_link *l;
658
659         sprintf(str,"D %s %s %d %c",myrpt->cmdnode,myrpt->name,++(myrpt->dtmfidx),c);
660         wf.frametype = AST_FRAME_TEXT;
661         wf.subclass = 0;
662         wf.offset = 0;
663         wf.mallocd = 1;
664         wf.datalen = strlen(str) + 1;
665         wf.samples = 0;
666         l = myrpt->links.next;
667         /* first, see if our dude is there */
668         while(l != &myrpt->links)
669         {
670                 if (!l->isremote)
671                 {
672                         /* if we found it, write it and were done */
673                         if (!strcmp(l->name,myrpt->cmdnode))
674                         {
675                                 wf.data = strdup(str);
676                                 ast_write(l->chan,&wf);
677                                 return;
678                         }
679                 }
680                 l = l->next;
681         }
682         l = myrpt->links.next;
683         /* if not, give it to everyone */
684         while(l != &myrpt->links)
685         {
686                 if (!l->isremote) 
687                 {
688                         wf.data = strdup(str);
689                         ast_write(l->chan,&wf);
690                 }
691                 l = l->next;
692         }
693         return;
694 }
695
696 static void process_dtmf(char *cmd,struct rpt *myrpt, int allow_linkcmd)
697 {
698 pthread_attr_t attr;
699 char *tele,tmp[300],deststr[300],*val,*s,*s1;
700 struct rpt_link *l;
701 ZT_CONFINFO ci;  /* conference info */
702
703         switch(atoi(cmd) / 1000)
704         {
705         case 6: /* autopatch on / send asterisk (*) */
706                 ast_mutex_lock(&myrpt->lock);
707                 /* if on call, force * into current audio stream */
708                 if ((myrpt->callmode == 2) || (myrpt->callmode == 3))
709                 {
710                         myrpt->mydtmf = '*';
711                         ast_mutex_unlock(&myrpt->lock);
712                         break;
713                 }
714                 if (myrpt->callmode)
715                 {
716                         ast_mutex_unlock(&myrpt->lock);
717                         return;
718                 }
719                 myrpt->callmode = 1;
720                 myrpt->cidx = 0;
721                 myrpt->exten[myrpt->cidx] = 0;
722                 ast_mutex_unlock(&myrpt->lock);
723                 pthread_attr_init(&attr);
724                 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
725                 pthread_create(&myrpt->rpt_call_thread,&attr,rpt_call,(void *) myrpt);
726                 return;
727         case 0: /* autopatch off */
728                 ast_mutex_lock(&myrpt->lock);
729                 if (!myrpt->callmode)
730                 {
731                         ast_mutex_unlock(&myrpt->lock);
732                         return;
733                 }
734                 myrpt->callmode = 0;
735                 ast_mutex_unlock(&myrpt->lock);
736                 rpt_telemetry(myrpt,TERM,NULL);
737                 return;
738         case 9: /* master reset */
739                 ast_mutex_lock(&myrpt->lock);
740                 myrpt->callmode = 0;
741                 ast_mutex_unlock(&myrpt->lock);
742                 l = myrpt->links.next;
743                 /* disconnect all of the remote stuff */
744                 while(l != &myrpt->links)
745                 {
746                         ast_softhangup(l->chan,AST_SOFTHANGUP_DEV);
747                         l = l->next;
748                 }
749                 break;
750         case 1: /* remote base off */
751                 val = ast_variable_retrieve(cfg,NODES,cmd + 1);
752                 if (!val)
753                 {
754                         rpt_telemetry(myrpt,REMNOTFOUND,NULL);
755                         return;
756                 }
757                 strncpy(tmp,val,sizeof(tmp) - 1);
758                 s = tmp;
759                 s1 = strsep(&s,",");
760                 ast_mutex_lock(&myrpt->lock);
761                 l = myrpt->links.next;
762                 /* try to find this one in queue */
763                 while(l != &myrpt->links)
764                 {
765                         /* if found matching string */
766                         if (!strcmp(l->name,cmd + 1)) break;
767                         l = l->next;
768                 }
769                 if (l != &myrpt->links) /* if found */
770                 {
771                         ast_mutex_unlock(&myrpt->lock);
772                         ast_softhangup(l->chan,AST_SOFTHANGUP_DEV);
773                         break;
774                 }
775                 ast_mutex_unlock(&myrpt->lock);
776                 return;
777         case 2: /* remote base monitor */
778                 val = ast_variable_retrieve(cfg,NODES,cmd + 1);
779                 if (!val)
780                 {
781                         rpt_telemetry(myrpt,REMNOTFOUND,NULL);
782                         return;
783                 }
784                 strncpy(tmp,val,sizeof(tmp) - 1);
785                 s = tmp;
786                 s1 = strsep(&s,",");
787                 ast_mutex_lock(&myrpt->lock);
788                 l = myrpt->links.next;
789                 /* try to find this one in queue */
790                 while(l != &myrpt->links)
791                 {
792                         /* if found matching string */
793                         if (!strcmp(l->name,cmd + 1)) break;
794                         l = l->next;
795                 }
796                 /* if found */
797                 if (l != &myrpt->links) 
798                 {
799                         /* if already in this mode, just ignore */
800                         if (!l->mode) {
801                                 ast_mutex_unlock(&myrpt->lock);
802                                 rpt_telemetry(myrpt,REMALREADY,NULL);
803                                 return;
804                         }
805                         ast_softhangup(l->chan,AST_SOFTHANGUP_DEV);
806                         usleep(500000); 
807                 }
808                 ast_mutex_unlock(&myrpt->lock);
809                 /* establish call in monitor mode */
810                 l = malloc(sizeof(struct rpt_link));
811                 if (!l)
812                 {
813                         ast_log(LOG_WARNING, "Unable to malloc\n");
814                         pthread_exit(NULL);
815                 }
816                 /* zero the silly thing */
817                 memset((char *)l,0,sizeof(struct rpt_link));
818                 sprintf(deststr,"IAX2/%s",s1);
819                 tele = strchr(deststr,'/');
820                 if (!tele)
821                 {
822                         fprintf(stderr,"rpt:Dial number (%s) must be in format tech/number\n",deststr);
823                         pthread_exit(NULL);
824                 }
825                 *tele++ = 0;
826                 l->isremote = (s && ast_true(s));
827                 strncpy(l->name,cmd + 1,MAXNODESTR - 1);
828                 l->chan = ast_request(deststr,AST_FORMAT_SLINEAR,tele);
829                 if (l->chan)
830                 {
831                         ast_set_read_format(l->chan,AST_FORMAT_SLINEAR);
832                         ast_set_write_format(l->chan,AST_FORMAT_SLINEAR);
833                         l->chan->whentohangup = 0;
834                         l->chan->appl = "Apprpt";
835                         l->chan->data = "(Remote Rx)";
836                         if (option_verbose > 2)
837                                 ast_verbose(VERBOSE_PREFIX_3 "rpt (remote) initiating call to %s/%s on %s\n",
838                                         deststr,tele,l->chan->name);
839                         l->chan->callerid = strdup(myrpt->name);
840                         ast_call(l->chan,tele,0);
841                 }
842                 else
843                 {
844                         free(l);
845                         if (option_verbose > 2)
846                                 ast_verbose(VERBOSE_PREFIX_3 "Unable to place call to %s/%s on %s\n",
847                                         deststr,tele,l->chan->name);
848                         return;
849                 }
850                 /* allocate a pseudo-channel thru asterisk */
851                 l->pchan = ast_request("zap",AST_FORMAT_SLINEAR,"pseudo");
852                 if (!l->pchan)
853                 {
854                         fprintf(stderr,"rpt:Sorry unable to obtain pseudo channel\n");
855                         pthread_exit(NULL);
856                 }
857                 ast_set_read_format(l->pchan,AST_FORMAT_SLINEAR);
858                 ast_set_write_format(l->pchan,AST_FORMAT_SLINEAR);
859                 /* make a conference for the pseudo-one */
860                 ci.chan = 0;
861                 ci.confno = myrpt->conf;
862                 ci.confmode = ZT_CONF_CONF | ZT_CONF_LISTENER | ZT_CONF_TALKER;
863                 /* first put the channel on the conference in proper mode */
864                 if (ioctl(l->pchan->fds[0],ZT_SETCONF,&ci) == -1)
865                 {
866                         ast_log(LOG_WARNING, "Unable to set conference mode to Announce\n");
867                         pthread_exit(NULL);
868                 }
869                 ast_mutex_lock(&myrpt->lock);
870                 /* insert at end of queue */
871                 insque((struct qelem *)l,(struct qelem *)myrpt->links.next);
872                 ast_mutex_unlock(&myrpt->lock);
873                 break;
874         case 3: /* remote base tranceieve */
875                 val = ast_variable_retrieve(cfg,NODES,cmd + 1);
876                 if (!val)
877                 {
878                         rpt_telemetry(myrpt,REMNOTFOUND,NULL);
879                         return;
880                 }
881                 strncpy(tmp,val,sizeof(tmp) - 1);
882                 s = tmp;
883                 s1 = strsep(&s,",");
884                 ast_mutex_lock(&myrpt->lock);
885                 l = myrpt->links.next;
886                 /* try to find this one in queue */
887                 while(l != &myrpt->links)
888                 {
889                         /* if found matching string */
890                         if (!strcmp(l->name,cmd + 1)) break;
891                 }
892                 /* if found */
893                 if (l != &myrpt->links) 
894                 {
895                         /* if already in this mode, just ignore */
896                         if (l->mode)
897                         {
898                                 ast_mutex_unlock(&myrpt->lock);
899                                 rpt_telemetry(myrpt,REMALREADY,NULL);
900                                 return;
901                         }
902                         ast_softhangup(l->chan,AST_SOFTHANGUP_DEV);
903                         usleep(500000); 
904                 }
905                 ast_mutex_unlock(&myrpt->lock);
906                 /* establish call in tranceive mode */
907                 l = malloc(sizeof(struct rpt_link));
908                 if (!l)
909                 {
910                         ast_log(LOG_WARNING, "Unable to malloc\n");
911                         pthread_exit(NULL);
912                 }
913                 /* zero the silly thing */
914                 memset((char *)l,0,sizeof(struct rpt_link));
915                 l->mode = 1;
916                 strncpy(l->name,cmd + 1,MAXNODESTR - 1);
917                 l->isremote = (s && ast_true(s));
918                 sprintf(deststr,"IAX2/%s",s1);
919                 tele = strchr(deststr,'/');
920                 if (!tele)
921                 {
922                         fprintf(stderr,"rpt:Dial number must be in format tech/number\n");
923                         pthread_exit(NULL);
924                 }
925                 *tele++ = 0;
926                 l->chan = ast_request(deststr,AST_FORMAT_SLINEAR,tele);
927                 if (l->chan)
928                 {
929                         ast_set_read_format(l->chan,AST_FORMAT_SLINEAR);
930                         ast_set_write_format(l->chan,AST_FORMAT_SLINEAR);
931                         l->chan->whentohangup = 0;
932                         l->chan->appl = "Apprpt";
933                         l->chan->data = "(Remote Rx)";
934                         if (option_verbose > 2)
935                                 ast_verbose(VERBOSE_PREFIX_3 "rpt (remote) initiating call to %s/%s on %s\n",
936                                         deststr,tele,l->chan->name);
937                         l->chan->callerid = strdup(myrpt->name);
938                         ast_call(l->chan,tele,999);
939                 }
940                 else
941                 {
942                         free(l);
943                         if (option_verbose > 2)
944                                 ast_verbose(VERBOSE_PREFIX_3 "Unable to place call to %s/%s on %s\n",
945                                         deststr,tele,l->chan->name);
946                         return;
947                 }
948                 /* allocate a pseudo-channel thru asterisk */
949                 l->pchan = ast_request("zap",AST_FORMAT_SLINEAR,"pseudo");
950                 if (!l->pchan)
951                 {
952                         fprintf(stderr,"rpt:Sorry unable to obtain pseudo channel\n");
953                         pthread_exit(NULL);
954                 }
955                 ast_set_read_format(l->pchan,AST_FORMAT_SLINEAR);
956                 ast_set_write_format(l->pchan,AST_FORMAT_SLINEAR);
957                 /* make a conference for the tx */
958                 ci.chan = 0;
959                 ci.confno = myrpt->conf;
960                 ci.confmode = ZT_CONF_CONF | ZT_CONF_LISTENER | ZT_CONF_TALKER;
961                 /* first put the channel on the conference in proper mode */
962                 if (ioctl(l->pchan->fds[0],ZT_SETCONF,&ci) == -1)
963                 {
964                         ast_log(LOG_WARNING, "Unable to set conference mode to Announce\n");
965                         pthread_exit(NULL);
966                 }
967                 ast_mutex_lock(&myrpt->lock);
968                 /* insert at end of queue */
969                 insque((struct qelem *)l,(struct qelem *)myrpt->links.next);
970                 ast_mutex_unlock(&myrpt->lock);
971                 break;
972         case 4: /* remote cmd mode */
973                 /* if doesnt allow link cmd, return */
974                 if ((!allow_linkcmd) || (myrpt->links.next == &myrpt->links)) return;
975                 /* if already in cmd mode, or selected self, forget it */
976                 if ((myrpt->cmdnode[0]) || (!strcmp(myrpt->name,cmd + 1)))
977                 {
978                         rpt_telemetry(myrpt,REMALREADY,NULL);
979                         return;
980                 }
981                 /* node must at least exist in list */
982                 val = ast_variable_retrieve(cfg,NODES,cmd + 1);
983                 if (!val)
984                 {
985                         rpt_telemetry(myrpt,REMNOTFOUND,NULL);
986                         return;
987                 }
988                 ast_mutex_lock(&myrpt->lock);
989                 myrpt->dtmfidx = -1;
990                 myrpt->dtmfbuf[0] = 0;
991                 myrpt->rem_dtmfidx = -1;
992                 myrpt->rem_dtmfbuf[0] = 0;
993                 strcpy(myrpt->cmdnode,cmd + 1);
994                 ast_mutex_unlock(&myrpt->lock);
995                 rpt_telemetry(myrpt,REMGO,NULL);                                
996                 return;
997         case 7: /* system status */
998                 rpt_telemetry(myrpt,STATUS,NULL);
999                 return;
1000         case 8: /* force ID */
1001                 myrpt->idtimer = 0;
1002                 return;
1003         default:
1004                 return;
1005         }
1006         rpt_telemetry(myrpt,COMPLETE,NULL);
1007 }
1008
1009 static void handle_link_data(struct rpt *myrpt, char *str)
1010 {
1011 char    tmp[300],cmd[300],dest[300],src[300],c;
1012 int     seq;
1013 struct rpt_link *l;
1014 struct  ast_frame wf;
1015
1016         /* if we are a remote, we dont want to do this */
1017         if (myrpt->remote) return;
1018         wf.frametype = AST_FRAME_TEXT;
1019         wf.subclass = 0;
1020         wf.offset = 0;
1021         wf.mallocd = 1;
1022         wf.datalen = strlen(str) + 1;
1023         wf.samples = 0;
1024         l = myrpt->links.next;
1025         /* put string in our buffer */
1026         strncpy(tmp,str,sizeof(tmp) - 1);
1027         if (sscanf(tmp,"%s %s %s %d %c",cmd,dest,src,&seq,&c) != 5)
1028         {
1029                 ast_log(LOG_WARNING, "Unable to parse link string %s\n",str);
1030                 return;
1031         }
1032         if (strcmp(cmd,"D"))
1033         {
1034                 ast_log(LOG_WARNING, "Unable to parse link string %s\n",str);
1035                 return;
1036         }
1037         /* if not for me, redistribute to all links */
1038         if (strcmp(dest,myrpt->name))
1039         {
1040                 l = myrpt->links.next;
1041                 while(l != &myrpt->links)
1042                 {
1043                         if (!l->isremote)
1044                         {
1045                                 wf.data = strdup(str);
1046                                 ast_write(l->chan,&wf);
1047                         }
1048                         l = l->next;
1049                 }
1050                 return;
1051         }
1052         ast_mutex_lock(&myrpt->lock);
1053         if (c == '*')
1054         {
1055                 myrpt->rem_dtmfidx = 0;
1056                 myrpt->rem_dtmfbuf[myrpt->rem_dtmfidx] = 0;
1057                 time(&myrpt->rem_dtmf_time);
1058                 ast_mutex_unlock(&myrpt->lock);
1059                 return;
1060         } 
1061         else if ((c != '#') && (myrpt->rem_dtmfidx >= 0))
1062         {
1063                 time(&myrpt->rem_dtmf_time);
1064                 if (myrpt->rem_dtmfidx < MAXDTMF)
1065                 {
1066                         myrpt->rem_dtmfbuf[myrpt->rem_dtmfidx++] = c;
1067                         myrpt->rem_dtmfbuf[myrpt->rem_dtmfidx] = 0;
1068                         /* if to terminate function now */
1069                         if ((myrpt->rem_dtmfidx == 1) && strchr(SHORTFUNCS,c))
1070                         {
1071                                 while(myrpt->rem_dtmfidx < FUNCTION_LEN)
1072                                         myrpt->rem_dtmfbuf[myrpt->rem_dtmfidx++] = '0';
1073                                 myrpt->rem_dtmfbuf[myrpt->rem_dtmfidx] = 0;
1074                         }
1075                 }
1076                 if (myrpt->rem_dtmfidx == FUNCTION_LEN)
1077                 {
1078                         strcpy(cmd,myrpt->rem_dtmfbuf);
1079                         myrpt->rem_dtmfbuf[0] = 0;
1080                         myrpt->rem_dtmfidx = -1;
1081                         ast_mutex_unlock(&myrpt->lock);
1082                         process_dtmf(cmd,myrpt,0);
1083                         return;
1084                 }
1085         }
1086         ast_mutex_unlock(&myrpt->lock);
1087         return;
1088 }
1089
1090 /* single thread with one file (request) to dial */
1091 static void *rpt(void *this)
1092 {
1093 struct  rpt *myrpt = (struct rpt *)this;
1094 char *tele;
1095 int ms = MSWAIT,lasttx,keyed,val,remrx;
1096 struct ast_channel *who;
1097 ZT_CONFINFO ci;  /* conference info */
1098 time_t  dtmf_time,t;
1099 struct rpt_link *l,*m;
1100 pthread_attr_t attr;
1101
1102         ast_mutex_lock(&myrpt->lock);
1103         tele = strchr(myrpt->rxchanname,'/');
1104         if (!tele)
1105         {
1106                 fprintf(stderr,"rpt:Dial number must be in format tech/number\n");
1107                 ast_mutex_unlock(&myrpt->lock);
1108                 pthread_exit(NULL);
1109         }
1110         *tele++ = 0;
1111         myrpt->rxchannel = ast_request(myrpt->rxchanname,AST_FORMAT_SLINEAR,tele);
1112         if (myrpt->rxchannel)
1113         {
1114                 ast_set_read_format(myrpt->rxchannel,AST_FORMAT_SLINEAR);
1115                 ast_set_write_format(myrpt->rxchannel,AST_FORMAT_SLINEAR);
1116                 myrpt->rxchannel->whentohangup = 0;
1117                 myrpt->rxchannel->appl = "Apprpt";
1118                 myrpt->rxchannel->data = "(Repeater Rx)";
1119                 if (option_verbose > 2)
1120                         ast_verbose(VERBOSE_PREFIX_3 "rpt (Rx) initiating call to %s/%s on %s\n",
1121                                 myrpt->rxchanname,tele,myrpt->rxchannel->name);
1122                 ast_call(myrpt->rxchannel,tele,999);
1123         }
1124         else
1125         {
1126                 fprintf(stderr,"rpt:Sorry unable to obtain Rx channel\n");
1127                 ast_mutex_unlock(&myrpt->lock);
1128                 pthread_exit(NULL);
1129         }
1130         if (myrpt->txchanname)
1131         {
1132                 tele = strchr(myrpt->txchanname,'/');
1133                 if (!tele)
1134                 {
1135                         fprintf(stderr,"rpt:Dial number must be in format tech/number\n");
1136                         ast_mutex_unlock(&myrpt->lock);
1137                         pthread_exit(NULL);
1138                 }
1139                 *tele++ = 0;
1140                 myrpt->txchannel = ast_request(myrpt->txchanname,AST_FORMAT_SLINEAR,tele);
1141                 if (myrpt->txchannel)
1142                 {
1143                         ast_set_read_format(myrpt->txchannel,AST_FORMAT_SLINEAR);
1144                         ast_set_write_format(myrpt->txchannel,AST_FORMAT_SLINEAR);
1145                         myrpt->txchannel->whentohangup = 0;
1146                         myrpt->txchannel->appl = "Apprpt";
1147                         myrpt->txchannel->data = "(Repeater Rx)";
1148                         if (option_verbose > 2)
1149                                 ast_verbose(VERBOSE_PREFIX_3 "rpt (Tx) initiating call to %s/%s on %s\n",
1150                                         myrpt->txchanname,tele,myrpt->txchannel->name);
1151                         ast_call(myrpt->txchannel,tele,999);
1152                 }
1153                 else
1154                 {
1155                         fprintf(stderr,"rpt:Sorry unable to obtain Tx channel\n");
1156                         ast_mutex_unlock(&myrpt->lock);
1157                         pthread_exit(NULL);
1158                 }
1159         }
1160         else
1161         {
1162                 myrpt->txchannel = myrpt->rxchannel;
1163         }
1164         /* allocate a pseudo-channel thru asterisk */
1165         myrpt->pchannel = ast_request("zap",AST_FORMAT_SLINEAR,"pseudo");
1166         if (!myrpt->pchannel)
1167         {
1168                 fprintf(stderr,"rpt:Sorry unable to obtain pseudo channel\n");
1169                 ast_mutex_unlock(&myrpt->lock);
1170                 pthread_exit(NULL);
1171         }
1172         /* make a conference for the tx */
1173         ci.chan = 0;
1174         ci.confno = -1; /* make a new conf */
1175         ci.confmode = ZT_CONF_CONF | ZT_CONF_LISTENER;
1176         /* first put the channel on the conference in proper mode */
1177         if (ioctl(myrpt->txchannel->fds[0],ZT_SETCONF,&ci) == -1)
1178         {
1179                 ast_log(LOG_WARNING, "Unable to set conference mode to Announce\n");
1180                 ast_mutex_unlock(&myrpt->lock);
1181                 pthread_exit(NULL);
1182         }
1183         /* save tx conference number */
1184         myrpt->txconf = ci.confno;
1185         /* make a conference for the pseudo */
1186         ci.chan = 0;
1187         ci.confno = -1; /* make a new conf */
1188         ci.confmode = ZT_CONF_CONFANNMON; 
1189         /* first put the channel on the conference in announce mode */
1190         if (ioctl(myrpt->pchannel->fds[0],ZT_SETCONF,&ci) == -1)
1191         {
1192                 ast_log(LOG_WARNING, "Unable to set conference mode to Announce\n");
1193                 ast_mutex_unlock(&myrpt->lock);
1194                 pthread_exit(NULL);
1195         }
1196         /* save pseudo channel conference number */
1197         myrpt->conf = ci.confno;
1198         /* allocate a pseudo-channel thru asterisk */
1199         myrpt->txpchannel = ast_request("zap",AST_FORMAT_SLINEAR,"pseudo");
1200         if (!myrpt->txpchannel)
1201         {
1202                 fprintf(stderr,"rpt:Sorry unable to obtain pseudo channel\n");
1203                 ast_mutex_unlock(&myrpt->lock);
1204                 pthread_exit(NULL);
1205         }
1206         /* make a conference for the tx */
1207         ci.chan = 0;
1208         ci.confno = myrpt->txconf;
1209         ci.confmode = ZT_CONF_CONF | ZT_CONF_TALKER ;
1210         /* first put the channel on the conference in proper mode */
1211         if (ioctl(myrpt->txpchannel->fds[0],ZT_SETCONF,&ci) == -1)
1212         {
1213                 ast_log(LOG_WARNING, "Unable to set conference mode to Announce\n");
1214                 ast_mutex_unlock(&myrpt->lock);
1215                 pthread_exit(NULL);
1216         }
1217         /* Now, the idea here is to copy from the physical rx channel buffer
1218            into the pseudo tx buffer, and from the pseudo rx buffer into the 
1219            tx channel buffer */
1220         myrpt->links.next = &myrpt->links;
1221         myrpt->links.prev = &myrpt->links;
1222         myrpt->tailtimer = 0;
1223         myrpt->totimer = 0;
1224         myrpt->idtimer = 0;
1225         myrpt->callmode = 0;
1226         ast_mutex_unlock(&myrpt->lock);
1227         lasttx = 0;
1228         keyed = 0;
1229         myrpt->dtmfidx = -1;
1230         myrpt->dtmfbuf[0] = 0;
1231         myrpt->rem_dtmfidx = -1;
1232         myrpt->rem_dtmfbuf[0] = 0;
1233         dtmf_time = 0;
1234         myrpt->rem_dtmf_time = 0;
1235         val = 0;
1236         ast_channel_setoption(myrpt->rxchannel,AST_OPTION_TONE_VERIFY,&val,sizeof(char),0);
1237         val = 1;
1238         ast_channel_setoption(myrpt->rxchannel,AST_OPTION_RELAXDTMF,&val,sizeof(char),0);
1239         while (ms >= 0)
1240         {
1241                 struct ast_frame *f;
1242                 struct ast_channel *cs[300];
1243                 int totx,elap,n,toexit;
1244
1245                 if (ast_check_hangup(myrpt->rxchannel)) break;
1246                 if (ast_check_hangup(myrpt->txchannel)) break;
1247                 if (ast_check_hangup(myrpt->pchannel)) break;
1248                 if (ast_check_hangup(myrpt->txpchannel)) break;
1249                 ast_mutex_lock(&myrpt->lock);
1250                 myrpt->localtx = keyed;
1251                 l = myrpt->links.next;
1252                 remrx = 0;
1253                 while(l != &myrpt->links)
1254                 {
1255                         if (l->lastrx) remrx = 1;
1256                         l = l->next;
1257                 }
1258                 totx = (keyed || myrpt->callmode || 
1259                         (myrpt->tele.next != &myrpt->tele));
1260                 myrpt->exttx = totx;
1261                 totx |= remrx;
1262                 if (!totx) myrpt->totimer = myrpt->totime;
1263                 else myrpt->tailtimer = myrpt->hangtime;
1264                 totx = (totx || myrpt->tailtimer) && myrpt->totimer;
1265                 /* if wants to transmit and in phone call, but timed out, 
1266                         reset time-out timer if keyed */
1267                 if ((!totx) && (!myrpt->totimer) && myrpt->callmode && keyed)
1268                 {
1269                         myrpt->totimer = myrpt->totime;
1270                         ast_mutex_unlock(&myrpt->lock);
1271                         continue;
1272                 }
1273                 /* if timed-out and in circuit busy after call */
1274                 if ((!totx) && (!myrpt->totimer) && (myrpt->callmode == 4))
1275                 {
1276                         myrpt->callmode = 0;
1277                 }
1278                 if (totx && (!myrpt->idtimer))
1279                 {
1280                         myrpt->idtimer = myrpt->idtime;
1281                         ast_mutex_unlock(&myrpt->lock);
1282                         rpt_telemetry(myrpt,ID,NULL);
1283                         ast_mutex_lock(&myrpt->lock);
1284                 }
1285                 if (totx && (!lasttx))
1286                 {
1287                         lasttx = 1;
1288                         ast_mutex_unlock(&myrpt->lock);
1289                         ast_indicate(myrpt->txchannel,AST_CONTROL_RADIO_KEY);
1290                         ast_mutex_lock(&myrpt->lock);
1291                 }
1292                 if ((!totx) && lasttx)
1293                 {
1294                         lasttx = 0;
1295                         ast_mutex_unlock(&myrpt->lock);
1296                         ast_indicate(myrpt->txchannel,AST_CONTROL_RADIO_UNKEY);
1297                         ast_mutex_lock(&myrpt->lock);
1298                 }
1299                 time(&t);
1300                 /* if DTMF timeout */
1301                 if ((!myrpt->cmdnode[0]) && (myrpt->dtmfidx >= 0) && ((dtmf_time + DTMF_TIMEOUT) < t))
1302                 {
1303                         myrpt->dtmfidx = -1;
1304                         myrpt->dtmfbuf[0] = 0;
1305                 }                       
1306                 /* if remote DTMF timeout */
1307                 if ((myrpt->rem_dtmfidx >= 0) && ((myrpt->rem_dtmf_time + DTMF_TIMEOUT) < t))
1308                 {
1309                         myrpt->rem_dtmfidx = -1;
1310                         myrpt->rem_dtmfbuf[0] = 0;
1311                 }                       
1312                 n = 0;
1313                 cs[n++] = myrpt->rxchannel;
1314                 cs[n++] = myrpt->pchannel;
1315                 cs[n++] = myrpt->txpchannel;
1316                 if (myrpt->txchannel != myrpt->rxchannel) cs[n++] = myrpt->txchannel;
1317                 l = myrpt->links.next;
1318                 while(l != &myrpt->links)
1319                 {
1320                         cs[n++] = l->chan;
1321                         cs[n++] = l->pchan;
1322                         l = l->next;
1323                 }
1324                 ast_mutex_unlock(&myrpt->lock);
1325                 ms = MSWAIT;
1326                 who = ast_waitfor_n(cs,n,&ms);
1327                 if (who == NULL) ms = 0;
1328                 elap = MSWAIT - ms;
1329                 ast_mutex_lock(&myrpt->lock);
1330                 l = myrpt->links.next;
1331                 while(l != &myrpt->links)
1332                 {
1333                         /* ignore non-timing channels */
1334                         if (l->elaptime < 0)
1335                         {
1336                                 l = l->next;
1337                                 continue;
1338                         }
1339                         l->elaptime += elap;
1340                         /* if connection has taken too long */
1341                         if ((l->elaptime > MAXCONNECTTIME) && 
1342                            (l->chan->_state != AST_STATE_UP))
1343                         {
1344                                 ast_mutex_unlock(&myrpt->lock);
1345                                 ast_softhangup(l->chan,AST_SOFTHANGUP_DEV);
1346                                 rpt_telemetry(myrpt,CONNFAIL,l);
1347                                 ast_mutex_lock(&myrpt->lock);
1348                         }
1349                         l = l->next;
1350                 }
1351                 if (myrpt->tailtimer) myrpt->tailtimer -= elap;
1352                 if (myrpt->tailtimer < 0) myrpt->tailtimer = 0;
1353                 if (myrpt->totimer) myrpt->totimer -= elap;
1354                 if (myrpt->totimer < 0) myrpt->totimer = 0;
1355                 if (myrpt->idtimer) myrpt->idtimer -= elap;
1356                 if (myrpt->idtimer < 0) myrpt->idtimer = 0;
1357                 ast_mutex_unlock(&myrpt->lock);
1358                 if (!ms) continue;
1359                 if (who == myrpt->rxchannel) /* if it was a read from rx */
1360                 {
1361                         f = ast_read(myrpt->rxchannel);
1362                         if (!f)
1363                         {
1364                                 if (debug) printf("@@@@ rpt:Hung Up\n");
1365                                 break;
1366                         }
1367                         if (f->frametype == AST_FRAME_VOICE)
1368                         {
1369                                 ast_write(myrpt->pchannel,f);
1370                         }
1371                         else if (f->frametype == AST_FRAME_DTMF)
1372                         {
1373                                 char c;
1374
1375                                 c = (char) f->subclass; /* get DTMF char */
1376                                 if (c == '#')
1377                                 {
1378                                         /* if in simple mode, kill autopatch */
1379                                         if (myrpt->simple && myrpt->callmode)
1380                                         {
1381                                                 myrpt->callmode = 0;
1382                                                 rpt_telemetry(myrpt,TERM,NULL);
1383                                                 continue;
1384                                         }
1385                                         ast_mutex_lock(&myrpt->lock);
1386                                         if (myrpt->cmdnode[0])
1387                                         {
1388                                                 myrpt->cmdnode[0] = 0;
1389                                                 myrpt->dtmfidx = -1;
1390                                                 myrpt->dtmfbuf[0] = 0;
1391                                                 ast_mutex_unlock(&myrpt->lock);
1392                                                 rpt_telemetry(myrpt,COMPLETE,NULL);
1393                                         } else ast_mutex_unlock(&myrpt->lock);
1394                                         continue;
1395                                 }
1396                                 if (myrpt->cmdnode[0])
1397                                 {
1398                                         send_link_dtmf(myrpt,c);
1399                                         continue;
1400                                 }
1401                                 if (!myrpt->simple)
1402                                 {
1403                                         if (c == '*')
1404                                         {
1405                                                 myrpt->dtmfidx = 0;
1406                                                 myrpt->dtmfbuf[myrpt->dtmfidx] = 0;
1407                                                 time(&dtmf_time);
1408                                                 continue;
1409                                         } 
1410                                         else if ((c != '#') && (myrpt->dtmfidx >= 0))
1411                                         {
1412                                                 time(&dtmf_time);
1413                                                 if (myrpt->dtmfidx < MAXDTMF)
1414                                                 {
1415                                                         myrpt->dtmfbuf[myrpt->dtmfidx++] = c;
1416                                                         myrpt->dtmfbuf[myrpt->dtmfidx] = 0;
1417                                                         /* if to terminate function now */
1418                                                         if ((myrpt->dtmfidx == 1) && strchr(SHORTFUNCS,c))
1419                                                         {
1420                                                                 while(myrpt->dtmfidx < FUNCTION_LEN)
1421                                                                         myrpt->dtmfbuf[myrpt->dtmfidx++] = '0';
1422                                                                 myrpt->dtmfbuf[myrpt->dtmfidx] = 0;
1423                                                         }
1424                                                 }
1425                                                 if (myrpt->dtmfidx == FUNCTION_LEN)
1426                                                 {
1427                                                         process_dtmf(myrpt->dtmfbuf,myrpt,1);
1428                                                         myrpt->dtmfbuf[0] = 0;
1429                                                         myrpt->dtmfidx = -1;
1430                                                         continue;
1431                                                 }
1432                                         }
1433                                 }
1434                                 else
1435                                 {
1436                                         if ((!myrpt->callmode) && (c == '*'))
1437                                         {
1438                                                 myrpt->callmode = 1;
1439                                                 myrpt->cidx = 0;
1440                                                 myrpt->exten[myrpt->cidx] = 0;
1441                                                 pthread_attr_init(&attr);
1442                                                 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
1443                                                 pthread_create(&myrpt->rpt_call_thread,&attr,rpt_call,(void *)myrpt);
1444                                                 continue;
1445                                         }
1446                                 }
1447                                 if (myrpt->callmode == 1)
1448                                 {
1449                                         myrpt->exten[myrpt->cidx++] = c;
1450                                         myrpt->exten[myrpt->cidx] = 0;
1451                                         /* if this exists */
1452                                         if (ast_exists_extension(myrpt->pchannel,myrpt->ourcontext,myrpt->exten,1,NULL))
1453                                         {
1454                                                 myrpt->callmode = 2;
1455                                                 rpt_telemetry(myrpt,PROC,NULL);
1456                                         }
1457                                         /* if can continue, do so */
1458                                         if (ast_canmatch_extension(myrpt->pchannel,myrpt->ourcontext,myrpt->exten,1,NULL)) continue;
1459                                         /* call has failed, inform user */
1460                                         myrpt->callmode = 4;
1461                                         continue;
1462                                 }
1463                                 if ((myrpt->callmode == 2) || (myrpt->callmode == 3))
1464                                 {
1465                                         myrpt->mydtmf = f->subclass;
1466                                 }
1467                         }                                               
1468                         else if (f->frametype == AST_FRAME_CONTROL)
1469                         {
1470                                 if (f->subclass == AST_CONTROL_HANGUP)
1471                                 {
1472                                         if (debug) printf("@@@@ rpt:Hung Up\n");
1473                                         ast_frfree(f);
1474                                         break;
1475                                 }
1476                                 /* if RX key */
1477                                 if (f->subclass == AST_CONTROL_RADIO_KEY)
1478                                 {
1479                                         if (debug) printf("@@@@ rx key\n");
1480                                         keyed = 1;
1481                                 }
1482                                 /* if RX un-key */
1483                                 if (f->subclass == AST_CONTROL_RADIO_UNKEY)
1484                                 {
1485                                         if (debug) printf("@@@@ rx un-key\n");
1486                                         keyed = 0;
1487                                         /* if we have remotes, twiddle */
1488                                         if (myrpt->cmdnode[0] || (myrpt->links.next != &myrpt->links))
1489                                         {
1490                                                 rpt_telemetry(myrpt,UNKEY,NULL);
1491                                         }
1492                                 }
1493                         }
1494                         ast_frfree(f);
1495                         continue;
1496                 }
1497                 if (who == myrpt->pchannel) /* if it was a read from pseudo */
1498                 {
1499                         f = ast_read(myrpt->pchannel);
1500                         if (!f)
1501                         {
1502                                 if (debug) printf("@@@@ rpt:Hung Up\n");
1503                                 break;
1504                         }
1505                         if (f->frametype == AST_FRAME_VOICE)
1506                         {
1507                                 ast_write(myrpt->txpchannel,f);
1508                         }
1509                         if (f->frametype == AST_FRAME_CONTROL)
1510                         {
1511                                 if (f->subclass == AST_CONTROL_HANGUP)
1512                                 {
1513                                         if (debug) printf("@@@@ rpt:Hung Up\n");
1514                                         ast_frfree(f);
1515                                         break;
1516                                 }
1517                         }
1518                         ast_frfree(f);
1519                         continue;
1520                 }
1521                 if (who == myrpt->txchannel) /* if it was a read from tx */
1522                 {
1523                         f = ast_read(myrpt->txchannel);
1524                         if (!f)
1525                         {
1526                                 if (debug) printf("@@@@ rpt:Hung Up\n");
1527                                 break;
1528                         }
1529                         if (f->frametype == AST_FRAME_CONTROL)
1530                         {
1531                                 if (f->subclass == AST_CONTROL_HANGUP)
1532                                 {
1533                                         if (debug) printf("@@@@ rpt:Hung Up\n");
1534                                         ast_frfree(f);
1535                                         break;
1536                                 }
1537                         }
1538                         ast_frfree(f);
1539                         continue;
1540                 }
1541                 toexit = 0;
1542                 l = myrpt->links.next;
1543                 while(l != &myrpt->links)
1544                 {
1545                         if (who == l->chan) /* if it was a read from rx */
1546                         {
1547                                 ast_mutex_lock(&myrpt->lock);
1548                                 remrx = 0;
1549                                 /* see if any other links are receiving */
1550                                 m = myrpt->links.next;
1551                                 while(m != &myrpt->links)
1552                                 {
1553                                         /* if not us, count it */
1554                                         if ((m != l) && (m->lastrx)) remrx = 1;
1555                                         m = m->next;
1556                                 }
1557                                 ast_mutex_unlock(&myrpt->lock);
1558                                 totx = (((l->isremote) ? myrpt->localtx : 
1559                                         myrpt->exttx) || remrx) && l->mode;
1560                                 if (l->lasttx != totx)
1561                                 {
1562                                         if (totx)
1563                                         {
1564                                                 ast_indicate(l->chan,AST_CONTROL_RADIO_KEY);
1565                                         }
1566                                         else
1567                                         {
1568                                                 ast_indicate(l->chan,AST_CONTROL_RADIO_UNKEY);
1569                                         }
1570                                 }
1571                                 l->lasttx = totx;
1572                                 f = ast_read(l->chan);
1573                                 if (!f)
1574                                 {
1575                                         ast_mutex_lock(&myrpt->lock);
1576                                         /* remove from queue */
1577                                         remque((struct qelem *) l);
1578                                         ast_mutex_unlock(&myrpt->lock);
1579                                         rpt_telemetry(myrpt,REMDISC,l);
1580                                         /* hang-up on call to device */
1581                                         ast_hangup(l->chan);
1582                                         ast_hangup(l->pchan);
1583                                         free(l);
1584                                         break;
1585                                 }
1586                                 if (f->frametype == AST_FRAME_VOICE)
1587                                 {
1588                                         ast_write(l->pchan,f);
1589                                 }
1590                                 if (f->frametype == AST_FRAME_TEXT)
1591                                 {
1592                                         handle_link_data(myrpt,f->data);
1593                                 }
1594                                 if (f->frametype == AST_FRAME_CONTROL)
1595                                 {
1596                                         if (f->subclass == AST_CONTROL_ANSWER)
1597                                         {
1598                                                 l->connected = 1;
1599                                                 l->elaptime = -1;
1600                                                 rpt_telemetry(myrpt,CONNECTED,l);
1601                                         }
1602                                         /* if RX key */
1603                                         if (f->subclass == AST_CONTROL_RADIO_KEY)
1604                                         {
1605                                                 if (debug) printf("@@@@ rx key\n");
1606                                                 l->lastrx = 1;
1607                                         }
1608                                         /* if RX un-key */
1609                                         if (f->subclass == AST_CONTROL_RADIO_UNKEY)
1610                                         {
1611                                                 if (debug) printf("@@@@ rx un-key\n");
1612                                                 l->lastrx = 0;
1613                                         }
1614                                         if (f->subclass == AST_CONTROL_HANGUP)
1615                                         {
1616                                                 ast_frfree(f);
1617                                                 ast_mutex_lock(&myrpt->lock);
1618                                                 /* remove from queue */
1619                                                 remque((struct qelem *) l);
1620                                                 ast_mutex_unlock(&myrpt->lock);
1621                                                 rpt_telemetry(myrpt,REMDISC,l);
1622                                                 /* hang-up on call to device */
1623                                                 ast_hangup(l->chan);
1624                                                 ast_hangup(l->pchan);
1625                                                 free(l);
1626                                                 break;
1627                                         }
1628                                 }
1629                                 ast_frfree(f);
1630                                 break;
1631                         }
1632                         if (who == l->pchan) 
1633                         {
1634                                 f = ast_read(l->pchan);
1635                                 if (!f)
1636                                 {
1637                                         if (debug) printf("@@@@ rpt:Hung Up\n");
1638                                         toexit = 1;
1639                                         break;
1640                                 }
1641                                 if (f->frametype == AST_FRAME_VOICE)
1642                                 {
1643                                         ast_write(l->chan,f);
1644                                 }
1645                                 if (f->frametype == AST_FRAME_CONTROL)
1646                                 {
1647                                         if (f->subclass == AST_CONTROL_HANGUP)
1648                                         {
1649                                                 if (debug) printf("@@@@ rpt:Hung Up\n");
1650                                                 ast_frfree(f);
1651                                                 toexit = 1;
1652                                                 break;
1653                                         }
1654                                 }
1655                                 ast_frfree(f);
1656                                 break;
1657                         }
1658                         l = l->next;
1659                 }
1660                 if (toexit) break;
1661                 if (who == myrpt->txpchannel) /* if it was a read from remote tx */
1662                 {
1663                         f = ast_read(myrpt->txpchannel);
1664                         if (!f)
1665                         {
1666                                 if (debug) printf("@@@@ rpt:Hung Up\n");
1667                                 break;
1668                         }
1669                         if (f->frametype == AST_FRAME_CONTROL)
1670                         {
1671                                 if (f->subclass == AST_CONTROL_HANGUP)
1672                                 {
1673                                         if (debug) printf("@@@@ rpt:Hung Up\n");
1674                                         ast_frfree(f);
1675                                         break;
1676                                 }
1677                         }
1678                         ast_frfree(f);
1679                         continue;
1680                 }
1681         }
1682         ast_mutex_lock(&myrpt->lock);
1683         ast_hangup(myrpt->pchannel);
1684         ast_hangup(myrpt->txpchannel);
1685         ast_hangup(myrpt->rxchannel);
1686         if (myrpt->txchannel != myrpt->rxchannel) ast_hangup(myrpt->txchannel);
1687         l = myrpt->links.next;
1688         while(l != &myrpt->links)
1689         {
1690                 struct rpt_link *ll = l;
1691                 /* remove from queue */
1692                 remque((struct qelem *) l);
1693                 /* hang-up on call to device */
1694                 ast_hangup(l->chan);
1695                 ast_hangup(l->pchan);
1696                 l = l->next;
1697                 free(ll);
1698         }
1699         ast_mutex_unlock(&myrpt->lock);
1700         if (debug) printf("@@@@ rpt:Hung up channel\n");
1701         pthread_exit(NULL); 
1702         return NULL;
1703 }
1704
1705 static void *rpt_master(void *ignore)
1706 {
1707 char *this,*val;
1708 int     i,n;
1709
1710         /* start with blank config */
1711         memset(&rpt_vars,0,sizeof(rpt_vars));
1712
1713         cfg = ast_load("rpt.conf");
1714         if (!cfg) {
1715                 ast_log(LOG_NOTICE, "Unable to open radio repeater configuration rpt.conf.  Radio Repeater disabled.\n");
1716                 pthread_exit(NULL);
1717         }
1718
1719         /* go thru all the specified repeaters */
1720         this = NULL;
1721         n = 0;
1722         while((this = ast_category_browse(cfg,this)) != NULL)
1723         {
1724                 if (!strcmp(this,NODES)) continue;
1725                 ast_log(LOG_DEBUG,"Loading config for repeater %s\n",this);
1726                 ast_mutex_init(&rpt_vars[n].lock);
1727                 rpt_vars[n].tele.next = &rpt_vars[n].tele;
1728                 rpt_vars[n].tele.prev = &rpt_vars[n].tele;
1729                 rpt_vars[n].name = this;
1730                 rpt_vars[n].rxchanname = ast_variable_retrieve(cfg,this,"rxchannel");
1731                 rpt_vars[n].txchanname = ast_variable_retrieve(cfg,this,"txchannel");
1732                 rpt_vars[n].ourcontext = ast_variable_retrieve(cfg,this,"context");
1733                 if (!rpt_vars[n].ourcontext) rpt_vars[n].ourcontext = this;
1734                 rpt_vars[n].ourcallerid = ast_variable_retrieve(cfg,this,"callerid");
1735                 rpt_vars[n].acctcode = ast_variable_retrieve(cfg,this,"accountcode");
1736                 rpt_vars[n].ident = ast_variable_retrieve(cfg,this,"idrecording");
1737                 val = ast_variable_retrieve(cfg,this,"hangtime");
1738                 if (val) rpt_vars[n].hangtime = atoi(val);
1739                         else rpt_vars[n].hangtime = HANGTIME;
1740                 val = ast_variable_retrieve(cfg,this,"totime");
1741                 if (val) rpt_vars[n].totime = atoi(val);
1742                         else rpt_vars[n].totime = TOTIME;
1743                 val = ast_variable_retrieve(cfg,this,"idtime");
1744                 if (val) rpt_vars[n].idtime = atoi(val);
1745                         else rpt_vars[n].idtime = IDTIME;
1746                 val = ast_variable_retrieve(cfg,this,"simple");
1747                 if (val) rpt_vars[n].simple = ast_true(val); 
1748                         else rpt_vars[n].simple = 0;
1749                 val = ast_variable_retrieve(cfg,this,"remote");
1750                 if (val) rpt_vars[n].remote = ast_true(val); 
1751                         else rpt_vars[n].remote = 0;
1752                 rpt_vars[n].tonezone = ast_variable_retrieve(cfg,this,"tonezone");
1753                 n++;
1754         }
1755         nrpts = n;
1756         ast_log(LOG_DEBUG, "Total of %d repeaters configured.\n",n);
1757         /* start em all */
1758         for(i = 0; i < n; i++)
1759         {
1760                 if (!rpt_vars[i].rxchanname)
1761                 {
1762                         ast_log(LOG_WARNING,"Did not specify rxchanname for node %s\n",rpt_vars[i].name);
1763                         pthread_exit(NULL);
1764                 }
1765                 /* if is a remote, dont start one for it */
1766                 if (rpt_vars[i].remote) continue;
1767                 if (!rpt_vars[i].ident)
1768                 {
1769                         ast_log(LOG_WARNING,"Did not specify ident for node %s\n",rpt_vars[i].name);
1770                         pthread_exit(NULL);
1771                 }
1772                 pthread_create(&rpt_vars[i].rpt_thread,NULL,rpt,(void *) &rpt_vars[i]);
1773         }
1774         /* wait for first one to die (should be never) */
1775         pthread_join(rpt_vars[0].rpt_thread,NULL);
1776         pthread_exit(NULL);
1777 }
1778
1779 static int rpt_exec(struct ast_channel *chan, void *data)
1780 {
1781         int res=-1,i,keyed = 0,rem_totx;
1782         struct localuser *u;
1783         char tmp[256];
1784         char *options,*stringp,*tele;
1785         struct  rpt *myrpt;
1786         struct ast_frame *f;
1787         struct ast_channel *who;
1788         struct ast_channel *cs[20];
1789         struct  rpt_link *l;
1790         ZT_CONFINFO ci;  /* conference info */
1791         int ms,elap;
1792
1793         if (!data || ast_strlen_zero((char *)data)) {
1794                 ast_log(LOG_WARNING, "Rpt requires an argument (system node)\n");
1795                 return -1;
1796         }
1797         strncpy(tmp, (char *)data, sizeof(tmp)-1);
1798         stringp=tmp;
1799         strsep(&stringp, "|");
1800         options = strsep(&stringp, "|");
1801         myrpt = NULL;
1802         /* see if we can find our specified one */
1803         for(i = 0; i < nrpts; i++)
1804         {
1805                 /* if name matches, assign it and exit loop */
1806                 if (!strcmp(tmp,rpt_vars[i].name))
1807                 {
1808                         myrpt = &rpt_vars[i];
1809                         break;
1810                 }
1811         }
1812         if (myrpt == NULL)
1813         {
1814                 ast_log(LOG_WARNING, "Cannot find specified system node %s\n",tmp);
1815                 return -1;
1816         }
1817         /* if is not a remote */
1818         if (!myrpt->remote)
1819         {
1820                 char *b,*b1;
1821
1822                 /* look at callerid to see what node this comes from */
1823                 if (!chan->callerid) /* if doesnt have callerid */
1824                 {
1825                         ast_log(LOG_WARNING, "Trying to use busy link on %s\n",tmp);
1826                         return -1;
1827                 }
1828                 ast_callerid_parse(chan->callerid,&b,&b1);
1829                 ast_shrink_phone_number(b1);
1830                 if (!strcmp(myrpt->name,b1))
1831                 {
1832                         ast_log(LOG_WARNING, "Trying to link to self!!\n");
1833                         return -1;
1834                 }
1835                 ast_mutex_lock(&myrpt->lock);
1836                 l = myrpt->links.next;
1837                 /* try to find this one in queue */
1838                 while(l != &myrpt->links)
1839                 {
1840                         /* if found matching string */
1841                         if (!strcmp(l->name,b1)) break;
1842                 }
1843                 /* if found */
1844                 if (l != &myrpt->links) 
1845                 {
1846                         /* remove from queue */
1847                         remque((struct qelem *) l);
1848                         ast_mutex_unlock(&myrpt->lock);
1849                         /* hang-up on call to device */
1850                         ast_hangup(l->chan);
1851                         ast_hangup(l->pchan);
1852                         free(l);
1853                         usleep(500000); 
1854                 } else 
1855                         ast_mutex_unlock(&myrpt->lock);
1856                 /* establish call in tranceive mode */
1857                 l = malloc(sizeof(struct rpt_link));
1858                 if (!l)
1859                 {
1860                         ast_log(LOG_WARNING, "Unable to malloc\n");
1861                         pthread_exit(NULL);
1862                 }
1863                 /* zero the silly thing */
1864                 memset((char *)l,0,sizeof(struct rpt_link));
1865                 l->mode = 1;
1866                 strncpy(l->name,b1,MAXNODESTR - 1);
1867                 l->isremote = 0;
1868                 l->chan = chan;
1869                 l->connected = 1;
1870                 ast_set_read_format(l->chan,AST_FORMAT_SLINEAR);
1871                 ast_set_write_format(l->chan,AST_FORMAT_SLINEAR);
1872                 /* allocate a pseudo-channel thru asterisk */
1873                 l->pchan = ast_request("zap",AST_FORMAT_SLINEAR,"pseudo");
1874                 if (!l->pchan)
1875                 {
1876                         fprintf(stderr,"rpt:Sorry unable to obtain pseudo channel\n");
1877                         pthread_exit(NULL);
1878                 }
1879                 ast_set_read_format(l->pchan,AST_FORMAT_SLINEAR);
1880                 ast_set_write_format(l->pchan,AST_FORMAT_SLINEAR);
1881                 /* make a conference for the tx */
1882                 ci.chan = 0;
1883                 ci.confno = myrpt->conf;
1884                 ci.confmode = ZT_CONF_CONF | ZT_CONF_LISTENER | ZT_CONF_TALKER;
1885                 /* first put the channel on the conference in proper mode */
1886                 if (ioctl(l->pchan->fds[0],ZT_SETCONF,&ci) == -1)
1887                 {
1888                         ast_log(LOG_WARNING, "Unable to set conference mode to Announce\n");
1889                         pthread_exit(NULL);
1890                 }
1891                 ast_mutex_lock(&myrpt->lock);
1892                 /* insert at end of queue */
1893                 insque((struct qelem *)l,(struct qelem *)myrpt->links.next);
1894                 ast_mutex_unlock(&myrpt->lock);
1895                 if (chan->_state != AST_STATE_UP) {
1896                         ast_answer(chan);
1897                 }
1898                 return AST_PBX_KEEPALIVE;
1899         }
1900         /* if remote, error if anyone else already linked */
1901         if (myrpt->remoteon)
1902         {
1903                 ast_mutex_unlock(&myrpt->lock);
1904                 ast_log(LOG_WARNING, "Trying to use busy link on %s\n",tmp);
1905                 return -1;
1906         }
1907         LOCAL_USER_ADD(u);
1908         tele = strchr(myrpt->rxchanname,'/');
1909         if (!tele)
1910         {
1911                 fprintf(stderr,"rpt:Dial number must be in format tech/number\n");
1912                 ast_mutex_unlock(&myrpt->lock);
1913                 pthread_exit(NULL);
1914         }
1915         *tele++ = 0;
1916         ast_mutex_lock(&myrpt->lock);
1917         myrpt->rxchannel = ast_request(myrpt->rxchanname,AST_FORMAT_SLINEAR,tele);
1918         if (myrpt->rxchannel)
1919         {
1920                 ast_set_read_format(myrpt->rxchannel,AST_FORMAT_SLINEAR);
1921                 ast_set_write_format(myrpt->rxchannel,AST_FORMAT_SLINEAR);
1922                 myrpt->rxchannel->whentohangup = 0;
1923                 myrpt->rxchannel->appl = "Apprpt";
1924                 myrpt->rxchannel->data = "(Repeater Rx)";
1925                 if (option_verbose > 2)
1926                         ast_verbose(VERBOSE_PREFIX_3 "rpt (Rx) initiating call to %s/%s on %s\n",
1927                                 myrpt->rxchanname,tele,myrpt->rxchannel->name);
1928                 ast_mutex_unlock(&myrpt->lock);
1929                 ast_call(myrpt->rxchannel,tele,999);
1930                 ast_mutex_lock(&myrpt->lock);
1931         }
1932         else
1933         {
1934                 fprintf(stderr,"rpt:Sorry unable to obtain Rx channel\n");
1935                 ast_mutex_unlock(&myrpt->lock);
1936                 pthread_exit(NULL);
1937         }
1938         *--tele = '/';
1939         if (myrpt->txchanname)
1940         {
1941                 tele = strchr(myrpt->txchanname,'/');
1942                 if (!tele)
1943                 {
1944                         fprintf(stderr,"rpt:Dial number must be in format tech/number\n");
1945                         ast_mutex_unlock(&myrpt->lock);
1946                         pthread_exit(NULL);
1947                 }
1948                 *tele++ = 0;
1949                 myrpt->txchannel = ast_request(myrpt->txchanname,AST_FORMAT_SLINEAR,tele);
1950                 if (myrpt->txchannel)
1951                 {
1952                         ast_set_read_format(myrpt->txchannel,AST_FORMAT_SLINEAR);
1953                         ast_set_write_format(myrpt->txchannel,AST_FORMAT_SLINEAR);
1954                         myrpt->txchannel->whentohangup = 0;
1955                         myrpt->txchannel->appl = "Apprpt";
1956                         myrpt->txchannel->data = "(Repeater Rx)";
1957                         if (option_verbose > 2)
1958                                 ast_verbose(VERBOSE_PREFIX_3 "rpt (Tx) initiating call to %s/%s on %s\n",
1959                                         myrpt->txchanname,tele,myrpt->txchannel->name);
1960                         ast_mutex_unlock(&myrpt->lock);
1961                         ast_call(myrpt->txchannel,tele,999);
1962                         ast_mutex_lock(&myrpt->lock);
1963                 }
1964                 else
1965                 {
1966                         fprintf(stderr,"rpt:Sorry unable to obtain Tx channel\n");
1967                         ast_mutex_unlock(&myrpt->lock);
1968                         pthread_exit(NULL);
1969                 }
1970                 *--tele = '/';
1971         }
1972         else
1973         {
1974                 myrpt->txchannel = myrpt->rxchannel;
1975         }
1976         myrpt->remoterx = 0;
1977         myrpt->remotetx = 0;
1978         myrpt->remoteon = 1;
1979         ast_mutex_unlock(&myrpt->lock);
1980         ast_set_write_format(chan, AST_FORMAT_SLINEAR);
1981         ast_set_read_format(chan, AST_FORMAT_SLINEAR);
1982         /* if we are on 2w loop and are a remote, turn EC on */
1983         if (myrpt->remote && (myrpt->rxchannel == myrpt->txchannel))
1984         {
1985                 i = 128;
1986                 ioctl(myrpt->rxchannel->fds[0],ZT_ECHOCANCEL,&i);
1987         }
1988         if (chan->_state != AST_STATE_UP) {
1989                 ast_answer(chan);
1990         }
1991         cs[0] = chan;
1992         cs[1] = myrpt->rxchannel;
1993         for(;;)
1994         {
1995                 if (ast_check_hangup(chan)) break;
1996                 if (ast_check_hangup(myrpt->rxchannel)) break;
1997                 ms = MSWAIT;
1998                 who = ast_waitfor_n(cs,2,&ms);
1999                 if (who == NULL) ms = 0;
2000                 elap = MSWAIT - ms;
2001                 if (!ms) continue;
2002                 rem_totx = keyed;
2003                 if (rem_totx && (!myrpt->remotetx))
2004                 {
2005                         myrpt->remotetx = 1;
2006                         ast_indicate(myrpt->txchannel,AST_CONTROL_RADIO_KEY);
2007                 }
2008                 if ((!rem_totx) && myrpt->remotetx)
2009                 {
2010                         myrpt->remotetx = 0;
2011                         ast_indicate(myrpt->txchannel,AST_CONTROL_RADIO_UNKEY);
2012                 }
2013                 if (who == chan) /* if it was a read from incomming */
2014                 {
2015                         f = ast_read(chan);
2016                         if (!f)
2017                         {
2018                                 if (debug) printf("@@@@ link:Hung Up\n");
2019                                 break;
2020                         }
2021                         if (f->frametype == AST_FRAME_VOICE)
2022                         {
2023                                 /* if not transmitting, zero-out audio */
2024                                 if (!myrpt->remotetx)
2025                                         memset(f->data,0,f->datalen);
2026                                 ast_write(myrpt->txchannel,f);
2027                         }
2028                         else if (f->frametype == AST_FRAME_TEXT)
2029                         {
2030                                 handle_link_data(myrpt,f->data);
2031                         }
2032                         else if (f->frametype == AST_FRAME_CONTROL)
2033                         {
2034                                 if (f->subclass == AST_CONTROL_HANGUP)
2035                                 {
2036                                         if (debug) printf("@@@@ rpt:Hung Up\n");
2037                                         ast_frfree(f);
2038                                         break;
2039                                 }
2040                                 /* if RX key */
2041                                 if (f->subclass == AST_CONTROL_RADIO_KEY)
2042                                 {
2043                                         if (debug) printf("@@@@ rx key\n");
2044                                         keyed = 1;
2045                                 }
2046                                 /* if RX un-key */
2047                                 if (f->subclass == AST_CONTROL_RADIO_UNKEY)
2048                                 {
2049                                         if (debug) printf("@@@@ rx un-key\n");
2050                                         keyed = 0;
2051                                 }
2052                         }
2053                         ast_frfree(f);
2054                         continue;
2055                 }
2056                 if (who == myrpt->rxchannel) /* if it was a read from radio */
2057                 {
2058                         f = ast_read(myrpt->rxchannel);
2059                         if (!f)
2060                         {
2061                                 if (debug) printf("@@@@ link:Hung Up\n");
2062                                 break;
2063                         }
2064                         if (f->frametype == AST_FRAME_VOICE)
2065                         {
2066                                 if ((myrpt->remote) && (myrpt->remotetx))
2067                                         memset(f->data,0,f->datalen);
2068                                  ast_write(chan,f);
2069                         }
2070                         else if (f->frametype == AST_FRAME_CONTROL)
2071                         {
2072                                 if (f->subclass == AST_CONTROL_HANGUP)
2073                                 {
2074                                         if (debug) printf("@@@@ rpt:Hung Up\n");
2075                                         ast_frfree(f);
2076                                         break;
2077                                 }
2078                                 /* if RX key */
2079                                 if (f->subclass == AST_CONTROL_RADIO_KEY)
2080                                 {
2081                                         if (debug) printf("@@@@ remote rx key\n");
2082                                         if (!myrpt->remotetx)
2083                                         {
2084                                                 ast_indicate(chan,AST_CONTROL_RADIO_KEY);
2085                                                 myrpt->remoterx = 1;
2086                                         }
2087                                 }
2088                                 /* if RX un-key */
2089                                 if (f->subclass == AST_CONTROL_RADIO_UNKEY)
2090                                 {
2091                                         if (debug) printf("@@@@ remote rx un-key\n");
2092                                         if (!myrpt->remotetx) 
2093                                         {
2094                                                 ast_indicate(chan,AST_CONTROL_RADIO_UNKEY);
2095                                                 myrpt->remoterx = 0;
2096                                         }
2097                                 }
2098                         }
2099                         ast_frfree(f);
2100                         continue;
2101                 }
2102
2103         }
2104         ast_mutex_lock(&myrpt->lock);
2105         if (myrpt->rxchannel != myrpt->txchannel) ast_hangup(myrpt->txchannel);
2106         ast_hangup(myrpt->rxchannel);
2107         myrpt->remoteon = 0;
2108         ast_mutex_unlock(&myrpt->lock);
2109         LOCAL_USER_REMOVE(u);
2110         return res;
2111 }
2112
2113 int unload_module(void)
2114 {
2115         int i;
2116         STANDARD_HANGUP_LOCALUSERS;
2117         for(i = 0; i < nrpts; i++) {
2118                 ast_mutex_destroy(&rpt_vars[i].lock);
2119         return ast_unregister_application(app);
2120         return 0;
2121 }
2122
2123 int load_module(void)
2124 {
2125         pthread_create(&rpt_master_thread,NULL,rpt_master,NULL);
2126         return ast_register_application(app, rpt_exec, synopsis, descrip);
2127 }
2128
2129 char *description(void)
2130 {
2131         return tdesc;
2132 }
2133
2134 int usecount(void)
2135 {
2136         int res;
2137         STANDARD_USECOUNT(res);
2138         return res;
2139 }
2140
2141 char *key()
2142 {
2143         return ASTERISK_GPL_KEY;
2144 }