00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089
00090
00091
00092
00093
00094
00095
00096
00097
00098
00099
00100
00101 #define RECONNECT_KLUDGE
00102
00103
00104
00105 #define MAXDTMF 32
00106 #define DTMF_TIMEOUT 3
00107
00108 #define DISC_TIME 10000
00109 #define MAX_RETRIES 5
00110
00111 #define REDUNDANT_TX_TIME 2000
00112
00113 #define RETRY_TIMER_MS 5000
00114
00115 #define MAXREMSTR 15
00116
00117 #define NODES "nodes"
00118 #define MEMORY "memory"
00119 #define FUNCTIONS "functions"
00120 #define TELEMETRY "telemetry"
00121 #define MORSE "morse"
00122 #define FUNCCHAR '*'
00123 #define ENDCHAR '#'
00124
00125 #define DEFAULT_IOBASE 0x378
00126
00127 #define MAXCONNECTTIME 5000
00128
00129 #define MAXNODESTR 300
00130
00131 #define ACTIONSIZE 32
00132
00133 #define TELEPARAMSIZE 256
00134
00135 #define REM_SCANTIME 100
00136
00137
00138 enum {REM_OFF,REM_MONITOR,REM_TX};
00139
00140 enum{ID,PROC,TERM,COMPLETE,UNKEY,REMDISC,REMALREADY,REMNOTFOUND,REMGO,
00141 CONNECTED,CONNFAIL,STATUS,TIMEOUT,ID1, STATS_TIME,
00142 STATS_VERSION, IDTALKOVER, ARB_ALPHA, TEST_TONE, REV_PATCH};
00143
00144 enum {REM_SIMPLEX,REM_MINUS,REM_PLUS};
00145
00146 enum {REM_LOWPWR,REM_MEDPWR,REM_HIPWR};
00147
00148 enum {DC_INDETERMINATE, DC_REQ_FLUSH, DC_ERROR, DC_COMPLETE, DC_DOKEY};
00149
00150 enum {SOURCE_RPT, SOURCE_LNK, SOURCE_RMT, SOURCE_PHONE, SOURCE_DPHONE};
00151
00152 enum {DLY_TELEM, DLY_ID, DLY_UNKEY, DLY_CALLTERM};
00153
00154 enum {REM_MODE_FM,REM_MODE_USB,REM_MODE_LSB,REM_MODE_AM};
00155
00156 enum {HF_SCAN_OFF,HF_SCAN_DOWN_SLOW,HF_SCAN_DOWN_QUICK,HF_SCAN_DOWN_FAST,HF_SCAN_UP_SLOW,HF_SCAN_UP_QUICK,HF_SCAN_UP_FAST};
00157
00158 #include "asterisk.h"
00159
00160 ASTERISK_FILE_VERSION(__FILE__, "$Revision: 7221 $")
00161
00162 #include <signal.h>
00163 #include <stdio.h>
00164 #include <unistd.h>
00165 #include <string.h>
00166 #include <stdlib.h>
00167 #include <search.h>
00168 #include <sys/types.h>
00169 #include <sys/stat.h>
00170 #include <errno.h>
00171 #include <dirent.h>
00172 #include <ctype.h>
00173 #include <sys/stat.h>
00174 #include <sys/time.h>
00175 #include <sys/file.h>
00176 #include <sys/ioctl.h>
00177 #include <sys/io.h>
00178 #include <math.h>
00179 #include <tonezone.h>
00180 #include <linux/zaptel.h>
00181 #include <netinet/in.h>
00182 #include <arpa/inet.h>
00183
00184 #include "asterisk/utils.h"
00185 #include "asterisk/lock.h"
00186 #include "asterisk/file.h"
00187 #include "asterisk/logger.h"
00188 #include "asterisk/channel.h"
00189 #include "asterisk/callerid.h"
00190 #include "asterisk/pbx.h"
00191 #include "asterisk/module.h"
00192 #include "asterisk/translate.h"
00193 #include "asterisk/features.h"
00194 #include "asterisk/options.h"
00195 #include "asterisk/cli.h"
00196 #include "asterisk/config.h"
00197 #include "asterisk/say.h"
00198 #include "asterisk/localtime.h"
00199
00200 static char *tdesc = "Radio Repeater / Remote Base version 0.37 11/03/2005";
00201
00202 static char *app = "Rpt";
00203
00204 static char *synopsis = "Radio Repeater/Remote Base Control System";
00205
00206 static char *descrip =
00207 " Rpt(nodename[|options]): Radio Remote Link or Remote Base Link Endpoint Process.\n"
00208 "\n"
00209 " Not specifying an option puts it in normal endpoint mode (where source\n"
00210 " IP and nodename are verified).\n"
00211 "\n"
00212 " Options are as follows:\n"
00213 "\n"
00214 " X - Normal endpoint mode WITHOUT security check. Only specify\n"
00215 " this if you have checked security already (like with an IAX2\n"
00216 " user/password or something).\n"
00217 "\n"
00218 " Rannounce-string[|timeout[|timeout-destination]] - Amateur Radio\n"
00219 " Reverse Autopatch. Caller is put on hold, and announcement (as\n"
00220 " specified by the 'announce-string') is played on radio system.\n"
00221 " Users of radio system can access autopatch, dial specified\n"
00222 " code, and pick up call. Announce-string is list of names of\n"
00223 " recordings, or \"PARKED\" to substitute code for un-parking,\n"
00224 " or \"NODE\" to substitute node number.\n"
00225 "\n"
00226 " P - Phone Control mode. This allows a regular phone user to have\n"
00227 " full control and audio access to the radio system. For the\n"
00228 " user to have DTMF control, the 'phone_functions' parameter\n"
00229 " must be specified for the node in 'rpt.conf'. An additional\n"
00230 " function (cop,6) must be listed so that PTT control is available.\n"
00231 "\n"
00232 " D - Dumb Phone Control mode. This allows a regular phone user to\n"
00233 " have full control and audio access to the radio system. In this\n"
00234 " mode, the PTT is activated for the entire length of the call.\n"
00235 " For the user to have DTMF control (not generally recomended in\n"
00236 " this mode), the 'dphone_functions' parameter must be specified\n"
00237 " for the node in 'rpt.conf'. Otherwise no DTMF control will be\n"
00238 " available to the phone user.\n"
00239 "\n";
00240
00241 static int debug = 0;
00242 static int nrpts = 0;
00243
00244 char *discstr = "!!DISCONNECT!!";
00245 static char *remote_rig_ft897="ft897";
00246 static char *remote_rig_rbi="rbi";
00247
00248 struct ast_config *cfg;
00249
00250 STANDARD_LOCAL_USER;
00251 LOCAL_USER_DECL;
00252
00253 #define MSWAIT 200
00254 #define HANGTIME 5000
00255 #define TOTIME 180000
00256 #define IDTIME 300000
00257 #define MAXRPTS 20
00258 #define POLITEID 30000
00259 #define FUNCTDELAY 1500
00260
00261 static pthread_t rpt_master_thread;
00262
00263 struct rpt;
00264
00265 struct rpt_link
00266 {
00267 struct rpt_link *next;
00268 struct rpt_link *prev;
00269 char mode;
00270 char isremote;
00271 char phonemode;
00272 char name[MAXNODESTR];
00273 char lasttx;
00274 char lastrx;
00275 char connected;
00276 char hasconnected;
00277 char outbound;
00278 char disced;
00279 char killme;
00280 long elaptime;
00281 long disctime;
00282 long retrytimer;
00283 long retxtimer;
00284 int retries;
00285 struct ast_channel *chan;
00286 struct ast_channel *pchan;
00287 } ;
00288
00289 struct rpt_tele
00290 {
00291 struct rpt_tele *next;
00292 struct rpt_tele *prev;
00293 struct rpt *rpt;
00294 struct ast_channel *chan;
00295 int mode;
00296 struct rpt_link mylink;
00297 char param[TELEPARAMSIZE];
00298 pthread_t threadid;
00299 } ;
00300
00301 struct function_table_tag
00302 {
00303 char action[ACTIONSIZE];
00304 int (*function)(struct rpt *myrpt, char *param, char *digitbuf,
00305 int command_source, struct rpt_link *mylink);
00306 } ;
00307
00308
00309
00310 struct morse_bits
00311 {
00312 int len;
00313 int ddcomb;
00314 } ;
00315
00316 struct telem_defaults
00317 {
00318 char name[20];
00319 char value[80];
00320 } ;
00321
00322
00323 static struct rpt
00324 {
00325 char *name;
00326 ast_mutex_t lock;
00327 char *rxchanname;
00328 char *txchanname;
00329 char *ourcontext;
00330 char *ourcallerid;
00331 char *acctcode;
00332 char *ident;
00333 char *tonezone;
00334 char *functions;
00335 char *link_functions;
00336 char *phone_functions;
00337 char *dphone_functions;
00338 char *nodes;
00339 struct rpt_link links;
00340 int hangtime;
00341 int totime;
00342 int idtime;
00343 int unkeytocttimer;
00344 char keyed;
00345 char exttx;
00346 char localtx;
00347 char remoterx;
00348 char remotetx;
00349 char remoteon;
00350 char simple;
00351 char *remote;
00352 char tounkeyed;
00353 char tonotify;
00354 char enable;
00355 char dtmfbuf[MAXDTMF];
00356 char rem_dtmfbuf[MAXDTMF];
00357 char cmdnode[50];
00358 struct ast_channel *rxchannel,*txchannel;
00359 struct ast_channel *pchannel,*txpchannel, *remchannel;
00360 struct rpt_tele tele;
00361 pthread_t rpt_call_thread,rpt_thread;
00362 time_t rem_dtmf_time,dtmf_time_rem;
00363 int tailtimer,totimer,idtimer,txconf,conf,callmode,cidx,scantimer;
00364 int mustid;
00365 int politeid;
00366 int dtmfidx,rem_dtmfidx;
00367 long retxtimer;
00368 char mydtmf;
00369 int iobase;
00370 char exten[AST_MAX_EXTENSION];
00371 char freq[MAXREMSTR],rxpl[MAXREMSTR],txpl[MAXREMSTR];
00372 char offset;
00373 char powerlevel;
00374 char txplon;
00375 char rxplon;
00376 char remmode;
00377 char tunerequest;
00378 char hfscanmode;
00379 int hfscanstatus;
00380 char lastlinknode[MAXNODESTR];
00381 char funcchar;
00382 char endchar;
00383 char stopgen;
00384 int phone_longestfunc;
00385 int dphone_longestfunc;
00386 int link_longestfunc;
00387 int longestfunc;
00388 int longestnode;
00389 int threadrestarts;
00390 time_t disgorgetime;
00391 time_t lastthreadrestarttime;
00392 char nobusyout;
00393 } rpt_vars[MAXRPTS];
00394
00395
00396
00397
00398
00399
00400 static int rpt_do_debug(int fd, int argc, char *argv[]);
00401
00402 static char debug_usage[] =
00403 "Usage: rpt debug level {0-7}\n"
00404 " Enables debug messages in app_rpt\n";
00405
00406 static struct ast_cli_entry cli_debug =
00407 { { "rpt", "debug", "level" }, rpt_do_debug, "Enable app_rpt debugging", debug_usage };
00408
00409
00410
00411
00412
00413
00414
00415
00416 static struct telem_defaults tele_defs[] = {
00417 {"ct1","|t(350,0,100,3072)(500,0,100,3072)(660,0,100,3072)"},
00418 {"ct2","|t(660,880,150,3072)"},
00419 {"ct3","|t(440,0,150,3072)"},
00420 {"ct4","|t(550,0,150,3072)"},
00421 {"ct5","|t(660,0,150,3072)"},
00422 {"ct6","|t(880,0,150,3072)"},
00423 {"ct7","|t(660,440,150,3072)"},
00424 {"ct8","|t(700,1100,150,3072)"},
00425 {"remotemon","|t(1600,0,75,2048)"},
00426 {"remotetx","|t(2000,0,75,2048)(0,0,75,0)(1600,0,75,2048)"},
00427 {"cmdmode","|t(900,904,200,2048)"},
00428 {"functcomplete","|t(1000,0,100,2048)(0,0,100,0)(1000,0,100,2048)"}
00429 } ;
00430
00431
00432
00433
00434
00435 static int setrbi(struct rpt *myrpt);
00436
00437
00438
00439
00440
00441
00442
00443 static int function_ilink(struct rpt *myrpt, char *param, char *digitbuf, int command_source, struct rpt_link *mylink);
00444 static int function_autopatchup(struct rpt *myrpt, char *param, char *digitbuf, int command_source, struct rpt_link *mylink);
00445 static int function_autopatchdn(struct rpt *myrpt, char *param, char *digitbuf, int command_source, struct rpt_link *mylink);
00446 static int function_status(struct rpt *myrpt, char *param, char *digitbuf, int command_source, struct rpt_link *mylink);
00447 static int function_cop(struct rpt *myrpt, char *param, char *digitbuf, int command_source, struct rpt_link *mylink);
00448 static int function_remote(struct rpt *myrpt, char *param, char *digitbuf, int command_source, struct rpt_link *mylink);
00449
00450
00451
00452
00453 static struct function_table_tag function_table[] = {
00454 {"cop", function_cop},
00455 {"autopatchup", function_autopatchup},
00456 {"autopatchdn", function_autopatchdn},
00457 {"ilink", function_ilink},
00458 {"status", function_status},
00459 {"remote", function_remote}
00460 } ;
00461
00462 static int myatoi(char *str)
00463 {
00464 int ret;
00465
00466 if (str == NULL) return -1;
00467
00468 if (sscanf(str,"%i",&ret) != 1) return -1;
00469 return ret;
00470 }
00471
00472
00473
00474
00475
00476 static int rpt_do_debug(int fd, int argc, char *argv[])
00477 {
00478 int newlevel;
00479
00480 if (argc != 4)
00481 return RESULT_SHOWUSAGE;
00482 newlevel = myatoi(argv[3]);
00483 if((newlevel < 0) || (newlevel > 7))
00484 return RESULT_SHOWUSAGE;
00485 if(newlevel)
00486 ast_cli(fd, "app_rpt Debugging enabled, previous level: %d, new level: %d\n", debug, newlevel);
00487 else
00488 ast_cli(fd, "app_rpt Debugging disabled\n");
00489
00490 debug = newlevel;
00491 return RESULT_SUCCESS;
00492 }
00493
00494
00495
00496 static int play_tone_pair(struct ast_channel *chan, int f1, int f2, int duration, int amplitude)
00497 {
00498 int res;
00499
00500 if ((res = ast_tonepair_start(chan, f1, f2, duration, amplitude)))
00501 return res;
00502
00503 while(chan->generatordata) {
00504 if (ast_safe_sleep(chan,1)) return -1;
00505 }
00506
00507 return 0;
00508 }
00509
00510 static int play_tone(struct ast_channel *chan, int freq, int duration, int amplitude)
00511 {
00512 return play_tone_pair(chan, freq, 0, duration, amplitude);
00513 }
00514
00515 static int play_silence(struct ast_channel *chan, int duration)
00516 {
00517 return play_tone_pair(chan, 0, 0, duration, 0);
00518 }
00519
00520
00521 static int send_morse(struct ast_channel *chan, char *string, int speed, int freq, int amplitude)
00522 {
00523
00524 static struct morse_bits mbits[] = {
00525 {0, 0},
00526 {0, 0},
00527 {6, 18},
00528 {0, 0},
00529 {7, 72},
00530 {0, 0},
00531 {0, 0},
00532 {6, 30},
00533 {5, 13},
00534 {6, 29},
00535 {0, 0},
00536 {5, 10},
00537 {6, 51},
00538 {6, 33},
00539 {6, 42},
00540 {5, 9},
00541 {5, 31},
00542 {5, 30},
00543 {5, 28},
00544 {5, 24},
00545 {5, 16},
00546 {5, 0},
00547 {5, 1},
00548 {5, 3},
00549 {5, 7},
00550 {5, 15},
00551 {6, 7},
00552 {6, 21},
00553 {0, 0},
00554 {5, 33},
00555 {0, 0},
00556 {6, 12},
00557 {0, 0},
00558 {2, 2},
00559 {4, 1},
00560 {4, 5},
00561 {3, 1},
00562 {1, 0},
00563 {4, 4},
00564 {3, 3},
00565 {4, 0},
00566 {2, 0},
00567 {4, 14},
00568 {3, 5},
00569 {4, 2},
00570 {2, 3},
00571 {2, 1},
00572 {3, 7},
00573 {4, 6},
00574 {4, 11},
00575 {3, 2},
00576 {3, 0},
00577 {1, 1},
00578 {3, 4},
00579 {4, 8},
00580 {3, 6},
00581 {4, 9},
00582 {4, 13},
00583 {4, 3}
00584 };
00585
00586
00587 int dottime;
00588 int dashtime;
00589 int intralettertime;
00590 int interlettertime;
00591 int interwordtime;
00592 int len, ddcomb;
00593 int res;
00594 int c;
00595 int i;
00596 int flags;
00597
00598 res = 0;
00599
00600
00601
00602 dottime = 900/speed;
00603
00604
00605
00606 dashtime = 3 * dottime;
00607 intralettertime = dottime;
00608 interlettertime = dottime * 4 ;
00609 interwordtime = dottime * 7;
00610
00611 for(;(*string) && (!res); string++){
00612
00613 c = *string;
00614
00615
00616
00617 if((c >= 'a') && (c <= 'z'))
00618 c -= 0x20;
00619
00620
00621
00622 if(c > 'Z')
00623 continue;
00624
00625
00626
00627 if(c == ' '){
00628 if(!res)
00629 res = play_silence(chan, interwordtime);
00630 continue;
00631 }
00632
00633
00634
00635 c -= 0x20;
00636
00637
00638
00639 len = mbits[c].len;
00640 ddcomb = mbits[c].ddcomb;
00641
00642
00643
00644 for(; len ; len--){
00645 if(!res)
00646 res = play_tone(chan, freq, (ddcomb & 1) ? dashtime : dottime, amplitude);
00647 if(!res)
00648 res = play_silence(chan, intralettertime);
00649 ddcomb >>= 1;
00650 }
00651
00652
00653
00654 if(!res)
00655 res = play_silence(chan, interlettertime - intralettertime);
00656 }
00657
00658
00659
00660 if (!res)
00661 res = ast_waitstream(chan, "");
00662 ast_stopstream(chan);
00663
00664
00665
00666
00667
00668 for(i = 0; i < 20 ; i++){
00669 flags = ZT_IOMUX_WRITEEMPTY | ZT_IOMUX_NOWAIT;
00670 res = ioctl(chan->fds[0], ZT_IOMUX, &flags);
00671 if(flags & ZT_IOMUX_WRITEEMPTY)
00672 break;
00673 if( ast_safe_sleep(chan, 50)){
00674 res = -1;
00675 break;
00676 }
00677 }
00678
00679
00680 return res;
00681 }
00682
00683 static int send_tone_telemetry(struct ast_channel *chan, char *tonestring)
00684 {
00685 char *stringp;
00686 char *tonesubset;
00687 int f1,f2;
00688 int duration;
00689 int amplitude;
00690 int res;
00691 int i;
00692 int flags;
00693
00694 res = 0;
00695
00696 stringp = ast_strdupa(tonestring);
00697
00698 for(;tonestring;){
00699 tonesubset = strsep(&stringp,")");
00700 if(!tonesubset)
00701 break;
00702 if(sscanf(tonesubset,"(%d,%d,%d,%d", &f1, &f2, &duration, &litude) != 4)
00703 break;
00704 res = play_tone_pair(chan, f1, f2, duration, amplitude);
00705 if(res)
00706 break;
00707 }
00708 if(!res)
00709 res = play_tone_pair(chan, 0, 0, 100, 0);
00710
00711 if (!res)
00712 res = ast_waitstream(chan, "");
00713 ast_stopstream(chan);
00714
00715
00716
00717
00718
00719 for(i = 0; i < 20 ; i++){
00720 flags = ZT_IOMUX_WRITEEMPTY | ZT_IOMUX_NOWAIT;
00721 res = ioctl(chan->fds[0], ZT_IOMUX, &flags);
00722 if(flags & ZT_IOMUX_WRITEEMPTY)
00723 break;
00724 if( ast_safe_sleep(chan, 50)){
00725 res = -1;
00726 break;
00727 }
00728 }
00729
00730 return res;
00731
00732 }
00733
00734
00735 static int sayfile(struct ast_channel *mychannel,char *fname)
00736 {
00737 int res;
00738
00739 res = ast_streamfile(mychannel, fname, mychannel->language);
00740 if (!res)
00741 res = ast_waitstream(mychannel, "");
00742 else
00743 ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", mychannel->name);
00744 ast_stopstream(mychannel);
00745 return res;
00746 }
00747
00748 static int saycharstr(struct ast_channel *mychannel,char *str)
00749 {
00750 int res;
00751
00752 res = ast_say_character_str(mychannel,str,NULL,mychannel->language);
00753 if (!res)
00754 res = ast_waitstream(mychannel, "");
00755 else
00756 ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", mychannel->name);
00757 ast_stopstream(mychannel);
00758 return res;
00759 }
00760
00761 static int saynum(struct ast_channel *mychannel, int num)
00762 {
00763 int res;
00764 res = ast_say_number(mychannel, num, NULL, mychannel->language, NULL);
00765 if(!res)
00766 res = ast_waitstream(mychannel, "");
00767 else
00768 ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", mychannel->name);
00769 ast_stopstream(mychannel);
00770 return res;
00771 }
00772
00773
00774
00775
00776 static int retrieve_astcfgint(char *category, char *name, int min, int max, int defl)
00777 {
00778 char *var;
00779 int ret;
00780
00781 var = ast_variable_retrieve(cfg, category, name);
00782 if(var){
00783 ret = myatoi(var);
00784 if(ret < min)
00785 ret = min;
00786 if(ret > max)
00787 ret = max;
00788 }
00789 else
00790 ret = defl;
00791 return ret;
00792 }
00793
00794 static int telem_any(struct ast_channel *chan, char *entry)
00795 {
00796 int res;
00797 char c;
00798
00799 static int morsespeed;
00800 static int morsefreq;
00801 static int morseampl;
00802 static int morseidfreq = 0;
00803 static int morseidampl;
00804 static char mcat[] = MORSE;
00805
00806 res = 0;
00807
00808 if(!morseidfreq){
00809 morsespeed = retrieve_astcfgint( mcat, "speed", 5, 20, 20);
00810 morsefreq = retrieve_astcfgint( mcat, "frequency", 300, 3000, 800);
00811 morseampl = retrieve_astcfgint( mcat, "amplitude", 200, 8192, 4096);
00812 morseidampl = retrieve_astcfgint( mcat, "idamplitude", 200, 8192, 2048);
00813 morseidfreq = retrieve_astcfgint( mcat, "idfrequency", 300, 3000, 330);
00814 }
00815
00816
00817
00818 if(entry[0] == '|'){
00819 c = entry[1];
00820 if((c >= 'a')&&(c <= 'z'))
00821 c -= 0x20;
00822
00823 switch(c){
00824 case 'I':
00825 res = send_morse(chan, entry + 2, morsespeed, morseidfreq, morseidampl);
00826 break;
00827
00828 case 'M':
00829 res = send_morse(chan, entry + 2, morsespeed, morsefreq, morseampl);
00830 break;
00831
00832 case 'T':
00833 res = send_tone_telemetry(chan, entry + 2);
00834 break;
00835 default:
00836 res = -1;
00837 }
00838 }
00839 else
00840 res = sayfile(chan, entry);
00841 return res;
00842 }
00843
00844
00845
00846
00847
00848
00849
00850 static int telem_lookup(struct ast_channel *chan, char *node, char *name)
00851 {
00852
00853 int res;
00854 int i;
00855 char *entry;
00856 char *telemetry;
00857 char *telemetry_save;
00858
00859 res = 0;
00860 telemetry_save = NULL;
00861 entry = NULL;
00862
00863
00864
00865
00866 telemetry = ast_variable_retrieve(cfg, node, TELEMETRY);
00867 if(telemetry){
00868 telemetry_save = ast_strdupa(telemetry);
00869 if(!telemetry_save){
00870 ast_log(LOG_WARNING,"ast_strdupa() failed in telem_lookup()\n");
00871 return res;
00872 }
00873 entry = ast_variable_retrieve(cfg, telemetry_save, name);
00874 }
00875
00876
00877
00878 if(!entry){
00879
00880 for(i = 0; i < sizeof(tele_defs)/sizeof(struct telem_defaults) ; i++){
00881 if(!strcasecmp(tele_defs[i].name, name))
00882 entry = tele_defs[i].value;
00883 }
00884 }
00885 if(entry)
00886 telem_any(chan, entry);
00887 else{
00888 ast_log(LOG_WARNING, "Telemetry name not found: %s\n", name);
00889 res = -1;
00890 }
00891 return res;
00892 }
00893
00894
00895
00896
00897
00898 static int get_wait_interval(struct rpt *myrpt, int type)
00899 {
00900 int interval;
00901 char *wait_times;
00902 char *wait_times_save;
00903
00904 wait_times_save = NULL;
00905 wait_times = ast_variable_retrieve(cfg, myrpt->name, "wait_times");
00906
00907 if(wait_times){
00908 wait_times_save = ast_strdupa(wait_times);
00909 if(!wait_times_save){
00910 ast_log(LOG_WARNING, "Out of memory in wait_interval()\n");
00911 wait_times = NULL;
00912 }
00913 }
00914
00915 switch(type){
00916 case DLY_TELEM:
00917 if(wait_times)
00918 interval = retrieve_astcfgint(wait_times_save, "telemwait", 500, 5000, 1000);
00919 else
00920 interval = 1000;
00921 break;
00922
00923 case DLY_ID:
00924 if(wait_times)
00925 interval = retrieve_astcfgint(wait_times_save, "idwait",250,5000,500);
00926 else
00927 interval = 500;
00928 break;
00929
00930 case DLY_UNKEY:
00931 if(wait_times)
00932 interval = retrieve_astcfgint(wait_times_save, "unkeywait",500,5000,1000);
00933 else
00934 interval = 1000;
00935 break;
00936
00937 case DLY_CALLTERM:
00938 if(wait_times)
00939 interval = retrieve_astcfgint(wait_times_save, "calltermwait",500,5000,1500);
00940 else
00941 interval = 1500;
00942 break;
00943
00944 default:
00945 return 0;
00946 }
00947 return interval;
00948 }
00949
00950
00951
00952
00953
00954
00955
00956 static void wait_interval(struct rpt *myrpt, int type, struct ast_channel *chan)
00957 {
00958 int interval;
00959 if((interval = get_wait_interval(myrpt, type)))
00960 ast_safe_sleep(chan,interval);
00961 return;
00962 }
00963
00964
00965 static void *rpt_tele_thread(void *this)
00966 {
00967 ZT_CONFINFO ci;
00968 int res = 0,haslink,hastx,hasremote,imdone = 0, unkeys_queued, x;
00969 struct rpt_tele *mytele = (struct rpt_tele *)this;
00970 struct rpt_tele *tlist;
00971 struct rpt *myrpt;
00972 struct rpt_link *l,*m,linkbase;
00973 struct ast_channel *mychannel;
00974 int vmajor, vminor;
00975 char *p,*ct,*ct_copy,*ident, *nodename;
00976 time_t t;
00977 struct tm localtm;
00978
00979
00980
00981 myrpt = mytele->rpt;
00982
00983
00984 ast_mutex_lock(&myrpt->lock);
00985 nodename = ast_strdupa(myrpt->name);
00986 ident = ast_strdupa(myrpt->ident);
00987 ast_mutex_unlock(&myrpt->lock);
00988
00989
00990
00991 mychannel = ast_request("zap",AST_FORMAT_SLINEAR,"pseudo",NULL);
00992 if (!mychannel)
00993 {
00994 fprintf(stderr,"rpt:Sorry unable to obtain pseudo channel\n");
00995 ast_mutex_lock(&myrpt->lock);
00996 remque((struct qelem *)mytele);
00997 ast_mutex_unlock(&myrpt->lock);
00998 free(mytele);
00999 pthread_exit(NULL);
01000 }
01001 ast_mutex_lock(&myrpt->lock);
01002 mytele->chan = mychannel;
01003 ast_mutex_unlock(&myrpt->lock);
01004
01005
01006 ci.chan = 0;
01007
01008
01009 ci.confno = (((mytele->mode == ID) || (mytele->mode == IDTALKOVER) || (mytele->mode == UNKEY)) ?
01010 myrpt->txconf : myrpt->conf);
01011 ci.confmode = ZT_CONF_CONFANN;
01012
01013 if (ioctl(mychannel->fds[0],ZT_SETCONF,&ci) == -1)
01014 {
01015 ast_log(LOG_WARNING, "Unable to set conference mode to Announce\n");
01016 ast_mutex_lock(&myrpt->lock);
01017 remque((struct qelem *)mytele);
01018 ast_mutex_unlock(&myrpt->lock);
01019 free(mytele);
01020 ast_hangup(mychannel);
01021 pthread_exit(NULL);
01022 }
01023 ast_stopstream(mychannel);
01024 switch(mytele->mode)
01025 {
01026 case ID:
01027 case ID1:
01028
01029 wait_interval(myrpt, (mytele->mode == ID) ? DLY_ID : DLY_TELEM,mychannel);
01030 res = telem_any(mychannel, ident);
01031 imdone=1;
01032
01033 break;
01034
01035
01036 case IDTALKOVER:
01037 p = ast_variable_retrieve(cfg, nodename, "idtalkover");
01038 if(p)
01039 res = telem_any(mychannel, p);
01040 imdone=1;
01041 break;
01042
01043 case PROC:
01044
01045 wait_interval(myrpt, DLY_TELEM, mychannel);
01046 res = ast_streamfile(mychannel, "rpt/callproceeding", mychannel->language);
01047 break;
01048 case TERM:
01049
01050 wait_interval(myrpt, DLY_CALLTERM, mychannel);
01051 res = ast_streamfile(mychannel, "rpt/callterminated", mychannel->language);
01052 break;
01053 case COMPLETE:
01054
01055 wait_interval(myrpt, DLY_TELEM, mychannel);
01056 res = telem_lookup(mychannel, myrpt->name, "functcomplete");
01057 break;
01058 case UNKEY:
01059
01060
01061
01062
01063
01064 x = get_wait_interval(myrpt, DLY_UNKEY);
01065 ast_mutex_lock(&myrpt->lock);
01066 myrpt->unkeytocttimer = x;
01067 ast_mutex_unlock(&myrpt->lock);
01068
01069
01070
01071
01072
01073 tlist = myrpt->tele.next;
01074 unkeys_queued = 0;
01075 if (tlist != &myrpt->tele)
01076 {
01077 ast_mutex_lock(&myrpt->lock);
01078 while(tlist != &myrpt->tele){
01079 if (tlist->mode == UNKEY) unkeys_queued++;
01080 tlist = tlist->next;
01081 }
01082 ast_mutex_unlock(&myrpt->lock);
01083 }
01084 if( unkeys_queued > 1){
01085 imdone = 1;
01086 break;
01087 }
01088
01089
01090
01091
01092 while(myrpt->unkeytocttimer)
01093 {
01094 int ctint;
01095 if(myrpt->unkeytocttimer > 100)
01096 ctint = 100;
01097 else
01098 ctint = myrpt->unkeytocttimer;
01099 ast_safe_sleep(mychannel, ctint);
01100 ast_mutex_lock(&myrpt->lock);
01101 if(myrpt->unkeytocttimer < ctint)
01102 myrpt->unkeytocttimer = 0;
01103 else
01104 myrpt->unkeytocttimer -= ctint;
01105 ast_mutex_unlock(&myrpt->lock);
01106 }
01107
01108
01109
01110
01111
01112
01113 if(myrpt->keyed){
01114 imdone = 1;
01115 break;
01116 }
01117
01118 haslink = 0;
01119 hastx = 0;
01120 hasremote = 0;
01121 l = myrpt->links.next;
01122 if (l != &myrpt->links)
01123 {
01124 ast_mutex_lock(&myrpt->lock);
01125 while(l != &myrpt->links)
01126 {
01127 if (l->name[0] == '0')
01128 {
01129 l = l->next;
01130 continue;
01131 }
01132 haslink = 1;
01133 if (l->mode) {
01134 hastx++;
01135 if (l->isremote) hasremote++;
01136 }
01137 l = l->next;
01138 }
01139 ast_mutex_unlock(&myrpt->lock);
01140 }
01141 if (haslink)
01142 {
01143
01144 res = telem_lookup(mychannel, myrpt->name, (!hastx) ? "remotemon" : "remotetx");
01145 if(res)
01146 ast_log(LOG_WARNING, "telem_lookup:remotexx failed on %s\n", mychannel->name);
01147
01148
01149
01150 if (myrpt->cmdnode[0])
01151 {
01152 ast_safe_sleep(mychannel,200);
01153 res = telem_lookup(mychannel, myrpt->name, "cmdmode");
01154 if(res)
01155 ast_log(LOG_WARNING, "telem_lookup:cmdmode failed on %s\n", mychannel->name);
01156 ast_stopstream(mychannel);
01157 }
01158 }
01159 else if((ct = ast_variable_retrieve(cfg, nodename, "unlinkedct"))){
01160 ct_copy = ast_strdupa(ct);
01161 res = telem_lookup(mychannel, myrpt->name, ct_copy);
01162 if(res)
01163 ast_log(LOG_WARNING, "telem_lookup:ctx failed on %s\n", mychannel->name);
01164 }
01165
01166 if (hasremote && (!myrpt->cmdnode[0]))
01167 {
01168
01169 ci.chan = 0;
01170 ci.confno = myrpt->conf;
01171 ci.confmode = ZT_CONF_CONFANN;
01172
01173 if (ioctl(mychannel->fds[0],ZT_SETCONF,&ci) == -1)
01174 {
01175 ast_log(LOG_WARNING, "Unable to set conference mode to Announce\n");
01176 ast_mutex_lock(&myrpt->lock);
01177 remque((struct qelem *)mytele);
01178 ast_mutex_unlock(&myrpt->lock);
01179 free(mytele);
01180 ast_hangup(mychannel);
01181 pthread_exit(NULL);
01182 }
01183 if((ct = ast_variable_retrieve(cfg, nodename, "remotect"))){
01184 ast_safe_sleep(mychannel,200);
01185 ct_copy = ast_strdupa(ct);
01186 res = telem_lookup(mychannel, myrpt->name, ct_copy);
01187 if(res)
01188 ast_log(LOG_WARNING, "telem_lookup:ctx failed on %s\n", mychannel->name);
01189 }
01190 }
01191 imdone = 1;
01192 break;
01193 case REMDISC:
01194
01195 wait_interval(myrpt, DLY_TELEM, mychannel);
01196 res = ast_streamfile(mychannel, "rpt/node", mychannel->language);
01197 if (!res)
01198 res = ast_waitstream(mychannel, "");
01199 else
01200 ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", mychannel->name);
01201 ast_stopstream(mychannel);
01202 ast_say_character_str(mychannel,mytele->mylink.name,NULL,mychannel->language);
01203 res = ast_streamfile(mychannel, ((mytele->mylink.connected) ?
01204 "rpt/remote_disc" : "rpt/remote_busy"), mychannel->language);
01205 break;
01206 case REMALREADY:
01207
01208 wait_interval(myrpt, DLY_TELEM, mychannel);
01209 res = ast_streamfile(mychannel, "rpt/remote_already", mychannel->language);
01210 break;
01211 case REMNOTFOUND:
01212
01213 wait_interval(myrpt, DLY_TELEM, mychannel);
01214 res = ast_streamfile(mychannel, "rpt/remote_notfound", mychannel->language);
01215 break;
01216 case REMGO:
01217
01218 wait_interval(myrpt, DLY_TELEM, mychannel);
01219 res = ast_streamfile(mychannel, "rpt/remote_go", mychannel->language);
01220 break;
01221 case CONNECTED:
01222
01223 wait_interval(myrpt, DLY_TELEM, mychannel);
01224 res = ast_streamfile(mychannel, "rpt/node", mychannel->language);
01225 if (!res)
01226 res = ast_waitstream(mychannel, "");
01227 else
01228 ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", mychannel->name);
01229 ast_stopstream(mychannel);
01230 ast_say_character_str(mychannel,mytele->mylink.name,NULL,mychannel->language);
01231 res = ast_streamfile(mychannel, "rpt/connected", mychannel->language);
01232 break;
01233 case CONNFAIL:
01234 res = ast_streamfile(mychannel, "rpt/node", mychannel->language);
01235 if (!res)
01236 res = ast_waitstream(mychannel, "");
01237 else
01238 ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", mychannel->name);
01239 ast_stopstream(mychannel);
01240 ast_say_character_str(mychannel,mytele->mylink.name,NULL,mychannel->language);
01241 res = ast_streamfile(mychannel, "rpt/connection_failed", mychannel->language);
01242 break;
01243 case STATUS:
01244
01245 wait_interval(myrpt, DLY_TELEM, mychannel);
01246 hastx = 0;
01247 linkbase.next = &linkbase;
01248 linkbase.prev = &linkbase;
01249 ast_mutex_lock(&myrpt->lock);
01250
01251 l = myrpt->links.next;
01252 while(l != &myrpt->links)
01253 {
01254 if (l->name[0] == '0')
01255 {
01256 l = l->next;
01257 continue;
01258 }
01259 m = malloc(sizeof(struct rpt_link));
01260 if (!m)
01261 {
01262 ast_log(LOG_WARNING, "Cannot alloc memory on %s\n", mychannel->name);
01263 ast_mutex_lock(&myrpt->lock);
01264 remque((struct qelem *)mytele);
01265 ast_mutex_unlock(&myrpt->lock);
01266 free(mytele);
01267 ast_hangup(mychannel);
01268 pthread_exit(NULL);
01269 }
01270 memcpy(m,l,sizeof(struct rpt_link));
01271 m->next = m->prev = NULL;
01272 insque((struct qelem *)m,(struct qelem *)linkbase.next);
01273 l = l->next;
01274 }
01275 ast_mutex_unlock(&myrpt->lock);
01276 res = ast_streamfile(mychannel, "rpt/node", mychannel->language);
01277 if (!res)
01278 res = ast_waitstream(mychannel, "");
01279 else
01280 ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", mychannel->name);
01281 ast_stopstream(mychannel);
01282 ast_say_character_str(mychannel,myrpt->name,NULL,mychannel->language);
01283 if (!res)
01284 res = ast_waitstream(mychannel, "");
01285 else
01286 ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", mychannel->name);
01287 ast_stopstream(mychannel);
01288 if (myrpt->callmode)
01289 {
01290 hastx = 1;
01291 res = ast_streamfile(mychannel, "rpt/autopatch_on", mychannel->language);
01292 if (!res)
01293 res = ast_waitstream(mychannel, "");
01294 else
01295 ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", mychannel->name);
01296 ast_stopstream(mychannel);
01297 }
01298 l = linkbase.next;
01299 while(l != &linkbase)
01300 {
01301 hastx = 1;
01302 res = ast_streamfile(mychannel, "rpt/node", mychannel->language);
01303 if (!res)
01304 res = ast_waitstream(mychannel, "");
01305 else
01306 ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", mychannel->name);
01307 ast_stopstream(mychannel);
01308 ast_say_character_str(mychannel,l->name,NULL,mychannel->language);
01309 if (!res)
01310 res = ast_waitstream(mychannel, "");
01311 else
01312 ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", mychannel->name);
01313 ast_stopstream(mychannel);
01314 res = ast_streamfile(mychannel, ((l->mode) ?
01315 "rpt/tranceive" : "rpt/monitor"), mychannel->language);
01316 if (!res)
01317 res = ast_waitstream(mychannel, "");
01318 else
01319 ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", mychannel->name);
01320 ast_stopstream(mychannel);
01321 l = l->next;
01322 }
01323 if (!hastx)
01324 {
01325 res = ast_streamfile(mychannel, "rpt/repeat_only", mychannel->language);
01326 if (!res)
01327 res = ast_waitstream(mychannel, "");
01328 else
01329 ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", mychannel->name);
01330 ast_stopstream(mychannel);
01331 }
01332
01333 l = linkbase.next;
01334 while(l != &linkbase)
01335 {
01336 m = l;
01337 l = l->next;
01338 remque((struct qelem *)m);
01339 free(m);
01340 }
01341 imdone = 1;
01342 break;
01343 case TIMEOUT:
01344 res = ast_streamfile(mychannel, "rpt/node", mychannel->language);
01345 if (!res)
01346 res = ast_waitstream(mychannel, "");
01347 else
01348 ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", mychannel->name);
01349 ast_stopstream(mychannel);
01350 ast_say_character_str(mychannel,myrpt->name,NULL,mychannel->language);
01351 res = ast_streamfile(mychannel, "rpt/timeout", mychannel->language);
01352 break;
01353
01354 case STATS_TIME:
01355 wait_interval(myrpt, DLY_TELEM, mychannel);
01356 t = time(NULL);
01357 localtime_r(&t, &localtm);
01358
01359 if((localtm.tm_hour >= 0) && (localtm.tm_hour < 12))
01360 p = "rpt/goodmorning";
01361 else if((localtm.tm_hour >= 12) && (localtm.tm_hour < 18))
01362 p = "rpt/goodafternoon";
01363 else
01364 p = "rpt/goodevening";
01365 if (sayfile(mychannel,p) == -1)
01366 {
01367 imdone = 1;
01368 break;
01369 }
01370
01371 if (sayfile(mychannel,"rpt/thetimeis") == -1)
01372 {
01373 imdone = 1;
01374 break;
01375 }
01376
01377 res = ast_say_time(mychannel, t, "", mychannel->language);
01378 if (!res)
01379 res = ast_waitstream(mychannel, "");
01380 ast_stopstream(mychannel);
01381 imdone = 1;
01382 break;
01383 case STATS_VERSION:
01384 p = strstr(tdesc, "version");
01385 if(!p)
01386 break;
01387 if(sscanf(p, "version %d.%d", &vmajor, &vminor) != 2)
01388 break;
01389 wait_interval(myrpt, DLY_TELEM, mychannel);
01390
01391 if (sayfile(mychannel,"rpt/version") == -1)
01392 {
01393 imdone = 1;
01394 break;
01395 }
01396 if(!res)
01397 ast_say_number(mychannel, vmajor, "", mychannel->language, (char *) NULL);
01398 if (!res)
01399 res = ast_waitstream(mychannel, "");
01400 ast_stopstream(mychannel);
01401 if (saycharstr(mychannel,".") == -1)
01402 {
01403 imdone = 1;
01404 break;
01405 }
01406 if(!res)
01407 ast_say_number(mychannel, vminor, "", mychannel->language, (char *) NULL);
01408 if (!res){
01409 res = ast_waitstream(mychannel, "");
01410 ast_stopstream(mychannel);
01411 }
01412 else
01413 ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", mychannel->name);
01414 imdone = 1;
01415 break;
01416 case ARB_ALPHA:
01417 wait_interval(myrpt, DLY_TELEM, mychannel);
01418 if(mytele->param)
01419 saycharstr(mychannel, mytele->param);
01420 imdone = 1;
01421 break;
01422 case REV_PATCH:
01423 wait_interval(myrpt, DLY_TELEM, mychannel);
01424 if(mytele->param) {
01425
01426
01427 char *tpl_working, *tpl_current;
01428 char *tmp[100], *myparm;
01429 int looptemp=0,i=0, dres = 0;
01430
01431
01432 tpl_working = strdupa(mytele->param);
01433 myparm = strsep(&tpl_working,",");
01434 tpl_current=strsep(&tpl_working, ":");
01435
01436 while(tpl_current && looptemp < sizeof(tmp)) {
01437 tmp[looptemp]=tpl_current;
01438 looptemp++;
01439 tpl_current=strsep(&tpl_working,":");
01440 }
01441
01442 for(i=0; i<looptemp; i++) {
01443 if(!strcmp(tmp[i], "PARKED")) {
01444 ast_say_digits(mychannel, atoi(myparm), "", mychannel->language);
01445 } else if(!strcmp(tmp[i], "NODE")) {
01446 ast_say_digits(mychannel, atoi(myrpt->name), "", mychannel->language);
01447 } else {
01448 dres = ast_streamfile(mychannel, tmp[i], mychannel->language);
01449 if(!dres) {
01450 dres = ast_waitstream(mychannel, "");
01451 } else {
01452 ast_log(LOG_WARNING, "ast_streamfile of %s failed on %s\n", tmp[i], mychannel->name);
01453 dres = 0;
01454 }
01455 }
01456 }
01457 }
01458 imdone = 1;
01459 break;
01460 case TEST_TONE:
01461 imdone = 1;
01462 myrpt->stopgen = 0;
01463 if ((res = ast_tonepair_start(mychannel, 1004.0, 0, 99999999, 7200.0)))
01464 break;
01465 while(mychannel->generatordata && (!myrpt->stopgen)) {
01466 if (ast_safe_sleep(mychannel,1)) break;
01467 imdone = 1;
01468 }
01469 break;
01470 default:
01471 break;
01472 }
01473 myrpt->stopgen = 0;
01474 if (!imdone)
01475 {
01476 if (!res)
01477 res = ast_waitstream(mychannel, "");
01478 else {
01479 ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", mychannel->name);
01480 res = 0;
01481 }
01482 }
01483 ast_stopstream(mychannel);
01484 ast_mutex_lock(&myrpt->lock);
01485 remque((struct qelem *)mytele);
01486 ast_mutex_unlock(&myrpt->lock);
01487 free(mytele);
01488 ast_hangup(mychannel);
01489 pthread_exit(NULL);
01490 }
01491
01492 static void rpt_telemetry(struct rpt *myrpt,int mode, void *data)
01493 {
01494 struct rpt_tele *tele;
01495 struct rpt_link *mylink = (struct rpt_link *) data;
01496 pthread_attr_t attr;
01497
01498 tele = malloc(sizeof(struct rpt_tele));
01499 if (!tele)
01500 {
01501 ast_log(LOG_WARNING, "Unable to allocate memory\n");
01502 pthread_exit(NULL);
01503 return;
01504 }
01505
01506 memset((char *)tele,0,sizeof(struct rpt_tele));
01507 tele->rpt = myrpt;
01508 tele->mode = mode;
01509 ast_mutex_lock(&myrpt->lock);
01510 if((mode == CONNFAIL) || (mode == REMDISC) || (mode == CONNECTED)){
01511 memset(&tele->mylink,0,sizeof(struct rpt_link));
01512 if (mylink){
01513 memcpy(&tele->mylink,mylink,sizeof(struct rpt_link));
01514 }
01515 }
01516 else if ((mode == ARB_ALPHA) || (mode == REV_PATCH)) {
01517 strncpy(tele->param, (char *) data, TELEPARAMSIZE - 1);
01518 tele->param[TELEPARAMSIZE - 1] = 0;
01519 }
01520 insque((struct qelem *)tele,(struct qelem *)myrpt->tele.next);
01521 ast_mutex_unlock(&myrpt->lock);
01522 pthread_attr_init(&attr);
01523 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
01524 ast_pthread_create(&tele->threadid,&attr,rpt_tele_thread,(void *) tele);
01525 return;
01526 }
01527
01528 static void *rpt_call(void *this)
01529 {
01530 ZT_CONFINFO ci;
01531 struct rpt *myrpt = (struct rpt *)this;
01532 int res;
01533 struct ast_frame wf;
01534 int stopped,congstarted;
01535 struct ast_channel *mychannel,*genchannel;
01536
01537 myrpt->mydtmf = 0;
01538
01539 mychannel = ast_request("zap",AST_FORMAT_SLINEAR,"pseudo",NULL);
01540 if (!mychannel)
01541 {
01542 fprintf(stderr,"rpt:Sorry unable to obtain pseudo channel\n");
01543 pthread_exit(NULL);
01544 }
01545 ci.chan = 0;
01546 ci.confno = myrpt->conf;
01547 ci.confmode = ZT_CONF_REALANDPSEUDO | ZT_CONF_TALKER | ZT_CONF_LISTENER
01548 | ZT_CONF_PSEUDO_TALKER | ZT_CONF_PSEUDO_LISTENER;
01549
01550 if (ioctl(mychannel->fds[0],ZT_SETCONF,&ci) == -1)
01551 {
01552 ast_log(LOG_WARNING, "Unable to set conference mode to Announce\n");
01553 ast_hangup(mychannel);
01554 myrpt->callmode = 0;
01555 pthread_exit(NULL);
01556 }
01557
01558 genchannel = ast_request("zap",AST_FORMAT_SLINEAR,"pseudo",NULL);
01559 if (!genchannel)
01560 {
01561 fprintf(stderr,"rpt:Sorry unable to obtain pseudo channel\n");
01562 ast_hangup(mychannel);
01563 pthread_exit(NULL);
01564 }
01565 ci.chan = 0;
01566 ci.confno = myrpt->conf;
01567 ci.confmode = ZT_CONF_REALANDPSEUDO | ZT_CONF_TALKER | ZT_CONF_LISTENER
01568 | ZT_CONF_PSEUDO_TALKER | ZT_CONF_PSEUDO_LISTENER;
01569
01570 if (ioctl(genchannel->fds[0],ZT_SETCONF,&ci) == -1)
01571 {
01572 ast_log(LOG_WARNING, "Unable to set conference mode to Announce\n");
01573 ast_hangup(mychannel);
01574 ast_hangup(genchannel);
01575 myrpt->callmode = 0;
01576 pthread_exit(NULL);
01577 }
01578 if (myrpt->tonezone && (tone_zone_set_zone(mychannel->fds[0],myrpt->tonezone) == -1))
01579 {
01580 ast_log(LOG_WARNING, "Unable to set tone zone %s\n",myrpt->tonezone);
01581 ast_hangup(mychannel);
01582 ast_hangup(genchannel);
01583 myrpt->callmode = 0;
01584 pthread_exit(NULL);
01585 }
01586 if (myrpt->tonezone && (tone_zone_set_zone(genchannel->fds[0],myrpt->tonezone) == -1))
01587 {
01588 ast_log(LOG_WARNING, "Unable to set tone zone %s\n",myrpt->tonezone);
01589 ast_hangup(mychannel);
01590 ast_hangup(genchannel);
01591 myrpt->callmode = 0;
01592 pthread_exit(NULL);
01593 }
01594
01595 if (tone_zone_play_tone(mychannel->fds[0],ZT_TONE_DIALTONE) < 0)
01596 {
01597 ast_log(LOG_WARNING, "Cannot start dialtone\n");
01598 ast_hangup(mychannel);
01599 ast_hangup(genchannel);
01600 myrpt->callmode = 0;
01601 pthread_exit(NULL);
01602 }
01603 stopped = 0;
01604 congstarted = 0;
01605 while ((myrpt->callmode == 1) || (myrpt->callmode == 4))
01606 {
01607
01608 if ((myrpt->callmode == 1) && (myrpt->cidx > 0) && (!stopped))
01609 {
01610 stopped = 1;
01611
01612 tone_zone_play_tone(mychannel->fds[0],-1);
01613 }
01614 if ((myrpt->callmode == 4) && (!congstarted))
01615 {
01616 congstarted = 1;
01617
01618 tone_zone_play_tone(mychannel->fds[0],ZT_TONE_CONGESTION);
01619 }
01620 res = ast_safe_sleep(mychannel, MSWAIT);
01621 if (res < 0)
01622 {
01623 ast_hangup(mychannel);
01624 ast_hangup(genchannel);
01625 ast_mutex_lock(&myrpt->lock);
01626 myrpt->callmode = 0;
01627 ast_mutex_unlock(&myrpt->lock);
01628 pthread_exit(NULL);
01629 }
01630 }
01631
01632 tone_zone_play_tone(mychannel->fds[0],-1);
01633
01634 if (!myrpt->callmode)
01635 {
01636 ast_hangup(mychannel);
01637 ast_hangup(genchannel);
01638 ast_mutex_lock(&myrpt->lock);
01639 myrpt->callmode = 0;
01640 ast_mutex_unlock(&myrpt->lock);
01641 pthread_exit(NULL);
01642 }
01643
01644 if (myrpt->ourcallerid && *myrpt->ourcallerid){
01645 char *name, *loc, *instr;
01646 instr = strdup(myrpt->ourcallerid);
01647 if(instr){
01648 ast_callerid_parse(instr, &name, &loc);
01649 if(loc){
01650 if(mychannel->cid.cid_num)
01651 free(mychannel->cid.cid_num);
01652 mychannel->cid.cid_num = strdup(loc);
01653 }
01654 if(name){
01655 if(mychannel->cid.cid_name)
01656 free(mychannel->cid.cid_name);
01657 mychannel->cid.cid_name = strdup(name);
01658 }
01659 free(instr);
01660 }
01661 }
01662
01663 strncpy(mychannel->exten, myrpt->exten, sizeof(mychannel->exten) - 1);
01664 strncpy(mychannel->context, myrpt->ourcontext, sizeof(mychannel->context) - 1);
01665 if (myrpt->acctcode)
01666 strncpy(mychannel->accountcode, myrpt->acctcode, sizeof(mychannel->accountcode) - 1);
01667 mychannel->priority = 1;
01668 ast_channel_undefer_dtmf(mychannel);
01669 if (ast_pbx_start(mychannel) < 0)
01670 {
01671 ast_log(LOG_WARNING, "Unable to start PBX!!\n");
01672 ast_hangup(mychannel);
01673 ast_hangup(genchannel);
01674 ast_mutex_lock(&myrpt->lock);
01675 myrpt->callmode = 0;
01676 ast_mutex_unlock(&myrpt->lock);
01677 pthread_exit(NULL);
01678 }
01679 usleep(10000);
01680 ast_mutex_lock(&myrpt->lock);
01681 myrpt->callmode = 3;
01682 while(myrpt->callmode)
01683 {
01684 if ((!mychannel->pbx) && (myrpt->callmode != 4))
01685 {
01686 myrpt->callmode = 4;
01687 ast_mutex_unlock(&myrpt->lock);
01688
01689 tone_zone_play_tone(genchannel->fds[0],ZT_TONE_CONGESTION);
01690 ast_mutex_lock(&myrpt->lock);
01691 }
01692 if (myrpt->mydtmf)
01693 {
01694 wf.frametype = AST_FRAME_DTMF;
01695 wf.subclass = myrpt->mydtmf;
01696 wf.offset = 0;
01697 wf.mallocd = 0;
01698 wf.data = NULL;
01699 wf.datalen = 0;
01700 wf.samples = 0;
01701 ast_mutex_unlock(&myrpt->lock);
01702 ast_write(genchannel,&wf);
01703 ast_mutex_lock(&myrpt->lock);
01704 myrpt->mydtmf = 0;
01705 }
01706 ast_mutex_unlock(&myrpt->lock);
01707 usleep(MSWAIT * 1000);
01708 ast_mutex_lock(&myrpt->lock);
01709 }
01710 ast_mutex_unlock(&myrpt->lock);
01711 tone_zone_play_tone(genchannel->fds[0],-1);
01712 if (mychannel->pbx) ast_softhangup(mychannel,AST_SOFTHANGUP_DEV);
01713 ast_hangup(genchannel);
01714 ast_mutex_lock(&myrpt->lock);
01715 myrpt->callmode = 0;
01716 ast_mutex_unlock(&myrpt->lock);
01717 pthread_exit(NULL);
01718 }
01719
01720 static void send_link_dtmf(struct rpt *myrpt,char c)
01721 {
01722 char str[300];
01723 struct ast_frame wf;
01724 struct rpt_link *l;
01725
01726 snprintf(str, sizeof(str), "D %s %s %d %c", myrpt->cmdnode, myrpt->name, ++(myrpt->dtmfidx), c);
01727 wf.frametype = AST_FRAME_TEXT;
01728 wf.subclass = 0;
01729 wf.offset = 0;
01730 wf.mallocd = 1;
01731 wf.datalen = strlen(str) + 1;
01732 wf.samples = 0;
01733 l = myrpt->links.next;
01734
01735 while(l != &myrpt->links)
01736 {
01737 if (l->name[0] == '0')
01738 {
01739 l = l->next;
01740 continue;
01741 }
01742
01743 if (!strcmp(l->name,myrpt->cmdnode))
01744 {
01745 wf.data = strdup(str);
01746 if (l->chan) ast_write(l->chan,&wf);
01747 return;
01748 }
01749 l = l->next;
01750 }
01751 l = myrpt->links.next;
01752
01753 while(l != &myrpt->links)
01754 {
01755 wf.data = strdup(str);
01756 if (l->chan) ast_write(l->chan,&wf);
01757 l = l->next;
01758 }
01759 return;
01760 }
01761
01762
01763
01764
01765
01766 static int function_ilink(struct rpt *myrpt, char *param, char *digits, int command_source, struct rpt_link *mylink)
01767 {
01768
01769 char *val, *s, *s1, *s2, *tele;
01770 char tmp[300], deststr[300] = "",modechange = 0;
01771 char digitbuf[MAXNODESTR];
01772 struct rpt_link *l;
01773 ZT_CONFINFO ci;
01774
01775 if(!param)
01776 return DC_ERROR;
01777
01778
01779 if (!myrpt->enable)
01780 return DC_ERROR;
01781
01782 strncpy(digitbuf,digits,MAXNODESTR - 1);
01783
01784 if(debug)
01785 printf("@@@@ ilink param = %s, digitbuf = %s\n", (param)? param : "(null)", digitbuf);
01786
01787 switch(myatoi(param)){
01788 case 1:
01789 if ((digitbuf[0] == '0') && (myrpt->lastlinknode[0]))
01790 strcpy(digitbuf,myrpt->lastlinknode);
01791 val = ast_variable_retrieve(cfg, myrpt->nodes, digitbuf);
01792 if (!val){
01793 if(strlen(digitbuf) >= myrpt->longestnode)
01794 return DC_ERROR;
01795 break;
01796 }
01797 strncpy(tmp,val,sizeof(tmp) - 1);
01798 s = tmp;
01799 s1 = strsep(&s,",");
01800 s2 = strsep(&s,",");
01801 ast_mutex_lock(&myrpt->lock);
01802 l = myrpt->links.next;
01803
01804 while(l != &myrpt->links){
01805 if (l->name[0] == '0')
01806 {
01807 l = l->next;
01808 continue;
01809 }
01810
01811 if (!strcmp(l->name, digitbuf))
01812 break;
01813 l = l->next;
01814 }
01815 if (l != &myrpt->links){
01816 struct ast_frame wf;
01817
01818 strncpy(myrpt->lastlinknode,digitbuf,MAXNODESTR - 1);
01819 l->retries = MAX_RETRIES + 1;
01820 l->disced = 1;
01821 ast_mutex_unlock(&myrpt->lock);
01822 wf.frametype = AST_FRAME_TEXT;
01823 wf.subclass = 0;
01824 wf.offset = 0;
01825 wf.mallocd = 1;
01826 wf.datalen = strlen(discstr) + 1;
01827 wf.samples = 0;
01828 wf.data = strdup(discstr);
01829 if (l->chan)
01830 {
01831 ast_write(l->chan,&wf);
01832 if (ast_safe_sleep(l->chan,250) == -1) return DC_ERROR;
01833 ast_softhangup(l->chan,AST_SOFTHANGUP_DEV);
01834 }
01835 rpt_telemetry(myrpt, COMPLETE, NULL);
01836 return DC_COMPLETE;
01837 }
01838 ast_mutex_unlock(&myrpt->lock);
01839 return DC_COMPLETE;
01840 case 2:
01841 if ((digitbuf[0] == '0') && (myrpt->lastlinknode[0]))
01842 strcpy(digitbuf,myrpt->lastlinknode);
01843 val = ast_variable_retrieve(cfg, myrpt->nodes, digitbuf);
01844 if (!val){
01845 if(strlen(digitbuf) >= myrpt->longestnode)
01846 return DC_ERROR;
01847 break;
01848 }
01849 strncpy(tmp,val,sizeof(tmp) - 1);
01850 s = tmp;
01851 s1 = strsep(&s,",");
01852 s2 = strsep(&s,",");
01853 ast_mutex_lock(&myrpt->lock);
01854 l = myrpt->links.next;
01855
01856 while(l != &myrpt->links){
01857 if (l->name[0] == '0')
01858 {
01859 l = l->next;
01860 continue;
01861 }
01862
01863 if (!strcmp(l->name, digitbuf))
01864 break;
01865 l = l->next;
01866 }
01867
01868 if (l != &myrpt->links)
01869 {
01870
01871 if ((!l->mode) || (!l->chan)) {
01872 ast_mutex_unlock(&myrpt->lock);
01873 rpt_telemetry(myrpt,REMALREADY,NULL);
01874 return DC_COMPLETE;
01875
01876 }
01877 ast_mutex_unlock(&myrpt->lock);
01878 if (l->chan) ast_softhangup(l->chan,AST_SOFTHANGUP_DEV);
01879 l->retries = MAX_RETRIES + 1;
01880 l->disced = 2;
01881 modechange = 1;
01882 } else
01883 ast_mutex_unlock(&myrpt->lock);
01884 strncpy(myrpt->lastlinknode,digitbuf,MAXNODESTR - 1);
01885
01886 l = malloc(sizeof(struct rpt_link));
01887 if (!l){
01888 ast_log(LOG_WARNING, "Unable to malloc\n");
01889 return DC_ERROR;
01890 }
01891
01892 memset((char *)l,0,sizeof(struct rpt_link));
01893 snprintf(deststr, sizeof(deststr), "IAX2/%s", s1);
01894 tele = strchr(deststr,'/');
01895 if (!tele){
01896 fprintf(stderr,"link2:Dial number (%s) must be in format tech/number\n",deststr);
01897 return DC_ERROR;
01898 }
01899 *tele++ = 0;
01900 l->isremote = (s && ast_true(s));
01901 strncpy(l->name, digitbuf, MAXNODESTR - 1);
01902 l->chan = ast_request(deststr,AST_FORMAT_SLINEAR,tele,NULL);
01903 if (modechange) l->connected = 1;
01904 if (l->chan){
01905 ast_set_read_format(l->chan,AST_FORMAT_SLINEAR);
01906 ast_set_write_format(l->chan,AST_FORMAT_SLINEAR);
01907 l->chan->whentohangup = 0;
01908 l->chan->appl = "Apprpt";
01909 l->chan->data = "(Remote Rx)";
01910 if (option_verbose > 2)
01911 ast_verbose(VERBOSE_PREFIX_3 "rpt (remote) initiating call to %s/%s on %s\n",
01912 deststr,tele,l->chan->name);
01913 if(l->chan->cid.cid_num)
01914 free(l->chan->cid.cid_num);
01915 l->chan->cid.cid_num = strdup(myrpt->name);
01916 ast_call(l->chan,tele,0);
01917 }
01918 else
01919 {
01920 rpt_telemetry(myrpt,CONNFAIL,l);
01921 free(l);
01922 if (option_verbose > 2)
01923 ast_verbose(VERBOSE_PREFIX_3 "Unable to place call to %s/%s on %s\n",
01924 deststr,tele,l->chan->name);
01925 return DC_ERROR;
01926 }
01927
01928 l->pchan = ast_request("zap",AST_FORMAT_SLINEAR,"pseudo",NULL);
01929 if (!l->pchan){
01930 fprintf(stderr,"rpt:Sorry unable to obtain pseudo channel\n");
01931 ast_hangup(l->chan);
01932 free(l);
01933 return DC_ERROR;
01934 }
01935 ast_set_read_format(l->pchan,AST_FORMAT_SLINEAR);
01936 ast_set_write_format(l->pchan,AST_FORMAT_SLINEAR);
01937
01938 ci.chan = 0;
01939 ci.confno = myrpt->conf;
01940 ci.confmode = ZT_CONF_CONF | ZT_CONF_LISTENER | ZT_CONF_TALKER;
01941
01942 if (ioctl(l->pchan->fds[0],ZT_SETCONF,&ci) == -1)
01943 {
01944 ast_log(LOG_WARNING, "Unable to set conference mode to Announce\n");
01945 ast_hangup(l->chan);
01946 ast_hangup(l->pchan);
01947 free(l);
01948 return DC_ERROR;
01949 }
01950 ast_mutex_lock(&myrpt->lock);
01951
01952 insque((struct qelem *)l,(struct qelem *)myrpt->links.next);
01953 ast_mutex_unlock(&myrpt->lock);
01954 rpt_telemetry(myrpt,COMPLETE,NULL);
01955 return DC_COMPLETE;
01956 case 3:
01957 if ((digitbuf[0] == '0') && (myrpt->lastlinknode[0]))
01958 strcpy(digitbuf,myrpt->lastlinknode);
01959 val = ast_variable_retrieve(cfg, myrpt->nodes, digitbuf);
01960 if (!val){
01961 if(strlen(digitbuf) >= myrpt->longestnode)
01962 return DC_ERROR;
01963 break;
01964 }
01965 strncpy(tmp,val,sizeof(tmp) - 1);
01966 s = tmp;
01967 s1 = strsep(&s,",");
01968 s2 = strsep(&s,",");
01969 ast_mutex_lock(&myrpt->lock);
01970 l = myrpt->links.next;
01971
01972 while(l != &myrpt->links){
01973 if (l->name[0] == '0')
01974 {
01975 l = l->next;
01976 continue;
01977 }
01978
01979 if (!strcmp(l->name, digitbuf))
01980 break;
01981 l = l->next;
01982 }
01983
01984 if (l != &myrpt->links){
01985
01986 if ((l->mode) || (!l->chan)) {
01987 ast_mutex_unlock(&myrpt->lock);
01988 rpt_telemetry(myrpt, REMALREADY, NULL);
01989 return DC_COMPLETE;
01990 }
01991 ast_mutex_unlock(&myrpt->lock);
01992 if (l->chan) ast_softhangup(l->chan, AST_SOFTHANGUP_DEV);
01993 l->retries = MAX_RETRIES + 1;
01994 l->disced = 2;
01995 modechange = 1;
01996 } else
01997 ast_mutex_unlock(&myrpt->lock);
01998 strncpy(myrpt->lastlinknode,digitbuf,MAXNODESTR - 1);
01999
02000 l = malloc(sizeof(struct rpt_link));
02001 if (!l){
02002 ast_log(LOG_WARNING, "Unable to malloc\n");
02003 return(DC_ERROR);
02004 }
02005
02006 memset((char *)l,0,sizeof(struct rpt_link));
02007 l->mode = 1;
02008 l->outbound = 1;
02009 strncpy(l->name, digitbuf, MAXNODESTR - 1);
02010 l->isremote = (s && ast_true(s));
02011 if (modechange) l->connected = 1;
02012 snprintf(deststr, sizeof(deststr), "IAX2/%s", s1);
02013 tele = strchr(deststr, '/');
02014 if (!tele){
02015 fprintf(stderr,"link3:Dial number (%s) must be in format tech/number\n",deststr);
02016 free(l);
02017 return DC_ERROR;
02018 }
02019 *tele++ = 0;
02020 l->chan = ast_request(deststr, AST_FORMAT_SLINEAR, tele,NULL);
02021 if (l->chan){
02022 ast_set_read_format(l->chan, AST_FORMAT_SLINEAR);
02023 ast_set_write_format(l->chan, AST_FORMAT_SLINEAR);
02024 l->chan->whentohangup = 0;
02025 l->chan->appl = "Apprpt";
02026 l->chan->data = "(Remote Rx)";
02027 if (option_verbose > 2)
02028 ast_verbose(VERBOSE_PREFIX_3 "rpt (remote) initiating call to %s/%s on %s\n",
02029 deststr, tele, l->chan->name);
02030 if(l->chan->cid.cid_num)
02031 free(l->chan->cid.cid_num);
02032 l->chan->cid.cid_num = strdup(myrpt->name);
02033 ast_call(l->chan,tele,999);
02034 }
02035 else{
02036 rpt_telemetry(myrpt,CONNFAIL,l);
02037 free(l);
02038 if (option_verbose > 2)
02039 ast_verbose(VERBOSE_PREFIX_3 "Unable to place call to %s/%s on %s\n",
02040 deststr,tele,l->chan->name);
02041 return DC_ERROR;
02042 }
02043
02044 l->pchan = ast_request("zap",AST_FORMAT_SLINEAR,"pseudo",NULL);
02045 if (!l->pchan){
02046 fprintf(stderr,"rpt:Sorry unable to obtain pseudo channel\n");
02047 ast_hangup(l->chan);
02048 free(l);
02049 return DC_ERROR;
02050 }
02051 ast_set_read_format(l->pchan, AST_FORMAT_SLINEAR);
02052 ast_set_write_format(l->pchan, AST_FORMAT_SLINEAR);
02053
02054 ci.chan = 0;
02055 ci.confno = myrpt->conf;
02056 ci.confmode = ZT_CONF_CONF | ZT_CONF_LISTENER | ZT_CONF_TALKER;
02057
02058 if (ioctl(l->pchan->fds[0], ZT_SETCONF, &ci) == -1)
02059 {
02060 ast_log(LOG_WARNING, "Unable to set conference mode to Announce\n");
02061 ast_hangup(l->chan);
02062 ast_hangup(l->pchan);
02063 free(l);
02064 return DC_ERROR;
02065 }
02066 ast_mutex_lock(&myrpt->lock);
02067
02068 insque((struct qelem *)l,(struct qelem *)myrpt->links.next);
02069 ast_mutex_unlock(&myrpt->lock);
02070 rpt_telemetry(myrpt,COMPLETE,NULL);
02071 return DC_COMPLETE;
02072 case 4:
02073
02074
02075 if (((command_source != SOURCE_RPT) && (command_source != SOURCE_PHONE) && (command_source != SOURCE_DPHONE)) || (myrpt->links.next == &myrpt->links))
02076 return DC_COMPLETE;
02077
02078
02079 if ((myrpt->cmdnode[0]) || (!strcmp(myrpt->name, digitbuf))){
02080
02081 rpt_telemetry(myrpt, REMALREADY, NULL);
02082 return DC_COMPLETE;
02083 }
02084 if ((digitbuf[0] == '0') && (myrpt->lastlinknode[0]))
02085 strcpy(digitbuf,myrpt->lastlinknode);
02086
02087 val = ast_variable_retrieve(cfg, myrpt->nodes, digitbuf);
02088 if (!val){
02089 if(strlen(digitbuf) >= myrpt->longestnode)
02090 return DC_ERROR;
02091 break;
02092
02093 }
02094 ast_mutex_lock(&myrpt->lock);
02095 strcpy(myrpt->lastlinknode,digitbuf);
02096 strncpy(myrpt->cmdnode, digitbuf, sizeof(myrpt->cmdnode) - 1);
02097 ast_mutex_unlock(&myrpt->lock);
02098 rpt_telemetry(myrpt, REMGO, NULL);
02099 return DC_COMPLETE;
02100
02101 case 5:
02102 rpt_telemetry(myrpt, STATUS, NULL);
02103 return DC_COMPLETE;
02104
02105
02106 case 6:
02107 l = myrpt->links.next;
02108
02109 while(l != &myrpt->links){
02110 if (l->chan) ast_softhangup(l->chan, AST_SOFTHANGUP_DEV);
02111 l = l->next;
02112 }
02113 rpt_telemetry(myrpt, COMPLETE, NULL);
02114 break;
02115
02116 default:
02117 return DC_ERROR;
02118
02119 }
02120
02121 return DC_INDETERMINATE;
02122 }
02123
02124
02125
02126
02127
02128 static int function_autopatchup(struct rpt *myrpt, char *param, char *digitbuf, int command_source, struct rpt_link *mylink)
02129 {
02130 pthread_attr_t attr;
02131
02132
02133 if (!myrpt->enable)
02134 return DC_ERROR;
02135
02136 if(debug)
02137 printf("@@@@ Autopatch up\n");
02138
02139 ast_mutex_lock(&myrpt->lock);
02140
02141
02142
02143 if ((myrpt->callmode == 2) || (myrpt->callmode == 3)){
02144 myrpt->mydtmf = myrpt->funcchar;
02145 }
02146 if (myrpt->callmode){
02147 ast_mutex_unlock(&myrpt->lock);
02148 return DC_COMPLETE;
02149 }
02150 myrpt->callmode = 1;
02151 myrpt->cidx = 0;
02152 myrpt->exten[myrpt->cidx] = 0;
02153 ast_mutex_unlock(&myrpt->lock);
02154 pthread_attr_init(&attr);
02155 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
02156 ast_pthread_create(&myrpt->rpt_call_thread,&attr,rpt_call,(void *) myrpt);
02157 return DC_COMPLETE;
02158 }
02159
02160
02161
02162
02163
02164 static int function_autopatchdn(struct rpt *myrpt, char *param, char *digitbuf, int command_source, struct rpt_link *mylink)
02165 {
02166 if (!myrpt->enable)
02167 return DC_ERROR;
02168
02169 if(debug)
02170 printf("@@@@ Autopatch down\n");
02171
02172 ast_mutex_lock(&myrpt->lock);
02173
02174 if (!myrpt->callmode){
02175 ast_mutex_unlock(&myrpt->lock);
02176 return DC_COMPLETE;
02177 }
02178
02179 myrpt->callmode = 0;
02180 ast_mutex_unlock(&myrpt->lock);
02181 rpt_telemetry(myrpt, TERM, NULL);
02182 return DC_COMPLETE;
02183 }
02184
02185
02186
02187
02188
02189 static int function_status(struct rpt *myrpt, char *param, char *digitbuf, int command_source, struct rpt_link *mylink)
02190 {
02191
02192 if(!param)
02193 return DC_ERROR;
02194
02195
02196 if (!myrpt->enable)
02197 return DC_ERROR;
02198
02199 if(debug)
02200 printf("@@@@ status param = %s, digitbuf = %s\n", (param)? param : "(null)", digitbuf);
02201
02202 switch(myatoi(param)){
02203 case 1:
02204 rpt_telemetry(myrpt, ID1, NULL);
02205 return DC_COMPLETE;
02206 case 2:
02207 rpt_telemetry(myrpt, STATS_TIME, NULL);
02208 return DC_COMPLETE;
02209 case 3:
02210 rpt_telemetry(myrpt, STATS_VERSION, NULL);
02211 default:
02212 return DC_ERROR;
02213 }
02214 return DC_INDETERMINATE;
02215 }
02216
02217
02218
02219
02220
02221 static int function_cop(struct rpt *myrpt, char *param, char *digitbuf, int command_source, struct rpt_link *mylink)
02222 {
02223 if(!param)
02224 return DC_ERROR;
02225
02226 switch(myatoi(param)){
02227 case 1:
02228 system("killall -9 asterisk");
02229 return DC_COMPLETE;
02230
02231 case 2:
02232 myrpt->enable = 1;
02233 rpt_telemetry(myrpt, ARB_ALPHA, (void *) "RPTENA");
02234 return DC_COMPLETE;
02235
02236 case 3:
02237 myrpt->enable = 0;
02238 return DC_COMPLETE;
02239
02240 case 4:
02241 rpt_telemetry(myrpt, TEST_TONE, NULL);
02242 return DC_COMPLETE;
02243
02244 case 5:
02245 myrpt->disgorgetime = time(NULL) + 10;
02246 return DC_COMPLETE;
02247
02248 case 6:
02249 if (command_source != SOURCE_PHONE) return DC_INDETERMINATE;
02250 return DC_DOKEY;
02251
02252 }
02253 return DC_INDETERMINATE;
02254 }
02255
02256
02257
02258
02259
02260 static int collect_function_digits(struct rpt *myrpt, char *digits,
02261 int command_source, struct rpt_link *mylink)
02262 {
02263 int i;
02264 char *stringp,*action,*param,*functiondigits;
02265 char function_table_name[30] = "";
02266 char workstring[80];
02267
02268 struct ast_variable *vp;
02269
02270 if(debug)
02271 printf("@@@@ Digits collected: %s, source: %d\n", digits, command_source);
02272
02273 if (command_source == SOURCE_DPHONE) {
02274 if (!myrpt->dphone_functions) return DC_INDETERMINATE;
02275 strncpy(function_table_name, myrpt->dphone_functions, sizeof(function_table_name) - 1);
02276 }
02277 else if (command_source == SOURCE_PHONE) {
02278 if (!myrpt->phone_functions) return DC_INDETERMINATE;
02279 strncpy(function_table_name, myrpt->phone_functions, sizeof(function_table_name) - 1);
02280 }
02281 else if (command_source == SOURCE_LNK)
02282 strncpy(function_table_name, myrpt->link_functions, sizeof(function_table_name) - 1);
02283 else
02284 strncpy(function_table_name, myrpt->functions, sizeof(function_table_name) - 1);
02285 vp = ast_variable_browse(cfg, function_table_name);
02286 while(vp) {
02287 if(!strncasecmp(vp->name, digits, strlen(vp->name)))
02288 break;
02289 vp = vp->next;
02290 }
02291 if(!vp) {
02292 int n;
02293
02294 n = myrpt->longestfunc;
02295 if (command_source == SOURCE_LNK) n = myrpt->link_longestfunc;
02296 else
02297 if (command_source == SOURCE_PHONE) n = myrpt->phone_longestfunc;
02298 else
02299 if (command_source == SOURCE_DPHONE) n = myrpt->dphone_longestfunc;
02300
02301 if(strlen(digits) >= n)
02302 return DC_ERROR;
02303 else
02304 return DC_INDETERMINATE;
02305 }
02306
02307 strncpy(workstring, vp->value, sizeof(workstring) - 1 );
02308 stringp = workstring;
02309 action = strsep(&stringp, ",");
02310 param = stringp;
02311 if(debug)
02312 printf("@@@@ action: %s, param = %s\n",action, (param) ? param : "(null)");
02313
02314 for(i = 0 ; i < (sizeof(function_table)/sizeof(struct function_table_tag)); i++){
02315 if(!strncasecmp(action, function_table[i].action, strlen(action)))
02316 break;
02317 }
02318 if(debug)
02319 printf("@@@@ table index i = %d\n",i);
02320 if(i == (sizeof(function_table)/sizeof(struct function_table_tag))){
02321
02322 return DC_ERROR;
02323 }
02324 if(function_table[i].function == NULL){
02325
02326 if(debug)
02327 printf("@@@@ NULL for action: %s\n",action);
02328 return DC_ERROR;
02329 }
02330 functiondigits = digits + strlen(vp->name);
02331 return (*function_table[i].function)(myrpt, param, functiondigits, command_source, mylink);
02332 }
02333
02334
02335 static void handle_link_data(struct rpt *myrpt, struct rpt_link *mylink,
02336 char *str)
02337 {
02338 char tmp[300],cmd[300] = "",dest[300],src[300],c;
02339 int seq, res;
02340 struct rpt_link *l;
02341 struct ast_frame wf;
02342
02343 wf.frametype = AST_FRAME_TEXT;
02344 wf.subclass = 0;
02345 wf.offset = 0;
02346 wf.mallocd = 1;
02347 wf.datalen = strlen(str) + 1;
02348 wf.samples = 0;
02349
02350 strncpy(tmp,str,sizeof(tmp) - 1);
02351
02352 if (!strcmp(tmp,discstr))
02353 {
02354 mylink->disced = 1;
02355 mylink->retries = MAX_RETRIES + 1;
02356 ast_softhangup(mylink->chan,AST_SOFTHANGUP_DEV);
02357 return;
02358 }
02359 if (sscanf(tmp,"%s %s %s %d %c",cmd,dest,src,&seq,&c) != 5)
02360 {
02361 ast_log(LOG_WARNING, "Unable to parse link string %s\n",str);
02362 return;
02363 }
02364 if (strcmp(cmd,"D"))
02365 {
02366 ast_log(LOG_WARNING, "Unable to parse link string %s\n",str);
02367 return;
02368 }
02369
02370 if (dest[0] == '0')
02371 {
02372 strcpy(dest,myrpt->name);
02373 }
02374
02375
02376 if (strcmp(dest,myrpt->name))
02377 {
02378 l = myrpt->links.next;
02379
02380 while(l != &myrpt->links)
02381 {
02382 if (l->name[0] == '0')
02383 {
02384 l = l->next;
02385 continue;
02386 }
02387
02388 if ((l == mylink) || (!strcmp(l->name,mylink->name)))
02389 {
02390 l = l->next;
02391 continue;
02392 }
02393
02394 if (!strcmp(l->name,dest))
02395 {
02396
02397 if (strcmp(l->name,src)) {
02398 wf.data = strdup(str);
02399 if (l->chan) ast_write(l->chan,&wf);
02400 }
02401 return;
02402 }
02403 l = l->next;
02404 }
02405 l = myrpt->links.next;
02406
02407 while(l != &myrpt->links)
02408 {
02409 if (l->name[0] == '0')
02410 {
02411 l = l->next;
02412 continue;
02413 }
02414
02415 if ((l == mylink) || (!strcmp(l->name,mylink->name)))
02416 {
02417 l = l->next;
02418 continue;
02419 }
02420
02421 if (strcmp(l->name,src)) {
02422 wf.data = strdup(str);
02423 if (l->chan) ast_write(l->chan,&wf);
02424 }
02425 l = l->next;
02426 }
02427 return;
02428 }
02429 ast_mutex_lock(&myrpt->lock);
02430 if (c == myrpt->endchar) myrpt->stopgen = 1;
02431 if (myrpt->callmode == 1)
02432 {
02433 myrpt->exten[myrpt->cidx++] = c;
02434 myrpt->exten[myrpt->cidx] = 0;
02435
02436 if (ast_exists_extension(myrpt->pchannel,myrpt->ourcontext,myrpt->exten,1,NULL))
02437 {
02438 myrpt->callmode = 2;
02439 rpt_telemetry(myrpt,PROC,NULL);
02440 }
02441
02442 if (!ast_canmatch_extension(myrpt->pchannel,myrpt->ourcontext,myrpt->exten,1,NULL))
02443 {
02444
02445 myrpt->callmode = 4;
02446 }
02447 }
02448 if ((myrpt->callmode == 2) || (myrpt->callmode == 3))
02449 {
02450 myrpt->mydtmf = c;
02451 }
02452 if (c == myrpt->funcchar)
02453 {
02454 myrpt->rem_dtmfidx = 0;
02455 myrpt->rem_dtmfbuf[myrpt->rem_dtmfidx] = 0;
02456 time(&myrpt->rem_dtmf_time);
02457 ast_mutex_unlock(&myrpt->lock);
02458 return;
02459 }
02460 else if ((c != myrpt->endchar) && (myrpt->rem_dtmfidx >= 0))
02461 {
02462 time(&myrpt->rem_dtmf_time);
02463 if (myrpt->rem_dtmfidx < MAXDTMF)
02464 {
02465 myrpt->rem_dtmfbuf[myrpt->rem_dtmfidx++] = c;
02466 myrpt->rem_dtmfbuf[myrpt->rem_dtmfidx] = 0;
02467
02468 ast_mutex_unlock(&myrpt->lock);
02469 strncpy(cmd, myrpt->rem_dtmfbuf, sizeof(cmd) - 1);
02470 res = collect_function_digits(myrpt, cmd, SOURCE_LNK, mylink);
02471 ast_mutex_lock(&myrpt->lock);
02472
02473 switch(res){
02474
02475 case DC_INDETERMINATE:
02476 break;
02477
02478 case DC_REQ_FLUSH:
02479 myrpt->rem_dtmfidx = 0;
02480 myrpt->rem_dtmfbuf[0] = 0;
02481 break;
02482
02483
02484 case DC_COMPLETE:
02485 myrpt->rem_dtmfbuf[0] = 0;
02486 myrpt->rem_dtmfidx = -1;
02487 myrpt->rem_dtmf_time = 0;
02488 break;
02489
02490 case DC_ERROR:
02491 default:
02492 myrpt->rem_dtmfbuf[0] = 0;
02493 myrpt->rem_dtmfidx = -1;
02494 myrpt->rem_dtmf_time = 0;
02495 break;
02496 }
02497 }
02498
02499 }
02500 ast_mutex_unlock(&myrpt->lock);
02501 return;
02502 }
02503
02504 static void handle_link_phone_dtmf(struct rpt *myrpt, struct rpt_link *mylink,
02505 char c)
02506 {
02507
02508 char cmd[300];
02509 int res;
02510
02511 ast_mutex_lock(&myrpt->lock);
02512 if (c == myrpt->endchar)
02513 {
02514 if (mylink->lastrx)
02515 {
02516 mylink->lastrx = 0;
02517 ast_mutex_unlock(&myrpt->lock);
02518 return;
02519 }
02520 myrpt->stopgen = 1;
02521 if (myrpt->cmdnode[0])
02522 {
02523 myrpt->cmdnode[0] = 0;
02524 myrpt->dtmfidx = -1;
02525 myrpt->dtmfbuf[0] = 0;
02526 ast_mutex_unlock(&myrpt->lock);
02527 rpt_telemetry(myrpt,COMPLETE,NULL);
02528 ast_mutex_unlock(&myrpt->lock);
02529 return;
02530 }
02531 }
02532 if (myrpt->cmdnode[0])
02533 {
02534 ast_mutex_unlock(&myrpt->lock);
02535 send_link_dtmf(myrpt,c);
02536 return;
02537 }
02538 if (myrpt->callmode == 1)
02539 {
02540 myrpt->exten[myrpt->cidx++] = c;
02541 myrpt->exten[myrpt->cidx] = 0;
02542
02543 if (ast_exists_extension(myrpt->pchannel,myrpt->ourcontext,myrpt->exten,1,NULL))
02544 {
02545 myrpt->callmode = 2;
02546 rpt_telemetry(myrpt,PROC,NULL);
02547 }
02548
02549 if (!ast_canmatch_extension(myrpt->pchannel,myrpt->ourcontext,myrpt->exten,1,NULL))
02550 {
02551
02552 myrpt->callmode = 4;
02553 }
02554 }
02555 if ((myrpt->callmode == 2) || (myrpt->callmode == 3))
02556 {
02557 myrpt->mydtmf = c;
02558 }
02559 if (c == myrpt->funcchar)
02560 {
02561 myrpt->rem_dtmfidx = 0;
02562 myrpt->rem_dtmfbuf[myrpt->rem_dtmfidx] = 0;
02563 time(&myrpt->rem_dtmf_time);
02564 ast_mutex_unlock(&myrpt->lock);
02565 return;
02566 }
02567 else if ((c != myrpt->endchar) && (myrpt->rem_dtmfidx >= 0))
02568 {
02569 time(&myrpt->rem_dtmf_time);
02570 if (myrpt->rem_dtmfidx < MAXDTMF)
02571 {
02572 myrpt->rem_dtmfbuf[myrpt->rem_dtmfidx++] = c;
02573 myrpt->rem_dtmfbuf[myrpt->rem_dtmfidx] = 0;
02574
02575 ast_mutex_unlock(&myrpt->lock);
02576 strncpy(cmd, myrpt->rem_dtmfbuf, sizeof(cmd) - 1);
02577 res = collect_function_digits(myrpt, cmd,
02578 ((mylink->phonemode == 2) ? SOURCE_DPHONE : SOURCE_PHONE), mylink);
02579 ast_mutex_lock(&myrpt->lock);
02580
02581 switch(res){
02582
02583 case DC_INDETERMINATE:
02584 break;
02585
02586 case DC_DOKEY:
02587 mylink->lastrx = 1;
02588 break;
02589
02590 case DC_REQ_FLUSH:
02591 myrpt->rem_dtmfidx = 0;
02592 myrpt->rem_dtmfbuf[0] = 0;
02593 break;
02594
02595
02596 case DC_COMPLETE:
02597 myrpt->rem_dtmfbuf[0] = 0;
02598 myrpt->rem_dtmfidx = -1;
02599 myrpt->rem_dtmf_time = 0;
02600 break;
02601
02602 case DC_ERROR:
02603 default:
02604 myrpt->rem_dtmfbuf[0] = 0;
02605 myrpt->rem_dtmfidx = -1;
02606 myrpt->rem_dtmf_time = 0;
02607 break;
02608 }
02609 }
02610
02611 }
02612 ast_mutex_unlock(&myrpt->lock);
02613 return;
02614 }
02615
02616
02617
02618
02619
02620
02621
02622
02623
02624
02625
02626
02627
02628
02629
02630
02631
02632
02633
02634
02635
02636
02637
02638
02639
02640
02641
02642
02643
02644
02645
02646
02647 static int rbi_mhztoband(char *str)
02648 {
02649 int i;
02650
02651 i = atoi(str) / 10;
02652 switch(i)
02653 {
02654 case 2:
02655 return 10;
02656 case 5:
02657 return 11;
02658 case 14:
02659 return 2;
02660 case 22:
02661 return 3;
02662 case 44:
02663 return 4;
02664 case 124:
02665 return 0;
02666 case 125:
02667 return 1;
02668 case 126:
02669 return 8;
02670 case 127:
02671 return 5;
02672 case 128:
02673 return 6;
02674 case 129:
02675 return 7;
02676 default:
02677 break;
02678 }
02679 return -1;
02680 }
02681
02682
02683 static int rbi_pltocode(char *str)
02684 {
02685 int i;
02686 char *s;
02687
02688 s = strchr(str,'.');
02689 i = 0;
02690 if (s) i = atoi(s + 1);
02691 i += atoi(str) * 10;
02692 switch(i)
02693 {
02694 case 670:
02695 return 0;
02696 case 719:
02697 return 1;
02698 case 744:
02699 return 2;
02700 case 770:
02701 return 3;
02702 case 797:
02703 return 4;
02704 case 825:
02705 return 5;
02706 case 854:
02707 return 6;
02708 case 885:
02709 return 7;
02710 case 915:
02711 return 8;
02712 case 948:
02713 return 9;
02714 case 974:
02715 return 10;
02716 case 1000:
02717 return 11;
02718 case 1035:
02719 return 12;
02720 case 1072:
02721 return 13;
02722 case 1109:
02723 return 14;
02724 case 1148:
02725 return 15;
02726 case 1188:
02727 return 16;
02728 case 1230:
02729 return 17;
02730 case 1273:
02731 return 18;
02732 case 1318:
02733 return 19;
02734 case 1365:
02735 return 20;
02736 case 1413:
02737 return 21;
02738 case 1462:
02739 return 22;
02740 case 1514:
02741 return 23;
02742 case 1567:
02743 return 24;
02744 case 1622:
02745 return 25;
02746 case 1679:
02747 return 26;
02748 case 1738:
02749 return 27;
02750 case 1799:
02751 return 28;
02752 case 1862:
02753 return 29;
02754 case 1928:
02755 return 30;
02756 case 2035:
02757 return 31;
02758 case 2107:
02759 return 32;
02760 case 2181:
02761 return 33;
02762 case 2257:
02763 return 34;
02764 case 2336:
02765 return 35;
02766 case 2418:
02767 return 36;
02768 case 2503:
02769 return 37;
02770 }
02771 return -1;
02772 }
02773
02774
02775
02776
02777
02778 static void rbi_out_parallel(struct rpt *myrpt,unsigned char *data)
02779 {
02780 int i,j;
02781 unsigned char od,d;
02782 static volatile long long delayvar;
02783
02784 for(i = 0 ; i < 5 ; i++){
02785 od = *data++;
02786 for(j = 0 ; j < 8 ; j++){
02787 d = od & 1;
02788 outb(d,myrpt->iobase);
02789
02790 for(delayvar = 1; delayvar < 15000; delayvar++);
02791 od >>= 1;
02792 outb(d | 2,myrpt->iobase);
02793
02794 for(delayvar = 1; delayvar < 30000; delayvar++);
02795 outb(d,myrpt->iobase);
02796
02797 for(delayvar = 1; delayvar < 10000; delayvar++);
02798 }
02799 }
02800
02801 for(delayvar = 1; delayvar < 50000; delayvar++);
02802 }
02803
02804 static void rbi_out(struct rpt *myrpt,unsigned char *data)
02805 {
02806 struct zt_radio_param r;
02807
02808 memset(&r,0,sizeof(struct zt_radio_param));
02809 r.radpar = ZT_RADPAR_REMMODE;
02810 r.data = ZT_RADPAR_REM_RBI1;
02811
02812 if (ioctl(myrpt->rxchannel->fds[0],ZT_RADIO_SETPARAM,&r) == -1)
02813 {
02814 rbi_out_parallel(myrpt,data);
02815 return;
02816 }
02817 r.radpar = ZT_RADPAR_REMCOMMAND;
02818 memcpy(&r.data,data,5);
02819 if (ioctl(myrpt->rxchannel->fds[0],ZT_RADIO_SETPARAM,&r) == -1)
02820 {
02821 ast_log(LOG_WARNING,"Cannot send RBI command for channel %s\n",myrpt->rxchannel->name);
02822 return;
02823 }
02824 }
02825
02826 static int serial_remote_io(struct rpt *myrpt, char *txbuf, int txbytes, char *rxbuf,
02827 int rxmaxbytes, int asciiflag)
02828 {
02829 int i;
02830 struct zt_radio_param prm;
02831
02832 if(debug){
02833 printf("String output was: ");
02834 for(i = 0; i < txbytes; i++)
02835 printf("%02X ", (unsigned char ) txbuf[i]);
02836 printf("\n");
02837 }
02838
02839 prm.radpar = ZT_RADPAR_REMMODE;
02840 if (asciiflag) prm.data = ZT_RADPAR_REM_SERIAL_ASCII;
02841 else prm.data = ZT_RADPAR_REM_SERIAL;
02842 if (ioctl(myrpt->rxchannel->fds[0],ZT_RADIO_SETPARAM,&prm) == -1) return -1;
02843 prm.radpar = ZT_RADPAR_REMCOMMAND;
02844 prm.data = rxmaxbytes;
02845 memcpy(prm.buf,txbuf,txbytes);
02846 prm.index = txbytes;
02847 if (ioctl(myrpt->rxchannel->fds[0],ZT_RADIO_SETPARAM,&prm) == -1) return -1;
02848 if (rxbuf)
02849 {
02850 *rxbuf = 0;
02851 memcpy(rxbuf,prm.buf,prm.index);
02852 }
02853 return(prm.index);
02854 }
02855
02856 static int setrbi(struct rpt *myrpt)
02857 {
02858 char tmp[MAXREMSTR] = "",rbicmd[5],*s;
02859 int band,txoffset = 0,txpower = 0,txpl;
02860
02861
02862 if (!myrpt->remote) return(0);
02863
02864 if (strncmp(myrpt->remote,remote_rig_rbi,3)) return(0);
02865 strncpy(tmp, myrpt->freq, sizeof(tmp) - 1);
02866 s = strchr(tmp,'.');
02867
02868
02869 if (s == NULL){
02870 if(debug)
02871 printf("@@@@ Frequency needs a decimal\n");
02872 return -1;
02873 }
02874
02875 *s++ = 0;
02876 if (strlen(tmp) < 2){
02877 if(debug)
02878 printf("@@@@ Bad MHz digits: %s\n", tmp);
02879 return -1;
02880 }
02881
02882 if (strlen(s) < 3){
02883 if(debug)
02884 printf("@@@@ Bad KHz digits: %s\n", s);
02885 return -1;
02886 }
02887
02888 if ((s[2] != '0') && (s[2] != '5')){
02889 if(debug)
02890 printf("@@@@ KHz must end in 0 or 5: %c\n", s[2]);
02891 return -1;
02892 }
02893
02894 band = rbi_mhztoband(tmp);
02895 if (band == -1){
02896 if(debug)
02897 printf("@@@@ Bad Band: %s\n", tmp);
02898 return -1;
02899 }
02900
02901 txpl = rbi_pltocode(myrpt->txpl);
02902
02903 if (txpl == -1){
02904 if(debug)
02905 printf("@@@@ Bad TX PL: %s\n", myrpt->txpl);
02906 return -1;
02907 }
02908
02909
02910 switch(myrpt->offset)
02911 {
02912 case REM_MINUS:
02913 txoffset = 0;
02914 break;
02915 case REM_PLUS:
02916 txoffset = 0x10;
02917 break;
02918 case REM_SIMPLEX:
02919 txoffset = 0x20;
02920 break;
02921 }
02922 switch(myrpt->powerlevel)
02923 {
02924 case REM_LOWPWR:
02925 txpower = 0;
02926 break;
02927 case REM_MEDPWR:
02928 txpower = 0x20;
02929 break;
02930 case REM_HIPWR:
02931 txpower = 0x10;
02932 break;
02933 }
02934 rbicmd[0] = 0;
02935 rbicmd[1] = band | txpower | 0xc0;
02936 rbicmd[2] = (*(s - 2) - '0') | txoffset | 0x80;
02937 if (s[2] == '5') rbicmd[2] |= 0x40;
02938 rbicmd[3] = ((*s - '0') << 4) + (s[1] - '0');
02939 rbicmd[4] = txpl;
02940 if (myrpt->txplon) rbicmd[4] |= 0x40;
02941 if (myrpt->rxplon) rbicmd[4] |= 0x80;
02942 rbi_out(myrpt,rbicmd);
02943 return 0;
02944 }
02945
02946
02947
02948
02949
02950 static int check_freq_rbi(int m, int d, int *defmode)
02951 {
02952 int dflmd = REM_MODE_FM;
02953
02954 if(m == 50){
02955 if(d < 10100)
02956 return -1;
02957 }
02958 else if((m >= 51) && ( m < 54)){
02959 ;
02960 }
02961 else if(m == 144){
02962 if(d < 10100)
02963 return -1;
02964 }
02965 else if((m >= 145) && (m < 148)){
02966 ;
02967 }
02968 else if((m >= 222) && (m < 225)){
02969 ;
02970 }
02971 else if((m >= 430) && (m < 450)){
02972 ;
02973 }
02974 else if((m >= 1240) && (m < 1300)){
02975 ;
02976 }
02977 else
02978 return -1;
02979
02980 if(defmode)
02981 *defmode = dflmd;
02982
02983
02984 return 0;
02985 }
02986
02987
02988
02989
02990
02991 static int split_freq(char *mhz, char *decimals, char *freq)
02992 {
02993 char freq_copy[MAXREMSTR];
02994 char *decp;
02995
02996 decp = strchr(strncpy(freq_copy, freq, MAXREMSTR),'.');
02997 if(decp){
02998 *decp++ = 0;
02999 strncpy(mhz, freq_copy, MAXREMSTR);
03000 strcpy(decimals, "00000");
03001 strncpy(decimals, decp, strlen(decp));
03002 decimals[5] = 0;
03003 return 0;
03004 }
03005 else
03006 return -1;
03007
03008 }
03009
03010
03011
03012
03013
03014 static int split_ctcss_freq(char *hertz, char *decimal, char *freq)
03015 {
03016 char freq_copy[MAXREMSTR];
03017 char *decp;
03018
03019 decp = strchr(strncpy(freq_copy, freq, MAXREMSTR),'.');
03020 if(decp){
03021 *decp++ = 0;
03022 strncpy(hertz, freq_copy, MAXREMSTR);
03023 strncpy(decimal, decp, strlen(decp));
03024 decimal[strlen(decp)] = '\0';
03025 return 0;
03026 }
03027 else
03028 return -1;
03029 }
03030
03031
03032
03033
03034
03035
03036
03037
03038
03039
03040
03041 static int check_freq_ft897(int m, int d, int *defmode)
03042 {
03043 int dflmd = REM_MODE_FM;
03044
03045 if(m == 1){
03046 dflmd = REM_MODE_LSB;
03047 if(d < 80001)
03048 return -1;
03049 }
03050 else if(m == 3){
03051 dflmd = REM_MODE_LSB;
03052 if(d < 75001)
03053 return -1;
03054 }
03055 else if(m == 7){
03056 dflmd = REM_MODE_LSB;
03057 if((d < 15001) || (d > 29999))
03058 return -1;
03059 }
03060 else if(m == 14){
03061 dflmd = REM_MODE_USB;
03062 if((d < 15001) || (d > 34999))
03063 return -1;
03064 }
03065 else if(m == 18){
03066 dflmd = REM_MODE_USB;
03067 if((d < 11001) || (d > 16797))
03068 return -1;
03069 }
03070 else if(m == 21){
03071 dflmd = REM_MODE_USB;
03072 if((d < 20001) || (d > 44999))
03073 return -1;
03074 }
03075 else if(m == 24){
03076 dflmd = REM_MODE_USB;
03077 if((d < 93001) || (d > 98999))
03078 return -1;
03079 }
03080 else if(m == 28){
03081 dflmd = REM_MODE_USB;
03082 if(d < 30001)
03083 return -1;
03084 }
03085 else if(m == 29){
03086 if(d >= 51000)
03087 dflmd = REM_MODE_FM;
03088 else
03089 dflmd = REM_MODE_USB;
03090 if(d > 69999)
03091 return -1;
03092 }
03093 else if(m == 50){
03094 if(d < 10100)
03095 return -1;
03096 if(d >= 30000)
03097 dflmd = REM_MODE_FM;
03098 else
03099 dflmd = REM_MODE_USB;
03100
03101 }
03102 else if((m >= 51) && ( m < 54)){
03103 dflmd = REM_MODE_FM;
03104 }
03105 else if(m == 144){
03106 if(d < 10100)
03107 return -1;
03108 if(d >= 30000)
03109 dflmd = REM_MODE_FM;
03110 else
03111 dflmd = REM_MODE_USB;
03112 }
03113 else if((m >= 145) && (m < 148)){
03114 dflmd = REM_MODE_FM;
03115 }
03116 else if((m >= 430) && (m < 450)){
03117 if(m < 438)
03118 dflmd = REM_MODE_USB;
03119 else
03120 dflmd = REM_MODE_FM;
03121 ;
03122 }
03123 else
03124 return -1;
03125
03126 if(defmode)
03127 *defmode = dflmd;
03128
03129 return 0;
03130 }
03131
03132
03133
03134
03135
03136 static int set_freq_ft897(struct rpt *myrpt, char *newfreq)
03137 {
03138 char mhz[MAXREMSTR];
03139 char decimals[MAXREMSTR];
03140 unsigned char cmdstr[5];
03141 int fd,m,d;
03142
03143 fd = 0;
03144 if(debug)
03145 printf("New frequency: %s\n",newfreq);
03146
03147 if(split_freq(mhz, decimals, newfreq))
03148 return -1;
03149
03150 m = atoi(mhz);
03151 d = atoi(decimals);
03152
03153
03154
03155 cmdstr[0] = ((m / 100) << 4) + ((m % 100)/10);
03156 cmdstr[1] = ((m % 10) << 4) + (d / 10000);
03157 cmdstr[2] = (((d % 10000)/1000) << 4) + ((d % 1000)/ 100);
03158 cmdstr[3] = (((d % 100)/10) << 4) + (d % 10);
03159 cmdstr[4] = 0x01;
03160
03161 return serial_remote_io(myrpt, cmdstr, 5, NULL, 0, 0);
03162
03163 }
03164
03165
03166
03167 static int simple_command_ft897(struct rpt *myrpt, char command)
03168 {
03169 unsigned char cmdstr[5];
03170
03171 memset(cmdstr, 0, 5);
03172
03173 cmdstr[4] = command;
03174
03175 return serial_remote_io(myrpt, cmdstr, 5, NULL, 0, 0);
03176
03177 }
03178
03179
03180
03181 static int set_offset_ft897(struct rpt *myrpt, char offset)
03182 {
03183 unsigned char cmdstr[5];
03184
03185 memset(cmdstr, 0, 5);
03186
03187 switch(offset){
03188 case REM_SIMPLEX:
03189 cmdstr[0] = 0x89;
03190 break;
03191
03192 case REM_MINUS:
03193 cmdstr[0] = 0x09;
03194 break;
03195
03196 case REM_PLUS:
03197 cmdstr[0] = 0x49;
03198 break;
03199
03200 default:
03201 return -1;
03202 }
03203
03204 cmdstr[4] = 0x09;
03205
03206 return serial_remote_io(myrpt, cmdstr, 5, NULL, 0, 0);
03207 }
03208
03209
03210
03211 static int set_mode_ft897(struct rpt *myrpt, char newmode)
03212 {
03213 unsigned char cmdstr[5];
03214
03215 memset(cmdstr, 0, 5);
03216
03217 switch(newmode){
03218 case REM_MODE_FM:
03219 cmdstr[0] = 0x08;
03220 break;
03221
03222 case REM_MODE_USB:
03223 cmdstr[0] = 0x01;
03224 break;
03225
03226 case REM_MODE_LSB:
03227 cmdstr[0] = 0x00;
03228 break;
03229
03230 case REM_MODE_AM:
03231 cmdstr[0] = 0x04;
03232 break;
03233
03234 default:
03235 return -1;
03236 }
03237 cmdstr[4] = 0x07;
03238
03239 return serial_remote_io(myrpt, cmdstr, 5, NULL, 0, 0);
03240 }
03241
03242
03243
03244 static int set_ctcss_mode_ft897(struct rpt *myrpt, char txplon, char rxplon)
03245 {
03246 unsigned char cmdstr[5];
03247
03248 memset(cmdstr, 0, 5);
03249
03250 if(rxplon && txplon)
03251 cmdstr[0] = 0x2A;
03252 else if (!rxplon && txplon)
03253 cmdstr[0] = 0x4A;
03254 else if (rxplon && !txplon)
03255 cmdstr[0] = 0x3A;
03256 else
03257 cmdstr[0] = 0x8A;
03258
03259 cmdstr[4] = 0x0A;
03260
03261 return serial_remote_io(myrpt, cmdstr, 5, NULL, 0, 0);
03262 }
03263
03264
03265
03266
03267 static int set_ctcss_freq_ft897(struct rpt *myrpt, char *txtone, char *rxtone)
03268 {
03269 unsigned char cmdstr[5];
03270 char hertz[MAXREMSTR],decimal[MAXREMSTR];
03271 int h,d;
03272
03273 memset(cmdstr, 0, 5);
03274
03275 if(split_ctcss_freq(hertz, decimal, txtone))
03276 return -1;
03277
03278 h = atoi(hertz);
03279 d = atoi(decimal);
03280
03281 cmdstr[0] = ((h / 100) << 4) + (h % 100)/ 10;
03282 cmdstr[1] = ((h % 10) << 4) + (d % 10);
03283
03284 if(rxtone){
03285
03286 if(split_ctcss_freq(hertz, decimal, rxtone))
03287 return -1;
03288
03289 h = atoi(hertz);
03290 d = atoi(decimal);
03291
03292 cmdstr[2] = ((h / 100) << 4) + (h % 100)/ 10;
03293 cmdstr[3] = ((h % 10) << 4) + (d % 10);
03294 }
03295 cmdstr[4] = 0x0B;
03296
03297 return serial_remote_io(myrpt, cmdstr, 5, NULL, 0, 0);
03298 }
03299
03300
03301
03302 static int set_ft897(struct rpt *myrpt)
03303 {
03304 int res;
03305
03306 if(debug)
03307 printf("@@@@ lock on\n");
03308
03309 res = simple_command_ft897(myrpt, 0x00);
03310
03311 if(debug)
03312 printf("@@@@ ptt off\n");
03313
03314 if(!res)
03315 res = simple_command_ft897(myrpt, 0x88);
03316
03317 if(debug)
03318 printf("Modulation mode\n");
03319
03320 if(!res)
03321 res = set_mode_ft897(myrpt, myrpt->remmode);
03322
03323 if(debug)
03324 printf("Split off\n");
03325
03326 if(!res)
03327 simple_command_ft897(myrpt, 0x82);
03328
03329 if(debug)
03330 printf("Frequency\n");
03331
03332 if(!res)
03333 res = set_freq_ft897(myrpt, myrpt->freq);
03334 if((myrpt->remmode == REM_MODE_FM)){
03335 if(debug)
03336 printf("Offset\n");
03337 if(!res)
03338 res = set_offset_ft897(myrpt, myrpt->offset);
03339 if((!res)&&(myrpt->rxplon || myrpt->txplon)){
03340 if(debug)
03341 printf("CTCSS tone freqs.\n");
03342 res = set_ctcss_freq_ft897(myrpt, myrpt->txpl, myrpt->rxpl);
03343 }
03344 if(!res){
03345 if(debug)
03346 printf("CTCSS mode\n");
03347 res = set_ctcss_mode_ft897(myrpt, myrpt->txplon, myrpt->rxplon);
03348 }
03349 }
03350 if((myrpt->remmode == REM_MODE_USB)||(myrpt->remmode == REM_MODE_LSB)){
03351 if(debug)
03352 printf("Clarifier off\n");
03353 simple_command_ft897(myrpt, 0x85);
03354 }
03355 return res;
03356 }
03357
03358 static int closerem_ft897(struct rpt *myrpt)
03359 {
03360 simple_command_ft897(myrpt, 0x88);
03361 return 0;
03362 }
03363
03364
03365
03366
03367
03368
03369
03370 static int multimode_bump_freq_ft897(struct rpt *myrpt, int interval)
03371 {
03372 int m,d;
03373 char mhz[MAXREMSTR], decimals[MAXREMSTR];
03374
03375 if(debug)
03376 printf("Before bump: %s\n", myrpt->freq);
03377
03378 if(split_freq(mhz, decimals, myrpt->freq))
03379 return -1;
03380
03381 m = atoi(mhz);
03382 d = atoi(decimals);
03383
03384 d += (interval / 10);
03385 if(d < 0){
03386 m--;
03387 d += 100000;
03388 }
03389 else if(d >= 100000){
03390 m++;
03391 d -= 100000;
03392 }
03393
03394 if(check_freq_ft897(m, d, NULL)){
03395 if(debug)
03396 printf("Bump freq invalid\n");
03397 return -1;
03398 }
03399
03400 snprintf(myrpt->freq, MAXREMSTR, "%d.%05d", m, d);
03401
03402 if(debug)
03403 printf("After bump: %s\n", myrpt->freq);
03404
03405 return set_freq_ft897(myrpt, myrpt->freq);
03406 }
03407
03408
03409
03410
03411
03412
03413
03414 static int setrem(struct rpt *myrpt)
03415 {
03416 if(!strcmp(myrpt->remote, remote_rig_ft897))
03417 return set_ft897(myrpt);
03418 else if(!strcmp(myrpt->remote, remote_rig_rbi))
03419 return setrbi(myrpt);
03420 else
03421 return -1;
03422 }
03423
03424 static int closerem(struct rpt *myrpt)
03425 {
03426 if(!strcmp(myrpt->remote, remote_rig_ft897))
03427 return closerem_ft897(myrpt);
03428 else
03429 return 0;
03430 }
03431
03432
03433
03434
03435
03436 static int check_freq(struct rpt *myrpt, int m, int d, int *defmode)
03437 {
03438 if(!strcmp(myrpt->remote, remote_rig_ft897))
03439 return check_freq_ft897(m, d, defmode);
03440 else if(!strcmp(myrpt->remote, remote_rig_rbi))
03441 return check_freq_rbi(m, d, defmode);
03442 else
03443 return -1;
03444 }
03445
03446
03447
03448
03449
03450 static int multimode_capable(struct rpt *myrpt)
03451 {
03452 if(!strcmp(myrpt->remote, remote_rig_ft897))
03453 return 1;
03454 return 0;
03455 }
03456
03457
03458
03459
03460
03461 static int multimode_bump_freq(struct rpt *myrpt, int interval)
03462 {
03463 if(!strcmp(myrpt->remote, remote_rig_ft897))
03464 return multimode_bump_freq_ft897(myrpt, interval);
03465 else
03466 return -1;
03467 }
03468
03469
03470
03471
03472
03473
03474 static void stop_scan(struct rpt *myrpt, int flag)
03475 {
03476 myrpt->hfscanmode = 0;
03477 myrpt->hfscanstatus = ((flag) ? -2 : -1);
03478 }
03479
03480
03481
03482
03483
03484
03485 static int service_scan(struct rpt *myrpt)
03486 {
03487 int res, interval;
03488 char mhz[MAXREMSTR], decimals[MAXREMSTR], k10=0i, k100=0;
03489
03490 switch(myrpt->hfscanmode){
03491
03492 case HF_SCAN_DOWN_SLOW:
03493 interval = -10;
03494 break;
03495
03496 case HF_SCAN_DOWN_QUICK:
03497 interval = -50;
03498 break;
03499
03500 case HF_SCAN_DOWN_FAST:
03501 interval = -200;
03502 break;
03503
03504 case HF_SCAN_UP_SLOW:
03505 interval = 10;
03506 break;
03507
03508 case HF_SCAN_UP_QUICK:
03509 interval = 50;
03510 break;
03511
03512 case HF_SCAN_UP_FAST:
03513 interval = 200;
03514 break;
03515
03516 default:
03517 myrpt->hfscanmode = 0;
03518 return -1;
03519 }
03520
03521 res = split_freq(mhz, decimals, myrpt->freq);
03522
03523 if(!res){
03524 k100 =decimals[0];
03525 k10 = decimals[1];
03526 res = multimode_bump_freq(myrpt, interval);
03527 }
03528
03529 if(!res)
03530 res = split_freq(mhz, decimals, myrpt->freq);
03531
03532
03533 if(res){
03534 stop_scan(myrpt,1);
03535 return -1;
03536 }
03537
03538
03539 if(k10 != decimals[1]){
03540 int myhund = (interval < 0) ? k100 : decimals[0];
03541 int myten = (interval < 0) ? k10 : decimals[1];
03542 myrpt->hfscanstatus = (myten == '0') ? (myhund - '0') * 100 : (myten - '0') * 10;
03543 }
03544 return res;
03545
03546 }
03547
03548
03549 static int rmt_telem_start(struct rpt *myrpt, struct ast_channel *chan, int delay)
03550 {
03551 myrpt->remotetx = 0;
03552 ast_indicate(myrpt->txchannel,AST_CONTROL_RADIO_UNKEY);
03553 if (!myrpt->remoterx)
03554 ast_indicate(chan,AST_CONTROL_RADIO_KEY);
03555 if (ast_safe_sleep(chan, delay) == -1)
03556 return -1;
03557 return 0;
03558 }
03559
03560
03561 static int rmt_telem_finish(struct rpt *myrpt, struct ast_channel *chan)
03562 {
03563
03564 struct zt_params par;
03565
03566 if (ioctl(myrpt->txchannel->fds[0],ZT_GET_PARAMS,&par) == -1)
03567 {
03568 return -1;
03569
03570 }
03571 if (!par.rxisoffhook)
03572 {
03573 ast_indicate(myrpt->remchannel,AST_CONTROL_RADIO_UNKEY);
03574 myrpt->remoterx = 0;
03575 }
03576 else
03577 {
03578 myrpt->remoterx = 1;
03579 }
03580 return 0;
03581 }
03582
03583
03584 static int rmt_sayfile(struct rpt *myrpt, struct ast_channel *chan, int delay, char *filename)
03585 {
03586 int res;
03587
03588 res = rmt_telem_start(myrpt, chan, delay);
03589
03590 if(!res)
03591 res = sayfile(chan, filename);
03592
03593 if(!res)
03594 res = rmt_telem_finish(myrpt, chan);
03595 return res;
03596 }
03597
03598 static int rmt_saycharstr(struct rpt *myrpt, struct ast_channel *chan, int delay, char *charstr)
03599 {
03600 int res;
03601
03602 res = rmt_telem_start(myrpt, chan, delay);
03603
03604 if(!res)
03605 res = saycharstr(chan, charstr);
03606
03607 if(!res)
03608 res = rmt_telem_finish(myrpt, chan);
03609 return res;
03610 }
03611
03612
03613
03614
03615
03616
03617
03618 static int function_remote(struct rpt *myrpt, char *param, char *digitbuf, int command_source, struct rpt_link *mylink)
03619 {
03620 char *s,*s1,*s2,*val;
03621 int i,j,ht,k,l,ls2,m,d,res,offset,offsave, modesave, defmode;
03622 char multimode = 0;
03623 char oc;
03624 char tmp[20], freq[20] = "", savestr[20] = "";
03625 char mhz[MAXREMSTR], decimals[MAXREMSTR];
03626 struct ast_channel *mychannel;
03627
03628 if((!param) || (command_source == SOURCE_RPT) || (command_source == SOURCE_LNK))
03629 return DC_ERROR;
03630
03631 multimode = multimode_capable(myrpt);
03632
03633 mychannel = myrpt->remchannel;
03634
03635
03636 switch(myatoi(param)){
03637
03638 case 1:
03639 if(strlen(digitbuf) < 2)
03640 break;
03641
03642 for(i = 0 ; i < 2 ; i++){
03643 if((digitbuf[i] < '0') || (digitbuf[i] > '9'))
03644 return DC_ERROR;
03645 }
03646
03647 val = ast_variable_retrieve(cfg, MEMORY, digitbuf);
03648 if (!val){
03649 if (ast_safe_sleep(mychannel,1000) == -1)
03650 return DC_ERROR;
03651 sayfile(mychannel,"rpt/memory_notfound");
03652 return DC_COMPLETE;
03653 }
03654 strncpy(tmp,val,sizeof(tmp) - 1);
03655 s = strchr(tmp,',');
03656 if (!s)
03657 return DC_ERROR;
03658 *s++ = 0;
03659 s1 = strchr(s,',');
03660 if (!s1)
03661 return DC_ERROR;
03662 *s1++ = 0;
03663 strncpy(myrpt->freq, tmp, sizeof(myrpt->freq) - 1);
03664 strncpy(myrpt->rxpl, s, sizeof(myrpt->rxpl) - 1);
03665 strncpy(myrpt->txpl, s, sizeof(myrpt->rxpl) - 1);
03666 myrpt->remmode = REM_MODE_FM;
03667 myrpt->offset = REM_SIMPLEX;
03668 myrpt->powerlevel = REM_MEDPWR;
03669 myrpt->txplon = myrpt->rxplon = 0;
03670 while(*s1)
03671 {
03672 switch(*s1++){
03673 case 'A':
03674 case 'a':
03675 strcpy(myrpt->rxpl, "100.0");
03676 strcpy(myrpt->txpl, "100.0");
03677 myrpt->remmode = REM_MODE_AM;
03678 break;
03679
03680 case 'B':
03681 case 'b':
03682 strcpy(myrpt->rxpl, "100.0");
03683 strcpy(myrpt->txpl, "100.0");
03684 myrpt->remmode = REM_MODE_LSB;
03685 break;
03686
03687 case 'F':
03688 myrpt->remmode = REM_MODE_FM;
03689 break;
03690
03691 case 'L':
03692 case 'l':
03693 myrpt->powerlevel = REM_LOWPWR;
03694 break;
03695 case 'H':
03696 case 'h':
03697 myrpt->powerlevel = REM_HIPWR;
03698 break;
03699
03700 case 'M':
03701 case 'm':
03702 myrpt->powerlevel = REM_MEDPWR;
03703 break;
03704
03705 case '-':
03706 myrpt->offset = REM_MINUS;
03707 break;
03708
03709 case '+':
03710 myrpt->offset = REM_PLUS;
03711 break;
03712
03713 case 'S':
03714 case 's':
03715 myrpt->offset = REM_SIMPLEX;
03716 break;
03717
03718 case 'T':
03719 case 't':
03720 myrpt->txplon = 1;
03721 break;
03722
03723 case 'R':
03724 case 'r':
03725 myrpt->rxplon = 1;
03726 break;
03727
03728 case 'U':
03729 case 'u':
03730 strcpy(myrpt->rxpl, "100.0");
03731 strcpy(myrpt->txpl, "100.0");
03732 myrpt->remmode = REM_MODE_USB;
03733 break;
03734 }
03735 }
03736
03737
03738 if (setrem(myrpt) == -1)
03739 return DC_ERROR;
03740
03741
03742 return DC_COMPLETE;
03743
03744 case 2:
03745
03746
03747 for(i = 0, j = 0, k = 0, l = 0 ; digitbuf[i] ; i++){
03748 if(digitbuf[i] == '*'){
03749 j++;
03750 continue;
03751 }
03752 if((digitbuf[i] < '0') || (digitbuf[i] > '9'))
03753 goto invalid_freq;
03754 else{
03755 if(j == 0)
03756 l++;
03757 if(j == 1)
03758 k++;
03759 }
03760 }
03761
03762 i = strlen(digitbuf) - 1;
03763 if(multimode){
03764 if((j > 2) || (l > 3) || (k > 6))
03765 goto invalid_freq;
03766 }
03767 else{
03768 if((j > 2) || (l > 4) || (k > 3))
03769 goto invalid_freq;
03770 }
03771
03772
03773
03774 if(j < 2)
03775 break;
03776
03777
03778
03779 strncpy(tmp, digitbuf ,sizeof(tmp) - 1);
03780
03781 s = tmp;
03782 s1 = strsep(&s, "*");
03783 s2 = strsep(&s,"*");
03784 ls2 = strlen(s2);
03785
03786 switch(ls2){
03787 case 1:
03788 ht = 0;
03789 k = 100 * atoi(s2);
03790 break;
03791
03792 case 2:
03793 ht = 0;
03794 k = 10 * atoi(s2);
03795 break;
03796
03797 case 3:
03798 if(!multimode){
03799 if((s2[2] != '0')&&(s2[2] != '5'))
03800 goto invalid_freq;
03801 }
03802 ht = 0;
03803 k = atoi(s2);
03804 break;
03805 case 4:
03806 k = atoi(s2)/10;
03807 ht = 10 * (atoi(s2+(ls2-1)));
03808 break;
03809
03810 case 5:
03811 k = atoi(s2)/100;
03812 ht = (atoi(s2+(ls2-2)));
03813 break;
03814
03815 default:
03816 goto invalid_freq;
03817 }
03818
03819
03820
03821 snprintf(freq, sizeof(freq), "%s.%03d%02d",s1, k, ht);
03822
03823 if(debug)
03824 printf("New frequency: %s\n", freq);
03825
03826 split_freq(mhz, decimals, freq);
03827 m = atoi(mhz);
03828 d = atoi(decimals);
03829
03830 if(check_freq(myrpt, m, d, &defmode))
03831 goto invalid_freq;
03832
03833
03834 if((defmode == REM_MODE_FM) && (digitbuf[i] == '*'))
03835 break;
03836
03837
03838 offset = REM_SIMPLEX;
03839
03840 if(defmode == REM_MODE_FM){
03841 oc = *s;
03842
03843 if (oc){
03844 switch(oc){
03845 case '1':
03846 offset = REM_MINUS;
03847 break;
03848
03849 case '2':
03850 offset = REM_SIMPLEX;
03851 break;
03852
03853 case '3':
03854 offset = REM_PLUS;
03855 break;
03856
03857 default:
03858 goto invalid_freq;
03859 }
03860 }
03861 }
03862 offsave = myrpt->offset;
03863 modesave = myrpt->remmode;
03864 strncpy(savestr, myrpt->freq, sizeof(savestr) - 1);
03865 strncpy(myrpt->freq, freq, sizeof(myrpt->freq) - 1);
03866 myrpt->offset = offset;
03867 myrpt->remmode = defmode;
03868
03869 if (setrem(myrpt) == -1){
03870 myrpt->offset = offsave;
03871 myrpt->remmode = modesave;
03872 strncpy(myrpt->freq, savestr, sizeof(myrpt->freq) - 1);
03873 goto invalid_freq;
03874 }
03875
03876 return DC_COMPLETE;
03877
03878
03879 invalid_freq:
03880
03881 rmt_sayfile(myrpt, mychannel, 1000, "rpt/invalid-freq");
03882
03883 return DC_ERROR;
03884
03885 case 3:
03886
03887 for(i = 0, j = 0, k = 0, l = 0 ; digitbuf[i] ; i++){
03888 if(digitbuf[i] == '*'){
03889 j++;
03890 continue;
03891 }
03892 if((digitbuf[i] < '0') || (digitbuf[i] > '9'))
03893 return DC_ERROR;
03894 else{
03895 if(j)
03896 l++;
03897 else
03898 k++;
03899 }
03900 }
03901 if((j > 1) || (k > 3) || (l > 1))
03902 return DC_ERROR;
03903 i = strlen(digitbuf) - 1;
03904 if((j != 1) || (k < 2)|| (l != 1))
03905 break;
03906 if(debug)
03907 printf("PL digits entered %s\n", digitbuf);
03908
03909 strncpy(tmp, digitbuf, sizeof(tmp) - 1);
03910
03911 s = strchr(tmp,'*');
03912 if(s)
03913 *s = '.';
03914 strncpy(savestr, myrpt->rxpl, sizeof(savestr) - 1);
03915 strncpy(myrpt->rxpl, tmp, sizeof(myrpt->rxpl) - 1);
03916
03917 if (setrem(myrpt) == -1){
03918 strncpy(myrpt->rxpl, savestr, sizeof(myrpt->rxpl) - 1);
03919 return DC_ERROR;
03920 }
03921
03922
03923 return DC_COMPLETE;
03924
03925 case 4:
03926
03927 for(i = 0, j = 0, k = 0, l = 0 ; digitbuf[i] ; i++){
03928 if(digitbuf[i] == '*'){
03929 j++;
03930 continue;
03931 }
03932 if((digitbuf[i] < '0') || (digitbuf[i] > '9'))
03933 return DC_ERROR;
03934 else{
03935 if(j)
03936 l++;
03937 else
03938 k++;
03939 }
03940 }
03941 if((j > 1) || (k > 3) || (l > 1))
03942 return DC_ERROR;
03943 i = strlen(digitbuf) - 1;
03944 if((j != 1) || (k < 2)|| (l != 1))
03945 break;
03946 if(debug)
03947 printf("PL digits entered %s\n", digitbuf);
03948
03949 strncpy(tmp, digitbuf, sizeof(tmp) - 1);
03950
03951 s = strchr(tmp,'*');
03952 if(s)
03953 *s = '.';
03954 strncpy(savestr, myrpt->txpl, sizeof(savestr) - 1);
03955 strncpy(myrpt->txpl, tmp, sizeof(myrpt->txpl) - 1);
03956
03957 if (setrem(myrpt) == -1){
03958 strncpy(myrpt->txpl, savestr, sizeof(myrpt->txpl) - 1);
03959 return DC_ERROR;
03960 }
03961
03962
03963 return DC_COMPLETE;
03964
03965
03966 case 6:
03967 if(strlen(digitbuf) < 1)
03968 break;
03969
03970 if(!multimode)
03971 return DC_ERROR;
03972
03973 switch(*digitbuf){
03974 case '1':
03975 split_freq(mhz, decimals, myrpt->freq);
03976 m=atoi(mhz);
03977 if(m < 29)
03978 return DC_ERROR;
03979 myrpt->remmode = REM_MODE_FM;
03980 res = rmt_saycharstr(myrpt, mychannel, 1000,"FM");
03981 break;
03982
03983 case '2':
03984 myrpt->remmode = REM_MODE_USB;
03985 res = rmt_saycharstr(myrpt, mychannel, 1000,"USB");
03986 break;
03987
03988 case '3':
03989 myrpt->remmode = REM_MODE_LSB;
03990 res = rmt_saycharstr(myrpt, mychannel, 1000,"LSB");
03991 break;
03992
03993 case '4':
03994 myrpt->remmode = REM_MODE_AM;
03995 res = rmt_saycharstr(myrpt, mychannel, 1000,"AM");
03996 break;
03997
03998 default:
03999 return DC_ERROR;
04000 }
04001 if(res)
04002 return DC_ERROR;
04003
04004 if(setrem(myrpt))
04005 return DC_ERROR;
04006 return DC_COMPLETE;
04007
04008 case 100:
04009 case 101:
04010 case 102:
04011 case 103:
04012 case 104:
04013 case 105:
04014 case 106:
04015 res = rmt_telem_start(myrpt, mychannel, 1000);
04016 switch(myatoi(param)){
04017 case 100:
04018 myrpt->rxplon = 0;
04019 if(!res)
04020 res = sayfile(mychannel, "rpt/rxpl");
04021 if(!res)
04022 sayfile(mychannel, "rpt/off");
04023 break;
04024
04025 case 101:
04026 myrpt->rxplon = 1;
04027 if(!res)
04028 res = sayfile(mychannel, "rpt/rxpl");
04029 if(!res)
04030 sayfile(mychannel, "rpt/on");
04031 break;
04032
04033
04034 case 102:
04035 myrpt->txplon = 0;
04036 if(!res)
04037 res = sayfile(mychannel, "rpt/txpl");
04038 if(!res)
04039 sayfile(mychannel, "rpt/off");
04040 break;
04041
04042 case 103:
04043 myrpt->txplon = 1;
04044 if(!res)
04045 res = sayfile(mychannel, "rpt/txpl");
04046 if(!res)
04047 sayfile(mychannel, "rpt/on");
04048 break;
04049
04050 case 104:
04051 myrpt->powerlevel = REM_LOWPWR;
04052 if(!res)
04053 res = sayfile(mychannel, "rpt/lopwr");
04054 break;
04055
04056 case 105:
04057 myrpt->powerlevel = REM_MEDPWR;
04058 if(!res)
04059 res = sayfile(mychannel, "rpt/medpwr");
04060 break;
04061
04062 case 106:
04063 myrpt->powerlevel = REM_HIPWR;
04064 if(!res)
04065 res = sayfile(mychannel, "rpt/hipwr");
04066 break;
04067
04068 default:
04069 if(!res)
04070 rmt_telem_finish(myrpt, mychannel);
04071 return DC_ERROR;
04072 }
04073 if(!res)
04074 res = rmt_telem_finish(myrpt, mychannel);
04075 if(res)
04076 return DC_ERROR;
04077
04078 if (setrem(myrpt) == -1)
04079 return DC_ERROR;
04080 return DC_COMPLETE;
04081
04082 case 107:
04083 multimode_bump_freq(myrpt, -20);
04084 return DC_COMPLETE;
04085
04086 case 108:
04087 multimode_bump_freq(myrpt, -100);
04088 return DC_COMPLETE;
04089
04090 case 109:
04091 multimode_bump_freq(myrpt, -500);
04092 return DC_COMPLETE;
04093
04094 case 110:
04095 multimode_bump_freq(myrpt, 20);
04096 return DC_COMPLETE;
04097
04098 case 111:
04099 multimode_bump_freq(myrpt, 100);
04100 return DC_COMPLETE;
04101
04102 case 112:
04103 multimode_bump_freq(myrpt, 500);
04104 return DC_COMPLETE;
04105
04106
04107 case 113:
04108 case 114:
04109 case 115:
04110 case 116:
04111 case 117:
04112 case 118:
04113 myrpt->remotetx = 0;
04114 ast_indicate(myrpt->txchannel,AST_CONTROL_RADIO_UNKEY);
04115 if (!myrpt->remoterx)
04116 ast_indicate(mychannel,AST_CONTROL_RADIO_KEY);
04117 if (ast_safe_sleep(mychannel,1000) == -1)
04118 return DC_ERROR;
04119
04120 switch(myatoi(param)){
04121
04122 case 113:
04123 res = sayfile(mychannel,"rpt/down");
04124 if(!res)
04125 res = sayfile(mychannel, "rpt/slow");
04126 if(!res){
04127 myrpt->scantimer = REM_SCANTIME;
04128 myrpt->hfscanmode = HF_SCAN_DOWN_SLOW;
04129 }
04130 break;
04131
04132 case 114:
04133 res = sayfile(mychannel,"rpt/down");
04134 if(!res)
04135 res = sayfile(mychannel, "rpt/quick");
04136 if(!res){
04137 myrpt->scantimer = REM_SCANTIME;
04138 myrpt->hfscanmode = HF_SCAN_DOWN_QUICK;
04139 }
04140 break;
04141
04142 case 115:
04143 res = sayfile(mychannel,"rpt/down");
04144 if(!res)
04145 res = sayfile(mychannel, "rpt/fast");
04146 if(!res){
04147 myrpt->scantimer = REM_SCANTIME;
04148 myrpt->hfscanmode = HF_SCAN_DOWN_FAST;
04149 }
04150 break;
04151
04152 case 116:
04153 res = sayfile(mychannel,"rpt/up");
04154 if(!res)
04155 res = sayfile(mychannel, "rpt/slow");
04156 if(!res){
04157 myrpt->scantimer = REM_SCANTIME;
04158 myrpt->hfscanmode = HF_SCAN_UP_SLOW;
04159 }
04160 break;
04161
04162 case 117:
04163 res = sayfile(mychannel,"rpt/up");
04164 if(!res)
04165 res = sayfile(mychannel, "rpt/quick");
04166 if(!res){
04167 myrpt->scantimer = REM_SCANTIME;
04168 myrpt->hfscanmode = HF_SCAN_UP_QUICK;
04169 }
04170 break;
04171
04172 case 118:
04173 res = sayfile(mychannel,"rpt/up");
04174 if(!res)
04175 res = sayfile(mychannel, "rpt/fast");
04176 if(!res){
04177 myrpt->scantimer = REM_SCANTIME;
04178 myrpt->hfscanmode = HF_SCAN_UP_FAST;
04179 }
04180 break;
04181 }
04182 rmt_telem_finish(myrpt,mychannel);
04183 return DC_COMPLETE;
04184
04185
04186 case 119:
04187 myrpt->tunerequest = 1;
04188 return DC_COMPLETE;
04189
04190 case 5:
04191 case 140:
04192 res = rmt_telem_start(myrpt, mychannel, 1000);
04193
04194 res = sayfile(mychannel,"rpt/node");
04195 if(!res)
04196 res = saycharstr(mychannel, myrpt->name);
04197 if(!res)
04198 res = sayfile(mychannel,"rpt/frequency");
04199 if(!res)
04200 res = split_freq(mhz, decimals, myrpt->freq);
04201 if(!res){
04202 m = atoi(mhz);
04203 if(m < 100)
04204 res = saynum(mychannel, m);
04205 else
04206 res = saycharstr(mychannel, mhz);
04207 }
04208 if(!res)
04209 res = sayfile(mychannel, "letters/dot");
04210 if(!res)
04211 res = saycharstr(mychannel, decimals);
04212
04213 if(res){
04214 rmt_telem_finish(myrpt,mychannel);
04215 return DC_ERROR;
04216 }
04217 if(myrpt->remmode == REM_MODE_FM){
04218 switch(myrpt->offset){
04219
04220 case REM_MINUS:
04221 res = sayfile(mychannel,"rpt/minus");
04222 break;
04223
04224 case REM_SIMPLEX:
04225 res = sayfile(mychannel,"rpt/simplex");
04226 break;
04227
04228 case REM_PLUS:
04229 res = sayfile(mychannel,"rpt/plus");
04230 break;
04231
04232 default:
04233 return DC_ERROR;
04234
04235 }
04236 }
04237 else{
04238 switch(myrpt->remmode){
04239
04240 case REM_MODE_USB:
04241 res = saycharstr(mychannel, "USB");
04242 break;
04243
04244 case REM_MODE_LSB:
04245 res = saycharstr(mychannel, "LSB");
04246 break;
04247
04248 case REM_MODE_AM:
04249 res = saycharstr(mychannel, "AM");
04250 break;
04251
04252
04253 default:
04254 return DC_ERROR;
04255 }
04256 }
04257
04258 if (res == -1){
04259 rmt_telem_finish(myrpt,mychannel);
04260 return DC_ERROR;
04261 }
04262
04263 if(myatoi(param) == 140){
04264 if(!res)
04265 res = rmt_telem_finish(myrpt, mychannel);
04266 if(res)
04267 return DC_ERROR;
04268 return DC_COMPLETE;
04269 }
04270
04271 switch(myrpt->powerlevel){
04272
04273 case REM_LOWPWR:
04274 res = sayfile(mychannel,"rpt/lopwr") ;
04275 break;
04276
04277 case REM_MEDPWR:
04278 res = sayfile(mychannel,"rpt/medpwr");
04279 break;
04280 case REM_HIPWR:
04281 res = sayfile(mychannel,"rpt/hipwr");
04282 break;
04283 }
04284 if (res || (sayfile(mychannel,"rpt/rxpl") == -1) ||
04285 (sayfile(mychannel,"rpt/frequency") == -1) ||
04286 (saycharstr(mychannel,myrpt->rxpl) == -1) ||
04287 (sayfile(mychannel,"rpt/txpl") == -1) ||
04288 (sayfile(mychannel,"rpt/frequency") == -1) ||
04289 (saycharstr(mychannel,myrpt->txpl) == -1) ||
04290 (sayfile(mychannel,"rpt/txpl") == -1) ||
04291 (sayfile(mychannel,((myrpt->txplon) ? "rpt/on" : "rpt/off")) == -1) ||
04292 (sayfile(mychannel,"rpt/rxpl") == -1) ||
04293 (sayfile(mychannel,((myrpt->rxplon) ? "rpt/on" : "rpt/off")) == -1))
04294 {
04295 rmt_telem_finish(myrpt,mychannel);
04296 return DC_ERROR;
04297 }
04298 if(!res)
04299 res = rmt_telem_finish(myrpt,mychannel);
04300 if(res)
04301 return DC_ERROR;
04302
04303 return DC_COMPLETE;
04304 default:
04305 return DC_ERROR;
04306 }
04307
04308 return DC_INDETERMINATE;
04309 }
04310
04311 static int handle_remote_dtmf_digit(struct rpt *myrpt,char c, char *keyed, int phonemode)
04312 {
04313 time_t now;
04314 int ret,res = 0,src;
04315
04316
04317 if(myrpt->hfscanmode){
04318 stop_scan(myrpt,0);
04319 return 0;
04320 }
04321
04322 time(&now);
04323
04324 if ((myrpt->dtmf_time_rem + DTMF_TIMEOUT) < now)
04325 {
04326 myrpt->dtmfidx = -1;
04327 myrpt->dtmfbuf[0] = 0;
04328 myrpt->dtmf_time_rem = 0;
04329 }
04330
04331 if (myrpt->dtmfidx == -1)
04332 {
04333
04334 if (c != myrpt->funcchar) return 0;
04335 myrpt->dtmfidx = 0;
04336 myrpt->dtmfbuf[0] = 0;
04337 myrpt->dtmf_time_rem = now;
04338 return 0;
04339 }
04340
04341 if (myrpt->dtmfidx >= MAXDTMF)
04342 {
04343 myrpt->dtmfidx = 0;
04344 myrpt->dtmfbuf[0] = 0;
04345 myrpt->dtmf_time_rem = now;
04346 }
04347 if (c == myrpt->funcchar)
04348 {
04349
04350 if ((myrpt->dtmfidx < 1) ||
04351 (myrpt->dtmfbuf[myrpt->dtmfidx - 1] == myrpt->funcchar))
04352 {
04353 myrpt->dtmfidx = 0;
04354 myrpt->dtmfbuf[0] = 0;
04355 myrpt->dtmf_time_rem = now;
04356 return 0;
04357 }
04358 }
04359 myrpt->dtmfbuf[myrpt->dtmfidx++] = c;
04360 myrpt->dtmfbuf[myrpt->dtmfidx] = 0;
04361 myrpt->dtmf_time_rem = now;
04362
04363
04364 src = SOURCE_RMT;
04365 if (phonemode > 1) src = SOURCE_DPHONE;
04366 else if (phonemode) src = SOURCE_PHONE;
04367 ret = collect_function_digits(myrpt, myrpt->dtmfbuf, src, NULL);
04368
04369 switch(ret){
04370
04371 case DC_INDETERMINATE:
04372 res = 0;
04373 break;
04374
04375 case DC_DOKEY:
04376 if (keyed) *keyed = 1;
04377 res = 0;
04378 break;
04379
04380 case DC_REQ_FLUSH:
04381 myrpt->dtmfidx = 0;
04382 myrpt->dtmfbuf[0] = 0;
04383 res = 0;
04384 break;
04385
04386
04387 case DC_COMPLETE:
04388 myrpt->dtmfbuf[0] = 0;
04389 myrpt->dtmfidx = -1;
04390 myrpt->dtmf_time_rem = 0;
04391 res = 1;
04392 break;
04393
04394 case DC_ERROR:
04395 default:
04396 myrpt->dtmfbuf[0] = 0;
04397 myrpt->dtmfidx = -1;
04398 myrpt->dtmf_time_rem = 0;
04399 res = 0;
04400 break;
04401 }
04402
04403 return res;
04404 }
04405
04406 static int handle_remote_data(struct rpt *myrpt, char *str)
04407 {
04408 char tmp[300],cmd[300],dest[300],src[300],c;
04409 int seq,res;
04410
04411
04412 strncpy(tmp,str,sizeof(tmp) - 1);
04413 if (!strcmp(tmp,discstr)) return 0;
04414 if (sscanf(tmp,"%s %s %s %d %c",cmd,dest,src,&seq,&c) != 5)
04415 {
04416 ast_log(LOG_WARNING, "Unable to parse link string %s\n",str);
04417 return 0;
04418 }
04419 if (strcmp(cmd,"D"))
04420 {
04421 ast_log(LOG_WARNING, "Unable to parse link string %s\n",str);
04422 return 0;
04423 }
04424
04425 if (strcmp(dest,myrpt->name)) return 0;
04426 res = handle_remote_dtmf_digit(myrpt,c, NULL, 0);
04427 if (res != 1)
04428 return res;
04429 myrpt->remotetx = 0;
04430 ast_indicate(myrpt->txchannel,AST_CONTROL_RADIO_UNKEY);
04431 if (!myrpt->remoterx)
04432 {
04433 ast_indicate(myrpt->remchannel,AST_CONTROL_RADIO_KEY);
04434 }
04435 if (ast_safe_sleep(myrpt->remchannel,1000) == -1) return -1;
04436 res = telem_lookup(myrpt->remchannel, myrpt->name, "functcomplete");
04437 rmt_telem_finish(myrpt,myrpt->remchannel);
04438 return res;
04439 }
04440
04441 static int handle_remote_phone_dtmf(struct rpt *myrpt, char c, char *keyed, int phonemode)
04442 {
04443 int res;
04444
04445
04446 if (keyed && *keyed && (c == myrpt->endchar))
04447 {
04448 *keyed = 0;
04449 return DC_INDETERMINATE;
04450 }
04451
04452 res = handle_remote_dtmf_digit(myrpt,c,keyed, phonemode);
04453 if (res != 1)
04454 return res;
04455 myrpt->remotetx = 0;
04456 ast_indicate(myrpt->txchannel,AST_CONTROL_RADIO_UNKEY);
04457 if (!myrpt->remoterx)
04458 {
04459 ast_indicate(myrpt->remchannel,AST_CONTROL_RADIO_KEY);
04460 }
04461 if (ast_safe_sleep(myrpt->remchannel,1000) == -1) return -1;
04462 res = telem_lookup(myrpt->remchannel, myrpt->name, "functcomplete");
04463 rmt_telem_finish(myrpt,myrpt->remchannel);
04464 return res;
04465 }
04466
04467 static int attempt_reconnect(struct rpt *myrpt, struct rpt_link *l)
04468 {
04469 char *val, *s, *s1, *s2, *tele;
04470 char tmp[300], deststr[300] = "";
04471
04472 val = ast_variable_retrieve(cfg, myrpt->nodes, l->name);
04473 if (!val)
04474 {
04475 fprintf(stderr,"attempt_reconnect: cannot find node %s\n",l->name);
04476 return -1;
04477 }
04478
04479 ast_mutex_lock(&myrpt->lock);
04480
04481 remque((struct qelem *) l);
04482 ast_mutex_unlock(&myrpt->lock);
04483 strncpy(tmp,val,sizeof(tmp) - 1);
04484 s = tmp;
04485 s1 = strsep(&s,",");
04486 s2 = strsep(&s,",");
04487 snprintf(deststr, sizeof(deststr), "IAX2/%s", s1);
04488 tele = strchr(deststr, '/');
04489 if (!tele) {
04490 fprintf(stderr,"attempt_reconnect:Dial number (%s) must be in format tech/number\n",deststr);
04491 return -1;
04492 }
04493 *tele++ = 0;
04494 l->elaptime = 0;
04495 l->chan = ast_request(deststr, AST_FORMAT_SLINEAR, tele,NULL);
04496 if (l->chan){
04497 ast_set_read_format(l->chan, AST_FORMAT_SLINEAR);
04498 ast_set_write_format(l->chan, AST_FORMAT_SLINEAR);
04499 l->chan->whentohangup = 0;
04500 l->chan->appl = "Apprpt";
04501 l->chan->data = "(Remote Rx)";
04502 if (option_verbose > 2)
04503 ast_verbose(VERBOSE_PREFIX_3 "rpt (attempt_reconnect) initiating call to %s/%s on %s\n",
04504 deststr, tele, l->chan->name);
04505 if(l->chan->cid.cid_num)
04506 free(l->chan->cid.cid_num);
04507 l->chan->cid.cid_num = strdup(myrpt->name);
04508 ast_call(l->chan,tele,999);
04509
04510 }
04511 else
04512 {
04513 if (option_verbose > 2)
04514 ast_verbose(VERBOSE_PREFIX_3 "Unable to place call to %s/%s on %s\n",
04515 deststr,tele,l->chan->name);
04516 return -1;
04517 }
04518 ast_mutex_lock(&myrpt->lock);
04519
04520 insque((struct qelem *)l,(struct qelem *)myrpt->links.next);
04521 ast_mutex_unlock(&myrpt->lock);
04522 ast_log(LOG_NOTICE,"Reconnect Attempt to %s in process\n",l->name);
04523 return 0;
04524 }
04525
04526
04527 static void *rpt(void *this)
04528 {
04529 struct rpt *myrpt = (struct rpt *)this;
04530 char *tele,*idtalkover;
04531 int ms = MSWAIT,lasttx=0,val,remrx=0,identqueued,nonidentqueued,res;
04532 struct ast_channel *who;
04533 ZT_CONFINFO ci;
04534 time_t dtmf_time,t;
04535 struct rpt_link *l,*m;
04536 struct rpt_tele *telem;
04537 pthread_attr_t attr;
04538 char tmpstr[300];
04539 char cmd[MAXDTMF+1] = "";
04540
04541
04542 ast_mutex_lock(&myrpt->lock);
04543 strncpy(tmpstr,myrpt->rxchanname,sizeof(tmpstr) - 1);
04544 tele = strchr(tmpstr,'/');
04545 if (!tele)
04546 {
04547 fprintf(stderr,"rpt:Dial number (%s) must be in format tech/number\n",myrpt->rxchanname);
04548 ast_mutex_unlock(&myrpt->lock);
04549 myrpt->rpt_thread = AST_PTHREADT_STOP;
04550 pthread_exit(NULL);
04551 }
04552 *tele++ = 0;
04553 myrpt->rxchannel = ast_request(tmpstr,AST_FORMAT_SLINEAR,tele,NULL);
04554 if (myrpt->rxchannel)
04555 {
04556 if (myrpt->rxchannel->_state == AST_STATE_BUSY)
04557 {
04558 fprintf(stderr,"rpt:Sorry unable to obtain Rx channel\n");
04559 ast_mutex_unlock(&myrpt->lock);
04560 ast_hangup(myrpt->rxchannel);
04561 myrpt->rpt_thread = AST_PTHREADT_STOP;
04562 pthread_exit(NULL);
04563 }
04564 ast_set_read_format(myrpt->rxchannel,AST_FORMAT_SLINEAR);
04565 ast_set_write_format(myrpt->rxchannel,AST_FORMAT_SLINEAR);
04566 myrpt->rxchannel->whentohangup = 0;
04567 myrpt->rxchannel->appl = "Apprpt";
04568 myrpt->rxchannel->data = "(Repeater Rx)";
04569 if (option_verbose > 2)
04570 ast_verbose(VERBOSE_PREFIX_3 "rpt (Rx) initiating call to %s/%s on %s\n",
04571 tmpstr,tele,myrpt->rxchannel->name);
04572 ast_call(myrpt->rxchannel,tele,999);
04573 if (myrpt->rxchannel->_state != AST_STATE_UP)
04574 {
04575 ast_mutex_unlock(&myrpt->lock);
04576 ast_hangup(myrpt->rxchannel);
04577 myrpt->rpt_thread = AST_PTHREADT_STOP;
04578 pthread_exit(NULL);
04579 }
04580 }
04581 else
04582 {
04583 fprintf(stderr,"rpt:Sorry unable to obtain Rx channel\n");
04584 ast_mutex_unlock(&myrpt->lock);
04585 myrpt->rpt_thread = AST_PTHREADT_STOP;
04586 pthread_exit(NULL);
04587 }
04588 if (myrpt->txchanname)
04589 {
04590 strncpy(tmpstr,myrpt->txchanname,sizeof(tmpstr) - 1);
04591 tele = strchr(tmpstr,'/');
04592 if (!tele)
04593 {
04594 fprintf(stderr,"rpt:Dial number (%s) must be in format tech/number\n",myrpt->txchanname);
04595 ast_mutex_unlock(&myrpt->lock);
04596 ast_hangup(myrpt->rxchannel);
04597 myrpt->rpt_thread = AST_PTHREADT_STOP;
04598 pthread_exit(NULL);
04599 }
04600 *tele++ = 0;
04601 myrpt->txchannel = ast_request(tmpstr,AST_FORMAT_SLINEAR,tele,NULL);
04602 if (myrpt->txchannel)
04603 {
04604 if (myrpt->txchannel->_state == AST_STATE_BUSY)
04605 {
04606 fprintf(stderr,"rpt:Sorry unable to obtain Tx channel\n");
04607 ast_mutex_unlock(&myrpt->lock);
04608 ast_hangup(myrpt->txchannel);
04609 ast_hangup(myrpt->rxchannel);
04610 myrpt->rpt_thread = AST_PTHREADT_STOP;
04611 pthread_exit(NULL);
04612 }
04613 ast_set_read_format(myrpt->txchannel,AST_FORMAT_SLINEAR);
04614 ast_set_write_format(myrpt->txchannel,AST_FORMAT_SLINEAR);
04615 myrpt->txchannel->whentohangup = 0;
04616 myrpt->txchannel->appl = "Apprpt";
04617 myrpt->txchannel->data = "(Repeater Tx)";
04618 if (option_verbose > 2)
04619 ast_verbose(VERBOSE_PREFIX_3 "rpt (Tx) initiating call to %s/%s on %s\n",
04620 tmpstr,tele,myrpt->txchannel->name);
04621 ast_call(myrpt->txchannel,tele,999);
04622 if (myrpt->rxchannel->_state != AST_STATE_UP)
04623 {
04624 ast_mutex_unlock(&myrpt->lock);
04625 ast_hangup(myrpt->rxchannel);
04626 ast_hangup(myrpt->txchannel);
04627 myrpt->rpt_thread = AST_PTHREADT_STOP;
04628 pthread_exit(NULL);
04629 }
04630 }
04631 else
04632 {
04633 fprintf(stderr,"rpt:Sorry unable to obtain Tx channel\n");
04634 ast_mutex_unlock(&myrpt->lock);
04635 ast_hangup(myrpt->rxchannel);
04636 myrpt->rpt_thread = AST_PTHREADT_STOP;
04637 pthread_exit(NULL);
04638 }
04639 }
04640 else
04641 {
04642 myrpt->txchannel = myrpt->rxchannel;
04643 }
04644 ast_indicate(myrpt->txchannel,AST_CONTROL_RADIO_KEY);
04645 ast_indicate(myrpt->txchannel,AST_CONTROL_RADIO_UNKEY);
04646
04647 myrpt->pchannel = ast_request("zap",AST_FORMAT_SLINEAR,"pseudo",NULL);
04648 if (!myrpt->pchannel)
04649 {
04650 fprintf(stderr,"rpt:Sorry unable to obtain pseudo channel\n");
04651 ast_mutex_unlock(&myrpt->lock);
04652 if (myrpt->txchannel != myrpt->rxchannel)
04653 ast_hangup(myrpt->txchannel);
04654 ast_hangup(myrpt->rxchannel);
04655 myrpt->rpt_thread = AST_PTHREADT_STOP;
04656 pthread_exit(NULL);
04657 }
04658
04659 ci.chan = 0;
04660 ci.confno = -1;
04661 ci.confmode = ZT_CONF_CONF | ZT_CONF_LISTENER;
04662
04663 if (ioctl(myrpt->txchannel->fds[0],ZT_SETCONF,&ci) == -1)
04664 {
04665 ast_log(LOG_WARNING, "Unable to set conference mode to Announce\n");
04666 ast_mutex_unlock(&myrpt->lock);
04667 ast_hangup(myrpt->pchannel);
04668 if (myrpt->txchannel != myrpt->rxchannel)
04669 ast_hangup(myrpt->txchannel);
04670 ast_hangup(myrpt->rxchannel);
04671 myrpt->rpt_thread = AST_PTHREADT_STOP;
04672 pthread_exit(NULL);
04673 }
04674
04675 myrpt->txconf = ci.confno;
04676
04677 ci.chan = 0;
04678 ci.confno = -1;
04679 ci.confmode = ZT_CONF_CONFANNMON;
04680
04681 if (ioctl(myrpt->pchannel->fds[0],ZT_SETCONF,&ci) == -1)
04682 {
04683 ast_log(LOG_WARNING, "Unable to set conference mode to Announce\n");
04684 ast_mutex_unlock(&myrpt->lock);
04685 ast_hangup(myrpt->pchannel);
04686 if (myrpt->txchannel != myrpt->rxchannel)
04687 ast_hangup(myrpt->txchannel);
04688 ast_hangup(myrpt->rxchannel);
04689 myrpt->rpt_thread = AST_PTHREADT_STOP;
04690 pthread_exit(NULL);
04691 }
04692
04693 myrpt->conf = ci.confno;
04694
04695 myrpt->txpchannel = ast_request("zap",AST_FORMAT_SLINEAR,"pseudo",NULL);
04696 if (!myrpt->txpchannel)
04697 {
04698 fprintf(stderr,"rpt:Sorry unable to obtain pseudo channel\n");
04699 ast_mutex_unlock(&myrpt->lock);
04700 ast_hangup(myrpt->pchannel);
04701 if (myrpt->txchannel != myrpt->rxchannel)
04702 ast_hangup(myrpt->txchannel);
04703 ast_hangup(myrpt->rxchannel);
04704 myrpt->rpt_thread = AST_PTHREADT_STOP;
04705 pthread_exit(NULL);
04706 }
04707
04708 ci.chan = 0;
04709 ci.confno = myrpt->txconf;
04710 ci.confmode = ZT_CONF_CONF | ZT_CONF_TALKER ;
04711
04712 if (ioctl(myrpt->txpchannel->fds[0],ZT_SETCONF,&ci) == -1)
04713 {
04714 ast_log(LOG_WARNING, "Unable to set conference mode to Announce\n");
04715 ast_mutex_unlock(&myrpt->lock);
04716 ast_hangup(myrpt->txpchannel);
04717 ast_hangup(myrpt->pchannel);
04718 if (myrpt->txchannel != myrpt->rxchannel)
04719 ast_hangup(myrpt->txchannel);
04720 ast_hangup(myrpt->rxchannel);
04721 myrpt->rpt_thread = AST_PTHREADT_STOP;
04722 pthread_exit(NULL);
04723 }
04724
04725
04726
04727 myrpt->links.next = &myrpt->links;
04728 myrpt->links.prev = &myrpt->links;
04729 myrpt->tailtimer = 0;
04730 myrpt->totimer = 0;
04731 myrpt->idtimer = myrpt->politeid;
04732 myrpt->mustid = 0;
04733 myrpt->callmode = 0;
04734 myrpt->tounkeyed = 0;
04735 myrpt->tonotify = 0;
04736 myrpt->retxtimer = 0;
04737 lasttx = 0;
04738 myrpt->keyed = 0;
04739 idtalkover = ast_variable_retrieve(cfg, myrpt->name, "idtalkover");
04740 myrpt->dtmfidx = -1;
04741 myrpt->dtmfbuf[0] = 0;
04742 myrpt->rem_dtmfidx = -1;
04743 myrpt->rem_dtmfbuf[0] = 0;
04744 dtmf_time = 0;
04745 myrpt->rem_dtmf_time = 0;
04746 myrpt->enable = 1;
04747 myrpt->disgorgetime = 0;
04748 ast_mutex_unlock(&myrpt->lock);
04749 val = 0;
04750 ast_channel_setoption(myrpt->rxchannel,AST_OPTION_TONE_VERIFY,&val,sizeof(char),0);
04751 val = 1;
04752 ast_channel_setoption(myrpt->rxchannel,AST_OPTION_RELAXDTMF,&val,sizeof(char),0);
04753 while (ms >= 0)
04754 {
04755 struct ast_frame *f;
04756 struct ast_channel *cs[300];
04757 int totx=0,elap=0,n,toexit=0;
04758
04759
04760 if((myrpt->disgorgetime) && (time(NULL) >= myrpt->disgorgetime)){
04761 struct rpt_link *zl;
04762 struct rpt_tele *zt;
04763
04764 myrpt->disgorgetime = 0;
04765 ast_log(LOG_NOTICE,"********** Variable Dump Start (app_rpt) **********\n");
04766 ast_log(LOG_NOTICE,"totx = %d\n",totx);
04767 ast_log(LOG_NOTICE,"remrx = %d\n",remrx);
04768 ast_log(LOG_NOTICE,"lasttx = %d\n",lasttx);
04769 ast_log(LOG_NOTICE,"elap = %d\n",elap);
04770 ast_log(LOG_NOTICE,"toexit = %d\n",toexit);
04771
04772 ast_log(LOG_NOTICE,"myrpt->keyed = %d\n",myrpt->keyed);
04773 ast_log(LOG_NOTICE,"myrpt->localtx = %d\n",myrpt->localtx);
04774 ast_log(LOG_NOTICE,"myrpt->callmode = %d\n",myrpt->callmode);
04775 ast_log(LOG_NOTICE,"myrpt->enable = %d\n",myrpt->enable);
04776 ast_log(LOG_NOTICE,"myrpt->mustid = %d\n",myrpt->mustid);
04777 ast_log(LOG_NOTICE,"myrpt->tounkeyed = %d\n",myrpt->tounkeyed);
04778 ast_log(LOG_NOTICE,"myrpt->tonotify = %d\n",myrpt->tonotify);
04779 ast_log(LOG_NOTICE,"myrpt->retxtimer = %ld\n",myrpt->retxtimer);
04780 ast_log(LOG_NOTICE,"myrpt->totimer = %d\n",myrpt->totimer);
04781 ast_log(LOG_NOTICE,"myrpt->tailtimer = %d\n",myrpt->tailtimer);
04782
04783 zl = myrpt->links.next;
04784 while(zl != &myrpt->links){
04785 ast_log(LOG_NOTICE,"*** Link Name: %s ***\n",zl->name);
04786 ast_log(LOG_NOTICE," link->lasttx %d\n",zl->lasttx);
04787 ast_log(LOG_NOTICE," link->lastrx %d\n",zl->lastrx);
04788 ast_log(LOG_NOTICE," link->connected %d\n",zl->connected);
04789 ast_log(LOG_NOTICE," link->hasconnected %d\n",zl->hasconnected);
04790 ast_log(LOG_NOTICE," link->outbound %d\n",zl->outbound);
04791 ast_log(LOG_NOTICE," link->disced %d\n",zl->disced);
04792 ast_log(LOG_NOTICE," link->killme %d\n",zl->killme);
04793 ast_log(LOG_NOTICE," link->disctime %ld\n",zl->disctime);
04794 ast_log(LOG_NOTICE," link->retrytimer %ld\n",zl->retrytimer);
04795 ast_log(LOG_NOTICE," link->retries = %d\n",zl->retries);
04796
04797 zl = zl->next;
04798 }
04799
04800 zt = myrpt->tele.next;
04801 if(zt != &myrpt->tele)
04802 ast_log(LOG_NOTICE,"*** Telemetry Queue ***\n");
04803 while(zt != &myrpt->tele){
04804 ast_log(LOG_NOTICE," Telemetry mode: %d\n",zt->mode);
04805 zt = zt->next;
04806 }
04807 ast_log(LOG_NOTICE,"******* Variable Dump End (app_rpt) *******\n");
04808
04809 }
04810
04811
04812
04813
04814
04815 ast_mutex_lock(&myrpt->lock);
04816 if (ast_check_hangup(myrpt->rxchannel)) break;
04817 if (ast_check_hangup(myrpt->txchannel)) break;
04818 if (ast_check_hangup(myrpt->pchannel)) break;
04819 if (ast_check_hangup(myrpt->txpchannel)) break;
04820 myrpt->localtx = myrpt->keyed && (myrpt->dtmfidx == -1) && (!myrpt->cmdnode[0]);
04821
04822
04823
04824 l = myrpt->links.next;
04825 remrx = 0;
04826 while(l != &myrpt->links)
04827 {
04828 if (l->lastrx) remrx = 1;
04829 l = l->next;
04830 }
04831
04832
04833
04834 myrpt->mustid |= (myrpt->idtimer) && (myrpt->keyed || remrx) ;
04835
04836
04837
04838 totx = myrpt->localtx || myrpt->callmode;
04839
04840
04841
04842 identqueued = 0;
04843 nonidentqueued = 0;
04844
04845 telem = myrpt->tele.next;
04846 while(telem != &myrpt->tele)
04847 {
04848 if((telem->mode == ID) || (telem->mode == IDTALKOVER)){
04849 identqueued = 1;
04850 }
04851 else
04852 nonidentqueued = 1;
04853 telem = telem->next;
04854 }
04855
04856
04857
04858 totx = totx || nonidentqueued;
04859
04860
04861
04862 myrpt->exttx = totx;
04863
04864
04865
04866 totx = totx || remrx || identqueued;
04867
04868 if (!totx)
04869 {
04870 myrpt->totimer = myrpt->totime;
04871 myrpt->tounkeyed = 0;
04872 myrpt->tonotify = 0;
04873 }
04874 else myrpt->tailtimer = myrpt->hangtime;
04875 totx = totx && myrpt->totimer;
04876
04877 if ((!myrpt->totimer) && (!myrpt->tonotify))
04878 {
04879 myrpt->tonotify = 1;
04880 ast_mutex_unlock(&myrpt->lock);
04881 rpt_telemetry(myrpt,TIMEOUT,NULL);
04882 ast_mutex_lock(&myrpt->lock);
04883 }
04884
04885
04886 if ((!totx) && (!myrpt->totimer) && (!myrpt->tounkeyed) && (!myrpt->keyed))
04887 {
04888 myrpt->tounkeyed = 1;
04889 }
04890 if ((!totx) && (!myrpt->totimer) && myrpt->tounkeyed && myrpt->keyed)
04891 {
04892 myrpt->totimer = myrpt->totime;
04893 myrpt->tounkeyed = 0;
04894 myrpt->tonotify = 0;
04895 ast_mutex_unlock(&myrpt->lock);
04896 continue;
04897 }
04898
04899 if ((!totx) && (!myrpt->totimer) && (myrpt->callmode == 4))
04900 {
04901 myrpt->callmode = 0;
04902 }
04903
04904 if (!myrpt->totimer) myrpt->tailtimer = 0;
04905
04906 if (myrpt->totimer) totx = totx || myrpt->tailtimer;
04907
04908 if (identqueued && (myrpt->keyed || remrx) && idtalkover) {
04909 int hasid = 0,hastalkover = 0;
04910
04911 telem = myrpt->tele.next;
04912 while(telem != &myrpt->tele){
04913 if(telem->mode == ID){
04914 if (telem->chan) ast_softhangup(telem->chan, AST_SOFTHANGUP_DEV);
04915 hasid = 1;
04916 }
04917 if (telem->mode == IDTALKOVER) hastalkover = 1;
04918 telem = telem->next;
04919 }
04920 ast_mutex_unlock(&myrpt->lock);
04921 if (hasid && (!hastalkover)) rpt_telemetry(myrpt, IDTALKOVER, NULL);
04922 ast_mutex_lock(&myrpt->lock);
04923 }
04924
04925
04926
04927
04928
04929 if (((totx && (!myrpt->exttx) && (myrpt->idtimer <= myrpt->politeid) && myrpt->tailtimer)) ||
04930 (myrpt->mustid && (!myrpt->idtimer)))
04931 {
04932 myrpt->mustid = 0;
04933 myrpt->idtimer = myrpt->idtime;
04934 ast_mutex_unlock(&myrpt->lock);
04935 rpt_telemetry(myrpt,ID,NULL);
04936 ast_mutex_lock(&myrpt->lock);
04937 }
04938
04939 totx = totx || (myrpt->tele.next != &myrpt->tele);
04940 if (totx && (!lasttx))
04941 {
04942 lasttx = 1;
04943 ast_mutex_unlock(&myrpt->lock);
04944 ast_indicate(myrpt->txchannel,AST_CONTROL_RADIO_KEY);
04945 ast_mutex_lock(&myrpt->lock);
04946 }
04947 totx = totx && myrpt->enable;
04948 if ((!totx) && lasttx)
04949 {
04950 lasttx = 0;
04951 ast_mutex_unlock(&myrpt->lock);
04952 ast_indicate(myrpt->txchannel,AST_CONTROL_RADIO_UNKEY);
04953 ast_mutex_lock(&myrpt->lock);
04954 }
04955 time(&t);
04956
04957 if ((!myrpt->cmdnode[0]) && (myrpt->dtmfidx >= 0) && ((dtmf_time + DTMF_TIMEOUT) < t))
04958 {
04959 myrpt->dtmfidx = -1;
04960 myrpt->dtmfbuf[0] = 0;
04961 }
04962
04963 if ((myrpt->rem_dtmfidx >= 0) && ((myrpt->rem_dtmf_time + DTMF_TIMEOUT) < t))
04964 {
04965 myrpt->rem_dtmfidx = -1;
04966 myrpt->rem_dtmfbuf[0] = 0;
04967 }
04968
04969
04970 l = myrpt->links.next;
04971 while(l != &myrpt->links)
04972 {
04973 if (l->killme)
04974 {
04975
04976 remque((struct qelem *) l);
04977 if (!strcmp(myrpt->cmdnode,l->name))
04978 myrpt->cmdnode[0] = 0;
04979 ast_mutex_unlock(&myrpt->lock);
04980
04981 if (l->chan) ast_hangup(l->chan);
04982 ast_hangup(l->pchan);
04983 free(l);
04984 ast_mutex_lock(&myrpt->lock);
04985
04986 l = myrpt->links.next;
04987 continue;
04988 }
04989 l = l->next;
04990 }
04991 n = 0;
04992 cs[n++] = myrpt->rxchannel;
04993 cs[n++] = myrpt->pchannel;
04994 cs[n++] = myrpt->txpchannel;
04995 if (myrpt->txchannel != myrpt->rxchannel) cs[n++] = myrpt->txchannel;
04996 l = myrpt->links.next;
04997 while(l != &myrpt->links)
04998 {
04999 if ((!l->killme) && (!l->disctime) && l->chan)
05000 {
05001 cs[n++] = l->chan;
05002 cs[n++] = l->pchan;
05003 }
05004 l = l->next;
05005 }
05006 ast_mutex_unlock(&myrpt->lock);
05007 ms = MSWAIT;
05008 who = ast_waitfor_n(cs,n,&ms);
05009 if (who == NULL) ms = 0;
05010 elap = MSWAIT - ms;
05011 ast_mutex_lock(&myrpt->lock);
05012 l = myrpt->links.next;
05013 while(l != &myrpt->links)
05014 {
05015 if (!l->lasttx)
05016 {
05017 if ((l->retxtimer += elap) >= REDUNDANT_TX_TIME)
05018 {
05019 l->retxtimer = 0;
05020 if (l->chan) ast_indicate(l->chan,AST_CONTROL_RADIO_UNKEY);
05021 }
05022 } else l->retxtimer = 0;
05023 #ifdef RECONNECT_KLUDGE
05024 if (l->disctime)
05025 {
05026 l->disctime -= elap;
05027 if (l->disctime <= 0)
05028 l->disctime = 0;
05029 }
05030
05031 if (l->retrytimer)
05032 {
05033 l->retrytimer -= elap;
05034 if (l->retrytimer < 0) l->retrytimer = 0;
05035 }
05036 #endif
05037
05038 if (l->elaptime < 0)
05039 {
05040 l = l->next;
05041 continue;
05042 }
05043 l->elaptime += elap;
05044
05045 if ((l->elaptime > MAXCONNECTTIME) &&
05046 ((!l->chan) || (l->chan->_state != AST_STATE_UP)))
05047 {
05048 l->elaptime = 0;
05049 ast_mutex_unlock(&myrpt->lock);
05050 if (l->chan) ast_softhangup(l->chan,AST_SOFTHANGUP_DEV);
05051 #ifndef RECONNECT_KLUDGE
05052 rpt_telemetry(myrpt,CONNFAIL,l);
05053 #endif
05054 ast_mutex_lock(&myrpt->lock);
05055 break;
05056 }
05057 #ifdef RECONNECT_KLUDGE
05058 if ((!l->chan) && (!l->retrytimer) && l->outbound &&
05059 (l->retries++ < MAX_RETRIES) && (l->hasconnected))
05060 {
05061 if (l->chan) ast_hangup(l->chan);
05062 ast_mutex_unlock(&myrpt->lock);
05063 if ((l->name[0] != '0') && (!l->isremote))
05064 {
05065 l->retrytimer = MAX_RETRIES + 1;
05066 }
05067 else
05068 {
05069 if (attempt_reconnect(myrpt,l) == -1)
05070 {
05071 l->retrytimer = RETRY_TIMER_MS;
05072 }
05073 }
05074 ast_mutex_lock(&myrpt->lock);
05075 break;
05076 }
05077 if ((!l->chan) && (!l->retrytimer) && l->outbound &&
05078 (l->retries >= MAX_RETRIES))
05079 {
05080
05081 remque((struct qelem *) l);
05082 if (!strcmp(myrpt->cmdnode,l->name))
05083 myrpt->cmdnode[0] = 0;
05084 ast_mutex_unlock(&myrpt->lock);
05085 if (l->name[0] != '0')
05086 {
05087 if (!l->hasconnected)
05088 rpt_telemetry(myrpt,CONNFAIL,l);
05089 else rpt_telemetry(myrpt,REMDISC,l);
05090 }
05091
05092 ast_hangup(l->pchan);
05093 free(l);
05094 ast_mutex_lock(&myrpt->lock);
05095 break;
05096 }
05097 if ((!l->chan) && (!l->disctime) && (!l->outbound))
05098 {
05099
05100 remque((struct qelem *) l);
05101 if (!strcmp(myrpt->cmdnode,l->name))
05102 myrpt->cmdnode[0] = 0;
05103 ast_mutex_unlock(&myrpt->lock);
05104 if (l->name[0] != '0')
05105 {
05106 rpt_telemetry(myrpt,REMDISC,l);
05107 }
05108
05109 ast_hangup(l->pchan);
05110 free(l);
05111 ast_mutex_lock(&myrpt->lock);
05112 break;
05113 }
05114 #endif
05115 l = l->next;
05116 }
05117 if (myrpt->tailtimer) myrpt->tailtimer -= elap;
05118 if (myrpt->tailtimer < 0) myrpt->tailtimer = 0;
05119 if (myrpt->totimer) myrpt->totimer -= elap;
05120 if (myrpt->totimer < 0) myrpt->totimer = 0;
05121 if (myrpt->idtimer) myrpt->idtimer -= elap;
05122 if (myrpt->idtimer < 0) myrpt->idtimer = 0;
05123 ast_mutex_unlock(&myrpt->lock);
05124 if (!ms) continue;
05125 if (who == myrpt->rxchannel)
05126 {
05127 f = ast_read(myrpt->rxchannel);
05128 if (!f)
05129 {
05130 if (debug) printf("@@@@ rpt:Hung Up\n");
05131 break;
05132 }
05133 if (f->frametype == AST_FRAME_VOICE)
05134 {
05135 if (!myrpt->localtx)
05136 memset(f->data,0,f->datalen);
05137 ast_write(myrpt->pchannel,f);
05138 }
05139 else if (f->frametype == AST_FRAME_DTMF)
05140 {
05141 char c;
05142
05143 c = (char) f->subclass;
05144 ast_frfree(f);
05145 if (!myrpt->keyed) continue;
05146 if (c == myrpt->endchar)
05147 {
05148
05149 if (myrpt->simple && myrpt->callmode)
05150 {
05151 ast_mutex_lock(&myrpt->lock);
05152 myrpt->callmode = 0;
05153 ast_mutex_unlock(&myrpt->lock);
05154 rpt_telemetry(myrpt,TERM,NULL);
05155 continue;
05156 }
05157 ast_mutex_lock(&myrpt->lock);
05158 myrpt->stopgen = 1;
05159 if (myrpt->cmdnode[0])
05160 {
05161 myrpt->cmdnode[0] = 0;
05162 myrpt->dtmfidx = -1;
05163 myrpt->dtmfbuf[0] = 0;
05164 ast_mutex_unlock(&myrpt->lock);
05165 rpt_telemetry(myrpt,COMPLETE,NULL);
05166 } else ast_mutex_unlock(&myrpt->lock);
05167 continue;
05168 }
05169 ast_mutex_lock(&myrpt->lock);
05170 if (myrpt->cmdnode[0])
05171 {
05172 ast_mutex_unlock(&myrpt->lock);
05173 send_link_dtmf(myrpt,c);
05174 continue;
05175 }
05176 if (!myrpt->simple)
05177 {
05178 if (c == myrpt->funcchar)
05179 {
05180 myrpt->dtmfidx = 0;
05181 myrpt->dtmfbuf[myrpt->dtmfidx] = 0;
05182 ast_mutex_unlock(&myrpt->lock);
05183 time(&dtmf_time);
05184 continue;
05185 }
05186 else if ((c != myrpt->endchar) && (myrpt->dtmfidx >= 0))
05187 {
05188 time(&dtmf_time);
05189
05190 if (myrpt->dtmfidx < MAXDTMF)
05191 {
05192 myrpt->dtmfbuf[myrpt->dtmfidx++] = c;
05193 myrpt->dtmfbuf[myrpt->dtmfidx] = 0;
05194
05195 strncpy(cmd, myrpt->dtmfbuf, sizeof(cmd) - 1);
05196
05197 ast_mutex_unlock(&myrpt->lock);
05198 res = collect_function_digits(myrpt, cmd, SOURCE_RPT, NULL);
05199 ast_mutex_lock(&myrpt->lock);
05200
05201 switch(res){
05202
05203 case DC_INDETERMINATE:
05204 break;
05205
05206 case DC_REQ_FLUSH:
05207 myrpt->dtmfidx = 0;
05208 myrpt->dtmfbuf[0] = 0;
05209 break;
05210
05211
05212 case DC_COMPLETE:
05213 myrpt->dtmfbuf[0] = 0;
05214 myrpt->dtmfidx = -1;
05215 dtmf_time = 0;
05216 break;
05217
05218 case DC_ERROR:
05219 default:
05220 myrpt->dtmfbuf[0] = 0;
05221 myrpt->dtmfidx = -1;
05222 dtmf_time = 0;
05223 break;
05224 }
05225 if(res != DC_INDETERMINATE) {
05226 ast_mutex_unlock(&myrpt->lock);
05227 continue;
05228 }
05229 }
05230 }
05231 }
05232 else
05233 {
05234 if ((!myrpt->callmode) && (c == myrpt->funcchar))
05235 {
05236 myrpt->callmode = 1;
05237 myrpt->cidx = 0;
05238 myrpt->exten[myrpt->cidx] = 0;
05239 ast_mutex_unlock(&myrpt->lock);
05240 pthread_attr_init(&attr);
05241 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
05242 ast_pthread_create(&myrpt->rpt_call_thread,&attr,rpt_call,(void *)myrpt);
05243 continue;
05244 }
05245 }
05246 if (myrpt->callmode == 1)
05247 {
05248 myrpt->exten[myrpt->cidx++] = c;
05249 myrpt->exten[myrpt->cidx] = 0;
05250
05251 if (ast_exists_extension(myrpt->pchannel,myrpt->ourcontext,myrpt->exten,1,NULL))
05252 {
05253 myrpt->callmode = 2;
05254 ast_mutex_unlock(&myrpt->lock);
05255 rpt_telemetry(myrpt,PROC,NULL);
05256 continue;
05257 }
05258
05259 if (!ast_canmatch_extension(myrpt->pchannel,myrpt->ourcontext,myrpt->exten,1,NULL))
05260 {
05261
05262 myrpt->callmode = 4;
05263 }
05264 ast_mutex_unlock(&myrpt->lock);
05265 continue;
05266 }
05267 if ((myrpt->callmode == 2) || (myrpt->callmode == 3))
05268 {
05269 myrpt->mydtmf = c;
05270 }
05271 ast_mutex_unlock(&myrpt->lock);
05272 continue;
05273 }
05274 else if (f->frametype == AST_FRAME_CONTROL)
05275 {
05276 if (f->subclass == AST_CONTROL_HANGUP)
05277 {
05278 if (debug) printf("@@@@ rpt:Hung Up\n");
05279 ast_frfree(f);
05280 break;
05281 }
05282
05283 if (f->subclass == AST_CONTROL_RADIO_KEY)
05284 {
05285 if (debug) printf("@@@@ rx key\n");
05286 myrpt->keyed = 1;
05287 }
05288
05289 if (f->subclass == AST_CONTROL_RADIO_UNKEY)
05290 {
05291 if (debug) printf("@@@@ rx un-key\n");
05292 if(myrpt->keyed) {
05293 rpt_telemetry(myrpt,UNKEY,NULL);
05294 }
05295 myrpt->keyed = 0;
05296 }
05297 }
05298 ast_frfree(f);
05299 continue;
05300 }
05301 if (who == myrpt->pchannel)
05302 {
05303 f = ast_read(myrpt->pchannel);
05304 if (!f)
05305 {
05306 if (debug) printf("@@@@ rpt:Hung Up\n");
05307 break;
05308 }
05309 if (f->frametype == AST_FRAME_VOICE)
05310 {
05311 ast_write(myrpt->txpchannel,f);
05312 }
05313 if (f->frametype == AST_FRAME_CONTROL)
05314 {
05315 if (f->subclass == AST_CONTROL_HANGUP)
05316 {
05317 if (debug) printf("@@@@ rpt:Hung Up\n");
05318 ast_frfree(f);
05319 break;
05320 }
05321 }
05322 ast_frfree(f);
05323 continue;
05324 }
05325 if (who == myrpt->txchannel)
05326 {
05327 f = ast_read(myrpt->txchannel);
05328 if (!f)
05329 {
05330 if (debug) printf("@@@@ rpt:Hung Up\n");
05331 break;
05332 }
05333 if (f->frametype == AST_FRAME_CONTROL)
05334 {
05335 if (f->subclass == AST_CONTROL_HANGUP)
05336 {
05337 if (debug) printf("@@@@ rpt:Hung Up\n");
05338 ast_frfree(f);
05339 break;
05340 }
05341 }
05342 ast_frfree(f);
05343 continue;
05344 }
05345 toexit = 0;
05346 ast_mutex_lock(&myrpt->lock);
05347 l = myrpt->links.next;
05348 while(l != &myrpt->links)
05349 {
05350 if (l->disctime)
05351 {
05352 l = l->next;
05353 continue;
05354 }
05355 if (who == l->chan)
05356 {
05357 remrx = 0;
05358
05359 m = myrpt->links.next;
05360 while(m != &myrpt->links)
05361 {
05362
05363 if ((m != l) && (m->lastrx)) remrx = 1;
05364 m = m->next;
05365 }
05366 ast_mutex_unlock(&myrpt->lock);
05367 totx = (((l->isremote) ? myrpt->localtx :
05368 myrpt->exttx) || remrx) && l->mode;
05369 if (l->chan && (l->lasttx != totx))
05370 {
05371 if (totx)
05372 {
05373 ast_indicate(l->chan,AST_CONTROL_RADIO_KEY);
05374 }
05375 else
05376 {
05377 ast_indicate(l->chan,AST_CONTROL_RADIO_UNKEY);
05378 }
05379 }
05380 l->lasttx = totx;
05381 f = ast_read(l->chan);
05382 if (!f)
05383 {
05384 #ifdef RECONNECT_KLUDGE
05385 if ((!l->disced) && (!l->outbound))
05386 {
05387 if ((l->name[0] == '0') || l->isremote)
05388 l->disctime = 1;
05389 else
05390 l->disctime = DISC_TIME;
05391 ast_mutex_lock(&myrpt->lock);
05392 ast_hangup(l->chan);
05393 l->chan = 0;
05394 break;
05395 }
05396
05397 if (l->retrytimer)
05398 {
05399 ast_mutex_lock(&myrpt->lock);
05400 break;
05401 }
05402 if (l->outbound && (l->retries++ < MAX_RETRIES) && (l->hasconnected))
05403 {
05404 ast_mutex_lock(&myrpt->lock);
05405 ast_hangup(l->chan);
05406 l->chan = 0;
05407 ast_mutex_unlock(&myrpt->lock);
05408 if (attempt_reconnect(myrpt,l) == -1)
05409 {
05410 l->retrytimer = RETRY_TIMER_MS;
05411 }
05412 ast_mutex_lock(&myrpt->lock);
05413 break;
05414 }
05415 #endif
05416 ast_mutex_lock(&myrpt->lock);
05417
05418 remque((struct qelem *) l);
05419 if (!strcmp(myrpt->cmdnode,l->name))
05420 myrpt->cmdnode[0] = 0;
05421 ast_mutex_unlock(&myrpt->lock);
05422 if (!l->hasconnected)
05423 rpt_telemetry(myrpt,CONNFAIL,l);
05424 else if (l->disced != 2) rpt_telemetry(myrpt,REMDISC,l);
05425
05426 ast_hangup(l->chan);
05427 ast_hangup(l->pchan);
05428 free(l);
05429 ast_mutex_lock(&myrpt->lock);
05430 break;
05431 }
05432 if (f->frametype == AST_FRAME_VOICE)
05433 {
05434 if (l->phonemode && (!l->lastrx))
05435 {
05436 memset(f->data,0,f->datalen);
05437 }
05438 ast_write(l->pchan,f);
05439 }
05440 if (f->frametype == AST_FRAME_TEXT)
05441 {
05442 handle_link_data(myrpt,l,f->data);
05443 }
05444 if (f->frametype == AST_FRAME_DTMF)
05445 {
05446 handle_link_phone_dtmf(myrpt,l,f->subclass);
05447 }
05448 if (f->frametype == AST_FRAME_CONTROL)
05449 {
05450 if (f->subclass == AST_CONTROL_ANSWER)
05451 {
05452 char lconnected = l->connected;
05453 l->connected = 1;
05454 l->hasconnected = 1;
05455 l->elaptime = -1;
05456 l->retries = 0;
05457 if (!lconnected) rpt_telemetry(myrpt,CONNECTED,l);
05458 }
05459
05460 if (f->subclass == AST_CONTROL_RADIO_KEY)
05461 {
05462 if (debug) printf("@@@@ rx key\n");
05463 l->lastrx = 1;
05464 }
05465
05466 if (f->subclass == AST_CONTROL_RADIO_UNKEY)
05467 {
05468 if (debug) printf("@@@@ rx un-key\n");
05469 l->lastrx = 0;
05470 }
05471 if (f->subclass == AST_CONTROL_HANGUP)
05472 {
05473 ast_frfree(f);
05474 #ifdef RECONNECT_KLUDGE
05475 if ((!l->outbound) && (!l->disced))
05476 {
05477 if ((l->name[0] == '0') || l->isremote)
05478 l->disctime = 1;
05479 else
05480 l->disctime = DISC_TIME;
05481 ast_mutex_lock(&myrpt->lock);
05482 ast_hangup(l->chan);
05483 l->chan = 0;
05484 break;
05485 }
05486 if (l->retrytimer)
05487 {
05488 ast_mutex_lock(&myrpt->lock);
05489 break;
05490 }
05491 if (l->outbound && (l->retries++ < MAX_RETRIES) && (l->hasconnected))
05492 {
05493 ast_mutex_lock(&myrpt->lock);
05494 ast_hangup(l->chan);
05495 l->chan = 0;
05496 ast_mutex_unlock(&myrpt->lock);
05497 if (attempt_reconnect(myrpt,l) == -1)
05498 {
05499 l->retrytimer = RETRY_TIMER_MS;
05500 }
05501 ast_mutex_lock(&myrpt->lock);
05502 break;
05503 }
05504 #endif
05505 ast_mutex_lock(&myrpt->lock);
05506
05507 remque((struct qelem *) l);
05508 if (!strcmp(myrpt->cmdnode,l->name))
05509 myrpt->cmdnode[0] = 0;
05510 ast_mutex_unlock(&myrpt->lock);
05511 if (!l->hasconnected)
05512 rpt_telemetry(myrpt,CONNFAIL,l);
05513 else if (l->disced != 2) rpt_telemetry(myrpt,REMDISC,l);
05514
05515 ast_hangup(l->chan);
05516 ast_hangup(l->pchan);
05517 free(l);
05518 ast_mutex_lock(&myrpt->lock);
05519 break;
05520 }
05521 }
05522 ast_frfree(f);
05523 ast_mutex_lock(&myrpt->lock);
05524 break;
05525 }
05526 if (who == l->pchan)
05527 {
05528 ast_mutex_unlock(&myrpt->lock);
05529 f = ast_read(l->pchan);
05530 if (!f)
05531 {
05532 if (debug) printf("@@@@ rpt:Hung Up\n");
05533 toexit = 1;
05534 ast_mutex_lock(&myrpt->lock);
05535 break;
05536 }
05537 if (f->frametype == AST_FRAME_VOICE)
05538 {
05539 if (l->chan) ast_write(l->chan,f);
05540 }
05541 if (f->frametype == AST_FRAME_CONTROL)
05542 {
05543 if (f->subclass == AST_CONTROL_HANGUP)
05544 {
05545 if (debug) printf("@@@@ rpt:Hung Up\n");
05546 ast_frfree(f);
05547 toexit = 1;
05548 ast_mutex_lock(&myrpt->lock);
05549 break;
05550 }
05551 }
05552 ast_frfree(f);
05553 ast_mutex_lock(&myrpt->lock);
05554 break;
05555 }
05556 l = l->next;
05557 }
05558 ast_mutex_unlock(&myrpt->lock);
05559 if (toexit) break;
05560 if (who == myrpt->txpchannel)
05561 {
05562 f = ast_read(myrpt->txpchannel);
05563 if (!f)
05564 {
05565 if (debug) printf("@@@@ rpt:Hung Up\n");
05566 break;
05567 }
05568 if (f->frametype == AST_FRAME_CONTROL)
05569 {
05570 if (f->subclass == AST_CONTROL_HANGUP)
05571 {
05572 if (debug) printf("@@@@ rpt:Hung Up\n");
05573 ast_frfree(f);
05574 break;
05575 }
05576 }
05577 ast_frfree(f);
05578 continue;
05579 }
05580 }
05581 usleep(100000);
05582 ast_hangup(myrpt->pchannel);
05583 ast_hangup(myrpt->txpchannel);
05584 if (myrpt->txchannel != myrpt->rxchannel) ast_hangup(myrpt->txchannel);
05585 ast_hangup(myrpt->rxchannel);
05586 ast_mutex_lock(&myrpt->lock);
05587 l = myrpt->links.next;
05588 while(l != &myrpt->links)
05589 {
05590 struct rpt_link *ll = l;
05591
05592 remque((struct qelem *) l);
05593
05594 if (l->chan) ast_hangup(l->chan);
05595 ast_hangup(l->pchan);
05596 l = l->next;
05597 free(ll);
05598 }
05599 ast_mutex_unlock(&myrpt->lock);
05600 if (debug) printf("@@@@ rpt:Hung up channel\n");
05601 myrpt->rpt_thread = AST_PTHREADT_STOP;
05602 pthread_exit(NULL);
05603 return NULL;
05604 }
05605
05606
05607 static void *rpt_master(void *ignore)
05608 {
05609 char *this,*val;
05610 struct ast_variable *vp;
05611 int i,j,n,longestnode;
05612 pthread_attr_t attr;
05613
05614
05615 memset(&rpt_vars,0,sizeof(rpt_vars));
05616
05617 cfg = ast_config_load("rpt.conf");
05618 if (!cfg) {
05619 ast_log(LOG_NOTICE, "Unable to open radio repeater configuration rpt.conf. Radio Repeater disabled.\n");
05620 pthread_exit(NULL);
05621 }
05622
05623
05624 this = NULL;
05625 n = 0;
05626 while((this = ast_category_browse(cfg,this)) != NULL)
05627 {
05628
05629 for(i = 0 ; i < strlen(this) ; i++){
05630 if((this[i] < '0') || (this[i] > '9'))
05631 break;
05632 }
05633 if(i != strlen(this))
05634 continue;
05635
05636 ast_log(LOG_DEBUG,"Loading config for repeater %s\n",this);
05637 ast_mutex_init(&rpt_vars[n].lock);
05638 rpt_vars[n].tele.next = &rpt_vars[n].tele;
05639 rpt_vars[n].tele.prev = &rpt_vars[n].tele;
05640 rpt_vars[n].rpt_thread = AST_PTHREADT_NULL;
05641 rpt_vars[n].name = this;
05642 rpt_vars[n].rxchanname = ast_variable_retrieve(cfg,this,"rxchannel");
05643 rpt_vars[n].txchanname = ast_variable_retrieve(cfg,this,"txchannel");
05644 rpt_vars[n].ourcontext = ast_variable_retrieve(cfg,this,"context");
05645 if (!rpt_vars[n].ourcontext) rpt_vars[n].ourcontext = this;
05646 rpt_vars[n].ourcallerid = ast_variable_retrieve(cfg,this,"callerid");
05647 rpt_vars[n].acctcode = ast_variable_retrieve(cfg,this,"accountcode");
05648 rpt_vars[n].ident = ast_variable_retrieve(cfg,this,"idrecording");
05649 val = ast_variable_retrieve(cfg,this,"hangtime");
05650 if (val) rpt_vars[n].hangtime = atoi(val);
05651 else rpt_vars[n].hangtime = HANGTIME;
05652 val = ast_variable_retrieve(cfg,this,"totime");
05653 if (val) rpt_vars[n].totime = atoi(val);
05654 else rpt_vars[n].totime = TOTIME;
05655
05656 rpt_vars[n].idtime = retrieve_astcfgint( this, "idtime", 60000, 2400000, IDTIME);
05657 rpt_vars[n].politeid = retrieve_astcfgint( this, "politeid", 30000, 300000, POLITEID);
05658 rpt_vars[n].remote = ast_variable_retrieve(cfg,this,"remote");
05659 rpt_vars[n].tonezone = ast_variable_retrieve(cfg,this,"tonezone");
05660 val = ast_variable_retrieve(cfg,this,"iobase");
05661
05662
05663
05664 if ((!val) || (sscanf(val,"%i",&rpt_vars[n].iobase) != 1))
05665 rpt_vars[n].iobase = DEFAULT_IOBASE;
05666 rpt_vars[n].simple = 0;
05667 rpt_vars[n].functions = ast_variable_retrieve(cfg,this,"functions");
05668 if (!rpt_vars[n].functions)
05669 {
05670 rpt_vars[n].functions = FUNCTIONS;
05671 rpt_vars[n].simple = 1;
05672 }
05673 rpt_vars[n].link_functions = ast_variable_retrieve(cfg,this,"link_functions");
05674 if (!rpt_vars[n].link_functions)
05675 rpt_vars[n].link_functions = rpt_vars[n].functions;
05676 rpt_vars[n].phone_functions = ast_variable_retrieve(cfg,this,"phone_functions");
05677 rpt_vars[n].dphone_functions = ast_variable_retrieve(cfg,this,"dphone_functions");
05678 val = ast_variable_retrieve(cfg,this,"funcchar");
05679 if (!val) rpt_vars[n].funcchar = FUNCCHAR; else
05680 rpt_vars[n].funcchar = *val;
05681 val = ast_variable_retrieve(cfg,this,"endchar");
05682 if (!val) rpt_vars[n].endchar = ENDCHAR; else
05683 rpt_vars[n].endchar = *val;
05684 val = ast_variable_retrieve(cfg,this,"nobusyout");
05685 if (val) rpt_vars[n].nobusyout = ast_true(val);
05686 rpt_vars[n].nodes = ast_variable_retrieve(cfg,this,"nodes");
05687 if (!rpt_vars[n].nodes)
05688 rpt_vars[n].nodes = NODES;
05689 n++;
05690 }
05691 nrpts = n;
05692 ast_log(LOG_DEBUG, "Total of %d repeaters configured.\n",n);
05693
05694 for(i = 0; i < n; i++)
05695 {
05696
05697
05698
05699
05700 longestnode = 0;
05701
05702 vp = ast_variable_browse(cfg, rpt_vars[i].nodes);
05703
05704 while(vp){
05705 j = strlen(vp->name);
05706 if (j > longestnode)
05707 longestnode = j;
05708 vp = vp->next;
05709 }
05710
05711
05712 rpt_vars[i].longestnode = longestnode;
05713
05714
05715
05716
05717 rpt_vars[i].longestfunc = 0;
05718 vp = ast_variable_browse(cfg, rpt_vars[i].functions);
05719 while(vp){
05720 j = strlen(vp->name);
05721 if (j > rpt_vars[i].longestfunc)
05722 rpt_vars[i].longestfunc = j;
05723 vp = vp->next;
05724 }
05725
05726
05727
05728 rpt_vars[i].link_longestfunc = 0;
05729 vp = ast_variable_browse(cfg, rpt_vars[i].link_functions);
05730 while(vp){
05731 j = strlen(vp->name);
05732 if (j > rpt_vars[i].link_longestfunc)
05733 rpt_vars[i].link_longestfunc = j;
05734 vp = vp->next;
05735 }
05736 rpt_vars[i].phone_longestfunc = 0;
05737 if (rpt_vars[i].phone_functions)
05738 {
05739 vp = ast_variable_browse(cfg, rpt_vars[i].phone_functions);
05740 while(vp){
05741 j = strlen(vp->name);
05742 if (j > rpt_vars[i].phone_longestfunc)
05743 rpt_vars[i].phone_longestfunc = j;
05744 vp = vp->next;
05745 }
05746 }
05747 rpt_vars[i].dphone_longestfunc = 0;
05748 if (rpt_vars[i].dphone_functions)
05749 {
05750 vp = ast_variable_browse(cfg, rpt_vars[i].dphone_functions);
05751 while(vp){
05752 j = strlen(vp->name);
05753 if (j > rpt_vars[i].dphone_longestfunc)
05754 rpt_vars[i].dphone_longestfunc = j;
05755 vp = vp->next;
05756 }
05757 }
05758 if (!rpt_vars[i].rxchanname)
05759 {
05760 ast_log(LOG_WARNING,"Did not specify rxchanname for node %s\n",rpt_vars[i].name);
05761 ast_config_destroy(cfg);
05762 pthread_exit(NULL);
05763 }
05764
05765 if (rpt_vars[i].remote)
05766 {
05767 strncpy(rpt_vars[i].freq, "146.580", sizeof(rpt_vars[i].freq) - 1);
05768 strncpy(rpt_vars[i].rxpl, "100.0", sizeof(rpt_vars[i].rxpl) - 1);
05769
05770 strncpy(rpt_vars[i].txpl, "100.0", sizeof(rpt_vars[i].txpl) - 1);
05771 rpt_vars[i].remmode = REM_MODE_FM;
05772 rpt_vars[i].offset = REM_SIMPLEX;
05773 rpt_vars[i].powerlevel = REM_MEDPWR;
05774 continue;
05775 }
05776 if (!rpt_vars[i].ident)
05777 {
05778 ast_log(LOG_WARNING,"Did not specify ident for node %s\n",rpt_vars[i].name);
05779 ast_config_destroy(cfg);
05780 pthread_exit(NULL);
05781 }
05782 pthread_attr_init(&attr);
05783 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
05784 ast_pthread_create(&rpt_vars[i].rpt_thread,&attr,rpt,(void *) &rpt_vars[i]);
05785 }
05786 usleep(500000);
05787 for(;;)
05788 {
05789
05790 for(i = 0; i < n; i++)
05791 {
05792 int rv;
05793 if (rpt_vars[i].remote) continue;
05794 if (rpt_vars[i].rpt_thread == AST_PTHREADT_STOP)
05795 rv = -1;
05796 else
05797 rv = pthread_kill(rpt_vars[i].rpt_thread,0);
05798 if (rv)
05799 {
05800 if(time(NULL) - rpt_vars[i].lastthreadrestarttime <= 15)
05801 {
05802 if(rpt_vars[i].threadrestarts >= 5)
05803 {
05804 ast_log(LOG_ERROR,"Continual RPT thread restarts, killing Asterisk\n");
05805 exit(1);
05806 }
05807 else
05808 {
05809 ast_log(LOG_NOTICE,"RPT thread restarted on %s\n",rpt_vars[i].name);
05810 rpt_vars[i].threadrestarts++;
05811 }
05812 }
05813 else
05814 rpt_vars[i].threadrestarts = 0;
05815
05816 rpt_vars[i].lastthreadrestarttime = time(NULL);
05817 pthread_attr_init(&attr);
05818 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
05819 ast_pthread_create(&rpt_vars[i].rpt_thread,&attr,rpt,(void *) &rpt_vars[i]);
05820 ast_log(LOG_WARNING, "rpt_thread restarted on node %s\n", rpt_vars[i].name);
05821 }
05822
05823 }
05824 usleep(2000000);
05825 }
05826 ast_config_destroy(cfg);
05827 pthread_exit(NULL);
05828 }
05829
05830 static int rpt_exec(struct ast_channel *chan, void *data)
05831 {
05832 int res=-1,i,rem_totx,n,phone_mode = 0;
05833 struct localuser *u;
05834 char tmp[256], keyed = 0;
05835 char *options,*stringp,*tele;
05836 struct rpt *myrpt;
05837 struct ast_frame *f;
05838 struct ast_channel *who;
05839 struct ast_channel *cs[20];
05840 struct rpt_link *l;
05841 ZT_CONFINFO ci;
05842 ZT_PARAMS par;
05843 int ms,elap;
05844
05845 if (ast_strlen_zero(data)) {
05846 ast_log(LOG_WARNING, "Rpt requires an argument (system node)\n");
05847 return -1;
05848 }
05849 strncpy(tmp, (char *)data, sizeof(tmp)-1);
05850 stringp=tmp;
05851 strsep(&stringp, "|");
05852 options = stringp;
05853 myrpt = NULL;
05854
05855 for(i = 0; i < nrpts; i++)
05856 {
05857
05858 if (!strcmp(tmp,rpt_vars[i].name))
05859 {
05860 myrpt = &rpt_vars[i];
05861 break;
05862 }
05863 }
05864 if (myrpt == NULL)
05865 {
05866 ast_log(LOG_WARNING, "Cannot find specified system node %s\n",tmp);
05867 return -1;
05868 }
05869
05870
05871 if (options && ((*options == 'P') || (*options == 'D') || (*options == 'R')))
05872 {
05873 phone_mode = 1;
05874 if (*options == 'D') phone_mode = 2;
05875 ast_set_callerid(chan,"0","app_rpt user","0");
05876 }
05877 else
05878 {
05879 if (strncmp(chan->name,"IAX2",4))
05880 {
05881 ast_log(LOG_WARNING, "We only accept links via IAX2!!\n");
05882 return -1;
05883 }
05884 }
05885 if (options && (*options == 'R'))
05886 {
05887
05888
05889 char *return_context;
05890 int l, m, lot, timeout = 0;
05891 char tmp[256],*template;
05892 char *working, *context, *exten, *priority;
05893 char *s,*orig_s;
05894
05895
05896 ast_mutex_lock(&myrpt->lock);
05897 m = myrpt->callmode;
05898 ast_mutex_unlock(&myrpt->lock);
05899
05900 if ((!myrpt->nobusyout) && m)
05901 {
05902 if (chan->_state != AST_STATE_UP)
05903 {
05904 ast_indicate(chan,AST_CONTROL_BUSY);
05905 }
05906 while(ast_safe_sleep(chan,10000) != -1);
05907 return -1;
05908 }
05909
05910 if (chan->_state != AST_STATE_UP)
05911 {
05912 ast_answer(chan);
05913 }
05914
05915 l=strlen(options)+2;
05916 orig_s=malloc(l);
05917 if(!orig_s) {
05918 ast_log(LOG_WARNING, "Out of memory\n");
05919 return -1;
05920 }
05921 s=orig_s;
05922 strncpy(s,options,l);
05923
05924 template=strsep(&s,"|");
05925 if(!template) {
05926 ast_log(LOG_WARNING, "An announce template must be defined\n");
05927 free(orig_s);
05928 return -1;
05929 }
05930
05931 if(s) {
05932 timeout = atoi(strsep(&s, "|"));
05933 timeout *= 1000;
05934 }
05935
05936 return_context = s;
05937
05938 if(return_context != NULL) {
05939
05940
05941 working = return_context;
05942 context = strsep(&working, "|");
05943 exten = strsep(&working, "|");
05944 if(!exten) {
05945
05946 priority = context;
05947 exten = NULL;
05948 context = NULL;
05949 } else {
05950 priority = strsep(&working, "|");
05951 if(!priority) {
05952
05953 priority = exten;
05954 exten = context;
05955 context = NULL;
05956 }
05957 }
05958 if(atoi(priority) < 0) {
05959 ast_log(LOG_WARNING, "Priority '%s' must be a number > 0\n", priority);
05960 free(orig_s);
05961 return -1;
05962 }
05963
05964 chan->priority = atoi(priority);
05965 if(exten && strcasecmp(exten, "BYEXTENSION"))
05966 strncpy(chan->exten, exten, sizeof(chan->exten)-1);
05967 if(context)
05968 strncpy(chan->context, context, sizeof(chan->context)-1);
05969 } else {
05970 chan->priority++;
05971 }
05972
05973 if(option_verbose > 2) {
05974 ast_verbose( VERBOSE_PREFIX_3 "Return Context: (%s,%s,%d) ID: %s\n", chan->context,chan->exten, chan->priority, chan->cid.cid_num);
05975 if(!ast_exists_extension(chan, chan->context, chan->exten, chan->priority, chan->cid.cid_num)) {
05976 ast_verbose( VERBOSE_PREFIX_3 "Warning: Return Context Invalid, call will return to default|s\n");
05977 }
05978 }
05979
05980
05981
05982
05983 ast_masq_park_call(chan, NULL, timeout, &lot);
05984
05985 if (option_verbose > 2) ast_verbose( VERBOSE_PREFIX_3 "Call Parking Called, lot: %d, timeout: %d, context: %s\n", lot, timeout, return_context);
05986
05987 snprintf(tmp,sizeof(tmp) - 1,"%d,%s",lot,template + 1);
05988
05989 rpt_telemetry(myrpt,REV_PATCH,tmp);
05990
05991 free(orig_s);
05992
05993 return 0;
05994
05995 }
05996
05997 if (!options)
05998 {
05999 struct ast_hostent ahp;
06000 struct hostent *hp;
06001 struct in_addr ia;
06002 char hisip[100],nodeip[100],*val, *s, *s1, *s2, *b,*b1;
06003
06004
06005 if (!chan->cid.cid_num)
06006 {
06007 ast_log(LOG_WARNING, "Doesnt have callerid on %s\n",tmp);
06008 return -1;
06009 }
06010
06011
06012 memset(hisip,0,sizeof(hisip));
06013 pbx_substitute_variables_helper(chan,"${IAXPEER(CURRENTCHANNEL)}",hisip,sizeof(hisip) - 1);
06014 if (!hisip[0])
06015 {
06016 ast_log(LOG_WARNING, "Link IP address cannot be determined!!\n");
06017 return -1;
06018 }
06019
06020 ast_callerid_parse(chan->cid.cid_num,&b,&b1);
06021 ast_shrink_phone_number(b1);
06022 if (!strcmp(myrpt->name,b1))
06023 {
06024 ast_log(LOG_WARNING, "Trying to link to self!!\n");
06025 return -1;
06026 }
06027
06028 if (*b1 < '1')
06029 {
06030 ast_log(LOG_WARNING, "Node %s Invalid for connection here!!\n",b1);
06031 return -1;
06032 }
06033
06034
06035
06036 val = ast_variable_retrieve(cfg, myrpt->nodes, b1);
06037 if (!val)
06038 {
06039 ast_log(LOG_WARNING, "Reported node %s cannot be found!!\n",b1);
06040 return -1;
06041 }
06042 strncpy(tmp,val,sizeof(tmp) - 1);
06043 s = tmp;
06044 s1 = strsep(&s,",");
06045 s2 = strsep(&s,",");
06046 if (!s2)
06047 {
06048 ast_log(LOG_WARNING, "Reported node %s not in correct format!!\n",b1);
06049 return -1;
06050 }
06051 if (strcmp(s2,"NONE")) {
06052 hp = ast_gethostbyname(s2, &ahp);
06053 if (!hp)
06054 {
06055 ast_log(LOG_WARNING, "Reported node %s, name %s cannot be found!!\n",b1,s2);
06056 return -1;
06057 }
06058 memcpy(&ia,hp->h_addr,sizeof(in_addr_t));
06059 ast_inet_ntoa(nodeip,sizeof(nodeip) - 1,ia);
06060 if (strcmp(hisip,nodeip))
06061 {
06062 char *s3 = strchr(s1,'@');
06063 if (s3) s1 = s3 + 1;
06064 s3 = strchr(s1,'/');
06065 if (s3) *s3 = 0;
06066 hp = ast_gethostbyname(s1, &ahp);
06067 if (!hp)
06068 {
06069 ast_log(LOG_WARNING, "Reported node %s, name %s cannot be found!!\n",b1,s1);
06070 return -1;
06071 }
06072 memcpy(&ia,hp->h_addr,sizeof(in_addr_t));
06073 ast_inet_ntoa(nodeip,sizeof(nodeip) - 1,ia);
06074 if (strcmp(hisip,nodeip))
06075 {
06076 ast_log(LOG_WARNING, "Node %s IP %s does not match link IP %s!!\n",b1,nodeip,hisip);
06077 return -1;
06078 }
06079 }
06080 }
06081 }
06082
06083
06084 if (!myrpt->remote)
06085 {
06086
06087 char *b,*b1;
06088
06089
06090 if (!chan->cid.cid_num)
06091 {
06092 ast_log(LOG_WARNING, "Doesnt have callerid on %s\n",tmp);
06093 return -1;
06094 }
06095
06096 ast_callerid_parse(chan->cid.cid_num,&b,&b1);
06097 ast_shrink_phone_number(b1);
06098 if (!strcmp(myrpt->name,b1))
06099 {
06100 ast_log(LOG_WARNING, "Trying to link to self!!\n");
06101 return -1;
06102 }
06103 ast_mutex_lock(&myrpt->lock);
06104 l = myrpt->links.next;
06105
06106 while(l != &myrpt->links)
06107 {
06108 if (l->name[0] == '0')
06109 {
06110 l = l->next;
06111 continue;
06112 }
06113
06114 if (!strcmp(l->name,b1)) break;
06115 l = l->next;
06116 }
06117
06118 if (l != &myrpt->links)
06119 {
06120 l->killme = 1;
06121 l->retries = MAX_RETRIES + 1;
06122 l->disced = 2;
06123 ast_mutex_unlock(&myrpt->lock);
06124 usleep(500000);
06125 } else
06126 ast_mutex_unlock(&myrpt->lock);
06127
06128 l = malloc(sizeof(struct rpt_link));
06129 if (!l)
06130 {
06131 ast_log(LOG_WARNING, "Unable to malloc\n");
06132 pthread_exit(NULL);
06133 }
06134
06135 memset((char *)l,0,sizeof(struct rpt_link));
06136 l->mode = 1;
06137 strncpy(l->name,b1,MAXNODESTR - 1);
06138 l->isremote = 0;
06139 l->chan = chan;
06140 l->connected = 1;
06141 l->hasconnected = 1;
06142 l->phonemode = phone_mode;
06143 ast_set_read_format(l->chan,AST_FORMAT_SLINEAR);
06144 ast_set_write_format(l->chan,AST_FORMAT_SLINEAR);
06145
06146 l->pchan = ast_request("zap",AST_FORMAT_SLINEAR,"pseudo",NULL);
06147 if (!l->pchan)
06148 {
06149 fprintf(stderr,"rpt:Sorry unable to obtain pseudo channel\n");
06150 pthread_exit(NULL);
06151 }
06152 ast_set_read_format(l->pchan,AST_FORMAT_SLINEAR);
06153 ast_set_write_format(l->pchan,AST_FORMAT_SLINEAR);
06154
06155 ci.chan = 0;
06156 ci.confno = myrpt->conf;
06157 ci.confmode = ZT_CONF_CONF | ZT_CONF_LISTENER | ZT_CONF_TALKER;
06158
06159 if (ioctl(l->pchan->fds[0],ZT_SETCONF,&ci) == -1)
06160 {
06161 ast_log(LOG_WARNING, "Unable to set conference mode to Announce\n");
06162 pthread_exit(NULL);
06163 }
06164 ast_mutex_lock(&myrpt->lock);
06165 if (phone_mode > 1) l->lastrx = 1;
06166
06167 insque((struct qelem *)l,(struct qelem *)myrpt->links.next);
06168 ast_mutex_unlock(&myrpt->lock);
06169 if (chan->_state != AST_STATE_UP) {
06170 ast_answer(chan);
06171 }
06172 return AST_PBX_KEEPALIVE;
06173 }
06174 ast_mutex_lock(&myrpt->lock);
06175
06176 if (myrpt->remoteon)
06177 {
06178 ast_mutex_unlock(&myrpt->lock);
06179 usleep(500000);
06180 if (myrpt->remoteon)
06181 {
06182 ast_log(LOG_WARNING, "Trying to use busy link on %s\n",tmp);
06183 return -1;
06184 }
06185 ast_mutex_lock(&myrpt->lock);
06186 }
06187 myrpt->remoteon = 1;
06188 if (ioperm(myrpt->iobase,1,1) == -1)
06189 {
06190 ast_mutex_unlock(&myrpt->lock);
06191 ast_log(LOG_WARNING, "Cant get io permission on IO port %x hex\n",myrpt->iobase);
06192 return -1;
06193 }
06194 LOCAL_USER_ADD(u);
06195 tele = strchr(myrpt->rxchanname,'/');
06196 if (!tele)
06197 {
06198 fprintf(stderr,"rpt:Dial number must be in format tech/number\n");
06199 ast_mutex_unlock(&myrpt->lock);
06200 pthread_exit(NULL);
06201 }
06202 *tele++ = 0;
06203 myrpt->rxchannel = ast_request(myrpt->rxchanname,AST_FORMAT_SLINEAR,tele,NULL);
06204 if (myrpt->rxchannel)
06205 {
06206 ast_set_read_format(myrpt->rxchannel,AST_FORMAT_SLINEAR);
06207 ast_set_write_format(myrpt->rxchannel,AST_FORMAT_SLINEAR);
06208 myrpt->rxchannel->whentohangup = 0;
06209 myrpt->rxchannel->appl = "Apprpt";
06210 myrpt->rxchannel->data = "(Link Rx)";
06211 if (option_verbose > 2)
06212 ast_verbose(VERBOSE_PREFIX_3 "rpt (Rx) initiating call to %s/%s on %s\n",
06213 myrpt->rxchanname,tele,myrpt->rxchannel->name);
06214 ast_mutex_unlock(&myrpt->lock);
06215 ast_call(myrpt->rxchannel,tele,999);
06216 ast_mutex_lock(&myrpt->lock);
06217 }
06218 else
06219 {
06220 fprintf(stderr,"rpt:Sorry unable to obtain Rx channel\n");
06221 ast_mutex_unlock(&myrpt->lock);
06222 pthread_exit(NULL);
06223 }
06224 *--tele = '/';
06225 if (myrpt->txchanname)
06226 {
06227 tele = strchr(myrpt->txchanname,'/');
06228 if (!tele)
06229 {
06230 fprintf(stderr,"rpt:Dial number must be in format tech/number\n");
06231 ast_mutex_unlock(&myrpt->lock);
06232 ast_hangup(myrpt->rxchannel);
06233 pthread_exit(NULL);
06234 }
06235 *tele++ = 0;
06236 myrpt->txchannel = ast_request(myrpt->txchanname,AST_FORMAT_SLINEAR,tele,NULL);
06237 if (myrpt->txchannel)
06238 {
06239 ast_set_read_format(myrpt->txchannel,AST_FORMAT_SLINEAR);
06240 ast_set_write_format(myrpt->txchannel,AST_FORMAT_SLINEAR);
06241 myrpt->txchannel->whentohangup = 0;
06242 myrpt->txchannel->appl = "Apprpt";
06243 myrpt->txchannel->data = "(Link Tx)";
06244 if (option_verbose > 2)
06245 ast_verbose(VERBOSE_PREFIX_3 "rpt (Tx) initiating call to %s/%s on %s\n",
06246 myrpt->txchanname,tele,myrpt->txchannel->name);
06247 ast_mutex_unlock(&myrpt->lock);
06248 ast_call(myrpt->txchannel,tele,999);
06249 ast_mutex_lock(&myrpt->lock);
06250 }
06251 else
06252 {
06253 fprintf(stderr,"rpt:Sorry unable to obtain Tx channel\n");
06254 ast_mutex_unlock(&myrpt->lock);
06255 ast_hangup(myrpt->rxchannel);
06256 pthread_exit(NULL);
06257 }
06258 *--tele = '/';
06259 }
06260 else
06261 {
06262 myrpt->txchannel = myrpt->rxchannel;
06263 }
06264 myrpt->remoterx = 0;
06265 myrpt->remotetx = 0;
06266 myrpt->retxtimer = 0;
06267 myrpt->remoteon = 1;
06268 myrpt->dtmfidx = -1;
06269 myrpt->dtmfbuf[0] = 0;
06270 myrpt->dtmf_time_rem = 0;
06271 myrpt->hfscanmode = 0;
06272 myrpt->hfscanstatus = 0;
06273 ast_mutex_unlock(&myrpt->lock);
06274 setrem(myrpt);
06275 ast_set_write_format(chan, AST_FORMAT_SLINEAR);
06276 ast_set_read_format(chan, AST_FORMAT_SLINEAR);
06277
06278 if (myrpt->remote && (myrpt->rxchannel == myrpt->txchannel))
06279 {
06280 i = 128;
06281 ioctl(myrpt->rxchannel->fds[0],ZT_ECHOCANCEL,&i);
06282 }
06283 if (chan->_state != AST_STATE_UP) {
06284 ast_answer(chan);
06285 }
06286
06287 if (ioctl(myrpt->txchannel->fds[0],ZT_GET_PARAMS,&par) != -1)
06288 {
06289 if (par.rxisoffhook)
06290 {
06291 ast_indicate(chan,AST_CONTROL_RADIO_KEY);
06292 myrpt->remoterx = 1;
06293 }
06294 }
06295 n = 0;
06296 cs[n++] = chan;
06297 cs[n++] = myrpt->rxchannel;
06298 if (myrpt->rxchannel != myrpt->txchannel)
06299 cs[n++] = myrpt->txchannel;
06300 for(;;)
06301 {
06302 if (ast_check_hangup(chan)) break;
06303 if (ast_check_hangup(myrpt->rxchannel)) break;
06304 ms = MSWAIT;
06305 who = ast_waitfor_n(cs,n,&ms);
06306 if (who == NULL) ms = 0;
06307 elap = MSWAIT - ms;
06308 if (!ms) continue;
06309 rem_totx = keyed;
06310
06311
06312 if ((!myrpt->remoterx) && (!myrpt->remotetx))
06313 {
06314 if ((myrpt->retxtimer += elap) >= REDUNDANT_TX_TIME)
06315 {
06316 myrpt->retxtimer = 0;
06317 ast_indicate(chan,AST_CONTROL_RADIO_UNKEY);
06318 }
06319 } else myrpt->retxtimer = 0;
06320 if (rem_totx && (!myrpt->remotetx))
06321 {
06322 myrpt->remotetx = 1;
06323 ast_indicate(myrpt->txchannel,AST_CONTROL_RADIO_KEY);
06324 }
06325 if ((!rem_totx) && myrpt->remotetx)
06326 {
06327 myrpt->remotetx = 0;
06328 ast_indicate(myrpt->txchannel,AST_CONTROL_RADIO_UNKEY);
06329 }
06330
06331 if(myrpt->tunerequest && (!strcmp(myrpt->remote, remote_rig_ft897))){
06332 myrpt->tunerequest = 0;
06333 set_mode_ft897(myrpt, REM_MODE_AM);
06334 simple_command_ft897(myrpt, 8);
06335 myrpt->remotetx = 0;
06336 ast_indicate(myrpt->txchannel,AST_CONTROL_RADIO_UNKEY);
06337 if (!myrpt->remoterx)
06338 ast_indicate(chan, AST_CONTROL_RADIO_KEY);
06339 if(play_tone(chan, 800, 6000, 8192) == -1)
06340 break;
06341
06342 rmt_telem_finish(myrpt,chan);
06343 set_mode_ft897(myrpt, 0x88);
06344 setrem(myrpt);
06345 }
06346
06347 if (myrpt->hfscanmode){
06348 myrpt->scantimer -= elap;
06349 if(myrpt->scantimer <= 0){
06350 myrpt->scantimer = REM_SCANTIME;
06351 service_scan(myrpt);
06352 }
06353 }
06354
06355
06356 if (who == chan)
06357 {
06358 f = ast_read(chan);
06359 if (!f)
06360 {
06361 if (debug) printf("@@@@ link:Hung Up\n");
06362 break;
06363 }
06364 if (f->frametype == AST_FRAME_VOICE)
06365 {
06366
06367 if (!myrpt->remotetx)
06368 memset(f->data,0,f->datalen);
06369 ast_write(myrpt->txchannel,f);
06370 }
06371 if (f->frametype == AST_FRAME_DTMF)
06372 {
06373 myrpt->remchannel = chan;
06374 if (handle_remote_phone_dtmf(myrpt,f->subclass,&keyed,phone_mode) == -1)
06375 {
06376 if (debug) printf("@@@@ rpt:Hung Up\n");
06377 ast_frfree(f);
06378 break;
06379 }
06380 }
06381 if (f->frametype == AST_FRAME_TEXT)
06382 {
06383 myrpt->remchannel = chan;
06384 if (handle_remote_data(myrpt,f->data) == -1)
06385 {
06386 if (debug) printf("@@@@ rpt:Hung Up\n");
06387 ast_frfree(f);
06388 break;
06389 }
06390 }
06391 if (f->frametype == AST_FRAME_CONTROL)
06392 {
06393 if (f->subclass == AST_CONTROL_HANGUP)
06394 {
06395 if (debug) printf("@@@@ rpt:Hung Up\n");
06396 ast_frfree(f);
06397 break;
06398 }
06399
06400 if (f->subclass == AST_CONTROL_RADIO_KEY)
06401 {
06402 if (debug) printf("@@@@ rx key\n");
06403 keyed = 1;
06404 }
06405
06406 if (f->subclass == AST_CONTROL_RADIO_UNKEY)
06407 {
06408 if (debug) printf("@@@@ rx un-key\n");
06409 keyed = 0;
06410 }
06411 }
06412 if (myrpt->hfscanstatus){
06413 myrpt->remchannel = chan;
06414 myrpt->remotetx = 0;
06415 ast_indicate(myrpt->txchannel,AST_CONTROL_RADIO_UNKEY);
06416 if (!myrpt->remoterx)
06417 {
06418 ast_indicate(myrpt->remchannel,AST_CONTROL_RADIO_KEY);
06419 }
06420 if(myrpt->hfscanstatus < 0) {
06421 if (myrpt->hfscanstatus == -1) {
06422 if (ast_safe_sleep(myrpt->remchannel,1000) == -1) break;
06423 }
06424 sayfile(myrpt->remchannel, "rpt/stop");
06425 }
06426 else
06427 {
06428 saynum(myrpt->remchannel, myrpt->hfscanstatus );
06429 }
06430 rmt_telem_finish(myrpt,myrpt->remchannel);
06431 myrpt->hfscanstatus = 0;
06432 }
06433 ast_frfree(f);
06434 continue;
06435 }
06436 if (who == myrpt->rxchannel)
06437 {
06438 f = ast_read(myrpt->rxchannel);
06439 if (!f)
06440 {
06441 if (debug) printf("@@@@ link:Hung Up\n");
06442 break;
06443 }
06444 if (f->frametype == AST_FRAME_VOICE)
06445 {
06446 if ((myrpt->remote) && (myrpt->remotetx))
06447 memset(f->data,0,f->datalen);
06448 ast_write(chan,f);
06449 }
06450 else if (f->frametype == AST_FRAME_CONTROL)
06451 {
06452 if (f->subclass == AST_CONTROL_HANGUP)
06453 {
06454 if (debug) printf("@@@@ rpt:Hung Up\n");
06455 ast_frfree(f);
06456 break;
06457 }
06458
06459 if (f->subclass == AST_CONTROL_RADIO_KEY)
06460 {
06461 if (debug) printf("@@@@ remote rx key\n");
06462 if (!myrpt->remotetx)
06463 {
06464 ast_indicate(chan,AST_CONTROL_RADIO_KEY);
06465 myrpt->remoterx = 1;
06466 }
06467 }
06468
06469 if (f->subclass == AST_CONTROL_RADIO_UNKEY)
06470 {
06471 if (debug) printf("@@@@ remote rx un-key\n");
06472 if (!myrpt->remotetx)
06473 {
06474 ast_indicate(chan,AST_CONTROL_RADIO_UNKEY);
06475 myrpt->remoterx = 0;
06476 }
06477 }
06478 }
06479 ast_frfree(f);
06480 continue;
06481 }
06482 if ((myrpt->rxchannel != myrpt->txchannel) &&
06483 (who == myrpt->txchannel))
06484 {
06485 f = ast_read(myrpt->txchannel);
06486 if (!f)
06487 {
06488 if (debug) printf("@@@@ link:Hung Up\n");
06489 break;
06490 }
06491 if (f->frametype == AST_FRAME_CONTROL)
06492 {
06493 if (f->subclass == AST_CONTROL_HANGUP)
06494 {
06495 if (debug) printf("@@@@ rpt:Hung Up\n");
06496 ast_frfree(f);
06497 break;
06498 }
06499 }
06500 ast_frfree(f);
06501 continue;
06502 }
06503
06504 }
06505 ast_mutex_lock(&myrpt->lock);
06506 if (myrpt->rxchannel != myrpt->txchannel) ast_hangup(myrpt->txchannel);
06507 ast_hangup(myrpt->rxchannel);
06508 myrpt->hfscanmode = 0;
06509 myrpt->hfscanstatus = 0;
06510 myrpt->remoteon = 0;
06511 ast_mutex_unlock(&myrpt->lock);
06512 closerem(myrpt);
06513 LOCAL_USER_REMOVE(u);
06514 return res;
06515 }
06516
06517 int unload_module(void)
06518 {
06519 int i;
06520
06521 STANDARD_HANGUP_LOCALUSERS;
06522 for(i = 0; i < nrpts; i++) {
06523 if (!strcmp(rpt_vars[i].name,rpt_vars[i].nodes)) continue;
06524 ast_mutex_destroy(&rpt_vars[i].lock);
06525 }
06526 i = ast_unregister_application(app);
06527
06528
06529 ast_cli_unregister(&cli_debug);
06530
06531 return i;
06532 }
06533
06534 int load_module(void)
06535 {
06536 ast_pthread_create(&rpt_master_thread,NULL,rpt_master,NULL);
06537
06538
06539 ast_cli_register(&cli_debug);
06540
06541 return ast_register_application(app, rpt_exec, synopsis, descrip);
06542 }
06543
06544 char *description(void)
06545 {
06546 return tdesc;
06547 }
06548
06549 int usecount(void)
06550 {
06551 int res;
06552 STANDARD_USECOUNT(res);
06553 return res;
06554 }
06555
06556 char *key()
06557 {
06558 return ASTERISK_GPL_KEY;
06559 }
06560