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