00001
00002 #define OLDKEY
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
00102
00103
00104
00105
00106
00107
00108
00109
00110
00111
00112
00113
00114
00115
00116
00117
00118
00119
00120
00121
00122
00123
00124
00125
00126
00127
00128
00129
00130
00131
00132
00133
00134
00135
00136
00137
00138
00139
00140
00141
00142
00143
00144
00145
00146
00147
00148
00149
00150
00151
00152
00153
00154
00155
00156 #define MAXDTMF 32
00157 #define MAXMACRO 2048
00158 #define MAXLINKLIST 512
00159 #define LINKLISTTIME 10000
00160 #define LINKLISTSHORTTIME 200
00161 #define MACROTIME 100
00162 #define MACROPTIME 500
00163 #define DTMF_TIMEOUT 3
00164 #define KENWOOD_RETRIES 5
00165
00166 #define AUTHTELLTIME 7000
00167 #define AUTHTXTIME 1000
00168 #define AUTHLOGOUTTIME 25000
00169
00170 #ifdef __RPT_NOTCH
00171 #define MAXFILTERS 10
00172 #endif
00173
00174 #define DISC_TIME 10000
00175 #define MAX_RETRIES 5
00176 #define MAX_RETRIES_PERM 1000000000
00177
00178 #define REDUNDANT_TX_TIME 2000
00179
00180 #define RETRY_TIMER_MS 5000
00181
00182 #define START_DELAY 10
00183
00184 #define MAXPEERSTR 31
00185 #define MAXREMSTR 15
00186
00187 #define DELIMCHR ','
00188 #define QUOTECHR 34
00189
00190 #define MONITOR_DISK_BLOCKS_PER_MINUTE 38
00191
00192 #define DEFAULT_MONITOR_MIN_DISK_BLOCKS 10000
00193 #define DEFAULT_REMOTE_INACT_TIMEOUT (15 * 60)
00194 #define DEFAULT_REMOTE_TIMEOUT (60 * 60)
00195 #define DEFAULT_REMOTE_TIMEOUT_WARNING (3 * 60)
00196 #define DEFAULT_REMOTE_TIMEOUT_WARNING_FREQ 30
00197
00198 #define NODES "nodes"
00199 #define EXTNODES "extnodes"
00200 #define MEMORY "memory"
00201 #define MACRO "macro"
00202 #define FUNCTIONS "functions"
00203 #define TELEMETRY "telemetry"
00204 #define MORSE "morse"
00205 #define FUNCCHAR '*'
00206 #define ENDCHAR '#'
00207 #define EXTNODEFILE "/var/lib/asterisk/rpt_extnodes"
00208
00209 #define DEFAULT_IOBASE 0x378
00210
00211 #define DEFAULT_CIV_ADDR 0x58
00212
00213 #define MAXCONNECTTIME 5000
00214
00215 #define MAXNODESTR 300
00216
00217 #define MAXPATCHCONTEXT 100
00218
00219 #define ACTIONSIZE 32
00220
00221 #define TELEPARAMSIZE 256
00222
00223 #define REM_SCANTIME 100
00224
00225 #define DTMF_LOCAL_TIME 250
00226 #define DTMF_LOCAL_STARTTIME 500
00227
00228 #define IC706_PL_MEMORY_OFFSET 50
00229
00230 enum {REM_OFF,REM_MONITOR,REM_TX};
00231
00232 enum{ID,PROC,TERM,COMPLETE,UNKEY,REMDISC,REMALREADY,REMNOTFOUND,REMGO,
00233 CONNECTED,CONNFAIL,STATUS,TIMEOUT,ID1, STATS_TIME,
00234 STATS_VERSION, IDTALKOVER, ARB_ALPHA, TEST_TONE, REV_PATCH,
00235 TAILMSG, MACRO_NOTFOUND, MACRO_BUSY, LASTNODEKEY, FULLSTATUS,
00236 MEMNOTFOUND, INVFREQ, REMMODE, REMLOGIN, REMXXX, REMSHORTSTATUS,
00237 REMLONGSTATUS, LOGINREQ, SCAN, SCANSTAT, TUNE, SETREMOTE,
00238 TIMEOUT_WARNING, ACT_TIMEOUT_WARNING, LINKUNKEY, UNAUTHTX};
00239
00240
00241 enum {REM_SIMPLEX,REM_MINUS,REM_PLUS};
00242
00243 enum {REM_LOWPWR,REM_MEDPWR,REM_HIPWR};
00244
00245 enum {DC_INDETERMINATE, DC_REQ_FLUSH, DC_ERROR, DC_COMPLETE, DC_COMPLETEQUIET, DC_DOKEY};
00246
00247 enum {SOURCE_RPT, SOURCE_LNK, SOURCE_RMT, SOURCE_PHONE, SOURCE_DPHONE};
00248
00249 enum {DLY_TELEM, DLY_ID, DLY_UNKEY, DLY_CALLTERM, DLY_COMP, DLY_LINKUNKEY};
00250
00251 enum {REM_MODE_FM,REM_MODE_USB,REM_MODE_LSB,REM_MODE_AM};
00252
00253 enum {HF_SCAN_OFF,HF_SCAN_DOWN_SLOW,HF_SCAN_DOWN_QUICK,
00254 HF_SCAN_DOWN_FAST,HF_SCAN_UP_SLOW,HF_SCAN_UP_QUICK,HF_SCAN_UP_FAST};
00255
00256 #include "asterisk.h"
00257
00258 ASTERISK_FILE_VERSION(__FILE__, "$Revision: 77846 $")
00259
00260 #include <signal.h>
00261 #include <stdio.h>
00262 #include <unistd.h>
00263 #include <string.h>
00264 #include <stdlib.h>
00265 #include <search.h>
00266 #include <sys/types.h>
00267 #include <sys/stat.h>
00268 #include <errno.h>
00269 #include <dirent.h>
00270 #include <ctype.h>
00271 #include <sys/stat.h>
00272 #include <sys/time.h>
00273 #include <sys/file.h>
00274 #include <sys/ioctl.h>
00275 #include <sys/io.h>
00276 #include <sys/vfs.h>
00277 #include <math.h>
00278 #ifdef OLD_ASTERISK
00279 #include <linux/zaptel.h>
00280 #include <tonezone.h>
00281 #else
00282 #include <zaptel/zaptel.h>
00283 #include <zaptel/tonezone.h>
00284 #endif
00285 #include <netinet/in.h>
00286 #include <arpa/inet.h>
00287
00288 #include "asterisk/utils.h"
00289 #include "asterisk/lock.h"
00290 #include "asterisk/file.h"
00291 #include "asterisk/logger.h"
00292 #include "asterisk/channel.h"
00293 #include "asterisk/callerid.h"
00294 #include "asterisk/pbx.h"
00295 #include "asterisk/module.h"
00296 #include "asterisk/translate.h"
00297 #include "asterisk/features.h"
00298 #include "asterisk/options.h"
00299 #include "asterisk/cli.h"
00300 #include "asterisk/config.h"
00301 #include "asterisk/say.h"
00302 #include "asterisk/localtime.h"
00303 #include "asterisk/cdr.h"
00304 #include <termios.h>
00305
00306
00307 int ast_playtones_start(struct ast_channel *chan, int vol, const char* tonelist, int interruptible);
00308
00309 void ast_playtones_stop(struct ast_channel *chan);
00310
00311 static char *tdesc = "Radio Repeater / Remote Base version 0.70 07/22/2007";
00312
00313 static char *app = "Rpt";
00314
00315 static char *synopsis = "Radio Repeater/Remote Base Control System";
00316
00317 static char *descrip =
00318 " Rpt(nodename[|options]): Radio Remote Link or Remote Base Link Endpoint Process.\n"
00319 "\n"
00320 " Not specifying an option puts it in normal endpoint mode (where source\n"
00321 " IP and nodename are verified).\n"
00322 "\n"
00323 " Options are as follows:\n"
00324 "\n"
00325 " X - Normal endpoint mode WITHOUT security check. Only specify\n"
00326 " this if you have checked security already (like with an IAX2\n"
00327 " user/password or something).\n"
00328 "\n"
00329 " Rannounce-string[|timeout[|timeout-destination]] - Amateur Radio\n"
00330 " Reverse Autopatch. Caller is put on hold, and announcement (as\n"
00331 " specified by the 'announce-string') is played on radio system.\n"
00332 " Users of radio system can access autopatch, dial specified\n"
00333 " code, and pick up call. Announce-string is list of names of\n"
00334 " recordings, or \"PARKED\" to substitute code for un-parking,\n"
00335 " or \"NODE\" to substitute node number.\n"
00336 "\n"
00337 " P - Phone Control mode. This allows a regular phone user to have\n"
00338 " full control and audio access to the radio system. For the\n"
00339 " user to have DTMF control, the 'phone_functions' parameter\n"
00340 " must be specified for the node in 'rpt.conf'. An additional\n"
00341 " function (cop,6) must be listed so that PTT control is available.\n"
00342 "\n"
00343 " D - Dumb Phone Control mode. This allows a regular phone user to\n"
00344 " have full control and audio access to the radio system. In this\n"
00345 " mode, the PTT is activated for the entire length of the call.\n"
00346 " For the user to have DTMF control (not generally recomended in\n"
00347 " this mode), the 'dphone_functions' parameter must be specified\n"
00348 " for the node in 'rpt.conf'. Otherwise no DTMF control will be\n"
00349 " available to the phone user.\n"
00350 "\n";
00351
00352 static int debug = 0;
00353 static int nrpts = 0;
00354
00355 static char remdtmfstr[] = "0123456789*#ABCD";
00356
00357 enum {TOP_TOP,TOP_WON,WON_BEFREAD,BEFREAD_AFTERREAD};
00358
00359 int max_chan_stat [] = {22000,1000,22000,100,22000,2000,22000};
00360
00361 #define NRPTSTAT 7
00362
00363 struct rpt_chan_stat
00364 {
00365 struct timeval last;
00366 long long total;
00367 unsigned long count;
00368 unsigned long largest;
00369 struct timeval largest_time;
00370 };
00371
00372 char *discstr = "!!DISCONNECT!!";
00373 static char *remote_rig_ft897="ft897";
00374 static char *remote_rig_rbi="rbi";
00375 static char *remote_rig_kenwood="kenwood";
00376 static char *remote_rig_ic706="ic706";
00377
00378 #ifdef OLD_ASTERISK
00379 STANDARD_LOCAL_USER;
00380 LOCAL_USER_DECL;
00381 #endif
00382
00383 #define MSWAIT 200
00384 #define HANGTIME 5000
00385 #define TOTIME 180000
00386 #define IDTIME 300000
00387 #define MAXRPTS 20
00388 #define MAX_STAT_LINKS 32
00389 #define POLITEID 30000
00390 #define FUNCTDELAY 1500
00391
00392 #define MAXXLAT 20
00393 #define MAXXLATTIME 3
00394
00395 #define MAX_SYSSTATES 10
00396
00397 struct rpt_xlat
00398 {
00399 char funccharseq[MAXXLAT];
00400 char endcharseq[MAXXLAT];
00401 char passchars[MAXXLAT];
00402 int funcindex;
00403 int endindex;
00404 time_t lastone;
00405 } ;
00406
00407 static time_t starttime = 0;
00408
00409 static pthread_t rpt_master_thread;
00410
00411 struct rpt;
00412
00413 struct rpt_link
00414 {
00415 struct rpt_link *next;
00416 struct rpt_link *prev;
00417 char mode;
00418 char isremote;
00419 char phonemode;
00420 char name[MAXNODESTR];
00421 char lasttx;
00422 char lastrx;
00423 char lastrx1;
00424 char connected;
00425 char hasconnected;
00426 char perma;
00427 char thisconnected;
00428 char outbound;
00429 char disced;
00430 char killme;
00431 long elaptime;
00432 long disctime;
00433 long retrytimer;
00434 long retxtimer;
00435 long rerxtimer;
00436 int retries;
00437 int max_retries;
00438 int reconnects;
00439 long long connecttime;
00440 struct ast_channel *chan;
00441 struct ast_channel *pchan;
00442 char linklist[MAXLINKLIST];
00443 time_t linklistreceived;
00444 long linklisttimer;
00445 int dtmfed;
00446 int linkunkeytocttimer;
00447 struct ast_frame *lastf1,*lastf2;
00448 struct rpt_chan_stat chan_stat[NRPTSTAT];
00449 } ;
00450
00451 struct rpt_lstat
00452 {
00453 struct rpt_lstat *next;
00454 struct rpt_lstat *prev;
00455 char peer[MAXPEERSTR];
00456 char name[MAXNODESTR];
00457 char mode;
00458 char outbound;
00459 char reconnects;
00460 char thisconnected;
00461 long long connecttime;
00462 struct rpt_chan_stat chan_stat[NRPTSTAT];
00463 } ;
00464
00465 struct rpt_tele
00466 {
00467 struct rpt_tele *next;
00468 struct rpt_tele *prev;
00469 struct rpt *rpt;
00470 struct ast_channel *chan;
00471 int mode;
00472 struct rpt_link mylink;
00473 char param[TELEPARAMSIZE];
00474 int submode;
00475 pthread_t threadid;
00476 } ;
00477
00478 struct function_table_tag
00479 {
00480 char action[ACTIONSIZE];
00481 int (*function)(struct rpt *myrpt, char *param, char *digitbuf,
00482 int command_source, struct rpt_link *mylink);
00483 } ;
00484
00485
00486
00487 struct morse_bits
00488 {
00489 int len;
00490 int ddcomb;
00491 } ;
00492
00493 struct telem_defaults
00494 {
00495 char name[20];
00496 char value[80];
00497 } ;
00498
00499
00500 struct sysstate
00501 {
00502 char txdisable;
00503 char totdisable;
00504 char linkfundisable;
00505 char autopatchdisable;
00506 char schedulerdisable;
00507 char userfundisable;
00508 char alternatetail;
00509 };
00510
00511 static struct rpt
00512 {
00513 ast_mutex_t lock;
00514 ast_mutex_t remlock;
00515 struct ast_config *cfg;
00516 char reload;
00517
00518 char *name;
00519 char *rxchanname;
00520 char *txchanname;
00521 char *remote;
00522 struct rpt_chan_stat chan_stat[NRPTSTAT];
00523 unsigned int scram;
00524
00525 struct {
00526 char *ourcontext;
00527 char *ourcallerid;
00528 char *acctcode;
00529 char *ident;
00530 char *tonezone;
00531 char simple;
00532 char *functions;
00533 char *link_functions;
00534 char *phone_functions;
00535 char *dphone_functions;
00536 char *nodes;
00537 char *extnodes;
00538 char *extnodefile;
00539 int hangtime;
00540 int althangtime;
00541 int totime;
00542 int idtime;
00543 int tailmessagetime;
00544 int tailsquashedtime;
00545 int duplex;
00546 int politeid;
00547 char *tailmessages[500];
00548 int tailmessagemax;
00549 char *memory;
00550 char *macro;
00551 char *startupmacro;
00552 int iobase;
00553 char *ioport;
00554 char funcchar;
00555 char endchar;
00556 char nobusyout;
00557 char notelemtx;
00558 char propagate_dtmf;
00559 char propagate_phonedtmf;
00560 char linktolink;
00561 unsigned char civaddr;
00562 struct rpt_xlat inxlat;
00563 struct rpt_xlat outxlat;
00564 char *archivedir;
00565 int authlevel;
00566 char *csstanzaname;
00567 char *skedstanzaname;
00568 char *txlimitsstanzaname;
00569 long monminblocks;
00570 int remoteinacttimeout;
00571 int remotetimeout;
00572 int remotetimeoutwarning;
00573 int remotetimeoutwarningfreq;
00574 int sysstate_cur;
00575 struct sysstate s[MAX_SYSSTATES];
00576 } p;
00577 struct rpt_link links;
00578 int unkeytocttimer;
00579 char keyed;
00580 char exttx;
00581 char localtx;
00582 char remoterx;
00583 char remotetx;
00584 char remoteon;
00585 char remtxfreqok;
00586 char tounkeyed;
00587 char tonotify;
00588 char dtmfbuf[MAXDTMF];
00589 char macrobuf[MAXMACRO];
00590 char rem_dtmfbuf[MAXDTMF];
00591 char lastdtmfcommand[MAXDTMF];
00592 char cmdnode[50];
00593 struct ast_channel *rxchannel,*txchannel, *monchannel;
00594 struct ast_channel *pchannel,*txpchannel;
00595 struct ast_frame *lastf1,*lastf2;
00596 struct rpt_tele tele;
00597 struct timeval lasttv,curtv;
00598 pthread_t rpt_call_thread,rpt_thread;
00599 time_t dtmf_time,rem_dtmf_time,dtmf_time_rem;
00600 int tailtimer,totimer,idtimer,txconf,conf,callmode,cidx,scantimer,tmsgtimer,skedtimer;
00601 int mustid,tailid;
00602 int tailevent;
00603 int telemrefcount;
00604 int dtmfidx,rem_dtmfidx;
00605 int dailytxtime,dailykerchunks,totalkerchunks,dailykeyups,totalkeyups,timeouts;
00606 int totalexecdcommands, dailyexecdcommands;
00607 long retxtimer;
00608 long rerxtimer;
00609 long long totaltxtime;
00610 char mydtmf;
00611 char exten[AST_MAX_EXTENSION];
00612 char freq[MAXREMSTR],rxpl[MAXREMSTR],txpl[MAXREMSTR];
00613 char offset;
00614 char powerlevel;
00615 char txplon;
00616 char rxplon;
00617 char remmode;
00618 char tunerequest;
00619 char hfscanmode;
00620 int hfscanstatus;
00621 char hfscanstop;
00622 char lastlinknode[MAXNODESTR];
00623 char savednodes[MAXNODESTR];
00624 int stopgen;
00625 char patchfarenddisconnect;
00626 char patchnoct;
00627 char patchquiet;
00628 char patchcontext[MAXPATCHCONTEXT];
00629 int patchdialtime;
00630 int macro_longest;
00631 int phone_longestfunc;
00632 int dphone_longestfunc;
00633 int link_longestfunc;
00634 int longestfunc;
00635 int longestnode;
00636 int threadrestarts;
00637 int tailmessagen;
00638 time_t disgorgetime;
00639 time_t lastthreadrestarttime;
00640 long macrotimer;
00641 char lastnodewhichkeyedusup[MAXNODESTR];
00642 int dtmf_local_timer;
00643 char dtmf_local_str[100];
00644 struct ast_filestream *monstream;
00645 char loginuser[50];
00646 char loginlevel[10];
00647 long authtelltimer;
00648 long authtimer;
00649 int iofd;
00650 time_t start_time,last_activity_time;
00651 #ifdef __RPT_NOTCH
00652 struct rptfilter
00653 {
00654 char desc[100];
00655 float x0;
00656 float x1;
00657 float x2;
00658 float y0;
00659 float y1;
00660 float y2;
00661 float gain;
00662 float const0;
00663 float const1;
00664 float const2;
00665 } filters[MAXFILTERS];
00666 #endif
00667 #ifdef _MDC_DECODE_H_
00668 mdc_decoder_t *mdc;
00669 unsigned short lastunit;
00670 #endif
00671 } rpt_vars[MAXRPTS];
00672
00673 struct nodelog {
00674 struct nodelog *next;
00675 struct nodelog *prev;
00676 time_t timestamp;
00677 char archivedir[MAXNODESTR];
00678 char str[MAXNODESTR * 2];
00679 } nodelog;
00680
00681 static int service_scan(struct rpt *myrpt);
00682 static int set_mode_ft897(struct rpt *myrpt, char newmode);
00683 static int set_mode_ic706(struct rpt *myrpt, char newmode);
00684 static int simple_command_ft897(struct rpt *myrpt, char command);
00685 static int setrem(struct rpt *myrpt);
00686
00687 AST_MUTEX_DEFINE_STATIC(nodeloglock);
00688
00689 AST_MUTEX_DEFINE_STATIC(nodelookuplock);
00690
00691 #ifdef APP_RPT_LOCK_DEBUG
00692
00693 #warning COMPILING WITH LOCK-DEBUGGING ENABLED!!
00694
00695 #define MAXLOCKTHREAD 100
00696
00697 #define rpt_mutex_lock(x) _rpt_mutex_lock(x,myrpt,__LINE__)
00698 #define rpt_mutex_unlock(x) _rpt_mutex_unlock(x,myrpt,__LINE__)
00699
00700 struct lockthread
00701 {
00702 pthread_t id;
00703 int lockcount;
00704 int lastlock;
00705 int lastunlock;
00706 } lockthreads[MAXLOCKTHREAD];
00707
00708
00709 struct by_lightning
00710 {
00711 int line;
00712 struct timeval tv;
00713 struct rpt *rpt;
00714 struct lockthread lockthread;
00715 } lock_ring[32];
00716
00717 int lock_ring_index = 0;
00718
00719 AST_MUTEX_DEFINE_STATIC(locklock);
00720
00721 static struct lockthread *get_lockthread(pthread_t id)
00722 {
00723 int i;
00724
00725 for(i = 0; i < MAXLOCKTHREAD; i++)
00726 {
00727 if (lockthreads[i].id == id) return(&lockthreads[i]);
00728 }
00729 return(NULL);
00730 }
00731
00732 static struct lockthread *put_lockthread(pthread_t id)
00733 {
00734 int i;
00735
00736 for(i = 0; i < MAXLOCKTHREAD; i++)
00737 {
00738 if (lockthreads[i].id == id)
00739 return(&lockthreads[i]);
00740 }
00741 for(i = 0; i < MAXLOCKTHREAD; i++)
00742 {
00743 if (!lockthreads[i].id)
00744 {
00745 lockthreads[i].lockcount = 0;
00746 lockthreads[i].lastlock = 0;
00747 lockthreads[i].lastunlock = 0;
00748 lockthreads[i].id = id;
00749 return(&lockthreads[i]);
00750 }
00751 }
00752 return(NULL);
00753 }
00754
00755
00756 static void rpt_mutex_spew(void)
00757 {
00758 struct by_lightning lock_ring_copy[32];
00759 int lock_ring_index_copy;
00760 int i,j;
00761 long long diff;
00762 char a[100];
00763 struct timeval lasttv;
00764
00765 ast_mutex_lock(&locklock);
00766 memcpy(&lock_ring_copy, &lock_ring, sizeof(lock_ring_copy));
00767 lock_ring_index_copy = lock_ring_index;
00768 ast_mutex_unlock(&locklock);
00769
00770 lasttv.tv_sec = lasttv.tv_usec = 0;
00771 for(i = 0 ; i < 32 ; i++)
00772 {
00773 j = (i + lock_ring_index_copy) % 32;
00774 strftime(a,sizeof(a) - 1,"%m/%d/%Y %H:%M:%S",
00775 localtime(&lock_ring_copy[j].tv.tv_sec));
00776 diff = 0;
00777 if(lasttv.tv_sec)
00778 {
00779 diff = (lock_ring_copy[j].tv.tv_sec - lasttv.tv_sec)
00780 * 1000000;
00781 diff += (lock_ring_copy[j].tv.tv_usec - lasttv.tv_usec);
00782 }
00783 lasttv.tv_sec = lock_ring_copy[j].tv.tv_sec;
00784 lasttv.tv_usec = lock_ring_copy[j].tv.tv_usec;
00785 if (!lock_ring_copy[j].tv.tv_sec) continue;
00786 if (lock_ring_copy[j].line < 0)
00787 {
00788 ast_log(LOG_NOTICE,"LOCKDEBUG [#%d] UNLOCK app_rpt.c:%d node %s pid %x diff %lld us at %s.%06d\n",
00789 i - 31,-lock_ring_copy[j].line,lock_ring_copy[j].rpt->name,(int) lock_ring_copy[j].lockthread.id,diff,a,(int)lock_ring_copy[j].tv.tv_usec);
00790 }
00791 else
00792 {
00793 ast_log(LOG_NOTICE,"LOCKDEBUG [#%d] LOCK app_rpt.c:%d node %s pid %x diff %lld us at %s.%06d\n",
00794 i - 31,lock_ring_copy[j].line,lock_ring_copy[j].rpt->name,(int) lock_ring_copy[j].lockthread.id,diff,a,(int)lock_ring_copy[j].tv.tv_usec);
00795 }
00796 }
00797 }
00798
00799
00800 static void _rpt_mutex_lock(ast_mutex_t *lockp, struct rpt *myrpt, int line)
00801 {
00802 struct lockthread *t;
00803 pthread_t id;
00804
00805 id = pthread_self();
00806 ast_mutex_lock(&locklock);
00807 t = put_lockthread(id);
00808 if (!t)
00809 {
00810 ast_mutex_unlock(&locklock);
00811 return;
00812 }
00813 if (t->lockcount)
00814 {
00815 int lastline = t->lastlock;
00816 ast_mutex_unlock(&locklock);
00817 ast_log(LOG_NOTICE,"rpt_mutex_lock: Double lock request line %d node %s pid %x, last lock was line %d\n",line,myrpt->name,(int) t->id,lastline);
00818 rpt_mutex_spew();
00819 return;
00820 }
00821 t->lastlock = line;
00822 t->lockcount = 1;
00823 gettimeofday(&lock_ring[lock_ring_index].tv, NULL);
00824 lock_ring[lock_ring_index].rpt = myrpt;
00825 memcpy(&lock_ring[lock_ring_index].lockthread,t,sizeof(struct lockthread));
00826 lock_ring[lock_ring_index++].line = line;
00827 if(lock_ring_index == 32)
00828 lock_ring_index = 0;
00829 ast_mutex_unlock(&locklock);
00830 ast_mutex_lock(lockp);
00831 }
00832
00833
00834 static void _rpt_mutex_unlock(ast_mutex_t *lockp, struct rpt *myrpt, int line)
00835 {
00836 struct lockthread *t;
00837 pthread_t id;
00838
00839 id = pthread_self();
00840 ast_mutex_lock(&locklock);
00841 t = put_lockthread(id);
00842 if (!t)
00843 {
00844 ast_mutex_unlock(&locklock);
00845 return;
00846 }
00847 if (!t->lockcount)
00848 {
00849 int lastline = t->lastunlock;
00850 ast_mutex_unlock(&locklock);
00851 ast_log(LOG_NOTICE,"rpt_mutex_lock: Double un-lock request line %d node %s pid %x, last un-lock was line %d\n",line,myrpt->name,(int) t->id,lastline);
00852 rpt_mutex_spew();
00853 return;
00854 }
00855 t->lastunlock = line;
00856 t->lockcount = 0;
00857 gettimeofday(&lock_ring[lock_ring_index].tv, NULL);
00858 lock_ring[lock_ring_index].rpt = myrpt;
00859 memcpy(&lock_ring[lock_ring_index].lockthread,t,sizeof(struct lockthread));
00860 lock_ring[lock_ring_index++].line = -line;
00861 if(lock_ring_index == 32)
00862 lock_ring_index = 0;
00863 ast_mutex_unlock(&locklock);
00864 ast_mutex_unlock(lockp);
00865 }
00866
00867 #else
00868
00869 #define rpt_mutex_lock(x) ast_mutex_lock(x)
00870 #define rpt_mutex_unlock(x) ast_mutex_unlock(x)
00871
00872 #endif
00873
00874
00875
00876
00877
00878 static int multimode_capable(struct rpt *myrpt)
00879 {
00880 if(!strcmp(myrpt->remote, remote_rig_ft897))
00881 return 1;
00882 if(!strcmp(myrpt->remote, remote_rig_ic706))
00883 return 1;
00884 return 0;
00885 }
00886
00887
00888
00889
00890
00891
00892 static int rpt_do_debug(int fd, int argc, char *argv[]);
00893 static int rpt_do_dump(int fd, int argc, char *argv[]);
00894 static int rpt_do_stats(int fd, int argc, char *argv[]);
00895 static int rpt_do_lstats(int fd, int argc, char *argv[]);
00896 static int rpt_do_nodes(int fd, int argc, char *argv[]);
00897 static int rpt_do_reload(int fd, int argc, char *argv[]);
00898 static int rpt_do_restart(int fd, int argc, char *argv[]);
00899 static int rpt_do_fun(int fd, int argc, char *argv[]);
00900
00901 static char debug_usage[] =
00902 "Usage: rpt debug level {0-7}\n"
00903 " Enables debug messages in app_rpt\n";
00904
00905 static char dump_usage[] =
00906 "Usage: rpt dump <nodename>\n"
00907 " Dumps struct debug info to log\n";
00908
00909 static char dump_stats[] =
00910 "Usage: rpt stats <nodename>\n"
00911 " Dumps node statistics to console\n";
00912
00913 static char dump_lstats[] =
00914 "Usage: rpt lstats <nodename>\n"
00915 " Dumps link statistics to console\n";
00916
00917 static char dump_nodes[] =
00918 "Usage: rpt nodes <nodename>\n"
00919 " Dumps a list of directly and indirectly connected nodes to the console\n";
00920
00921 static char reload_usage[] =
00922 "Usage: rpt reload\n"
00923 " Reloads app_rpt running config parameters\n";
00924
00925 static char restart_usage[] =
00926 "Usage: rpt restart\n"
00927 " Restarts app_rpt\n";
00928
00929 static char fun_usage[] =
00930 "Usage: rpt fun <nodename> <command>\n"
00931 " Send a DTMF function to a node\n";
00932
00933
00934 static struct ast_cli_entry cli_debug =
00935 { { "rpt", "debug", "level" }, rpt_do_debug,
00936 "Enable app_rpt debugging", debug_usage };
00937
00938 static struct ast_cli_entry cli_dump =
00939 { { "rpt", "dump" }, rpt_do_dump,
00940 "Dump app_rpt structs for debugging", dump_usage };
00941
00942 static struct ast_cli_entry cli_stats =
00943 { { "rpt", "stats" }, rpt_do_stats,
00944 "Dump node statistics", dump_stats };
00945
00946 static struct ast_cli_entry cli_nodes =
00947 { { "rpt", "nodes" }, rpt_do_nodes,
00948 "Dump node list", dump_nodes };
00949
00950 static struct ast_cli_entry cli_lstats =
00951 { { "rpt", "lstats" }, rpt_do_lstats,
00952 "Dump link statistics", dump_lstats };
00953
00954 static struct ast_cli_entry cli_reload =
00955 { { "rpt", "reload" }, rpt_do_reload,
00956 "Reload app_rpt config", reload_usage };
00957
00958 static struct ast_cli_entry cli_restart =
00959 { { "rpt", "restart" }, rpt_do_restart,
00960 "Restart app_rpt", restart_usage };
00961
00962 static struct ast_cli_entry cli_fun =
00963 { { "rpt", "fun" }, rpt_do_fun,
00964 "Execute a DTMF function", fun_usage };
00965
00966
00967
00968
00969
00970
00971 static struct telem_defaults tele_defs[] = {
00972 {"ct1","|t(350,0,100,3072)(500,0,100,3072)(660,0,100,3072)"},
00973 {"ct2","|t(660,880,150,3072)"},
00974 {"ct3","|t(440,0,150,3072)"},
00975 {"ct4","|t(550,0,150,3072)"},
00976 {"ct5","|t(660,0,150,3072)"},
00977 {"ct6","|t(880,0,150,3072)"},
00978 {"ct7","|t(660,440,150,3072)"},
00979 {"ct8","|t(700,1100,150,3072)"},
00980 {"remotemon","|t(1600,0,75,2048)"},
00981 {"remotetx","|t(2000,0,75,2048)(0,0,75,0)(1600,0,75,2048)"},
00982 {"cmdmode","|t(900,904,200,2048)"},
00983 {"functcomplete","|t(1000,0,100,2048)(0,0,100,0)(1000,0,100,2048)"}
00984 } ;
00985
00986
00987
00988
00989
00990 static int setrbi(struct rpt *myrpt);
00991 static int set_ft897(struct rpt *myrpt);
00992 static int set_ic706(struct rpt *myrpt);
00993 static int setkenwood(struct rpt *myrpt);
00994 static int setrbi_check(struct rpt *myrpt);
00995
00996
00997
00998
00999
01000
01001
01002 static int function_ilink(struct rpt *myrpt, char *param, char *digitbuf, int command_source, struct rpt_link *mylink);
01003 static int function_autopatchup(struct rpt *myrpt, char *param, char *digitbuf, int command_source, struct rpt_link *mylink);
01004 static int function_autopatchdn(struct rpt *myrpt, char *param, char *digitbuf, int command_source, struct rpt_link *mylink);
01005 static int function_status(struct rpt *myrpt, char *param, char *digitbuf, int command_source, struct rpt_link *mylink);
01006 static int function_cop(struct rpt *myrpt, char *param, char *digitbuf, int command_source, struct rpt_link *mylink);
01007 static int function_remote(struct rpt *myrpt, char *param, char *digitbuf, int command_source, struct rpt_link *mylink);
01008 static int function_macro(struct rpt *myrpt, char *param, char *digitbuf, int command_source, struct rpt_link *mylink);
01009
01010
01011
01012
01013 static struct function_table_tag function_table[] = {
01014 {"cop", function_cop},
01015 {"autopatchup", function_autopatchup},
01016 {"autopatchdn", function_autopatchdn},
01017 {"ilink", function_ilink},
01018 {"status", function_status},
01019 {"remote", function_remote},
01020 {"macro", function_macro}
01021 } ;
01022
01023 static long diskavail(struct rpt *myrpt)
01024 {
01025 struct statfs statfsbuf;
01026
01027 if (!myrpt->p.archivedir) return(0);
01028 if (statfs(myrpt->p.archivedir,&statfsbuf) == -1)
01029 {
01030 ast_log(LOG_WARNING,"Cannot get filesystem size for %s node %s\n",
01031 myrpt->p.archivedir,myrpt->name);
01032 return(-1);
01033 }
01034 return(statfsbuf.f_bavail);
01035 }
01036
01037 static void do_dtmf_phone(struct rpt *myrpt, struct rpt_link *mylink, char c)
01038 {
01039 struct rpt_link *l;
01040
01041 l = myrpt->links.next;
01042
01043 while(l != &myrpt->links)
01044 {
01045 if (!l->phonemode)
01046 {
01047 l = l->next;
01048 continue;
01049 }
01050
01051 if (mylink && (l == mylink))
01052 {
01053 l = l->next;
01054 continue;
01055 }
01056 if (l->chan) ast_senddigit(l->chan,c);
01057 l = l->next;
01058 }
01059 return;
01060 }
01061
01062
01063 static void donodelog(struct rpt *myrpt,char *str)
01064 {
01065 struct nodelog *nodep;
01066 char datestr[100];
01067
01068 if (!myrpt->p.archivedir) return;
01069 nodep = (struct nodelog *)malloc(sizeof(struct nodelog));
01070 if (nodep == NULL)
01071 {
01072 ast_log(LOG_ERROR,"Cannot get memory for node log");
01073 return;
01074 }
01075 time(&nodep->timestamp);
01076 strncpy(nodep->archivedir,myrpt->p.archivedir,
01077 sizeof(nodep->archivedir) - 1);
01078 strftime(datestr,sizeof(datestr) - 1,"%Y%m%d%H%M%S",
01079 localtime(&nodep->timestamp));
01080 snprintf(nodep->str,sizeof(nodep->str) - 1,"%s %s,%s\n",
01081 myrpt->name,datestr,str);
01082 ast_mutex_lock(&nodeloglock);
01083 insque((struct qelem *) nodep, (struct qelem *) nodelog.prev);
01084 ast_mutex_unlock(&nodeloglock);
01085 }
01086
01087
01088 static void do_dtmf_local(struct rpt *myrpt, char c)
01089 {
01090 int i;
01091 char digit;
01092 static const char* dtmf_tones[] = {
01093 "!941+1336/200,!0/200",
01094 "!697+1209/200,!0/200",
01095 "!697+1336/200,!0/200",
01096 "!697+1477/200,!0/200",
01097 "!770+1209/200,!0/200",
01098 "!770+1336/200,!0/200",
01099 "!770+1477/200,!0/200",
01100 "!852+1209/200,!0/200",
01101 "!852+1336/200,!0/200",
01102 "!852+1477/200,!0/200",
01103 "!697+1633/200,!0/200",
01104 "!770+1633/200,!0/200",
01105 "!852+1633/200,!0/200",
01106 "!941+1633/200,!0/200",
01107 "!941+1209/200,!0/200",
01108 "!941+1477/200,!0/200" };
01109
01110
01111 if (c)
01112 {
01113 snprintf(myrpt->dtmf_local_str + strlen(myrpt->dtmf_local_str),sizeof(myrpt->dtmf_local_str) - 1,"%c",c);
01114 if (!myrpt->dtmf_local_timer)
01115 myrpt->dtmf_local_timer = DTMF_LOCAL_STARTTIME;
01116 }
01117
01118 if (myrpt->dtmf_local_timer == 1)
01119 {
01120
01121 if (myrpt->dtmf_local_str[0])
01122 {
01123 digit = myrpt->dtmf_local_str[0];
01124 myrpt->dtmf_local_str[0] = 0;
01125 for(i = 1; myrpt->dtmf_local_str[i]; i++)
01126 {
01127 myrpt->dtmf_local_str[i - 1] =
01128 myrpt->dtmf_local_str[i];
01129 }
01130 myrpt->dtmf_local_str[i - 1] = 0;
01131 myrpt->dtmf_local_timer = DTMF_LOCAL_TIME;
01132 rpt_mutex_unlock(&myrpt->lock);
01133 if (digit >= '0' && digit <='9')
01134 ast_playtones_start(myrpt->txchannel, 0, dtmf_tones[digit-'0'], 0);
01135 else if (digit >= 'A' && digit <= 'D')
01136 ast_playtones_start(myrpt->txchannel, 0, dtmf_tones[digit-'A'+10], 0);
01137 else if (digit == '*')
01138 ast_playtones_start(myrpt->txchannel, 0, dtmf_tones[14], 0);
01139 else if (digit == '#')
01140 ast_playtones_start(myrpt->txchannel, 0, dtmf_tones[15], 0);
01141 else {
01142
01143 ast_log(LOG_DEBUG, "Unable to generate DTMF tone '%c' for '%s'\n", digit, myrpt->txchannel->name);
01144 }
01145 rpt_mutex_lock(&myrpt->lock);
01146 }
01147 else
01148 {
01149 myrpt->dtmf_local_timer = 0;
01150 }
01151 }
01152 }
01153
01154 static int openserial(char *fname)
01155 {
01156 struct termios mode;
01157 int fd;
01158
01159 fd = open(fname,O_RDWR);
01160 if (fd == -1)
01161 {
01162 ast_log(LOG_WARNING,"Cannot open serial port %s\n",fname);
01163 return -1;
01164 }
01165 memset(&mode, 0, sizeof(mode));
01166 if (tcgetattr(fd, &mode)) {
01167 ast_log(LOG_WARNING, "Unable to get serial parameters on %s: %s\n", fname, strerror(errno));
01168 return -1;
01169 }
01170 #ifndef SOLARIS
01171 cfmakeraw(&mode);
01172 #else
01173 mode.c_iflag &= ~(IGNBRK|BRKINT|PARMRK|ISTRIP
01174 |INLCR|IGNCR|ICRNL|IXON);
01175 mode.c_oflag &= ~OPOST;
01176 mode.c_lflag &= ~(ECHO|ECHONL|ICANON|ISIG|IEXTEN);
01177 mode.c_cflag &= ~(CSIZE|PARENB|CRTSCTS);
01178 mode.c_cflag |= CS8;
01179 mode.c_cc[TIME] = 3;
01180 mode.c_cc[MAX] = 1;
01181 #endif
01182
01183 cfsetispeed(&mode, B9600);
01184 cfsetospeed(&mode, B9600);
01185 if (tcsetattr(fd, TCSANOW, &mode))
01186 ast_log(LOG_WARNING, "Unable to set serial parameters on %s: %s\n", fname, strerror(errno));
01187 return(fd);
01188 }
01189
01190 static char func_xlat(struct rpt *myrpt,char c,struct rpt_xlat *xlat)
01191 {
01192 time_t now;
01193 int gotone;
01194
01195 time(&now);
01196 gotone = 0;
01197
01198 if ((now - xlat->lastone) > MAXXLATTIME)
01199 {
01200 xlat->funcindex = xlat->endindex = 0;
01201 }
01202 if (xlat->funccharseq[0] && (c == xlat->funccharseq[xlat->funcindex++]))
01203 {
01204 time(&xlat->lastone);
01205 gotone = 1;
01206 if (!xlat->funccharseq[xlat->funcindex])
01207 {
01208 xlat->funcindex = xlat->endindex = 0;
01209 return(myrpt->p.funcchar);
01210 }
01211 } else xlat->funcindex = 0;
01212 if (xlat->endcharseq[0] && (c == xlat->endcharseq[xlat->endindex++]))
01213 {
01214 time(&xlat->lastone);
01215 gotone = 1;
01216 if (!xlat->endcharseq[xlat->endindex])
01217 {
01218 xlat->funcindex = xlat->endindex = 0;
01219 return(myrpt->p.endchar);
01220 }
01221 } else xlat->endindex = 0;
01222
01223 if (gotone) return(0);
01224
01225 if (!xlat->passchars[0]) return(c);
01226
01227 if (strchr(xlat->passchars,c)) return(c);
01228 return(0);
01229 }
01230
01231
01232
01233
01234
01235 static char *eatwhite(char *s)
01236 {
01237 while((*s == ' ') || (*s == 0x09)){
01238 if(!*s)
01239 break;
01240 s++;
01241 }
01242 return s;
01243 }
01244
01245
01246
01247
01248
01249
01250
01251
01252
01253
01254
01255 static int finddelim(char *str, char *strp[], int limit)
01256 {
01257 int i,l,inquo;
01258
01259 inquo = 0;
01260 i = 0;
01261 strp[i++] = str;
01262 if (!*str)
01263 {
01264 strp[0] = 0;
01265 return(0);
01266 }
01267 for(l = 0; *str && (l < limit) ; str++)
01268 {
01269 if (*str == QUOTECHR)
01270 {
01271 if (inquo)
01272 {
01273 *str = 0;
01274 inquo = 0;
01275 }
01276 else
01277 {
01278 strp[i - 1] = str + 1;
01279 inquo = 1;
01280 }
01281 }
01282 if ((*str == DELIMCHR) && (!inquo))
01283 {
01284 *str = 0;
01285 l++;
01286 strp[i++] = str + 1;
01287 }
01288 }
01289 strp[i] = 0;
01290 return(i);
01291
01292 }
01293
01294
01295 static void __mklinklist(struct rpt *myrpt, struct rpt_link *mylink, char *buf)
01296 {
01297 struct rpt_link *l;
01298 char mode;
01299 int i,spos;
01300
01301 buf[0] = 0;
01302
01303 for(l = myrpt->links.next; l != &myrpt->links; l = l->next)
01304 {
01305
01306 if (l->name[0] == '0') continue;
01307
01308 if (l == mylink) continue;
01309 if (mylink && (!strcmp(l->name,mylink->name))) continue;
01310
01311 mode = 'T';
01312 if (!l->mode) mode = 'R';
01313 if (!l->thisconnected) mode = 'C';
01314 spos = strlen(buf);
01315 if (spos)
01316 {
01317 strcat(buf,",");
01318 spos++;
01319 }
01320
01321 if (l->linklist[0])
01322 {
01323 snprintf(buf + spos,MAXLINKLIST - spos,
01324 "%c%s,%s",mode,l->name,l->linklist);
01325 }
01326 else
01327 {
01328 snprintf(buf + spos,MAXLINKLIST - spos,
01329 "%c%s",mode,l->name);
01330 }
01331
01332 if (mode == 'T') continue;
01333
01334 for(i = spos; buf[i]; i++)
01335 {
01336 if (buf[i] == 'T') buf[i] = mode;
01337 if ((buf[i] == 'R') && (mode == 'C')) buf[i] = mode;
01338 }
01339 }
01340 return;
01341 }
01342
01343
01344 static void __kickshort(struct rpt *myrpt)
01345 {
01346 struct rpt_link *l;
01347
01348 for(l = myrpt->links.next; l != &myrpt->links; l = l->next)
01349 {
01350
01351 if (l->name[0] == '0') continue;
01352 l->linklisttimer = LINKLISTSHORTTIME;
01353 }
01354 return;
01355 }
01356
01357 static char *node_lookup(struct rpt *myrpt,char *digitbuf)
01358 {
01359
01360 char *val;
01361 int longestnode,j;
01362 struct stat mystat;
01363 static time_t last = 0;
01364 static struct ast_config *ourcfg = NULL;
01365 struct ast_variable *vp;
01366
01367
01368 val = (char *) ast_variable_retrieve(myrpt->cfg, myrpt->p.nodes, digitbuf);
01369 if (val) return(val);
01370 ast_mutex_lock(&nodelookuplock);
01371
01372 if (stat(myrpt->p.extnodefile,&mystat) == -1)
01373 {
01374 if (ourcfg) ast_config_destroy(ourcfg);
01375 ourcfg = NULL;
01376 ast_mutex_unlock(&nodelookuplock);
01377 return(NULL);
01378 }
01379
01380 if (mystat.st_mtime > last)
01381 {
01382 if (ourcfg) ast_config_destroy(ourcfg);
01383 ourcfg = ast_config_load(myrpt->p.extnodefile);
01384
01385 if (!ourcfg)
01386 {
01387 ast_mutex_unlock(&nodelookuplock);
01388 return(NULL);
01389 }
01390
01391 last = mystat.st_mtime;
01392
01393
01394 longestnode = 0;
01395 vp = ast_variable_browse(myrpt->cfg, myrpt->p.nodes);
01396 while(vp){
01397 j = strlen(vp->name);
01398 if (j > longestnode)
01399 longestnode = j;
01400 vp = vp->next;
01401 }
01402
01403 vp = ast_variable_browse(ourcfg, myrpt->p.extnodes);
01404 while(vp){
01405 j = strlen(vp->name);
01406 if (j > longestnode)
01407 longestnode = j;
01408 vp = vp->next;
01409 }
01410
01411 myrpt->longestnode = longestnode;
01412 }
01413 val = NULL;
01414 if (ourcfg)
01415 val = (char *) ast_variable_retrieve(ourcfg, myrpt->p.extnodes, digitbuf);
01416 ast_mutex_unlock(&nodelookuplock);
01417 return(val);
01418 }
01419
01420
01421
01422
01423
01424
01425 static int matchkeyword(char *string, char **param, char *keywords[])
01426 {
01427 int i,ls;
01428 for( i = 0 ; keywords[i] ; i++){
01429 ls = strlen(keywords[i]);
01430 if(!ls){
01431 *param = NULL;
01432 return 0;
01433 }
01434 if(!strncmp(string, keywords[i], ls)){
01435 if(param)
01436 *param = string + ls;
01437 return i + 1;
01438 }
01439 }
01440 param = NULL;
01441 return 0;
01442 }
01443
01444
01445
01446
01447
01448
01449 static char *skipchars(char *string, char *charlist)
01450 {
01451 int i;
01452 while(*string){
01453 for(i = 0; charlist[i] ; i++){
01454 if(*string == charlist[i]){
01455 string++;
01456 break;
01457 }
01458 }
01459 if(!charlist[i])
01460 return string;
01461 }
01462 return string;
01463 }
01464
01465
01466
01467 static int myatoi(char *str)
01468 {
01469 int ret;
01470
01471 if (str == NULL) return -1;
01472
01473 if (sscanf(str,"%i",&ret) != 1) return -1;
01474 return ret;
01475 }
01476
01477 static int mycompar(const void *a, const void *b)
01478 {
01479 char **x = (char **) a;
01480 char **y = (char **) b;
01481 int xoff,yoff;
01482
01483 if ((**x < '0') || (**x > '9')) xoff = 1; else xoff = 0;
01484 if ((**y < '0') || (**y > '9')) yoff = 1; else yoff = 0;
01485 return(strcmp((*x) + xoff,(*y) + yoff));
01486 }
01487
01488 #ifdef __RPT_NOTCH
01489
01490
01491 static void rpt_filter(struct rpt *myrpt, volatile short *buf, int len)
01492 {
01493 int i,j;
01494 struct rptfilter *f;
01495
01496 for(i = 0; i < len; i++)
01497 {
01498 for(j = 0; j < MAXFILTERS; j++)
01499 {
01500 f = &myrpt->filters[j];
01501 if (!*f->desc) continue;
01502 f->x0 = f->x1; f->x1 = f->x2;
01503 f->x2 = ((float)buf[i]) / f->gain;
01504 f->y0 = f->y1; f->y1 = f->y2;
01505 f->y2 = (f->x0 + f->x2) + f->const0 * f->x1
01506 + (f->const1 * f->y0) + (f->const2 * f->y1);
01507 buf[i] = (short)f->y2;
01508 }
01509 }
01510 }
01511
01512 #endif
01513
01514
01515
01516
01517
01518
01519
01520
01521
01522
01523
01524
01525
01526
01527
01528
01529
01530
01531 static void rpt_localtime( time_t * t, struct tm *lt)
01532 {
01533 #ifdef OLD_ASTERISK
01534 localtime_r(t, lt);
01535 #else
01536 ast_localtime(t, lt, NULL);
01537 #endif
01538 }
01539
01540
01541
01542 static int retrieve_astcfgint(struct rpt *myrpt,char *category, char *name, int min, int max, int defl)
01543 {
01544 char *var;
01545 int ret;
01546 char include_zero = 0;
01547
01548 if(min < 0){
01549 min = -min;
01550 include_zero = 1;
01551 }
01552
01553 var = (char *) ast_variable_retrieve(myrpt->cfg, category, name);
01554 if(var){
01555 ret = myatoi(var);
01556 if(include_zero && !ret)
01557 return 0;
01558 if(ret < min)
01559 ret = min;
01560 if(ret > max)
01561 ret = max;
01562 }
01563 else
01564 ret = defl;
01565 return ret;
01566 }
01567
01568
01569 static void load_rpt_vars(int n,int init)
01570 {
01571 char *this,*val;
01572 int i,j,longestnode;
01573 struct ast_variable *vp;
01574 struct ast_config *cfg;
01575 char *strs[100];
01576 char s1[256];
01577 static char *cs_keywords[] = {"rptena","rptdis","apena","apdis","lnkena","lnkdis","totena","totdis","skena","skdis",
01578 "ufena","ufdis","atena","atdis",NULL};
01579
01580 if (option_verbose > 2)
01581 ast_verbose(VERBOSE_PREFIX_3 "%s config for repeater %s\n",
01582 (init) ? "Loading initial" : "Re-Loading",rpt_vars[n].name);
01583 ast_mutex_lock(&rpt_vars[n].lock);
01584 if (rpt_vars[n].cfg) ast_config_destroy(rpt_vars[n].cfg);
01585 cfg = ast_config_load("rpt.conf");
01586 if (!cfg) {
01587 ast_mutex_unlock(&rpt_vars[n].lock);
01588 ast_log(LOG_NOTICE, "Unable to open radio repeater configuration rpt.conf. Radio Repeater disabled.\n");
01589 pthread_exit(NULL);
01590 }
01591 rpt_vars[n].cfg = cfg;
01592 this = rpt_vars[n].name;
01593 memset(&rpt_vars[n].p,0,sizeof(rpt_vars[n].p));
01594 if (init)
01595 {
01596 char *cp;
01597 int savearea = (char *)&rpt_vars[n].p - (char *)&rpt_vars[n];
01598
01599 cp = (char *) &rpt_vars[n].p;
01600 memset(cp + sizeof(rpt_vars[n].p),0,
01601 sizeof(rpt_vars[n]) - (sizeof(rpt_vars[n].p) + savearea));
01602 rpt_vars[n].tele.next = &rpt_vars[n].tele;
01603 rpt_vars[n].tele.prev = &rpt_vars[n].tele;
01604 rpt_vars[n].rpt_thread = AST_PTHREADT_NULL;
01605 rpt_vars[n].tailmessagen = 0;
01606 }
01607 #ifdef __RPT_NOTCH
01608
01609 memset(&rpt_vars[n].filters,0,sizeof(rpt_vars[n].filters));
01610 #endif
01611 val = (char *) ast_variable_retrieve(cfg,this,"context");
01612 if (val) rpt_vars[n].p.ourcontext = val;
01613 else rpt_vars[n].p.ourcontext = this;
01614 val = (char *) ast_variable_retrieve(cfg,this,"callerid");
01615 if (val) rpt_vars[n].p.ourcallerid = val;
01616 val = (char *) ast_variable_retrieve(cfg,this,"accountcode");
01617 if (val) rpt_vars[n].p.acctcode = val;
01618 val = (char *) ast_variable_retrieve(cfg,this,"idrecording");
01619 if (val) rpt_vars[n].p.ident = val;
01620 val = (char *) ast_variable_retrieve(cfg,this,"hangtime");
01621 if (val) rpt_vars[n].p.hangtime = atoi(val);
01622 else rpt_vars[n].p.hangtime = HANGTIME;
01623 val = (char *) ast_variable_retrieve(cfg,this,"althangtime");
01624 if (val) rpt_vars[n].p.althangtime = atoi(val);
01625 else rpt_vars[n].p.althangtime = HANGTIME;
01626 val = (char *) ast_variable_retrieve(cfg,this,"totime");
01627 if (val) rpt_vars[n].p.totime = atoi(val);
01628 else rpt_vars[n].p.totime = TOTIME;
01629 rpt_vars[n].p.tailmessagetime = retrieve_astcfgint(&rpt_vars[n],this, "tailmessagetime", 0, 2400000, 0);
01630 rpt_vars[n].p.tailsquashedtime = retrieve_astcfgint(&rpt_vars[n],this, "tailsquashedtime", 0, 2400000, 0);
01631 rpt_vars[n].p.duplex = retrieve_astcfgint(&rpt_vars[n],this,"duplex",0,4,2);
01632 rpt_vars[n].p.idtime = retrieve_astcfgint(&rpt_vars[n],this, "idtime", -60000, 2400000, IDTIME);
01633 rpt_vars[n].p.politeid = retrieve_astcfgint(&rpt_vars[n],this, "politeid", 30000, 300000, POLITEID);
01634 val = (char *) ast_variable_retrieve(cfg,this,"tonezone");
01635 if (val) rpt_vars[n].p.tonezone = val;
01636 rpt_vars[n].p.tailmessages[0] = 0;
01637 rpt_vars[n].p.tailmessagemax = 0;
01638 val = (char *) ast_variable_retrieve(cfg,this,"tailmessagelist");
01639 if (val) rpt_vars[n].p.tailmessagemax = finddelim(val, rpt_vars[n].p.tailmessages, 500);
01640 val = (char *) ast_variable_retrieve(cfg,this,"memory");
01641 if (!val) val = MEMORY;
01642 rpt_vars[n].p.memory = val;
01643 val = (char *) ast_variable_retrieve(cfg,this,"macro");
01644 if (!val) val = MACRO;
01645 rpt_vars[n].p.macro = val;
01646 val = (char *) ast_variable_retrieve(cfg,this,"startup_macro");
01647 if (val) rpt_vars[n].p.startupmacro = val;
01648 val = (char *) ast_variable_retrieve(cfg,this,"iobase");
01649
01650
01651
01652 if ((!val) || (sscanf(val,"%i",&rpt_vars[n].p.iobase) != 1))
01653 rpt_vars[n].p.iobase = DEFAULT_IOBASE;
01654 val = (char *) ast_variable_retrieve(cfg,this,"ioport");
01655 rpt_vars[n].p.ioport = val;
01656 val = (char *) ast_variable_retrieve(cfg,this,"functions");
01657 if (!val)
01658 {
01659 val = FUNCTIONS;
01660 rpt_vars[n].p.simple = 1;
01661 }
01662 rpt_vars[n].p.functions = val;
01663 val = (char *) ast_variable_retrieve(cfg,this,"link_functions");
01664 if (val) rpt_vars[n].p.link_functions = val;
01665 else
01666 rpt_vars[n].p.link_functions = rpt_vars[n].p.functions;
01667 val = (char *) ast_variable_retrieve(cfg,this,"phone_functions");
01668 if (val) rpt_vars[n].p.phone_functions = val;
01669 val = (char *) ast_variable_retrieve(cfg,this,"dphone_functions");
01670 if (val) rpt_vars[n].p.dphone_functions = val;
01671 val = (char *) ast_variable_retrieve(cfg,this,"funcchar");
01672 if (!val) rpt_vars[n].p.funcchar = FUNCCHAR; else
01673 rpt_vars[n].p.funcchar = *val;
01674 val = (char *) ast_variable_retrieve(cfg,this,"endchar");
01675 if (!val) rpt_vars[n].p.endchar = ENDCHAR; else
01676 rpt_vars[n].p.endchar = *val;
01677 val = (char *) ast_variable_retrieve(cfg,this,"nobusyout");
01678 if (val) rpt_vars[n].p.nobusyout = ast_true(val);
01679 val = (char *) ast_variable_retrieve(cfg,this,"notelemtx");
01680 if (val) rpt_vars[n].p.notelemtx = ast_true(val);
01681 val = (char *) ast_variable_retrieve(cfg,this,"propagate_dtmf");
01682 if (val) rpt_vars[n].p.propagate_dtmf = ast_true(val);
01683 val = (char *) ast_variable_retrieve(cfg,this,"propagate_phonedtmf");
01684 if (val) rpt_vars[n].p.propagate_phonedtmf = ast_true(val);
01685 val = (char *) ast_variable_retrieve(cfg,this,"linktolink");
01686 if (val) rpt_vars[n].p.linktolink = ast_true(val);
01687 val = (char *) ast_variable_retrieve(cfg,this,"nodes");
01688 if (!val) val = NODES;
01689 rpt_vars[n].p.nodes = val;
01690 val = (char *) ast_variable_retrieve(cfg,this,"extnodes");
01691 if (!val) val = EXTNODES;
01692 rpt_vars[n].p.extnodes = val;
01693 val = (char *) ast_variable_retrieve(cfg,this,"extnodefile");
01694 if (!val) val = EXTNODEFILE;
01695 rpt_vars[n].p.extnodefile = val;
01696 val = (char *) ast_variable_retrieve(cfg,this,"archivedir");
01697 if (val) rpt_vars[n].p.archivedir = val;
01698 val = (char *) ast_variable_retrieve(cfg,this,"authlevel");
01699 if (val) rpt_vars[n].p.authlevel = atoi(val);
01700 else rpt_vars[n].p.authlevel = 0;
01701 val = (char *) ast_variable_retrieve(cfg,this,"monminblocks");
01702 if (val) rpt_vars[n].p.monminblocks = atol(val);
01703 else rpt_vars[n].p.monminblocks = DEFAULT_MONITOR_MIN_DISK_BLOCKS;
01704 val = (char *) ast_variable_retrieve(cfg,this,"remote_inact_timeout");
01705 if (val) rpt_vars[n].p.remoteinacttimeout = atoi(val);
01706 else rpt_vars[n].p.remoteinacttimeout = DEFAULT_REMOTE_INACT_TIMEOUT;
01707 val = (char *) ast_variable_retrieve(cfg,this,"civaddr");
01708 if (val) rpt_vars[n].p.civaddr = atoi(val);
01709 else rpt_vars[n].p.civaddr = DEFAULT_CIV_ADDR;
01710 val = (char *) ast_variable_retrieve(cfg,this,"remote_timeout");
01711 if (val) rpt_vars[n].p.remotetimeout = atoi(val);
01712 else rpt_vars[n].p.remotetimeout = DEFAULT_REMOTE_TIMEOUT;
01713 val = (char *) ast_variable_retrieve(cfg,this,"remote_timeout_warning");
01714 if (val) rpt_vars[n].p.remotetimeoutwarning = atoi(val);
01715 else rpt_vars[n].p.remotetimeoutwarning = DEFAULT_REMOTE_TIMEOUT_WARNING;
01716 val = (char *) ast_variable_retrieve(cfg,this,"remote_timeout_warning_freq");
01717 if (val) rpt_vars[n].p.remotetimeoutwarningfreq = atoi(val);
01718 else rpt_vars[n].p.remotetimeoutwarningfreq = DEFAULT_REMOTE_TIMEOUT_WARNING_FREQ;
01719 #ifdef __RPT_NOTCH
01720 val = (char *) ast_variable_retrieve(cfg,this,"rxnotch");
01721 if (val) {
01722 i = finddelim(val,strs,MAXFILTERS * 2);
01723 i &= ~1;
01724 if (i >= 2) for(j = 0; j < i; j += 2)
01725 {
01726 rpt_mknotch(atof(strs[j]),atof(strs[j + 1]),
01727 &rpt_vars[n].filters[j >> 1].gain,
01728 &rpt_vars[n].filters[j >> 1].const0,
01729 &rpt_vars[n].filters[j >> 1].const1,
01730 &rpt_vars[n].filters[j >> 1].const2);
01731 sprintf(rpt_vars[n].filters[j >> 1].desc,"%s Hz, BW = %s",
01732 strs[j],strs[j + 1]);
01733 }
01734
01735 }
01736 #endif
01737 val = (char *) ast_variable_retrieve(cfg,this,"inxlat");
01738 if (val) {
01739 memset(&rpt_vars[n].p.inxlat,0,sizeof(struct rpt_xlat));
01740 i = finddelim(val,strs,3);
01741 if (i) strncpy(rpt_vars[n].p.inxlat.funccharseq,strs[0],MAXXLAT - 1);
01742 if (i > 1) strncpy(rpt_vars[n].p.inxlat.endcharseq,strs[1],MAXXLAT - 1);
01743 if (i > 2) strncpy(rpt_vars[n].p.inxlat.passchars,strs[2],MAXXLAT - 1);
01744 }
01745 val = (char *) ast_variable_retrieve(cfg,this,"outxlat");
01746 if (val) {
01747 memset(&rpt_vars[n].p.outxlat,0,sizeof(struct rpt_xlat));
01748 i = finddelim(val,strs,3);
01749 if (i) strncpy(rpt_vars[n].p.outxlat.funccharseq,strs[0],MAXXLAT - 1);
01750 if (i > 1) strncpy(rpt_vars[n].p.outxlat.endcharseq,strs[1],MAXXLAT - 1);
01751 if (i > 2) strncpy(rpt_vars[n].p.outxlat.passchars,strs[2],MAXXLAT - 1);
01752 }
01753
01754 val = (char *) ast_variable_retrieve(cfg,this,"controlstates");
01755 rpt_vars[n].p.csstanzaname = val;
01756
01757
01758 val = (char *) ast_variable_retrieve(cfg,this,"scheduler");
01759 rpt_vars[n].p.skedstanzaname = val;
01760
01761
01762 val = (char *) ast_variable_retrieve(cfg,this,"txlimits");
01763 rpt_vars[n].p.txlimitsstanzaname = val;
01764
01765 longestnode = 0;
01766
01767 vp = ast_variable_browse(cfg, rpt_vars[n].p.nodes);
01768
01769 while(vp){
01770 j = strlen(vp->name);
01771 if (j > longestnode)
01772 longestnode = j;
01773 vp = vp->next;
01774 }
01775
01776 rpt_vars[n].longestnode = longestnode;
01777
01778
01779
01780
01781 rpt_vars[n].longestfunc = 0;
01782 vp = ast_variable_browse(cfg, rpt_vars[n].p.functions);
01783 while(vp){
01784 j = strlen(vp->name);
01785 if (j > rpt_vars[n].longestfunc)
01786 rpt_vars[n].longestfunc = j;
01787 vp = vp->next;
01788 }
01789
01790
01791
01792 rpt_vars[n].link_longestfunc = 0;
01793 vp = ast_variable_browse(cfg, rpt_vars[n].p.link_functions);
01794 while(vp){
01795 j = strlen(vp->name);
01796 if (j > rpt_vars[n].link_longestfunc)
01797 rpt_vars[n].link_longestfunc = j;
01798 vp = vp->next;
01799 }
01800 rpt_vars[n].phone_longestfunc = 0;
01801 if (rpt_vars[n].p.phone_functions)
01802 {
01803 vp = ast_variable_browse(cfg, rpt_vars[n].p.phone_functions);
01804 while(vp){
01805 j = strlen(vp->name);
01806 if (j > rpt_vars[n].phone_longestfunc)
01807 rpt_vars[n].phone_longestfunc = j;
01808 vp = vp->next;
01809 }
01810 }
01811 rpt_vars[n].dphone_longestfunc = 0;
01812 if (rpt_vars[n].p.dphone_functions)
01813 {
01814 vp = ast_variable_browse(cfg, rpt_vars[n].p.dphone_functions);
01815 while(vp){
01816 j = strlen(vp->name);
01817 if (j > rpt_vars[n].dphone_longestfunc)
01818 rpt_vars[n].dphone_longestfunc = j;
01819 vp = vp->next;
01820 }
01821 }
01822 rpt_vars[n].macro_longest = 1;
01823 vp = ast_variable_browse(cfg, rpt_vars[n].p.macro);
01824 while(vp){
01825 j = strlen(vp->name);
01826 if (j > rpt_vars[n].macro_longest)
01827 rpt_vars[n].macro_longest = j;
01828 vp = vp->next;
01829 }
01830
01831
01832 if(rpt_vars[n].p.csstanzaname)
01833 vp = ast_variable_browse(cfg, rpt_vars[n].p.csstanzaname);
01834 else
01835 vp = NULL;
01836 for( i = 0 ; vp && (i < MAX_SYSSTATES) ; i++){
01837 int k,nukw,statenum;
01838 statenum=atoi(vp->name);
01839 strncpy(s1, vp->value, 255);
01840 s1[255] = 0;
01841 nukw = finddelim(s1,strs,32);
01842
01843 for (k = 0 ; k < nukw ; k++){
01844 for(j = 0 ; cs_keywords[j] != NULL ; j++){
01845 if(!strcmp(strs[k],cs_keywords[j])){
01846 switch(j){
01847 case 0:
01848 rpt_vars[n].p.s[statenum].txdisable = 0;
01849 break;
01850 case 1:
01851 rpt_vars[n].p.s[statenum].txdisable = 1;
01852 break;
01853
01854 case 2:
01855 rpt_vars[n].p.s[statenum].autopatchdisable = 0;
01856 break;
01857
01858 case 3:
01859 rpt_vars[n].p.s[statenum].autopatchdisable = 1;
01860 break;
01861
01862 case 4:
01863 rpt_vars[n].p.s[statenum].linkfundisable = 0;
01864 break;
01865
01866 case 5:
01867 rpt_vars[n].p.s[statenum].linkfundisable = 1;
01868 break;
01869
01870 case 6:
01871 rpt_vars[n].p.s[statenum].totdisable = 0;
01872 break;
01873
01874 case 7:
01875 rpt_vars[n].p.s[statenum].totdisable = 1;
01876 break;
01877
01878 case 8:
01879 rpt_vars[n].p.s[statenum].schedulerdisable = 0;
01880 break;
01881
01882 case 9:
01883 rpt_vars[n].p.s[statenum].schedulerdisable = 1;
01884 break;
01885
01886 case 10:
01887 rpt_vars[n].p.s[statenum].userfundisable = 0;
01888 break;
01889
01890 case 11:
01891 rpt_vars[n].p.s[statenum].userfundisable = 1;
01892 break;
01893
01894 case 12:
01895 rpt_vars[n].p.s[statenum].alternatetail = 1;
01896 break;
01897
01898 case 13:
01899 rpt_vars[n].p.s[statenum].alternatetail = 0;
01900 break;
01901
01902 default:
01903 ast_log(LOG_WARNING,
01904 "Unhandled control state keyword %s", cs_keywords[i]);
01905 break;
01906 }
01907 }
01908 }
01909 }
01910 vp = vp->next;
01911 }
01912 ast_mutex_unlock(&rpt_vars[n].lock);
01913 }
01914
01915
01916
01917
01918
01919 static int rpt_do_debug(int fd, int argc, char *argv[])
01920 {
01921 int newlevel;
01922
01923 if (argc != 4)
01924 return RESULT_SHOWUSAGE;
01925 newlevel = myatoi(argv[3]);
01926 if((newlevel < 0) || (newlevel > 7))
01927 return RESULT_SHOWUSAGE;
01928 if(newlevel)
01929 ast_cli(fd, "app_rpt Debugging enabled, previous level: %d, new level: %d\n", debug, newlevel);
01930 else
01931 ast_cli(fd, "app_rpt Debugging disabled\n");
01932
01933 debug = newlevel;
01934 return RESULT_SUCCESS;
01935 }
01936
01937
01938
01939
01940
01941 static int rpt_do_dump(int fd, int argc, char *argv[])
01942 {
01943 int i;
01944
01945 if (argc != 3)
01946 return RESULT_SHOWUSAGE;
01947
01948 for(i = 0; i < nrpts; i++)
01949 {
01950 if (!strcmp(argv[2],rpt_vars[i].name))
01951 {
01952 rpt_vars[i].disgorgetime = time(NULL) + 10;
01953 ast_cli(fd, "app_rpt struct dump requested for node %s\n",argv[2]);
01954 return RESULT_SUCCESS;
01955 }
01956 }
01957 return RESULT_FAILURE;
01958 }
01959
01960
01961
01962
01963
01964 static int rpt_do_stats(int fd, int argc, char *argv[])
01965 {
01966 int i,j;
01967 int dailytxtime, dailykerchunks;
01968 int totalkerchunks, dailykeyups, totalkeyups, timeouts;
01969 int totalexecdcommands, dailyexecdcommands, hours, minutes, seconds;
01970 long long totaltxtime;
01971 struct rpt_link *l;
01972 char *listoflinks[MAX_STAT_LINKS];
01973 char *lastnodewhichkeyedusup, *lastdtmfcommand;
01974 char *tot_state, *ider_state, *patch_state;
01975 char *reverse_patch_state, *sys_ena, *tot_ena, *link_ena, *patch_ena;
01976 char *sch_ena, *input_signal, *called_number, *user_funs, *tail_type;
01977 struct rpt *myrpt;
01978
01979 static char *not_applicable = "N/A";
01980
01981 if(argc != 3)
01982 return RESULT_SHOWUSAGE;
01983
01984 for(i = 0 ; i < MAX_STAT_LINKS; i++)
01985 listoflinks[i] = NULL;
01986
01987 tot_state = ider_state =
01988 patch_state = reverse_patch_state =
01989 input_signal = called_number =
01990 lastdtmfcommand = not_applicable;
01991
01992 for(i = 0; i < nrpts; i++)
01993 {
01994 if (!strcmp(argv[2],rpt_vars[i].name)){
01995
01996 myrpt = &rpt_vars[i];
01997 rpt_mutex_lock(&myrpt->lock);
01998
01999 dailytxtime = myrpt->dailytxtime;
02000 totaltxtime = myrpt->totaltxtime;
02001 dailykeyups = myrpt->dailykeyups;
02002 totalkeyups = myrpt->totalkeyups;
02003 dailykerchunks = myrpt->dailykerchunks;
02004 totalkerchunks = myrpt->totalkerchunks;
02005 dailyexecdcommands = myrpt->dailyexecdcommands;
02006 totalexecdcommands = myrpt->totalexecdcommands;
02007 timeouts = myrpt->timeouts;
02008
02009
02010 reverse_patch_state = "DOWN";
02011 j = 0;
02012 l = myrpt->links.next;
02013 while(l && (l != &myrpt->links)){
02014 if (l->name[0] == '0'){
02015 reverse_patch_state = "UP";
02016 l = l->next;
02017 continue;
02018 }
02019 listoflinks[j] = ast_strdupa(l->name);
02020 if(listoflinks[j])
02021 j++;
02022 l = l->next;
02023 }
02024
02025 lastnodewhichkeyedusup = ast_strdupa(myrpt->lastnodewhichkeyedusup);
02026 if((!lastnodewhichkeyedusup) || (!strlen(lastnodewhichkeyedusup)))
02027 lastnodewhichkeyedusup = not_applicable;
02028
02029 if(myrpt->keyed)
02030 input_signal = "YES";
02031 else
02032 input_signal = "NO";
02033
02034 if(myrpt->p.s[myrpt->p.sysstate_cur].txdisable)
02035 sys_ena = "DISABLED";
02036 else
02037 sys_ena = "ENABLED";
02038
02039 if(myrpt->p.s[myrpt->p.sysstate_cur].totdisable)
02040 tot_ena = "DISABLED";
02041 else
02042 tot_ena = "ENABLED";
02043
02044 if(myrpt->p.s[myrpt->p.sysstate_cur].linkfundisable)
02045 link_ena = "DISABLED";
02046 else
02047 link_ena = "ENABLED";
02048
02049 if(myrpt->p.s[myrpt->p.sysstate_cur].autopatchdisable)
02050 patch_ena = "DISABLED";
02051 else
02052 patch_ena = "ENABLED";
02053
02054 if(myrpt->p.s[myrpt->p.sysstate_cur].schedulerdisable)
02055 sch_ena = "DISABLED";
02056 else
02057 sch_ena = "ENABLED";
02058
02059 if(myrpt->p.s[myrpt->p.sysstate_cur].userfundisable)
02060 user_funs = "DISABLED";
02061 else
02062 user_funs = "ENABLED";
02063
02064 if(myrpt->p.s[myrpt->p.sysstate_cur].alternatetail)
02065 tail_type = "ALTERNATE";
02066 else
02067 tail_type = "STANDARD";
02068
02069 if(!myrpt->totimer)
02070 tot_state = "TIMED OUT!";
02071 else if(myrpt->totimer != myrpt->p.totime)
02072 tot_state = "ARMED";
02073 else
02074 tot_state = "RESET";
02075
02076 if(myrpt->tailid)
02077 ider_state = "QUEUED IN TAIL";
02078 else if(myrpt->mustid)
02079 ider_state = "QUEUED FOR CLEANUP";
02080 else
02081 ider_state = "CLEAN";
02082
02083 switch(myrpt->callmode){
02084 case 1:
02085 patch_state = "DIALING";
02086 break;
02087 case 2:
02088 patch_state = "CONNECTING";
02089 break;
02090 case 3:
02091 patch_state = "UP";
02092 break;
02093
02094 case 4:
02095 patch_state = "CALL FAILED";
02096 break;
02097
02098 default:
02099 patch_state = "DOWN";
02100 }
02101
02102 if(strlen(myrpt->exten)){
02103 called_number = ast_strdupa(myrpt->exten);
02104 if(!called_number)
02105 called_number = not_applicable;
02106 }
02107
02108 if(strlen(myrpt->lastdtmfcommand)){
02109 lastdtmfcommand = ast_strdupa(myrpt->lastdtmfcommand);
02110 if(!lastdtmfcommand)
02111 lastdtmfcommand = not_applicable;
02112 }
02113
02114 rpt_mutex_unlock(&myrpt->lock);
02115
02116 ast_cli(fd, "************************ NODE %s STATISTICS *************************\n\n", myrpt->name);
02117 ast_cli(fd, "Selected system state............................: %d\n", myrpt->p.sysstate_cur);
02118 ast_cli(fd, "Signal on input..................................: %s\n", input_signal);
02119 ast_cli(fd, "System...........................................: %s\n", sys_ena);
02120 ast_cli(fd, "Scheduler........................................: %s\n", sch_ena);
02121 ast_cli(fd, "Tail Time........................................: %s\n", tail_type);
02122 ast_cli(fd, "Time out timer...................................: %s\n", tot_ena);
02123 ast_cli(fd, "Time out timer state.............................: %s\n", tot_state);
02124 ast_cli(fd, "Time outs since system initialization............: %d\n", timeouts);
02125 ast_cli(fd, "Identifier state.................................: %s\n", ider_state);
02126 ast_cli(fd, "Kerchunks today..................................: %d\n", dailykerchunks);
02127 ast_cli(fd, "Kerchunks since system initialization............: %d\n", totalkerchunks);
02128 ast_cli(fd, "Keyups today.....................................: %d\n", dailykeyups);
02129 ast_cli(fd, "Keyups since system initialization...............: %d\n", totalkeyups);
02130 ast_cli(fd, "DTMF commands today..............................: %d\n", dailyexecdcommands);
02131 ast_cli(fd, "DTMF commands since system initialization........: %d\n", totalexecdcommands);
02132 ast_cli(fd, "Last DTMF command executed.......................: %s\n", lastdtmfcommand);
02133 hours = dailytxtime/3600000;
02134 dailytxtime %= 3600000;
02135 minutes = dailytxtime/60000;
02136 dailytxtime %= 60000;
02137 seconds = dailytxtime/1000;
02138 dailytxtime %= 1000;
02139
02140 ast_cli(fd, "TX time today ...................................: %02d:%02d:%02d.%d\n",
02141 hours, minutes, seconds, dailytxtime);
02142
02143 hours = (int) totaltxtime/3600000;
02144 totaltxtime %= 3600000;
02145 minutes = (int) totaltxtime/60000;
02146 totaltxtime %= 60000;
02147 seconds = (int) totaltxtime/1000;
02148 totaltxtime %= 1000;
02149
02150 ast_cli(fd, "TX time since system initialization..............: %02d:%02d:%02d.%d\n",
02151 hours, minutes, seconds, (int) totaltxtime);
02152 ast_cli(fd, "Nodes currently connected to us..................: ");
02153 for(j = 0 ;; j++){
02154 if(!listoflinks[j]){
02155 if(!j){
02156 ast_cli(fd,"<NONE>");
02157 }
02158 break;
02159 }
02160 ast_cli(fd, "%s", listoflinks[j]);
02161 if(j % 4 == 3){
02162 ast_cli(fd, "\n");
02163 ast_cli(fd, " : ");
02164 }
02165 else{
02166 if(listoflinks[j + 1])
02167 ast_cli(fd, ", ");
02168 }
02169 }
02170 ast_cli(fd,"\n");
02171
02172 ast_cli(fd, "Last node which transmitted to us................: %s\n", lastnodewhichkeyedusup);
02173 ast_cli(fd, "Autopatch........................................: %s\n", patch_ena);
02174 ast_cli(fd, "Autopatch state..................................: %s\n", patch_state);
02175 ast_cli(fd, "Autopatch called number..........................: %s\n", called_number);
02176 ast_cli(fd, "Reverse patch/IAXRPT connected...................: %s\n", reverse_patch_state);
02177 ast_cli(fd, "User linking commands............................: %s\n", link_ena);
02178 ast_cli(fd, "User functions...................................: %s\n\n", user_funs);
02179 return RESULT_SUCCESS;
02180 }
02181 }
02182 return RESULT_FAILURE;
02183 }
02184
02185
02186
02187
02188
02189 static int rpt_do_lstats(int fd, int argc, char *argv[])
02190 {
02191 int i,j;
02192 char *connstate;
02193 struct rpt *myrpt;
02194 struct rpt_link *l;
02195 struct rpt_lstat *s,*t;
02196 struct rpt_lstat s_head;
02197 if(argc != 3)
02198 return RESULT_SHOWUSAGE;
02199
02200 s = NULL;
02201 s_head.next = &s_head;
02202 s_head.prev = &s_head;
02203
02204 for(i = 0; i < nrpts; i++)
02205 {
02206 if (!strcmp(argv[2],rpt_vars[i].name)){
02207
02208 myrpt = &rpt_vars[i];
02209 rpt_mutex_lock(&myrpt->lock);
02210
02211 j = 0;
02212 l = myrpt->links.next;
02213 while(l && (l != &myrpt->links)){
02214 if (l->name[0] == '0'){
02215 l = l->next;
02216 continue;
02217 }
02218 if((s = (struct rpt_lstat *) malloc(sizeof(struct rpt_lstat))) == NULL){
02219 ast_log(LOG_ERROR, "Malloc failed in rpt_do_lstats\n");
02220 rpt_mutex_unlock(&myrpt->lock);
02221 return RESULT_FAILURE;
02222 }
02223 memset(s, 0, sizeof(struct rpt_lstat));
02224 strncpy(s->name, l->name, MAXREMSTR - 1);
02225 if (l->chan) pbx_substitute_variables_helper(l->chan, "${IAXPEER(CURRENTCHANNEL)}", s->peer, MAXPEERSTR - 1);
02226 else strcpy(s->peer,"(none)");
02227 s->mode = l->mode;
02228 s->outbound = l->outbound;
02229 s->reconnects = l->reconnects;
02230 s->connecttime = l->connecttime;
02231 s->thisconnected = l->thisconnected;
02232 memcpy(s->chan_stat,l->chan_stat,NRPTSTAT * sizeof(struct rpt_chan_stat));
02233 insque((struct qelem *) s, (struct qelem *) s_head.next);
02234 memset(l->chan_stat,0,NRPTSTAT * sizeof(struct rpt_chan_stat));
02235 l = l->next;
02236 }
02237 rpt_mutex_unlock(&myrpt->lock);
02238 ast_cli(fd, "NODE PEER RECONNECTS DIRECTION CONNECT TIME CONNECT STATE\n");
02239 ast_cli(fd, "---- ---- ---------- --------- ------------ -------------\n");
02240
02241 for(s = s_head.next; s != &s_head; s = s->next){
02242 int hours, minutes, seconds;
02243 long long connecttime = s->connecttime;
02244 char conntime[21];
02245 hours = (int) connecttime/3600000;
02246 connecttime %= 3600000;
02247 minutes = (int) connecttime/60000;
02248 connecttime %= 60000;
02249 seconds = (int) connecttime/1000;
02250 connecttime %= 1000;
02251 snprintf(conntime, 20, "%02d:%02d:%02d.%d",
02252 hours, minutes, seconds, (int) connecttime);
02253 conntime[20] = 0;
02254 if(s->thisconnected)
02255 connstate = "ESTABLISHED";
02256 else
02257 connstate = "CONNECTING";
02258 ast_cli(fd, "%-10s%-20s%-12d%-11s%-20s%-20s\n",
02259 s->name, s->peer, s->reconnects, (s->outbound)? "OUT":"IN", conntime, connstate);
02260 }
02261
02262 s = s_head.next;
02263 while(s != &s_head){
02264 t = s;
02265 s = s->next;
02266 remque((struct qelem *)t);
02267 free(t);
02268 }
02269 return RESULT_SUCCESS;
02270 }
02271 }
02272 return RESULT_FAILURE;
02273 }
02274
02275
02276
02277
02278
02279 static int rpt_do_nodes(int fd, int argc, char *argv[])
02280 {
02281 int i,j;
02282 char ns;
02283 char lbuf[MAXLINKLIST],*strs[MAXLINKLIST];
02284 struct rpt *myrpt;
02285 if(argc != 3)
02286 return RESULT_SHOWUSAGE;
02287
02288 for(i = 0; i < nrpts; i++)
02289 {
02290 if (!strcmp(argv[2],rpt_vars[i].name)){
02291
02292 myrpt = &rpt_vars[i];
02293 rpt_mutex_lock(&myrpt->lock);
02294 __mklinklist(myrpt,NULL,lbuf);
02295 rpt_mutex_unlock(&myrpt->lock);
02296
02297 ns = finddelim(lbuf,strs,MAXLINKLIST);
02298
02299 if (ns) qsort((void *)strs,ns,sizeof(char *),mycompar);
02300 ast_cli(fd,"\n");
02301 ast_cli(fd, "************************* CONNECTED NODES *************************\n\n");
02302 for(j = 0 ;; j++){
02303 if(!strs[j]){
02304 if(!j){
02305 ast_cli(fd,"<NONE>");
02306 }
02307 break;
02308 }
02309 ast_cli(fd, "%s", strs[j]);
02310 if(j % 8 == 7){
02311 ast_cli(fd, "\n");
02312 }
02313 else{
02314 if(strs[j + 1])
02315 ast_cli(fd, ", ");
02316 }
02317 }
02318 ast_cli(fd,"\n\n");
02319 return RESULT_SUCCESS;
02320 }
02321 }
02322 return RESULT_FAILURE;
02323 }
02324
02325
02326
02327
02328
02329 static int rpt_do_reload(int fd, int argc, char *argv[])
02330 {
02331 int n;
02332
02333 if (argc > 2) return RESULT_SHOWUSAGE;
02334
02335 for(n = 0; n < nrpts; n++) rpt_vars[n].reload = 1;
02336
02337 return RESULT_FAILURE;
02338 }
02339
02340
02341
02342
02343
02344 static int rpt_do_restart(int fd, int argc, char *argv[])
02345 {
02346 int i;
02347
02348 if (argc > 2) return RESULT_SHOWUSAGE;
02349 for(i = 0; i < nrpts; i++)
02350 {
02351 if (rpt_vars[i].rxchannel) ast_softhangup(rpt_vars[i].rxchannel,AST_SOFTHANGUP_DEV);
02352 }
02353 return RESULT_FAILURE;
02354 }
02355
02356
02357
02358
02359
02360
02361 static int rpt_do_fun(int fd, int argc, char *argv[])
02362 {
02363 int i,busy=0;
02364
02365 if (argc != 4) return RESULT_SHOWUSAGE;
02366
02367 for(i = 0; i < nrpts; i++){
02368 if(!strcmp(argv[2], rpt_vars[i].name)){
02369 struct rpt *myrpt = &rpt_vars[i];
02370 rpt_mutex_lock(&myrpt->lock);
02371 if ((MAXMACRO - strlen(myrpt->macrobuf)) < strlen(argv[3])){
02372 rpt_mutex_unlock(&myrpt->lock);
02373 busy=1;
02374 }
02375 if(!busy){
02376 myrpt->macrotimer = MACROTIME;
02377 strncat(myrpt->macrobuf,argv[3],MAXMACRO - 1);
02378 }
02379 rpt_mutex_unlock(&myrpt->lock);
02380 }
02381 }
02382 if(busy){
02383 ast_cli(fd, "Function decoder busy");
02384 }
02385 return RESULT_FAILURE;
02386 }
02387
02388
02389
02390 static int play_tone_pair(struct ast_channel *chan, int f1, int f2, int duration, int amplitude)
02391 {
02392 int res;
02393
02394 if ((res = ast_tonepair_start(chan, f1, f2, duration, amplitude)))
02395 return res;
02396
02397 while(chan->generatordata) {
02398 if (ast_safe_sleep(chan,1)) return -1;
02399 }
02400
02401 return 0;
02402 }
02403
02404 static int play_tone(struct ast_channel *chan, int freq, int duration, int amplitude)
02405 {
02406 return play_tone_pair(chan, freq, 0, duration, amplitude);
02407 }
02408
02409 static int play_silence(struct ast_channel *chan, int duration)
02410 {
02411 return play_tone_pair(chan, 0, 0, duration, 0);
02412 }
02413
02414
02415 static int send_morse(struct ast_channel *chan, char *string, int speed, int freq, int amplitude)
02416 {
02417
02418 static struct morse_bits mbits[] = {
02419 {0, 0},
02420 {0, 0},
02421 {6, 18},
02422 {0, 0},
02423 {7, 72},
02424 {0, 0},
02425 {0, 0},
02426 {6, 30},
02427 {5, 13},
02428 {6, 29},
02429 {0, 0},
02430 {5, 10},
02431 {6, 51},
02432 {6, 33},
02433 {6, 42},
02434 {5, 9},
02435 {5, 31},
02436 {5, 30},
02437 {5, 28},
02438 {5, 24},
02439 {5, 16},
02440 {5, 0},
02441 {5, 1},
02442 {5, 3},
02443 {5, 7},
02444 {5, 15},
02445 {6, 7},
02446 {6, 21},
02447 {0, 0},
02448 {5, 33},
02449 {0, 0},
02450 {6, 12},
02451 {0, 0},
02452 {2, 2},
02453 {4, 1},
02454 {4, 5},
02455 {3, 1},
02456 {1, 0},
02457 {4, 4},
02458 {3, 3},
02459 {4, 0},
02460 {2, 0},
02461 {4, 14},
02462 {3, 5},
02463 {4, 2},
02464 {2, 3},
02465 {2, 1},
02466 {3, 7},
02467 {4, 6},
02468 {4, 11},
02469 {3, 2},
02470 {3, 0},
02471 {1, 1},
02472 {3, 4},
02473 {4, 8},
02474 {3, 6},
02475 {4, 9},
02476 {4, 13},
02477 {4, 3}
02478 };
02479
02480
02481 int dottime;
02482 int dashtime;
02483 int intralettertime;
02484 int interlettertime;
02485 int interwordtime;
02486 int len, ddcomb;
02487 int res;
02488 int c;
02489 int i;
02490 int flags;
02491
02492 res = 0;
02493
02494
02495
02496 dottime = 900/speed;
02497
02498
02499
02500 dashtime = 3 * dottime;
02501 intralettertime = dottime;
02502 interlettertime = dottime * 4 ;
02503 interwordtime = dottime * 7;
02504
02505 for(;(*string) && (!res); string++){
02506
02507 c = *string;
02508
02509
02510
02511 if((c >= 'a') && (c <= 'z'))
02512 c -= 0x20;
02513
02514
02515
02516 if(c > 'Z')
02517 continue;
02518
02519
02520
02521 if(c == ' '){
02522 if(!res)
02523 res = play_silence(chan, interwordtime);
02524 continue;
02525 }
02526
02527
02528
02529 c -= 0x20;
02530
02531
02532
02533 len = mbits[c].len;
02534 ddcomb = mbits[c].ddcomb;
02535
02536
02537
02538 for(; len ; len--){
02539 if(!res)
02540 res = play_tone(chan, freq, (ddcomb & 1) ? dashtime : dottime, amplitude);
02541 if(!res)
02542 res = play_silence(chan, intralettertime);
02543 ddcomb >>= 1;
02544 }
02545
02546
02547
02548 if(!res)
02549 res = play_silence(chan, interlettertime - intralettertime);
02550 }
02551
02552
02553
02554 if (!res)
02555 res = ast_waitstream(chan, "");
02556 ast_stopstream(chan);
02557
02558
02559
02560
02561
02562 for(i = 0; i < 20 ; i++){
02563 flags = ZT_IOMUX_WRITEEMPTY | ZT_IOMUX_NOWAIT;
02564 res = ioctl(chan->fds[0], ZT_IOMUX, &flags);
02565 if(flags & ZT_IOMUX_WRITEEMPTY)
02566 break;
02567 if( ast_safe_sleep(chan, 50)){
02568 res = -1;
02569 break;
02570 }
02571 }
02572
02573
02574 return res;
02575 }
02576
02577 static int send_tone_telemetry(struct ast_channel *chan, char *tonestring)
02578 {
02579 char *stringp;
02580 char *tonesubset;
02581 int f1,f2;
02582 int duration;
02583 int amplitude;
02584 int res;
02585 int i;
02586 int flags;
02587
02588 res = 0;
02589
02590 stringp = ast_strdupa(tonestring);
02591
02592 for(;tonestring;){
02593 tonesubset = strsep(&stringp,")");
02594 if(!tonesubset)
02595 break;
02596 if(sscanf(tonesubset,"(%d,%d,%d,%d", &f1, &f2, &duration, &litude) != 4)
02597 break;
02598 res = play_tone_pair(chan, f1, f2, duration, amplitude);
02599 if(res)
02600 break;
02601 }
02602 if(!res)
02603 res = play_tone_pair(chan, 0, 0, 100, 0);
02604
02605 if (!res)
02606 res = ast_waitstream(chan, "");
02607 ast_stopstream(chan);
02608
02609
02610
02611
02612
02613 for(i = 0; i < 20 ; i++){
02614 flags = ZT_IOMUX_WRITEEMPTY | ZT_IOMUX_NOWAIT;
02615 res = ioctl(chan->fds[0], ZT_IOMUX, &flags);
02616 if(flags & ZT_IOMUX_WRITEEMPTY)
02617 break;
02618 if( ast_safe_sleep(chan, 50)){
02619 res = -1;
02620 break;
02621 }
02622 }
02623
02624 return res;
02625
02626 }
02627
02628 static int sayfile(struct ast_channel *mychannel,char *fname)
02629 {
02630 int res;
02631
02632 res = ast_streamfile(mychannel, fname, mychannel->language);
02633 if (!res)
02634 res = ast_waitstream(mychannel, "");
02635 else
02636 ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", mychannel->name);
02637 ast_stopstream(mychannel);
02638 return res;
02639 }
02640
02641 static int saycharstr(struct ast_channel *mychannel,char *str)
02642 {
02643 int res;
02644
02645 res = ast_say_character_str(mychannel,str,NULL,mychannel->language);
02646 if (!res)
02647 res = ast_waitstream(mychannel, "");
02648 else
02649 ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", mychannel->name);
02650 ast_stopstream(mychannel);
02651 return res;
02652 }
02653
02654 static int saynum(struct ast_channel *mychannel, int num)
02655 {
02656 int res;
02657 res = ast_say_number(mychannel, num, NULL, mychannel->language, NULL);
02658 if(!res)
02659 res = ast_waitstream(mychannel, "");
02660 else
02661 ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", mychannel->name);
02662 ast_stopstream(mychannel);
02663 return res;
02664 }
02665
02666
02667 static int telem_any(struct rpt *myrpt,struct ast_channel *chan, char *entry)
02668 {
02669 int res;
02670 char c;
02671
02672 static int morsespeed;
02673 static int morsefreq;
02674 static int morseampl;
02675 static int morseidfreq = 0;
02676 static int morseidampl;
02677 static char mcat[] = MORSE;
02678
02679 res = 0;
02680
02681 if(!morseidfreq){
02682 morsespeed = retrieve_astcfgint(myrpt, mcat, "speed", 5, 20, 20);
02683 morsefreq = retrieve_astcfgint(myrpt, mcat, "frequency", 300, 3000, 800);
02684 morseampl = retrieve_astcfgint(myrpt, mcat, "amplitude", 200, 8192, 4096);
02685 morseidampl = retrieve_astcfgint(myrpt, mcat, "idamplitude", 200, 8192, 2048);
02686 morseidfreq = retrieve_astcfgint(myrpt, mcat, "idfrequency", 300, 3000, 330);
02687 }
02688
02689
02690
02691 if(entry[0] == '|'){
02692 c = entry[1];
02693 if((c >= 'a')&&(c <= 'z'))
02694 c -= 0x20;
02695
02696 switch(c){
02697 case 'I':
02698 res = send_morse(chan, entry + 2, morsespeed, morseidfreq, morseidampl);
02699 break;
02700
02701 case 'M':
02702 res = send_morse(chan, entry + 2, morsespeed, morsefreq, morseampl);
02703 break;
02704
02705 case 'T':
02706 res = send_tone_telemetry(chan, entry + 2);
02707 break;
02708 default:
02709 res = -1;
02710 }
02711 }
02712 else
02713 res = sayfile(chan, entry);
02714 return res;
02715 }
02716
02717
02718
02719
02720
02721
02722
02723 static int telem_lookup(struct rpt *myrpt,struct ast_channel *chan, char *node, char *name)
02724 {
02725
02726 int res;
02727 int i;
02728 char *entry;
02729 char *telemetry;
02730 char *telemetry_save;
02731
02732 res = 0;
02733 telemetry_save = NULL;
02734 entry = NULL;
02735
02736
02737 telemetry = (char *) ast_variable_retrieve(myrpt->cfg, node, TELEMETRY);
02738 if(telemetry ){
02739 telemetry_save = ast_strdupa(telemetry);
02740 if(!telemetry_save){
02741 ast_log(LOG_WARNING,"ast_strdupa() failed in telem_lookup()\n");
02742 return res;
02743 }
02744 entry = (char *) ast_variable_retrieve(myrpt->cfg, telemetry_save, name);
02745 }
02746
02747
02748
02749 if(!entry){
02750
02751 for(i = 0; i < sizeof(tele_defs)/sizeof(struct telem_defaults) ; i++){
02752 if(!strcasecmp(tele_defs[i].name, name))
02753 entry = tele_defs[i].value;
02754 }
02755 }
02756 if(entry){
02757 if(strlen(entry))
02758 telem_any(myrpt,chan, entry);
02759 }
02760 else{
02761 res = -1;
02762 }
02763 return res;
02764 }
02765
02766
02767
02768
02769
02770 static int get_wait_interval(struct rpt *myrpt, int type)
02771 {
02772 int interval;
02773 char *wait_times;
02774 char *wait_times_save;
02775
02776 wait_times_save = NULL;
02777 wait_times = (char *) ast_variable_retrieve(myrpt->cfg, myrpt->name, "wait_times");
02778
02779 if(wait_times){
02780 wait_times_save = ast_strdupa(wait_times);
02781 if(!wait_times_save){
02782 ast_log(LOG_WARNING, "Out of memory in wait_interval()\n");
02783 wait_times = NULL;
02784 }
02785 }
02786
02787 switch(type){
02788 case DLY_TELEM:
02789 if(wait_times)
02790 interval = retrieve_astcfgint(myrpt,wait_times_save, "telemwait", 500, 5000, 1000);
02791 else
02792 interval = 1000;
02793 break;
02794
02795 case DLY_ID:
02796 if(wait_times)
02797 interval = retrieve_astcfgint(myrpt,wait_times_save, "idwait",250,5000,500);
02798 else
02799 interval = 500;
02800 break;
02801
02802 case DLY_UNKEY:
02803 if(wait_times)
02804 interval = retrieve_astcfgint(myrpt,wait_times_save, "unkeywait",500,5000,1000);
02805 else
02806 interval = 1000;
02807 break;
02808
02809 case DLY_LINKUNKEY:
02810 if(wait_times)
02811 interval = retrieve_astcfgint(myrpt,wait_times_save, "linkunkeywait",500,5000,1000);
02812 else
02813 interval = 1000;
02814 break;
02815
02816 case DLY_CALLTERM:
02817 if(wait_times)
02818 interval = retrieve_astcfgint(myrpt,wait_times_save, "calltermwait",500,5000,1500);
02819 else
02820 interval = 1500;
02821 break;
02822
02823 case DLY_COMP:
02824 if(wait_times)
02825 interval = retrieve_astcfgint(myrpt,wait_times_save, "compwait",500,5000,200);
02826 else
02827 interval = 200;
02828 break;
02829
02830 default:
02831 return 0;
02832 }
02833 return interval;
02834 }
02835
02836
02837
02838
02839
02840
02841
02842 static void wait_interval(struct rpt *myrpt, int type, struct ast_channel *chan)
02843 {
02844 int interval;
02845 interval = get_wait_interval(myrpt, type);
02846 if(debug)
02847 ast_log(LOG_NOTICE," Delay interval = %d\n", interval);
02848 if(interval)
02849 ast_safe_sleep(chan,interval);
02850 if(debug)
02851 ast_log(LOG_NOTICE,"Delay complete\n");
02852 return;
02853 }
02854
02855 static int split_freq(char *mhz, char *decimals, char *freq);
02856
02857 static void *rpt_tele_thread(void *this)
02858 {
02859 ZT_CONFINFO ci;
02860 int res = 0,haslink,hastx,hasremote,imdone = 0, unkeys_queued, x;
02861 struct rpt_tele *mytele = (struct rpt_tele *)this;
02862 struct rpt_tele *tlist;
02863 struct rpt *myrpt;
02864 struct rpt_link *l,*l1,linkbase;
02865 struct ast_channel *mychannel;
02866 int vmajor, vminor, m;
02867 char *p,*ct,*ct_copy,*ident, *nodename,*cp;
02868 time_t t;
02869 struct tm localtm;
02870 char lbuf[MAXLINKLIST],*strs[MAXLINKLIST];
02871 int i,ns,rbimode;
02872 char mhz[MAXREMSTR];
02873 char decimals[MAXREMSTR];
02874 struct zt_params par;
02875
02876
02877
02878 myrpt = mytele->rpt;
02879
02880
02881 rpt_mutex_lock(&myrpt->lock);
02882 nodename = ast_strdupa(myrpt->name);
02883 if (myrpt->p.ident) ident = ast_strdupa(myrpt->p.ident);
02884 else ident = "";
02885 rpt_mutex_unlock(&myrpt->lock);
02886
02887
02888 mychannel = ast_request("zap",AST_FORMAT_SLINEAR,"pseudo",NULL);
02889 if (!mychannel)
02890 {
02891 fprintf(stderr,"rpt:Sorry unable to obtain pseudo channel\n");
02892 rpt_mutex_lock(&myrpt->lock);
02893 remque((struct qelem *)mytele);
02894 ast_log(LOG_NOTICE,"Telemetry thread aborted at line %d, mode: %d\n",__LINE__, mytele->mode);
02895 rpt_mutex_unlock(&myrpt->lock);
02896 free(mytele);
02897 pthread_exit(NULL);
02898 }
02899 rpt_mutex_lock(&myrpt->lock);
02900 mytele->chan = mychannel;
02901 rpt_mutex_unlock(&myrpt->lock);
02902
02903 ci.chan = 0;
02904
02905
02906
02907 ci.confno = (((mytele->mode == ID) || (mytele->mode == IDTALKOVER) || (mytele->mode == UNKEY) ||
02908 (mytele->mode == TAILMSG) || (mytele->mode == LINKUNKEY)) || (mytele->mode == TIMEOUT) ?
02909 myrpt->txconf : myrpt->conf);
02910 ci.confmode = ZT_CONF_CONFANN;
02911
02912 if (ioctl(mychannel->fds[0],ZT_SETCONF,&ci) == -1)
02913 {
02914 ast_log(LOG_WARNING, "Unable to set conference mode to Announce\n");
02915 rpt_mutex_lock(&myrpt->lock);
02916 remque((struct qelem *)mytele);
02917 rpt_mutex_unlock(&myrpt->lock);
02918 ast_log(LOG_NOTICE,"Telemetry thread aborted at line %d, mode: %d\n",__LINE__, mytele->mode);
02919 free(mytele);
02920 ast_hangup(mychannel);
02921 pthread_exit(NULL);
02922 }
02923 ast_stopstream(mychannel);
02924 switch(mytele->mode)
02925 {
02926 case ID:
02927 case ID1:
02928
02929 wait_interval(myrpt, (mytele->mode == ID) ? DLY_ID : DLY_TELEM,mychannel);
02930 res = telem_any(myrpt,mychannel, ident);
02931 imdone=1;
02932 break;
02933
02934 case TAILMSG:
02935 res = ast_streamfile(mychannel, myrpt->p.tailmessages[myrpt->tailmessagen], mychannel->language);
02936 break;
02937
02938 case IDTALKOVER:
02939 p = (char *) ast_variable_retrieve(myrpt->cfg, nodename, "idtalkover");
02940 if(p)
02941 res = telem_any(myrpt,mychannel, p);
02942 imdone=1;
02943 break;
02944
02945 case PROC:
02946
02947 wait_interval(myrpt, DLY_TELEM, mychannel);
02948 res = telem_lookup(myrpt, mychannel, myrpt->name, "patchup");
02949 if(res < 0){
02950 res = ast_streamfile(mychannel, "rpt/callproceeding", mychannel->language);
02951 }
02952 break;
02953 case TERM:
02954
02955 wait_interval(myrpt, DLY_CALLTERM, mychannel);
02956 res = telem_lookup(myrpt, mychannel, myrpt->name, "patchdown");
02957 if(res < 0){
02958 res = ast_streamfile(mychannel, "rpt/callterminated", mychannel->language);
02959 }
02960 break;
02961 case COMPLETE:
02962
02963 wait_interval(myrpt, DLY_TELEM, mychannel);
02964 res = telem_lookup(myrpt,mychannel, myrpt->name, "functcomplete");
02965 break;
02966 case MACRO_NOTFOUND:
02967
02968 wait_interval(myrpt, DLY_TELEM, mychannel);
02969 res = ast_streamfile(mychannel, "rpt/macro_notfound", mychannel->language);
02970 break;
02971 case MACRO_BUSY:
02972
02973 wait_interval(myrpt, DLY_TELEM, mychannel);
02974 res = ast_streamfile(mychannel, "rpt/macro_busy", mychannel->language);
02975 break;
02976 case UNKEY:
02977 if(myrpt->patchnoct && myrpt->callmode){
02978 imdone = 1;
02979 break;
02980 }
02981
02982
02983
02984
02985
02986 x = get_wait_interval(myrpt, DLY_UNKEY);
02987 rpt_mutex_lock(&myrpt->lock);
02988 myrpt->unkeytocttimer = x;
02989 rpt_mutex_unlock(&myrpt->lock);
02990
02991
02992
02993
02994
02995 tlist = myrpt->tele.next;
02996 unkeys_queued = 0;
02997 if (tlist != &myrpt->tele)
02998 {
02999 rpt_mutex_lock(&myrpt->lock);
03000 while(tlist != &myrpt->tele){
03001 if (tlist->mode == UNKEY) unkeys_queued++;
03002 tlist = tlist->next;
03003 }
03004 rpt_mutex_unlock(&myrpt->lock);
03005 }
03006 if( unkeys_queued > 1){
03007 imdone = 1;
03008 break;
03009 }
03010
03011
03012
03013 while(myrpt->unkeytocttimer)
03014 {
03015 int ctint;
03016 if(myrpt->unkeytocttimer > 100)
03017 ctint = 100;
03018 else
03019 ctint = myrpt->unkeytocttimer;
03020 ast_safe_sleep(mychannel, ctint);
03021 rpt_mutex_lock(&myrpt->lock);
03022 if(myrpt->unkeytocttimer < ctint)
03023 myrpt->unkeytocttimer = 0;
03024 else
03025 myrpt->unkeytocttimer -= ctint;
03026 rpt_mutex_unlock(&myrpt->lock);
03027 }
03028
03029
03030
03031
03032
03033 if(myrpt->keyed){
03034 imdone = 1;
03035 break;
03036 }
03037
03038 rpt_mutex_lock(&myrpt->lock);
03039 myrpt->dailykerchunks++;
03040 myrpt->totalkerchunks++;
03041 rpt_mutex_unlock(&myrpt->lock);
03042
03043 haslink = 0;
03044 hastx = 0;
03045 hasremote = 0;
03046 l = myrpt->links.next;
03047 if (l != &myrpt->links)
03048 {
03049 rpt_mutex_lock(&myrpt->lock);
03050 while(l != &myrpt->links)
03051 {
03052 if (l->name[0] == '0')
03053 {
03054 l = l->next;
03055 continue;
03056 }
03057 haslink = 1;
03058 if (l->mode) {
03059 hastx++;
03060 if (l->isremote) hasremote++;
03061 }
03062 l = l->next;
03063 }
03064 rpt_mutex_unlock(&myrpt->lock);
03065 }
03066 if (haslink)
03067 {
03068
03069 res = telem_lookup(myrpt,mychannel, myrpt->name, (!hastx) ? "remotemon" : "remotetx");
03070 if(res)
03071 ast_log(LOG_WARNING, "telem_lookup:remotexx failed on %s\n", mychannel->name);
03072
03073
03074
03075 if (myrpt->cmdnode[0])
03076 {
03077 ast_safe_sleep(mychannel,200);
03078 res = telem_lookup(myrpt,mychannel, myrpt->name, "cmdmode");
03079 if(res)
03080 ast_log(LOG_WARNING, "telem_lookup:cmdmode failed on %s\n", mychannel->name);
03081 ast_stopstream(mychannel);
03082 }
03083 }
03084 else if((ct = (char *) ast_variable_retrieve(myrpt->cfg, nodename, "unlinkedct"))){
03085 ct_copy = ast_strdupa(ct);
03086 res = telem_lookup(myrpt,mychannel, myrpt->name, ct_copy);
03087 if(res)
03088 ast_log(LOG_WARNING, "telem_lookup:ctx failed on %s\n", mychannel->name);
03089 }
03090 if (hasremote && (!myrpt->cmdnode[0]))
03091 {
03092
03093 ci.chan = 0;
03094 ci.confno = myrpt->conf;
03095 ci.confmode = ZT_CONF_CONFANN;
03096
03097 if (ioctl(mychannel->fds[0],ZT_SETCONF,&ci) == -1)
03098 {
03099 ast_log(LOG_WARNING, "Unable to set conference mode to Announce\n");
03100 rpt_mutex_lock(&myrpt->lock);
03101 remque((struct qelem *)mytele);
03102 rpt_mutex_unlock(&myrpt->lock);
03103 ast_log(LOG_NOTICE,"Telemetry thread aborted at line %d, mode: %d\n",__LINE__, mytele->mode);
03104 free(mytele);
03105 ast_hangup(mychannel);
03106 pthread_exit(NULL);
03107 }
03108 if((ct = (char *) ast_variable_retrieve(myrpt->cfg, nodename, "remotect"))){
03109 ast_safe_sleep(mychannel,200);
03110 ct_copy = ast_strdupa(ct);
03111 res = telem_lookup(myrpt,mychannel, myrpt->name, ct_copy);
03112 if(res)
03113 ast_log(LOG_WARNING, "telem_lookup:ctx failed on %s\n", mychannel->name);
03114 }
03115 }
03116 #ifdef _MDC_DECODE_H_
03117 if (myrpt->lastunit)
03118 {
03119 char mystr[10];
03120
03121 ast_safe_sleep(mychannel,200);
03122
03123 ci.chan = 0;
03124 ci.confno = myrpt->txconf;
03125 ci.confmode = ZT_CONF_CONFANN;
03126
03127 if (ioctl(mychannel->fds[0],ZT_SETCONF,&ci) == -1)
03128 {
03129 ast_log(LOG_WARNING, "Unable to set conference mode to Announce\n");
03130 rpt_mutex_lock(&myrpt->lock);
03131 remque((struct qelem *)mytele);
03132 rpt_mutex_unlock(&myrpt->lock);
03133 ast_log(LOG_NOTICE,"Telemetry thread aborted at line %d, mode: %d\n",__LINE__, mytele->mode);
03134 free(mytele);
03135 ast_hangup(mychannel);
03136 pthread_exit(NULL);
03137 }
03138 sprintf(mystr,"%04x",myrpt->lastunit);
03139 myrpt->lastunit = 0;
03140 ast_say_character_str(mychannel,mystr,NULL,mychannel->language);
03141 break;
03142 }
03143 #endif
03144 imdone = 1;
03145 break;
03146 case LINKUNKEY:
03147 if(myrpt->patchnoct && myrpt->callmode){
03148 imdone = 1;
03149 break;
03150 }
03151
03152
03153
03154
03155
03156 x = get_wait_interval(myrpt, DLY_LINKUNKEY);
03157 mytele->mylink.linkunkeytocttimer = x;
03158
03159
03160
03161
03162
03163 tlist = myrpt->tele.next;
03164 unkeys_queued = 0;
03165 if (tlist != &myrpt->tele)
03166 {
03167 rpt_mutex_lock(&myrpt->lock);
03168 while(tlist != &myrpt->tele){
03169 if (tlist->mode == LINKUNKEY) unkeys_queued++;
03170 tlist = tlist->next;
03171 }
03172 rpt_mutex_unlock(&myrpt->lock);
03173 }
03174 if( unkeys_queued > 1){
03175 imdone = 1;
03176 break;
03177 }
03178
03179
03180
03181 while(mytele->mylink.linkunkeytocttimer)
03182 {
03183 int ctint;
03184 if(mytele->mylink.linkunkeytocttimer > 100)
03185 ctint = 100;
03186 else
03187 ctint = mytele->mylink.linkunkeytocttimer;
03188 ast_safe_sleep(mychannel, ctint);
03189 rpt_mutex_lock(&myrpt->lock);
03190 if(mytele->mylink.linkunkeytocttimer < ctint)
03191 mytele->mylink.linkunkeytocttimer = 0;
03192 else
03193 mytele->mylink.linkunkeytocttimer -= ctint;
03194 rpt_mutex_unlock(&myrpt->lock);
03195 }
03196
03197 if((ct = (char *) ast_variable_retrieve(myrpt->cfg, nodename, "linkunkeyct"))){
03198 ct_copy = ast_strdupa(ct);
03199 res = telem_lookup(myrpt,mychannel, myrpt->name, ct_copy);
03200 if(res)
03201 ast_log(LOG_WARNING, "telem_lookup:ctx failed on %s\n", mychannel->name);
03202 }
03203 imdone = 1;
03204 break;
03205 case REMDISC:
03206
03207 wait_interval(myrpt, DLY_TELEM, mychannel);
03208 l = myrpt->links.next;
03209 haslink = 0;
03210
03211 if (l != &myrpt->links)
03212 {
03213 rpt_mutex_lock(&myrpt->lock);
03214 while(l != &myrpt->links)
03215 {
03216 if (l->name[0] == '0')
03217 {
03218 l = l->next;
03219 continue;
03220 }
03221 if (!strcmp(l->name,mytele->mylink.name))
03222 {
03223 haslink = 1;
03224 break;
03225 }
03226 l = l->next;
03227 }
03228 rpt_mutex_unlock(&myrpt->lock);
03229 }
03230 if (haslink)
03231 {
03232 imdone = 1;
03233 break;
03234 }
03235 res = ast_streamfile(mychannel, "rpt/node", mychannel->language);
03236 if (!res)
03237 res = ast_waitstream(mychannel, "");
03238 else
03239 ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", mychannel->name);
03240 ast_stopstream(mychannel);
03241 ast_say_character_str(mychannel,mytele->mylink.name,NULL,mychannel->language);
03242 res = ast_streamfile(mychannel, ((mytele->mylink.hasconnected) ?
03243 "rpt/remote_disc" : "rpt/remote_busy"), mychannel->language);
03244 break;
03245 case REMALREADY:
03246
03247 wait_interval(myrpt, DLY_TELEM, mychannel);
03248 res = ast_streamfile(mychannel, "rpt/remote_already", mychannel->language);
03249 break;
03250 case REMNOTFOUND:
03251
03252 wait_interval(myrpt, DLY_TELEM, mychannel);
03253 res = ast_streamfile(mychannel, "rpt/remote_notfound", mychannel->language);
03254 break;
03255 case REMGO:
03256
03257 wait_interval(myrpt, DLY_TELEM, mychannel);
03258 res = ast_streamfile(mychannel, "rpt/remote_go", mychannel->language);
03259 break;
03260 case CONNECTED:
03261
03262 wait_interval(myrpt, DLY_TELEM, mychannel);
03263 res = ast_streamfile(mychannel, "rpt/node", mychannel->language);
03264 if (!res)
03265 res = ast_waitstream(mychannel, "");
03266 else
03267 ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", mychannel->name);
03268 ast_stopstream(mychannel);
03269 ast_say_character_str(mychannel,mytele->mylink.name,NULL,mychannel->language);
03270 res = ast_streamfile(mychannel, "rpt/connected", mychannel->language);
03271 if (!res)
03272 res = ast_waitstream(mychannel, "");
03273 else
03274 ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", mychannel->name);
03275 ast_stopstream(mychannel);
03276 res = ast_streamfile(mychannel, "digits/2", mychannel->language);
03277 if (!res)
03278 res = ast_waitstream(mychannel, "");
03279 else
03280 ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", mychannel->name);
03281 ast_stopstream(mychannel);
03282 res = ast_streamfile(mychannel, "rpt/node", mychannel->language);
03283 if (!res)
03284 res = ast_waitstream(mychannel, "");
03285 else
03286 ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", mychannel->name);
03287 ast_stopstream(mychannel);
03288 ast_say_character_str(mychannel,myrpt->name,NULL,mychannel->language);
03289 imdone = 1;
03290 break;
03291 case CONNFAIL:
03292 res = ast_streamfile(mychannel, "rpt/node", mychannel->language);
03293 if (!res)
03294 res = ast_waitstream(mychannel, "");
03295 else
03296 ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", mychannel->name);
03297 ast_stopstream(mychannel);
03298 ast_say_character_str(mychannel,mytele->mylink.name,NULL,mychannel->language);
03299 res = ast_streamfile(mychannel, "rpt/connection_failed", mychannel->language);
03300 break;
03301 case MEMNOTFOUND:
03302
03303 wait_interval(myrpt, DLY_TELEM, mychannel);
03304 res = ast_streamfile(mychannel, "rpt/memory_notfound", mychannel->language);
03305 break;
03306 case SETREMOTE:
03307 ast_mutex_lock(&myrpt->remlock);
03308 res = 0;
03309 if(!strcmp(myrpt->remote, remote_rig_ft897))
03310 {
03311 res = set_ft897(myrpt);
03312 }
03313 if(!strcmp(myrpt->remote, remote_rig_ic706))
03314 {
03315 res = set_ic706(myrpt);
03316 }
03317 else if(!strcmp(myrpt->remote, remote_rig_rbi))
03318 {
03319 if (ioperm(myrpt->p.iobase,1,1) == -1)
03320 {
03321 rpt_mutex_unlock(&myrpt->lock);
03322 ast_log(LOG_WARNING, "Cant get io permission on IO port %x hex\n",myrpt->p.iobase);
03323 res = -1;
03324 }
03325 else res = setrbi(myrpt);
03326 }
03327 else if(!strcmp(myrpt->remote, remote_rig_kenwood))
03328 {
03329 res = setkenwood(myrpt);
03330 if (ast_safe_sleep(mychannel,200) == -1)
03331 {
03332 ast_mutex_unlock(&myrpt->remlock);
03333 res = -1;
03334 break;
03335 }
03336 i = ZT_FLUSH_EVENT;
03337 if (ioctl(myrpt->txchannel->fds[0],ZT_FLUSH,&i) == -1)
03338 {
03339 ast_mutex_unlock(&myrpt->remlock);
03340 ast_log(LOG_ERROR,"Cant flush events");
03341 res = -1;
03342 break;
03343 }
03344 if (ioctl(myrpt->rxchannel->fds[0],ZT_GET_PARAMS,&par) == -1)
03345 {
03346 ast_mutex_unlock(&myrpt->remlock);
03347 ast_log(LOG_ERROR,"Cant get params");
03348 res = -1;
03349 break;
03350 }
03351 myrpt->remoterx =
03352 (par.rxisoffhook || (myrpt->tele.next != &myrpt->tele));
03353 }
03354 ast_mutex_unlock(&myrpt->remlock);
03355 if (!res)
03356 {
03357 imdone = 1;
03358 break;
03359 }
03360
03361 case INVFREQ:
03362
03363 wait_interval(myrpt, DLY_TELEM, mychannel);
03364 res = ast_streamfile(mychannel, "rpt/invalid-freq", mychannel->language);
03365 break;
03366 case REMMODE:
03367 cp = 0;
03368 wait_interval(myrpt, DLY_TELEM, mychannel);
03369 switch(myrpt->remmode)
03370 {
03371 case REM_MODE_FM:
03372 saycharstr(mychannel,"FM");
03373 break;
03374 case REM_MODE_USB:
03375 saycharstr(mychannel,"USB");
03376 break;
03377 case REM_MODE_LSB:
03378 saycharstr(mychannel,"LSB");
03379 break;
03380 case REM_MODE_AM:
03381 saycharstr(mychannel,"AM");
03382 break;
03383 }
03384 wait_interval(myrpt, DLY_COMP, mychannel);
03385 if (!res) res = telem_lookup(myrpt,mychannel, myrpt->name, "functcomplete");
03386 break;
03387 case LOGINREQ:
03388 wait_interval(myrpt, DLY_TELEM, mychannel);
03389 sayfile(mychannel,"rpt/login");
03390 saycharstr(mychannel,myrpt->name);
03391 break;
03392 case REMLOGIN:
03393 wait_interval(myrpt, DLY_TELEM, mychannel);
03394 saycharstr(mychannel,myrpt->loginuser);
03395 sayfile(mychannel,"rpt/node");
03396 saycharstr(mychannel,myrpt->name);
03397 wait_interval(myrpt, DLY_COMP, mychannel);
03398 if (!res) res = telem_lookup(myrpt,mychannel, myrpt->name, "functcomplete");
03399 break;
03400 case REMXXX:
03401 wait_interval(myrpt, DLY_TELEM, mychannel);
03402 res = 0;
03403 switch(mytele->submode)
03404 {
03405 case 100:
03406 sayfile(mychannel, "rpt/rxpl");
03407 sayfile(mychannel, "rpt/off");
03408 break;
03409 case 101:
03410 sayfile(mychannel, "rpt/rxpl");
03411 sayfile(mychannel, "rpt/on");
03412 break;
03413 case 102:
03414 sayfile(mychannel, "rpt/txpl");
03415 sayfile(mychannel, "rpt/off");
03416 break;
03417 case 103:
03418 sayfile(mychannel, "rpt/txpl");
03419 sayfile(mychannel, "rpt/on");
03420 break;
03421 case 104:
03422 sayfile(mychannel, "rpt/lopwr");
03423 break;
03424 case 105:
03425 sayfile(mychannel, "rpt/medpwr");
03426 break;
03427 case 106:
03428 sayfile(mychannel, "rpt/hipwr");
03429 break;
03430 case 113:
03431 sayfile(mychannel,"rpt/down");
03432 sayfile(mychannel, "rpt/slow");
03433 break;
03434 case 114:
03435 sayfile(mychannel,"rpt/down");
03436 sayfile(mychannel, "rpt/quick");
03437 break;
03438 case 115:
03439 sayfile(mychannel,"rpt/down");
03440 sayfile(mychannel, "rpt/fast");
03441 break;
03442 case 116:
03443 sayfile(mychannel,"rpt/up");
03444 sayfile(mychannel, "rpt/slow");
03445 break;
03446 case 117:
03447 sayfile(mychannel,"rpt/up");
03448 sayfile(mychannel, "rpt/quick");
03449 break;
03450 case 118:
03451 sayfile(mychannel,"rpt/up");
03452 sayfile(mychannel, "rpt/fast");
03453 break;
03454 default:
03455 res = -1;
03456 }
03457 wait_interval(myrpt, DLY_COMP, mychannel);
03458 if (!res) res = telem_lookup(myrpt,mychannel, myrpt->name, "functcomplete");
03459 break;
03460 case SCAN:
03461 ast_mutex_lock(&myrpt->remlock);
03462 if (myrpt->hfscanstop)
03463 {
03464 myrpt->hfscanstatus = 0;
03465 myrpt->hfscanmode = 0;
03466 myrpt->hfscanstop = 0;
03467 mytele->mode = SCANSTAT;
03468 ast_mutex_unlock(&myrpt->remlock);
03469 if (ast_safe_sleep(mychannel,1000) == -1) break;
03470 sayfile(mychannel, "rpt/stop");
03471 imdone = 1;
03472 break;
03473 }
03474 if (myrpt->hfscanstatus > -2) service_scan(myrpt);
03475 i = myrpt->hfscanstatus;
03476 myrpt->hfscanstatus = 0;
03477 if (i) mytele->mode = SCANSTAT;
03478 ast_mutex_unlock(&myrpt->remlock);
03479 if (i < 0) sayfile(mychannel, "rpt/stop");
03480 else if (i > 0) saynum(mychannel,i);
03481 imdone = 1;
03482 break;
03483 case TUNE:
03484 ast_mutex_lock(&myrpt->remlock);
03485 if (!strcmp(myrpt->remote,remote_rig_ic706))
03486 {
03487 set_mode_ic706(myrpt, REM_MODE_AM);
03488 if(play_tone(mychannel, 800, 6000, 8192) == -1) break;
03489 ast_safe_sleep(mychannel,500);
03490 set_mode_ic706(myrpt, myrpt->remmode);
03491 myrpt->tunerequest = 0;
03492 ast_mutex_unlock(&myrpt->remlock);
03493 imdone = 1;
03494 break;
03495 }
03496 set_mode_ft897(myrpt, REM_MODE_AM);
03497 simple_command_ft897(myrpt, 8);
03498 if(play_tone(mychannel, 800, 6000, 8192) == -1) break;
03499 simple_command_ft897(myrpt, 0x88);
03500 ast_safe_sleep(mychannel,500);
03501 set_mode_ft897(myrpt, myrpt->remmode);
03502 myrpt->tunerequest = 0;
03503 ast_mutex_unlock(&myrpt->remlock);
03504 imdone = 1;
03505 break;
03506 case REMSHORTSTATUS:
03507 case REMLONGSTATUS:
03508 wait_interval(myrpt, DLY_TELEM, mychannel);
03509 res = sayfile(mychannel,"rpt/node");
03510 if(!res)
03511 res = saycharstr(mychannel, myrpt->name);
03512 if(!res)
03513 res = sayfile(mychannel,"rpt/frequency");
03514 if(!res)
03515 res = split_freq(mhz, decimals, myrpt->freq);
03516 if (!multimode_capable(myrpt)) decimals[3] = 0;
03517 if(!res){
03518 m = atoi(mhz);
03519 if(m < 100)
03520 res = saynum(mychannel, m);
03521 else
03522 res = saycharstr(mychannel, mhz);
03523 }
03524 if(!res)
03525 res = sayfile(mychannel, "letters/dot");
03526 if(!res)
03527 res = saycharstr(mychannel, decimals);
03528
03529 if(res) break;
03530 if(myrpt->remmode == REM_MODE_FM){
03531 switch(myrpt->offset){
03532
03533 case REM_MINUS:
03534 res = sayfile(mychannel,"rpt/minus");
03535 break;
03536
03537 case REM_SIMPLEX:
03538 res = sayfile(mychannel,"rpt/simplex");
03539 break;
03540
03541 case REM_PLUS:
03542 res = sayfile(mychannel,"rpt/plus");
03543 break;
03544
03545 default:
03546 break;
03547 }
03548 }
03549 else{
03550 switch(myrpt->remmode){
03551
03552 case REM_MODE_USB:
03553 res = saycharstr(mychannel, "USB");
03554 break;
03555
03556 case REM_MODE_LSB:
03557 res = saycharstr(mychannel, "LSB");
03558 break;
03559
03560 case REM_MODE_AM:
03561 res = saycharstr(mychannel, "AM");
03562 break;
03563
03564
03565 default:
03566 break;
03567 }
03568 }
03569
03570 if (res == -1) break;
03571
03572 if(mytele->mode == REMSHORTSTATUS){
03573 wait_interval(myrpt, DLY_COMP, mychannel);
03574 if (!res) res = telem_lookup(myrpt,mychannel, myrpt->name, "functcomplete");
03575 break;
03576 }
03577
03578 if (strcmp(myrpt->remote,remote_rig_ic706))
03579 {
03580 switch(myrpt->powerlevel){
03581
03582 case REM_LOWPWR:
03583 res = sayfile(mychannel,"rpt/lopwr") ;
03584 break;
03585 case REM_MEDPWR:
03586 res = sayfile(mychannel,"rpt/medpwr");
03587 break;
03588 case REM_HIPWR:
03589 res = sayfile(mychannel,"rpt/hipwr");
03590 break;
03591 }
03592 }
03593
03594 rbimode = ((!strncmp(myrpt->remote,remote_rig_rbi,3))
03595 || (!strncmp(myrpt->remote,remote_rig_ic706,3)));
03596 if (res || (sayfile(mychannel,"rpt/rxpl") == -1)) break;
03597 if (rbimode && (sayfile(mychannel,"rpt/txpl") == -1)) break;
03598 if ((sayfile(mychannel,"rpt/frequency") == -1) ||
03599 (saycharstr(mychannel,myrpt->rxpl) == -1)) break;
03600 if ((!rbimode) && ((sayfile(mychannel,"rpt/txpl") == -1) ||
03601 (sayfile(mychannel,"rpt/frequency") == -1) ||
03602 (saycharstr(mychannel,myrpt->txpl) == -1))) break;
03603 if(myrpt->remmode == REM_MODE_FM){
03604 if ((sayfile(mychannel,"rpt/rxpl") == -1) ||
03605 (sayfile(mychannel,((myrpt->rxplon) ? "rpt/on" : "rpt/off")) == -1) ||
03606 (sayfile(mychannel,"rpt/txpl") == -1) ||
03607 (sayfile(mychannel,((myrpt->txplon) ? "rpt/on" : "rpt/off")) == -1))
03608 {
03609 break;
03610 }
03611 }
03612 wait_interval(myrpt, DLY_COMP, mychannel);
03613 if (!res) res = telem_lookup(myrpt,mychannel, myrpt->name, "functcomplete");
03614 break;
03615 case STATUS:
03616
03617 wait_interval(myrpt, DLY_TELEM, mychannel);
03618 hastx = 0;
03619 linkbase.next = &linkbase;
03620 linkbase.prev = &linkbase;
03621 rpt_mutex_lock(&myrpt->lock);
03622
03623 l = myrpt->links.next;
03624 while(l != &myrpt->links)
03625 {
03626 if (l->name[0] == '0')
03627 {
03628 l = l->next;
03629 continue;
03630 }
03631 l1 = malloc(sizeof(struct rpt_link));
03632 if (!l1)
03633 {
03634 ast_log(LOG_WARNING, "Cannot alloc memory on %s\n", mychannel->name);
03635 remque((struct qelem *)mytele);
03636 rpt_mutex_unlock(&myrpt->lock);
03637 ast_log(LOG_NOTICE,"Telemetry thread aborted at line %d, mode: %d\n",__LINE__, mytele->mode);
03638 free(mytele);
03639 ast_hangup(mychannel);
03640 pthread_exit(NULL);
03641 }
03642 memcpy(l1,l,sizeof(struct rpt_link));
03643 l1->next = l1->prev = NULL;
03644 insque((struct qelem *)l1,(struct qelem *)linkbase.next);
03645 l = l->next;
03646 }
03647 rpt_mutex_unlock(&myrpt->lock);
03648 res = ast_streamfile(mychannel, "rpt/node", mychannel->language);
03649 if (!res)
03650 res = ast_waitstream(mychannel, "");
03651 else
03652 ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", mychannel->name);
03653 ast_stopstream(mychannel);
03654 ast_say_character_str(mychannel,myrpt->name,NULL,mychannel->language);
03655 if (!res)
03656 res = ast_waitstream(mychannel, "");
03657 else
03658 ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", mychannel->name);
03659 ast_stopstream(mychannel);
03660 if (myrpt->callmode)
03661 {
03662 hastx = 1;
03663 res = ast_streamfile(mychannel, "rpt/autopatch_on", mychannel->language);
03664 if (!res)
03665 res = ast_waitstream(mychannel, "");
03666 else
03667 ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", mychannel->name);
03668 ast_stopstream(mychannel);
03669 }
03670 l = linkbase.next;
03671 while(l != &linkbase)
03672 {
03673 char *s;
03674
03675 hastx = 1;
03676 res = ast_streamfile(mychannel, "rpt/node", mychannel->language);
03677 if (!res)
03678 res = ast_waitstream(mychannel, "");
03679 else
03680 ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", mychannel->name);
03681 ast_stopstream(mychannel);
03682 ast_say_character_str(mychannel,l->name,NULL,mychannel->language);
03683 if (!res)
03684 res = ast_waitstream(mychannel, "");
03685 else
03686 ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", mychannel->name);
03687 ast_stopstream(mychannel);
03688 s = "rpt/tranceive";
03689 if (!l->mode) s = "rpt/monitor";
03690 if (!l->thisconnected) s = "rpt/connecting";
03691 res = ast_streamfile(mychannel, s, mychannel->language);
03692 if (!res)
03693 res = ast_waitstream(mychannel, "");
03694 else
03695 ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", mychannel->name);
03696 ast_stopstream(mychannel);
03697 l = l->next;
03698 }
03699 if (!hastx)
03700 {
03701 res = ast_streamfile(mychannel, "rpt/repeat_only", mychannel->language);
03702 if (!res)
03703 res = ast_waitstream(mychannel, "");
03704 else
03705 ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", mychannel->name);
03706 ast_stopstream(mychannel);
03707 }
03708
03709 l = linkbase.next;
03710 while(l != &linkbase)
03711 {
03712 l1 = l;
03713 l = l->next;
03714 remque((struct qelem *)l1);
03715 free(l1);
03716 }
03717 imdone = 1;
03718 break;
03719 case FULLSTATUS:
03720 rpt_mutex_lock(&myrpt->lock);
03721
03722 __mklinklist(myrpt,NULL,lbuf);
03723 rpt_mutex_unlock(&myrpt->lock);
03724
03725 ns = finddelim(lbuf,strs,MAXLINKLIST);
03726
03727 if (ns) qsort((void *)strs,ns,sizeof(char *),mycompar);
03728
03729 wait_interval(myrpt, DLY_TELEM, mychannel);
03730 hastx = 0;
03731 res = ast_streamfile(mychannel, "rpt/node", mychannel->language);
03732 if (!res)
03733 res = ast_waitstream(mychannel, "");
03734 else
03735 ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", mychannel->name);
03736 ast_stopstream(mychannel);
03737 ast_say_character_str(mychannel,myrpt->name,NULL,mychannel->language);
03738 if (!res)
03739 res = ast_waitstream(mychannel, "");
03740 else
03741 ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", mychannel->name);
03742 ast_stopstream(mychannel);
03743 if (myrpt->callmode)
03744 {
03745 hastx = 1;
03746 res = ast_streamfile(mychannel, "rpt/autopatch_on", mychannel->language);
03747 if (!res)
03748 res = ast_waitstream(mychannel, "");
03749 else
03750 ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", mychannel->name);
03751 ast_stopstream(mychannel);
03752 }
03753
03754 for(i = 0; i < ns; i++)
03755 {
03756 char *s,mode = 'T';
03757
03758
03759 if ((*strs[i] < '0') || (*strs[i] > '9'))
03760 {
03761 mode = *strs[i];
03762 strs[i]++;
03763 }
03764
03765 hastx = 1;
03766 res = ast_streamfile(mychannel, "rpt/node", mychannel->language);
03767 if (!res)
03768 res = ast_waitstream(mychannel, "");
03769 else
03770 ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", mychannel->name);
03771 ast_stopstream(mychannel);
03772 ast_say_character_str(mychannel,strs[i],NULL,mychannel->language);
03773 if (!res)
03774 res = ast_waitstream(mychannel, "");
03775 else
03776 ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", mychannel->name);
03777 ast_stopstream(mychannel);
03778 s = "rpt/tranceive";
03779 if (mode == 'R') s = "rpt/monitor";
03780 if (mode == 'C') s = "rpt/connecting";
03781 res = ast_streamfile(mychannel, s, mychannel->language);
03782 if (!res)
03783 res = ast_waitstream(mychannel, "");
03784 else
03785 ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", mychannel->name);
03786 ast_stopstream(mychannel);
03787 }
03788 if (!hastx)
03789 {
03790 res = ast_streamfile(mychannel, "rpt/repeat_only", mychannel->language);
03791 if (!res)
03792 res = ast_waitstream(mychannel, "");
03793 else
03794 ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", mychannel->name);
03795 ast_stopstream(mychannel);
03796 }
03797 imdone = 1;
03798 break;
03799
03800 case LASTNODEKEY:
03801 rpt_mutex_lock(&myrpt->lock);
03802 if(myrpt->lastnodewhichkeyedusup)
03803 p = ast_strdupa(myrpt->lastnodewhichkeyedusup);
03804 else
03805 p = NULL;
03806 rpt_mutex_unlock(&myrpt->lock);
03807 if(!p){
03808 imdone = 1;
03809 break;
03810 }
03811 wait_interval(myrpt, DLY_TELEM, mychannel);
03812 res = ast_streamfile(mychannel, "rpt/node", mychannel->language);
03813 if (!res)
03814 res = ast_waitstream(mychannel, "");
03815 else
03816 ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", mychannel->name);
03817 ast_stopstream(mychannel);
03818 ast_say_character_str(mychannel, p, NULL, mychannel->language);
03819 if (!res)
03820 res = ast_waitstream(mychannel, "");
03821 else
03822 ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", mychannel->name);
03823 ast_stopstream(mychannel);
03824 imdone = 1;
03825 break;
03826
03827 case UNAUTHTX:
03828 wait_interval(myrpt, DLY_TELEM, mychannel);
03829 res = ast_streamfile(mychannel, "rpt/unauthtx", mychannel->language);
03830 if (!res)
03831 res = ast_waitstream(mychannel, "");
03832 else
03833 ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", mychannel->name);
03834 ast_stopstream(mychannel);
03835 imdone = 1;
03836 break;
03837
03838
03839 case TIMEOUT:
03840 res = ast_streamfile(mychannel, "rpt/node", mychannel->language);
03841 if (!res)
03842 res = ast_waitstream(mychannel, "");
03843 else
03844 ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", mychannel->name);
03845 ast_stopstream(mychannel);
03846 ast_say_character_str(mychannel,myrpt->name,NULL,mychannel->language);
03847 res = ast_streamfile(mychannel, "rpt/timeout", mychannel->language);
03848 break;
03849
03850 case TIMEOUT_WARNING:
03851 time(&t);
03852 res = ast_streamfile(mychannel, "rpt/node", mychannel->language);
03853 if (!res)
03854 res = ast_waitstream(mychannel, "");
03855 else
03856 ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", mychannel->name);
03857 ast_stopstream(mychannel);
03858 ast_say_character_str(mychannel,myrpt->name,NULL,mychannel->language);
03859 res = ast_streamfile(mychannel, "rpt/timeout-warning", mychannel->language);
03860 if (!res)
03861 res = ast_waitstream(mychannel, "");
03862 else
03863 ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", mychannel->name);
03864 ast_stopstream(mychannel);
03865 if(!res)
03866 ast_say_number(mychannel, myrpt->p.remotetimeout -
03867 (t - myrpt->last_activity_time),
03868 "", mychannel->language, (char *) NULL);
03869 if (!res)
03870 res = ast_waitstream(mychannel, "");
03871 ast_stopstream(mychannel);
03872 res = ast_streamfile(mychannel, "queue-seconds", mychannel->language);
03873 break;
03874
03875 case ACT_TIMEOUT_WARNING:
03876 time(&t);
03877 res = ast_streamfile(mychannel, "rpt/node", mychannel->language);
03878 if (!res)
03879 res = ast_waitstream(mychannel, "");
03880 else
03881 ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", mychannel->name);
03882 ast_stopstream(mychannel);
03883 ast_say_character_str(mychannel,myrpt->name,NULL,mychannel->language);
03884 res = ast_streamfile(mychannel, "rpt/act-timeout-warning", mychannel->language);
03885 if (!res)
03886 res = ast_waitstream(mychannel, "");
03887 else
03888 ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", mychannel->name);
03889 ast_stopstream(mychannel);
03890 if(!res)
03891 ast_say_number(mychannel, myrpt->p.remoteinacttimeout -
03892 (t - myrpt->last_activity_time),
03893 "", mychannel->language, (char *) NULL);
03894 if (!res)
03895 res = ast_waitstream(mychannel, "");
03896 ast_stopstream(mychannel);
03897 res = ast_streamfile(mychannel, "queue-seconds", mychannel->language);
03898 break;
03899
03900 case STATS_TIME:
03901 wait_interval(myrpt, DLY_TELEM, mychannel);
03902 t = time(NULL);
03903 rpt_localtime(&t, &localtm);
03904
03905 if((localtm.tm_hour >= 0) && (localtm.tm_hour < 12))
03906 p = "rpt/goodmorning";
03907 else if((localtm.tm_hour >= 12) && (localtm.tm_hour < 18))
03908 p = "rpt/goodafternoon";
03909 else
03910 p = "rpt/goodevening";
03911 if (sayfile(mychannel,p) == -1)
03912 {
03913 imdone = 1;
03914 break;
03915 }
03916
03917 if (sayfile(mychannel,"rpt/thetimeis") == -1)
03918 {
03919 imdone = 1;
03920 break;
03921 }
03922
03923 res = ast_say_time(mychannel, t, "", mychannel->language);
03924 if (!res)
03925 res = ast_waitstream(mychannel, "");
03926 ast_stopstream(mychannel);
03927 imdone = 1;
03928 break;
03929 case STATS_VERSION:
03930 p = strstr(tdesc, "version");
03931 if(!p)
03932 break;
03933 if(sscanf(p, "version %d.%d", &vmajor, &vminor) != 2)
03934 break;
03935 wait_interval(myrpt, DLY_TELEM, mychannel);
03936
03937 if (sayfile(mychannel,"rpt/version") == -1)
03938 {
03939 imdone = 1;
03940 break;
03941 }
03942 if(!res)
03943 ast_say_number(mychannel, vmajor, "", mychannel->language, (char *) NULL);
03944 if (!res)
03945 res = ast_waitstream(mychannel, "");
03946 ast_stopstream(mychannel);
03947 if (saycharstr(mychannel,".") == -1)
03948 {
03949 imdone = 1;
03950 break;
03951 }
03952 if(!res)
03953 ast_say_number(mychannel, vminor, "", mychannel->language, (char *) NULL);
03954 if (!res){
03955 res = ast_waitstream(mychannel, "");
03956 ast_stopstream(mychannel);
03957 }
03958 else
03959 ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", mychannel->name);
03960 imdone = 1;
03961 break;
03962 case ARB_ALPHA:
03963 wait_interval(myrpt, DLY_TELEM, mychannel);
03964 if(mytele->param)
03965 saycharstr(mychannel, mytele->param);
03966 imdone = 1;
03967 break;
03968 case REV_PATCH:
03969 wait_interval(myrpt, DLY_TELEM, mychannel);
03970 if(mytele->param) {
03971
03972
03973 char *tpl_working, *tpl_current;
03974 char *tmp[100], *myparm;
03975 int looptemp=0,i=0, dres = 0;
03976
03977
03978 tpl_working = strdupa(mytele->param);
03979 myparm = strsep(&tpl_working,",");
03980 tpl_current=strsep(&tpl_working, ":");
03981
03982 while(tpl_current && looptemp < sizeof(tmp)) {
03983 tmp[looptemp]=tpl_current;
03984 looptemp++;
03985 tpl_current=strsep(&tpl_working,":");
03986 }
03987
03988 for(i=0; i<looptemp; i++) {
03989 if(!strcmp(tmp[i], "PARKED")) {
03990 ast_say_digits(mychannel, atoi(myparm), "", mychannel->language);
03991 } else if(!strcmp(tmp[i], "NODE")) {
03992 ast_say_digits(mychannel, atoi(myrpt->name), "", mychannel->language);
03993 } else {
03994 dres = ast_streamfile(mychannel, tmp[i], mychannel->language);
03995 if(!dres) {
03996 dres = ast_waitstream(mychannel, "");
03997 } else {
03998 ast_log(LOG_WARNING, "ast_streamfile of %s failed on %s\n", tmp[i], mychannel->name);
03999 dres = 0;
04000 }
04001 }
04002 }
04003 }
04004 imdone = 1;
04005 break;
04006 case TEST_TONE:
04007 imdone = 1;
04008 if (myrpt->stopgen) break;
04009 myrpt->stopgen = -1;
04010 if ((res = ast_tonepair_start(mychannel, 1004.0, 0, 99999999, 7200.0)))
04011 {
04012 myrpt->stopgen = 0;
04013 break;
04014 }
04015 while(mychannel->generatordata && (myrpt->stopgen <= 0)) {
04016 if (ast_safe_sleep(mychannel,1)) break;
04017 imdone = 1;
04018 }
04019 myrpt->stopgen = 0;
04020 break;
04021 default:
04022 break;
04023 }
04024 if (!imdone)
04025 {
04026 if (!res)
04027 res = ast_waitstream(mychannel, "");
04028 else {
04029 ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", mychannel->name);
04030 res = 0;
04031 }
04032 }
04033 ast_stopstream(mychannel);
04034 rpt_mutex_lock(&myrpt->lock);
04035 if (mytele->mode == TAILMSG)
04036 {
04037 if (!res)
04038 {
04039 myrpt->tailmessagen++;
04040 if(myrpt->tailmessagen >= myrpt->p.tailmessagemax) myrpt->tailmessagen = 0;
04041 }
04042 else
04043 {
04044 myrpt->tmsgtimer = myrpt->p.tailsquashedtime;
04045 }
04046 }
04047 remque((struct qelem *)mytele);
04048 rpt_mutex_unlock(&myrpt->lock);
04049 free(mytele);
04050 ast_hangup(mychannel);
04051 #ifdef APP_RPT_LOCK_DEBUG
04052 {
04053 struct lockthread *t;
04054
04055 sleep(5);
04056 ast_mutex_lock(&locklock);
04057 t = get_lockthread(pthread_self());
04058 if (t) memset(t,0,sizeof(struct lockthread));
04059 ast_mutex_unlock(&locklock);
04060 }
04061 #endif
04062 pthread_exit(NULL);
04063 }
04064
04065 static void rpt_telemetry(struct rpt *myrpt,int mode, void *data)
04066 {
04067 struct rpt_tele *tele;
04068 struct rpt_link *mylink = (struct rpt_link *) data;
04069 int res;
04070 pthread_attr_t attr;
04071
04072 tele = malloc(sizeof(struct rpt_tele));
04073 if (!tele)
04074 {
04075 ast_log(LOG_WARNING, "Unable to allocate memory\n");
04076 pthread_exit(NULL);
04077 return;
04078 }
04079
04080 memset((char *)tele,0,sizeof(struct rpt_tele));
04081 tele->rpt = myrpt;
04082 tele->mode = mode;
04083 rpt_mutex_lock(&myrpt->lock);
04084 if((mode == CONNFAIL) || (mode == REMDISC) || (mode == CONNECTED) ||
04085 (mode == LINKUNKEY)){
04086 memset(&tele->mylink,0,sizeof(struct rpt_link));
04087 if (mylink){
04088 memcpy(&tele->mylink,mylink,sizeof(struct rpt_link));
04089 }
04090 }
04091 else if ((mode == ARB_ALPHA) || (mode == REV_PATCH)) {
04092 strncpy(tele->param, (char *) data, TELEPARAMSIZE - 1);
04093 tele->param[TELEPARAMSIZE - 1] = 0;
04094 }
04095 if (mode == REMXXX) tele->submode = (int) data;
04096 insque((struct qelem *)tele, (struct qelem *)myrpt->tele.next);
04097 rpt_mutex_unlock(&myrpt->lock);
04098 pthread_attr_init(&attr);
04099 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
04100 res = ast_pthread_create(&tele->threadid,&attr,rpt_tele_thread,(void *) tele);
04101 if(res < 0){
04102 rpt_mutex_lock(&myrpt->lock);
04103 remque((struct qlem *) tele);
04104 rpt_mutex_unlock(&myrpt->lock);
04105 ast_log(LOG_WARNING, "Could not create telemetry thread: %s",strerror(res));
04106 }
04107 return;
04108 }
04109
04110 static void *rpt_call(void *this)
04111 {
04112 ZT_CONFINFO ci;
04113 struct rpt *myrpt = (struct rpt *)this;
04114 int res;
04115 int stopped,congstarted,dialtimer,lastcidx,aborted;
04116 struct ast_channel *mychannel,*genchannel;
04117
04118
04119 myrpt->mydtmf = 0;
04120
04121 mychannel = ast_request("zap",AST_FORMAT_SLINEAR,"pseudo",NULL);
04122 if (!mychannel)
04123 {
04124 fprintf(stderr,"rpt:Sorry unable to obtain pseudo channel\n");
04125 pthread_exit(NULL);
04126 }
04127 ci.chan = 0;
04128 ci.confno = myrpt->conf;
04129 ci.confmode = ZT_CONF_REALANDPSEUDO | ZT_CONF_TALKER | ZT_CONF_LISTENER
04130 | ZT_CONF_PSEUDO_TALKER | ZT_CONF_PSEUDO_LISTENER;
04131
04132 if (ioctl(mychannel->fds[0],ZT_SETCONF,&ci) == -1)
04133 {
04134 ast_log(LOG_WARNING, "Unable to set conference mode to Announce\n");
04135 ast_hangup(mychannel);
04136 myrpt->callmode = 0;
04137 pthread_exit(NULL);
04138 }
04139
04140 genchannel = ast_request("zap",AST_FORMAT_SLINEAR,"pseudo",NULL);
04141 if (!genchannel)
04142 {
04143 fprintf(stderr,"rpt:Sorry unable to obtain pseudo channel\n");
04144 ast_hangup(mychannel);
04145 pthread_exit(NULL);
04146 }
04147 ci.chan = 0;
04148 ci.confno = myrpt->conf;
04149 ci.confmode = ZT_CONF_REALANDPSEUDO | ZT_CONF_TALKER | ZT_CONF_LISTENER
04150 | ZT_CONF_PSEUDO_TALKER | ZT_CONF_PSEUDO_LISTENER;
04151
04152 if (ioctl(genchannel->fds[0],ZT_SETCONF,&ci) == -1)
04153 {
04154 ast_log(LOG_WARNING, "Unable to set conference mode to Announce\n");
04155 ast_hangup(mychannel);
04156 ast_hangup(genchannel);
04157 myrpt->callmode = 0;
04158 pthread_exit(NULL);
04159 }
04160 if (myrpt->p.tonezone && (tone_zone_set_zone(mychannel->fds[0],myrpt->p.tonezone) == -1))
04161 {
04162 ast_log(LOG_WARNING, "Unable to set tone zone %s\n",myrpt->p.tonezone);
04163 ast_hangup(mychannel);
04164 ast_hangup(genchannel);
04165 myrpt->callmode = 0;
04166 pthread_exit(NULL);
04167 }
04168 if (myrpt->p.tonezone && (tone_zone_set_zone(genchannel->fds[0],myrpt->p.tonezone) == -1))
04169 {
04170 ast_log(LOG_WARNING, "Unable to set tone zone %s\n",myrpt->p.tonezone);
04171 ast_hangup(mychannel);
04172 ast_hangup(genchannel);
04173 myrpt->callmode = 0;
04174 pthread_exit(NULL);
04175 }
04176
04177 if ((!myrpt->patchquiet) && (tone_zone_play_tone(mychannel->fds[0],ZT_TONE_DIALTONE) < 0))
04178 {
04179 ast_log(LOG_WARNING, "Cannot start dialtone\n");
04180 ast_hangup(mychannel);
04181 ast_hangup(genchannel);
04182 myrpt->callmode = 0;
04183 pthread_exit(NULL);
04184 }
04185 stopped = 0;
04186 congstarted = 0;
04187 dialtimer = 0;
04188 lastcidx = 0;
04189 aborted = 0;
04190
04191
04192 while ((myrpt->callmode == 1) || (myrpt->callmode == 4))
04193 {
04194
04195 if((myrpt->patchdialtime)&&(myrpt->callmode == 1)&&(myrpt->cidx != lastcidx)){
04196 dialtimer = 0;
04197 lastcidx = myrpt->cidx;
04198 }
04199
04200 if((myrpt->patchdialtime)&&(dialtimer >= myrpt->patchdialtime)){
04201 rpt_mutex_lock(&myrpt->lock);
04202 aborted = 1;
04203 myrpt->callmode = 0;
04204 rpt_mutex_unlock(&myrpt->lock);
04205 break;
04206 }
04207
04208 if ((!myrpt->patchquiet) && (!stopped) && (myrpt->callmode == 1) && (myrpt->cidx > 0))
04209 {
04210 stopped = 1;
04211
04212 tone_zone_play_tone(mychannel->fds[0],-1);
04213 }
04214 if (myrpt->callmode == 4)
04215 {
04216 if(!congstarted){
04217 congstarted = 1;
04218
04219 tone_zone_play_tone(mychannel->fds[0],ZT_TONE_CONGESTION);
04220 }
04221 }
04222 res = ast_safe_sleep(mychannel, MSWAIT);
04223 if (res < 0)
04224 {
04225 ast_hangup(mychannel);
04226 ast_hangup(genchannel);
04227 rpt_mutex_lock(&myrpt->lock);
04228 myrpt->callmode = 0;
04229 rpt_mutex_unlock(&myrpt->lock);
04230 pthread_exit(NULL);
04231 }
04232 dialtimer += MSWAIT;
04233 }
04234
04235 tone_zone_play_tone(mychannel->fds[0],-1);
04236
04237 if (!myrpt->callmode)
04238 {
04239 ast_hangup(mychannel);
04240 ast_hangup(genchannel);
04241 rpt_mutex_lock(&myrpt->lock);
04242 myrpt->callmode = 0;
04243 rpt_mutex_unlock(&myrpt->lock);
04244 if((!myrpt->patchquiet) && aborted)
04245 rpt_telemetry(myrpt, TERM, NULL);
04246 pthread_exit(NULL);
04247 }
04248
04249 if (myrpt->p.ourcallerid && *myrpt->p.ourcallerid){
04250 char *name, *loc, *instr;
04251 instr = strdup(myrpt->p.ourcallerid);
04252 if(instr){
04253 ast_callerid_parse(instr, &name, &loc);
04254 if(loc){
04255 if(mychannel->cid.cid_num)
04256 free(mychannel->cid.cid_num);
04257 mychannel->cid.cid_num = strdup(loc);
04258 }
04259 if(name){
04260 if(mychannel->cid.cid_name)
04261 free(mychannel->cid.cid_name);
04262 mychannel->cid.cid_name = strdup(name);
04263 }
04264 free(instr);
04265 }
04266 }
04267
04268 ast_copy_string(mychannel->exten, myrpt->exten, sizeof(mychannel->exten) - 1);
04269 ast_copy_string(mychannel->context, myrpt->patchcontext, sizeof(mychannel->context) - 1);
04270
04271 if (myrpt->p.acctcode)
04272 ast_cdr_setaccount(mychannel,myrpt->p.acctcode);
04273 mychannel->priority = 1;
04274 ast_channel_undefer_dtmf(mychannel);
04275 if (ast_pbx_start(mychannel) < 0)
04276 {
04277 ast_log(LOG_WARNING, "Unable to start PBX!!\n");
04278 ast_hangup(mychannel);
04279 ast_hangup(genchannel);
04280 rpt_mutex_lock(&myrpt->lock);
04281 myrpt->callmode = 0;
04282 rpt_mutex_unlock(&myrpt->lock);
04283 pthread_exit(NULL);
04284 }
04285 usleep(10000);
04286 rpt_mutex_lock(&myrpt->lock);
04287 myrpt->callmode = 3;
04288
04289 ci.chan = 0;
04290 ci.confno = myrpt->conf;
04291 ci.confmode = (myrpt->p.duplex == 2) ? ZT_CONF_CONFANNMON :
04292 (ZT_CONF_CONF | ZT_CONF_LISTENER | ZT_CONF_TALKER);
04293
04294 if (ioctl(myrpt->pchannel->fds[0],ZT_SETCONF,&ci) == -1)
04295 {
04296 ast_log(LOG_WARNING, "Unable to set conference mode to Announce\n");
04297 ast_hangup(mychannel);
04298 ast_hangup(genchannel);
04299 myrpt->callmode = 0;
04300 pthread_exit(NULL);
04301 }
04302 while(myrpt->callmode)
04303 {
04304 if ((!mychannel->pbx) && (myrpt->callmode != 4))
04305 {
04306 if(myrpt->patchfarenddisconnect){
04307 myrpt->callmode = 0;
04308 if(!myrpt->patchquiet){
04309 rpt_mutex_unlock(&myrpt->lock);
04310 rpt_telemetry(myrpt, TERM, NULL);
04311 rpt_mutex_lock(&myrpt->lock);
04312 }
04313 }
04314 else{
04315 myrpt->callmode = 4;
04316 rpt_mutex_unlock(&myrpt->lock);
04317
04318 tone_zone_play_tone(genchannel->fds[0],ZT_TONE_CONGESTION);
04319 rpt_mutex_lock(&myrpt->lock);
04320 }
04321 }
04322 if (myrpt->mydtmf)
04323 {
04324 struct ast_frame wf = {AST_FRAME_DTMF, } ;
04325 wf.subclass = myrpt->mydtmf;
04326 rpt_mutex_unlock(&myrpt->lock);
04327 ast_queue_frame(mychannel,&wf);
04328 ast_senddigit(genchannel,myrpt->mydtmf);
04329 rpt_mutex_lock(&myrpt->lock);
04330 myrpt->mydtmf = 0;
04331 }
04332 rpt_mutex_unlock(&myrpt->lock);
04333 usleep(MSWAIT * 1000);
04334 rpt_mutex_lock(&myrpt->lock);
04335 }
04336 rpt_mutex_unlock(&myrpt->lock);
04337 tone_zone_play_tone(genchannel->fds[0],-1);
04338 if (mychannel->pbx) ast_softhangup(mychannel,AST_SOFTHANGUP_DEV);
04339 ast_hangup(genchannel);
04340 rpt_mutex_lock(&myrpt->lock);
04341 myrpt->callmode = 0;
04342 rpt_mutex_unlock(&myrpt->lock);
04343
04344 ci.chan = 0;
04345 ci.confno = myrpt->conf;
04346 ci.confmode = ((myrpt->p.duplex == 2) || (myrpt->p.duplex == 4)) ? ZT_CONF_CONFANNMON :
04347 (ZT_CONF_CONF | ZT_CONF_LISTENER | ZT_CONF_TALKER);
04348
04349 if (ioctl(myrpt->pchannel->fds[0],ZT_SETCONF,&ci) == -1)
04350 {
04351 ast_log(LOG_WARNING, "Unable to set conference mode to Announce\n");
04352 }
04353 pthread_exit(NULL);
04354 }
04355
04356 static void send_link_dtmf(struct rpt *myrpt,char c)
04357 {
04358 char str[300];
04359 struct ast_frame wf;
04360 struct rpt_link *l;
04361
04362 snprintf(str, sizeof(str), "D %s %s %d %c", myrpt->cmdnode, myrpt->name, ++(myrpt->dtmfidx), c);
04363 wf.frametype = AST_FRAME_TEXT;
04364 wf.subclass = 0;
04365 wf.offset = 0;
04366 wf.mallocd = 0;
04367 wf.datalen = strlen(str) + 1;
04368 wf.samples = 0;
04369 l = myrpt->links.next;
04370
04371 while(l != &myrpt->links)
04372 {
04373 if (l->name[0] == '0')
04374 {
04375 l = l->next;
04376 continue;
04377 }
04378
04379 if (!strcmp(l->name,myrpt->cmdnode))
04380 {
04381 wf.data = str;
04382 if (l->chan) ast_write(l->chan,&wf);
04383 return;
04384 }
04385 l = l->next;
04386 }
04387 l = myrpt->links.next;
04388
04389 while(l != &myrpt->links)
04390 {
04391 wf.data = str;
04392 if (l->chan) ast_write(l->chan,&wf);
04393 l = l->next;
04394 }
04395 return;
04396 }
04397
04398
04399
04400
04401
04402
04403
04404
04405
04406
04407
04408 static int connect_link(struct rpt *myrpt, char* node, int mode, int perma)
04409 {
04410 char *val, *s, *s1, *s2, *tele;
04411 char lstr[MAXLINKLIST],*strs[MAXLINKLIST];
04412 char tmp[300], deststr[300] = "",modechange = 0;
04413 struct rpt_link *l;
04414 int reconnects = 0;
04415 int i,n;
04416 ZT_CONFINFO ci;
04417
04418 val = node_lookup(myrpt,node);
04419 if (!val){
04420 if(strlen(node) >= myrpt->longestnode)
04421 return -1;
04422 return 1;
04423 }
04424 if(debug > 3){
04425 ast_log(LOG_NOTICE,"Connect attempt to node %s\n", node);
04426 ast_log(LOG_NOTICE,"Mode: %s\n",(mode)?"Transceive":"Monitor");
04427 ast_log(LOG_NOTICE,"Connection type: %s\n",(perma)?"Permalink":"Normal");
04428 }
04429
04430 strncpy(tmp,val,sizeof(tmp) - 1);
04431 s = tmp;
04432 s1 = strsep(&s,",");
04433 s2 = strsep(&s,",");
04434 rpt_mutex_lock(&myrpt->lock);
04435 l = myrpt->links.next;
04436
04437 while(l != &myrpt->links){
04438 if (l->name[0] == '0')
04439 {
04440 l = l->next;
04441 continue;
04442 }
04443
04444 if (!strcmp(l->name, node))
04445 break;
04446 l = l->next;
04447 }
04448
04449 if (l != &myrpt->links){
04450
04451 if ((l->mode) || (!l->chan)) {
04452 rpt_mutex_unlock(&myrpt->lock);
04453 return 2;
04454 }
04455 reconnects = l->reconnects;
04456 rpt_mutex_unlock(&myrpt->lock);
04457 if (l->chan) ast_softhangup(l->chan, AST_SOFTHANGUP_DEV);
04458 l->retries = l->max_retries + 1;
04459 l->disced = 2;
04460 modechange = 1;
04461 } else
04462 {
04463 __mklinklist(myrpt,NULL,lstr);
04464 rpt_mutex_unlock(&myrpt->lock);
04465 n = finddelim(lstr,strs,MAXLINKLIST);
04466 for(i = 0; i < n; i++)
04467 {
04468 if ((*strs[i] < '0') ||
04469 (*strs[i] > '9')) strs[i]++;
04470 if (!strcmp(strs[i],node))
04471 {
04472 return 2;
04473 }
04474 }
04475 }
04476 strncpy(myrpt->lastlinknode,node,MAXNODESTR - 1);
04477
04478 l = malloc(sizeof(struct rpt_link));
04479 if (!l)
04480 {
04481 ast_log(LOG_WARNING, "Unable to malloc\n");
04482 return -1;
04483 }
04484
04485 memset((char *)l,0,sizeof(struct rpt_link));
04486 l->mode = mode;
04487 l->outbound = 1;
04488 l->thisconnected = 0;
04489 strncpy(l->name, node, MAXNODESTR - 1);
04490 l->isremote = (s && ast_true(s));
04491 if (modechange) l->connected = 1;
04492 l->hasconnected = l->perma = perma;
04493 snprintf(deststr, sizeof(deststr), "IAX2/%s", s1);
04494 tele = strchr(deststr, '/');
04495 if (!tele){
04496 ast_log(LOG_WARNING,"link3:Dial number (%s) must be in format tech/number\n",deststr);
04497 free(l);
04498 return -1;
04499 }
04500 *tele++ = 0;
04501 l->chan = ast_request(deststr, AST_FORMAT_SLINEAR, tele,NULL);
04502 if (l->chan){
04503 ast_set_read_format(l->chan, AST_FORMAT_SLINEAR);
04504 ast_set_write_format(l->chan, AST_FORMAT_SLINEAR);
04505 l->chan->whentohangup = 0;
04506 l->chan->appl = "Apprpt";
04507 l->chan->data = "(Remote Rx)";
04508 if (debug > 3)
04509 ast_log(LOG_NOTICE, "rpt (remote) initiating call to %s/%s on %s\n",
04510 deststr, tele, l->chan->name);
04511 if(l->chan->cid.cid_num)
04512 free(l->chan->cid.cid_num);
04513 l->chan->cid.cid_num = strdup(myrpt->name);
04514 ast_call(l->chan,tele,999);
04515 }
04516 else {
04517 if(debug > 3)
04518 ast_log(LOG_NOTICE, "Unable to place call to %s/%s on %s\n",
04519 deststr,tele,l->chan->name);
04520 if (myrpt->p.archivedir)
04521 {
04522 char str[100];
04523 sprintf(str,"LINKFAIL,%s",l->name);
04524 donodelog(myrpt,str);
04525 }
04526 free(l);
04527 return -1;
04528 }
04529
04530 l->pchan = ast_request("zap",AST_FORMAT_SLINEAR,"pseudo",NULL);
04531 if (!l->pchan){
04532 ast_log(LOG_WARNING,"rpt connect: Sorry unable to obtain pseudo channel\n");
04533 ast_hangup(l->chan);
04534 free(l);
04535 return -1;
04536 }
04537 ast_set_read_format(l->pchan, AST_FORMAT_SLINEAR);
04538 ast_set_write_format(l->pchan, AST_FORMAT_SLINEAR);
04539
04540 ci.chan = 0;
04541 ci.confno = myrpt->conf;
04542 ci.confmode = ZT_CONF_CONF | ZT_CONF_LISTENER | ZT_CONF_TALKER;
04543
04544 if (ioctl(l->pchan->fds[0], ZT_SETCONF, &ci) == -1)
04545 {
04546 ast_log(LOG_WARNING, "Unable to set conference mode to Announce\n");
04547 ast_hangup(l->chan);
04548 ast_hangup(l->pchan);
04549 free(l);
04550 return -1;
04551 }
04552 rpt_mutex_lock(&myrpt->lock);
04553 l->reconnects = reconnects;
04554
04555 l->max_retries = MAX_RETRIES;
04556 if (perma)
04557 l->max_retries = MAX_RETRIES_PERM;
04558 if (l->isremote) l->retries = l->max_retries + 1;
04559 insque((struct qelem *)l,(struct qelem *)myrpt->links.next);
04560 __kickshort(myrpt);
04561 rpt_mutex_unlock(&myrpt->lock);
04562 return 0;
04563 }
04564
04565
04566
04567
04568
04569
04570
04571 static int function_ilink(struct rpt *myrpt, char *param, char *digits, int command_source, struct rpt_link *mylink)
04572 {
04573
04574 char *val, *s, *s1, *s2;
04575 char tmp[300];
04576 char digitbuf[MAXNODESTR],*strs[MAXLINKLIST];
04577 char mode,perma;
04578 struct rpt_link *l;
04579 int i,r;
04580
04581 if(!param)
04582 return DC_ERROR;
04583
04584
04585 if (myrpt->p.s[myrpt->p.sysstate_cur].txdisable || myrpt->p.s[myrpt->p.sysstate_cur].linkfundisable )
04586 return DC_ERROR;
04587
04588 strncpy(digitbuf,digits,MAXNODESTR - 1);
04589
04590 if(debug > 6)
04591 printf("@@@@ ilink param = %s, digitbuf = %s\n", (param)? param : "(null)", digitbuf);
04592
04593 switch(myatoi(param)){
04594 case 11:
04595 case 1:
04596 if ((digitbuf[0] == '0') && (myrpt->lastlinknode[0]))
04597 strcpy(digitbuf,myrpt->lastlinknode);
04598 val = node_lookup(myrpt,digitbuf);
04599 if (!val){
04600 if(strlen(digitbuf) >= myrpt->longestnode)
04601 return DC_ERROR;
04602 break;
04603 }
04604 strncpy(tmp,val,sizeof(tmp) - 1);
04605 s = tmp;
04606 s1 = strsep(&s,",");
04607 s2 = strsep(&s,",");
04608 rpt_mutex_lock(&myrpt->lock);
04609 l = myrpt->links.next;
04610
04611 while(l != &myrpt->links){
04612 if (l->name[0] == '0')
04613 {
04614 l = l->next;
04615 continue;
04616 }
04617
04618 if (!strcmp(l->name, digitbuf))
04619 break;
04620 l = l->next;
04621 }
04622 if (l != &myrpt->links){
04623 struct ast_frame wf;
04624
04625
04626 if ((myatoi(param) < 10) &&
04627 (l->max_retries > MAX_RETRIES))
04628 {
04629 rpt_mutex_unlock(&myrpt->lock);
04630 return DC_COMPLETE;
04631 }
04632 strncpy(myrpt->lastlinknode,digitbuf,MAXNODESTR - 1);
04633 l->retries = l->max_retries + 1;
04634 l->disced = 1;
04635 rpt_mutex_unlock(&myrpt->lock);
04636 wf.frametype = AST_FRAME_TEXT;
04637 wf.subclass = 0;
04638 wf.offset = 0;
04639 wf.mallocd = 0;
04640 wf.datalen = strlen(discstr) + 1;
04641 wf.samples = 0;
04642 wf.data = discstr;
04643 if (l->chan)
04644 {
04645 ast_write(l->chan,&wf);
04646 if (ast_safe_sleep(l->chan,250) == -1) return DC_ERROR;
04647 ast_softhangup(l->chan,AST_SOFTHANGUP_DEV);
04648 }
04649 rpt_telemetry(myrpt, COMPLETE, NULL);
04650 return DC_COMPLETE;
04651 }
04652 rpt_mutex_unlock(&myrpt->lock);
04653 return DC_COMPLETE;
04654 case 2:
04655 case 3:
04656 case 12:
04657 case 13:
04658 if ((digitbuf[0] == '0') && (myrpt->lastlinknode[0]))
04659 strcpy(digitbuf,myrpt->lastlinknode);
04660
04661 perma = (atoi(param) > 10) ? 1 : 0;
04662 mode = (atoi(param) & 1) ? 1 : 0;
04663 r = connect_link(myrpt, digitbuf, mode, perma);
04664 switch(r){
04665 case 0:
04666 rpt_telemetry(myrpt, COMPLETE, NULL);
04667 return DC_COMPLETE;
04668
04669 case 1:
04670 break;
04671
04672 case 2:
04673 rpt_telemetry(myrpt, REMALREADY, NULL);
04674 return DC_COMPLETE;
04675
04676 default:
04677 rpt_telemetry(myrpt, CONNFAIL, NULL);
04678 return DC_COMPLETE;
04679 }
04680 break;
04681
04682 case 4:
04683
04684
04685 if (((command_source != SOURCE_RPT) &&
04686 (command_source != SOURCE_PHONE) &&
04687 (command_source != SOURCE_DPHONE)) ||
04688 (myrpt->links.next == &myrpt->links))
04689 return DC_COMPLETE;
04690
04691
04692 if ((myrpt->cmdnode[0]) || (!strcmp(myrpt->name, digitbuf))){
04693
04694 rpt_telemetry(myrpt, REMALREADY, NULL);
04695 return DC_COMPLETE;
04696 }
04697 if ((digitbuf[0] == '0') && (myrpt->lastlinknode[0]))
04698 strcpy(digitbuf,myrpt->lastlinknode);
04699
04700 val = node_lookup(myrpt,digitbuf);
04701 if (!val){
04702 if(strlen(digitbuf) >= myrpt->longestnode)
04703 return DC_ERROR;
04704 break;
04705
04706 }
04707 rpt_mutex_lock(&myrpt->lock);
04708 strcpy(myrpt->lastlinknode,digitbuf);
04709 strncpy(myrpt->cmdnode, digitbuf, sizeof(myrpt->cmdnode) - 1);
04710 rpt_mutex_unlock(&myrpt->lock);
04711 rpt_telemetry(myrpt, REMGO, NULL);
04712 return DC_COMPLETE;
04713
04714 case 5:
04715 rpt_telemetry(myrpt, STATUS, NULL);
04716 return DC_COMPLETE;
04717
04718 case 15:
04719 rpt_telemetry(myrpt, FULLSTATUS, NULL);
04720 return DC_COMPLETE;
04721
04722
04723 case 6:
04724 rpt_mutex_lock(&myrpt->lock);
04725 myrpt->savednodes[0] = 0;
04726 l = myrpt->links.next;
04727
04728 while(l != &myrpt->links){
04729 struct ast_frame wf;
04730 if (l->name[0] == '0')
04731 {
04732 l = l->next;
04733 continue;
04734 }
04735
04736 sprintf(tmp,"%c%c%s",(l->mode) ? 'X' : 'M',(l->perma) ? 'P':'T',l->name);
04737 if(strlen(tmp) + strlen(myrpt->savednodes) + 1 < MAXNODESTR){
04738 if(myrpt->savednodes[0])
04739 strcat(myrpt->savednodes, ",");
04740 strcat(myrpt->savednodes, tmp);
04741 }
04742 l->retries = l->max_retries + 1;
04743 l->disced = 2;
04744 rpt_mutex_unlock(&myrpt->lock);
04745
04746
04747 wf.frametype = AST_FRAME_TEXT;
04748 wf.subclass = 0;
04749 wf.offset = 0;
04750 wf.mallocd = 0;
04751 wf.datalen = strlen(discstr) + 1;
04752 wf.samples = 0;
04753 wf.data = discstr;
04754 if (l->chan)
04755 {
04756 ast_write(l->chan,&wf);
04757 ast_safe_sleep(l->chan,250);
04758 ast_softhangup(l->chan,AST_SOFTHANGUP_DEV);
04759 }
04760 rpt_mutex_lock(&myrpt->lock);
04761 l = l->next;
04762 }
04763 rpt_mutex_unlock(&myrpt->lock);
04764 if(debug > 3)
04765 ast_log(LOG_NOTICE,"Nodes disconnected: %s\n",myrpt->savednodes);
04766 rpt_telemetry(myrpt, COMPLETE, NULL);
04767 return DC_COMPLETE;
04768
04769 case 7:
04770 rpt_telemetry(myrpt, LASTNODEKEY, NULL);
04771 break;
04772
04773
04774 case 16:
04775 strcpy(tmp, myrpt->savednodes);
04776 finddelim(tmp, strs, MAXLINKLIST);
04777 for(i = 0; tmp[0] && strs[i] != NULL && i < MAXLINKLIST; i++){
04778 s1 = strs[i];
04779 mode = (s1[0] == 'X') ? 1 : 0;
04780 perma = (s1[1] == 'P') ? 1 : 0;
04781 connect_link(myrpt, s1 + 2, mode, perma);
04782 }
04783 rpt_telemetry(myrpt, COMPLETE, NULL);
04784 break;
04785
04786 case 200:
04787 case 201:
04788 case 202:
04789 case 203:
04790 case 204:
04791 case 205:
04792 case 206:
04793 case 207:
04794 case 208:
04795 case 209:
04796 case 210:
04797 case 211:
04798 case 212:
04799 case 213:
04800 case 214:
04801 case 215:
04802 if (((myrpt->p.propagate_dtmf) &&
04803 (command_source == SOURCE_LNK)) ||
04804 ((myrpt->p.propagate_phonedtmf) &&
04805 ((command_source == SOURCE_PHONE) ||
04806 (command_source == SOURCE_DPHONE))))
04807 do_dtmf_local(myrpt,
04808 remdtmfstr[myatoi(param) - 200]);
04809 default:
04810 return DC_ERROR;
04811
04812 }
04813
04814 return DC_INDETERMINATE;
04815 }
04816
04817
04818
04819
04820
04821 static int function_autopatchup(struct rpt *myrpt, char *param, char *digitbuf, int command_source, struct rpt_link *mylink)
04822 {
04823 pthread_attr_t attr;
04824 int i, index, paramlength;
04825 char *lparam;
04826 char *value = NULL;
04827 char *paramlist[20];
04828
04829 static char *keywords[] = {
04830 "context",
04831 "dialtime",
04832 "farenddisconnect",
04833 "noct",
04834 "quiet",
04835 NULL
04836 };
04837
04838 if (myrpt->p.s[myrpt->p.sysstate_cur].txdisable || myrpt->p.s[myrpt->p.sysstate_cur].autopatchdisable)
04839 return DC_ERROR;
04840
04841 if(debug)
04842 printf("@@@@ Autopatch up\n");
04843
04844 if(!myrpt->callmode){
04845
04846 myrpt->patchnoct = 0;
04847 myrpt->patchdialtime = 0;
04848 myrpt->patchfarenddisconnect = 0;
04849 myrpt->patchquiet = 0;
04850 strncpy(myrpt->patchcontext, myrpt->p.ourcontext, MAXPATCHCONTEXT);
04851
04852 if(param){
04853
04854 lparam = ast_strdupa(param);
04855 if(!lparam){
04856 ast_log(LOG_ERROR,"App_rpt out of memory on line %d\n",__LINE__);
04857 return DC_ERROR;
04858 }
04859 paramlength = finddelim(lparam, paramlist, 20);
04860 for(i = 0; i < paramlength; i++){
04861 index = matchkeyword(paramlist[i], &value, keywords);
04862 if(value)
04863 value = skipchars(value, "= ");
04864 switch(index){
04865
04866 case 1:
04867 strncpy(myrpt->patchcontext, value, MAXPATCHCONTEXT - 1) ;
04868 break;
04869
04870 case 2:
04871 myrpt->patchdialtime = atoi(value);
04872 break;
04873
04874 case 3:
04875 myrpt->patchfarenddisconnect = atoi(value);
04876 break;
04877
04878 case 4:
04879 myrpt->patchnoct = atoi(value);
04880 break;
04881
04882 case 5:
04883 myrpt->patchquiet = atoi(value);
04884 break;
04885
04886 default:
04887 break;
04888 }
04889 }
04890 }
04891 }
04892
04893 rpt_mutex_lock(&myrpt->lock);
04894
04895
04896
04897 if ((myrpt->callmode == 2) || (myrpt->callmode == 3)){
04898 myrpt->mydtmf = myrpt->p.endchar;
04899 }
04900 if (myrpt->callmode){
04901 rpt_mutex_unlock(&myrpt->lock);
04902 return DC_COMPLETE;
04903 }
04904 myrpt->callmode = 1;
04905 myrpt->cidx = 0;
04906 myrpt->exten[myrpt->cidx] = 0;
04907 rpt_mutex_unlock(&myrpt->lock);
04908 pthread_attr_init(&attr);
04909 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
04910 ast_pthread_create(&myrpt->rpt_call_thread,&attr,rpt_call,(void *) myrpt);
04911 return DC_COMPLETE;
04912 }
04913
04914
04915
04916
04917
04918 static int function_autopatchdn(struct rpt *myrpt, char *param, char *digitbuf, int command_source, struct rpt_link *mylink)
04919 {
04920 if (myrpt->p.s[myrpt->p.sysstate_cur].txdisable || myrpt->p.s[myrpt->p.sysstate_cur].autopatchdisable)
04921 return DC_ERROR;
04922
04923 if(debug)
04924 printf("@@@@ Autopatch down\n");
04925
04926 rpt_mutex_lock(&myrpt->lock);
04927
04928 if (!myrpt->callmode){
04929 rpt_mutex_unlock(&myrpt->lock);
04930 return DC_COMPLETE;
04931 }
04932
04933 myrpt->callmode = 0;
04934 rpt_mutex_unlock(&myrpt->lock);
04935 rpt_telemetry(myrpt, TERM, NULL);
04936 return DC_COMPLETE;
04937 }
04938
04939
04940
04941
04942
04943 static int function_status(struct rpt *myrpt, char *param, char *digitbuf, int command_source, struct rpt_link *mylink)
04944 {
04945
04946 if (!param)
04947 return DC_ERROR;
04948
04949 if ((myrpt->p.s[myrpt->p.sysstate_cur].txdisable) || (myrpt->p.s[myrpt->p.sysstate_cur].userfundisable))
04950 return DC_ERROR;
04951
04952 if(debug)
04953 printf("@@@@ status param = %s, digitbuf = %s\n", (param)? param : "(null)", digitbuf);
04954
04955 switch(myatoi(param)){
04956 case 1:
04957 rpt_telemetry(myrpt, ID1, NULL);
04958 return DC_COMPLETE;
04959 case 2:
04960 rpt_telemetry(myrpt, STATS_TIME, NULL);
04961 return DC_COMPLETE;
04962 case 3:
04963 rpt_telemetry(myrpt, STATS_VERSION, NULL);
04964 default:
04965 return DC_ERROR;
04966 }
04967 return DC_INDETERMINATE;
04968 }
04969
04970
04971
04972
04973
04974 static int function_macro(struct rpt *myrpt, char *param, char *digitbuf, int command_source, struct rpt_link *mylink)
04975 {
04976
04977 char *val;
04978 int i;
04979 if (myrpt->remote)
04980 return DC_ERROR;
04981
04982 if(debug)
04983 printf("@@@@ macro-oni param = %s, digitbuf = %s\n", (param)? param : "(null)", digitbuf);
04984
04985 if(strlen(digitbuf) < 1)
04986 return DC_INDETERMINATE;
04987
04988 for(i = 0 ; i < digitbuf[i] ; i++) {
04989 if((digitbuf[i] < '0') || (digitbuf[i] > '9'))
04990 return DC_ERROR;
04991 }
04992
04993 if (*digitbuf == '0') val = myrpt->p.startupmacro;
04994 else val = (char *) ast_variable_retrieve(myrpt->cfg, myrpt->p.macro, digitbuf);
04995
04996 if (!val){
04997 if (strlen(digitbuf) < myrpt->macro_longest)
04998 return DC_INDETERMINATE;
04999 rpt_telemetry(myrpt, MACRO_NOTFOUND, NULL);
05000 return DC_COMPLETE;
05001 }
05002 rpt_mutex_lock(&myrpt->lock);
05003 if ((MAXMACRO - strlen(myrpt->macrobuf)) < strlen(val))
05004 {
05005 rpt_mutex_unlock(&myrpt->lock);
05006 rpt_telemetry(myrpt, MACRO_BUSY, NULL);
05007 return DC_ERROR;
05008 }
05009 myrpt->macrotimer = MACROTIME;
05010 strncat(myrpt->macrobuf,val,MAXMACRO - 1);
05011 rpt_mutex_unlock(&myrpt->lock);
05012 return DC_COMPLETE;
05013 }
05014
05015
05016
05017
05018
05019 static int function_cop(struct rpt *myrpt, char *param, char *digitbuf, int command_source, struct rpt_link *mylink)
05020 {
05021 char string[16];
05022
05023 if(!param)
05024 return DC_ERROR;
05025
05026 switch(myatoi(param)){
05027 case 1:
05028 system("killall -9 asterisk");
05029 return DC_COMPLETE;
05030
05031 case 2:
05032 myrpt->p.s[myrpt->p.sysstate_cur].txdisable = 0;
05033 rpt_telemetry(myrpt, ARB_ALPHA, (void *) "RPTENA");
05034 return DC_COMPLETE;
05035
05036 case 3:
05037 myrpt->p.s[myrpt->p.sysstate_cur].txdisable = 1;
05038 return DC_COMPLETE;
05039
05040 case 4:
05041 if (myrpt->stopgen < 0)
05042 {
05043 myrpt->stopgen = 1;
05044 }
05045 else
05046 {
05047 myrpt->stopgen = 0;
05048 rpt_telemetry(myrpt, TEST_TONE, NULL);
05049 }
05050 return DC_COMPLETE;
05051
05052 case 5:
05053 myrpt->disgorgetime = time(NULL) + 10;
05054 return DC_COMPLETE;
05055
05056 case 6:
05057 if (command_source != SOURCE_PHONE) return DC_INDETERMINATE;
05058 return DC_DOKEY;
05059
05060
05061 case 7:
05062 myrpt->p.s[myrpt->p.sysstate_cur].totdisable = 0;
05063 rpt_telemetry(myrpt, ARB_ALPHA, (void *) "TOTENA");
05064 return DC_COMPLETE;
05065
05066 case 8:
05067 myrpt->p.s[myrpt->p.sysstate_cur].totdisable = 1;
05068 rpt_telemetry(myrpt, ARB_ALPHA, (void *) "TOTDIS");
05069 return DC_COMPLETE;
05070
05071 case 9:
05072 myrpt->p.s[myrpt->p.sysstate_cur].autopatchdisable = 0;
05073 rpt_telemetry(myrpt, ARB_ALPHA, (void *) "APENA");
05074 return DC_COMPLETE;
05075
05076 case 10:
05077 myrpt->p.s[myrpt->p.sysstate_cur].autopatchdisable = 1;
05078 rpt_telemetry(myrpt, ARB_ALPHA, (void *) "APDIS");
05079 return DC_COMPLETE;
05080
05081 case 11:
05082 myrpt->p.s[myrpt->p.sysstate_cur].linkfundisable = 0;
05083 rpt_telemetry(myrpt, ARB_ALPHA, (void *) "LNKENA");
05084 return DC_COMPLETE;
05085
05086 case 12:
05087 myrpt->p.s[myrpt->p.sysstate_cur].linkfundisable = 1;
05088 rpt_telemetry(myrpt, ARB_ALPHA, (void *) "LNKDIS");
05089 return DC_COMPLETE;
05090
05091 case 13:
05092 string[0] = string[1] = 'S';
05093 string[2] = myrpt->p.sysstate_cur + '0';
05094 string[3] = '\0';
05095 rpt_telemetry(myrpt, ARB_ALPHA, (void *) string);
05096 return DC_COMPLETE;
05097
05098 case 14:
05099 if(strlen(digitbuf) == 0)
05100 break;
05101 if((digitbuf[0] < '0') || (digitbuf[0] > '9'))
05102 return DC_ERROR;
05103 myrpt->p.sysstate_cur = digitbuf[0] - '0';
05104 string[0] = string[1] = 'S';
05105 string[2] = myrpt->p.sysstate_cur + '0';
05106 string[3] = '\0';
05107 rpt_telemetry(myrpt, ARB_ALPHA, (void *) string);
05108 return DC_COMPLETE;
05109
05110 case 15:
05111 myrpt->p.s[myrpt->p.sysstate_cur].schedulerdisable = 0;
05112 rpt_telemetry(myrpt, ARB_ALPHA, (void *) "SKENA");
05113 return DC_COMPLETE;
05114
05115 case 16:
05116 myrpt->p.s[myrpt->p.sysstate_cur].schedulerdisable = 1;
05117 rpt_telemetry(myrpt, ARB_ALPHA, (void *) "SKDIS");
05118 return DC_COMPLETE;
05119
05120 case 17:
05121 myrpt->p.s[myrpt->p.sysstate_cur].userfundisable = 0;
05122 rpt_telemetry(myrpt, ARB_ALPHA, (void *) "UFENA");
05123 return DC_COMPLETE;
05124
05125 case 18:
05126 myrpt->p.s[myrpt->p.sysstate_cur].userfundisable = 1;
05127 rpt_telemetry(myrpt, ARB_ALPHA, (void *) "UFDIS");
05128 return DC_COMPLETE;
05129
05130 case 19:
05131 myrpt->p.s[myrpt->p.sysstate_cur].alternatetail = 1;
05132 rpt_telemetry(myrpt, ARB_ALPHA, (void *) "ATENA");
05133 return DC_COMPLETE;
05134
05135 case 20:
05136 myrpt->p.s[myrpt->p.sysstate_cur].alternatetail = 0;
05137 rpt_telemetry(myrpt, ARB_ALPHA, (void *) "ATDIS");
05138 return DC_COMPLETE;
05139 }
05140 return DC_INDETERMINATE;
05141 }
05142
05143
05144
05145
05146
05147 static int collect_function_digits(struct rpt *myrpt, char *digits,
05148 int command_source, struct rpt_link *mylink)
05149 {
05150 int i;
05151 char *stringp,*action,*param,*functiondigits;
05152 char function_table_name[30] = "";
05153 char workstring[200];
05154
05155 struct ast_variable *vp;
05156
05157 if(debug)
05158 printf("@@@@ Digits collected: %s, source: %d\n", digits, command_source);
05159
05160 if (command_source == SOURCE_DPHONE) {
05161 if (!myrpt->p.dphone_functions) return DC_INDETERMINATE;
05162 strncpy(function_table_name, myrpt->p.dphone_functions, sizeof(function_table_name) - 1);
05163 }
05164 else if (command_source == SOURCE_PHONE) {
05165 if (!myrpt->p.phone_functions) return DC_INDETERMINATE;
05166 strncpy(function_table_name, myrpt->p.phone_functions, sizeof(function_table_name) - 1);
05167 }
05168 else if (command_source == SOURCE_LNK)
05169 strncpy(function_table_name, myrpt->p.link_functions, sizeof(function_table_name) - 1);
05170 else
05171 strncpy(function_table_name, myrpt->p.functions, sizeof(function_table_name) - 1);
05172 vp = ast_variable_browse(myrpt->cfg, function_table_name);
05173 while(vp) {
05174 if(!strncasecmp(vp->name, digits, strlen(vp->name)))
05175 break;
05176 vp = vp->next;
05177 }
05178 if(!vp) {
05179 int n;
05180
05181 n = myrpt->longestfunc;
05182 if (command_source == SOURCE_LNK) n = myrpt->link_longestfunc;
05183 else
05184 if (command_source == SOURCE_PHONE) n = myrpt->phone_longestfunc;
05185 else
05186 if (command_source == SOURCE_DPHONE) n = myrpt->dphone_longestfunc;
05187
05188 if(strlen(digits) >= n)
05189 return DC_ERROR;
05190 else
05191 return DC_INDETERMINATE;
05192 }
05193
05194 strncpy(workstring, vp->value, sizeof(workstring) - 1 );
05195 stringp = workstring;
05196 action = strsep(&stringp, ",");
05197 param = stringp;
05198 if(debug)
05199 printf("@@@@ action: %s, param = %s\n",action, (param) ? param : "(null)");
05200
05201 for(i = 0 ; i < (sizeof(function_table)/sizeof(struct function_table_tag)); i++){
05202 if(!strncasecmp(action, function_table[i].action, strlen(action)))
05203 break;
05204 }
05205 if(debug)
05206 printf("@@@@ table index i = %d\n",i);
05207 if(i == (sizeof(function_table)/sizeof(struct function_table_tag))){
05208
05209 return DC_ERROR;
05210 }
05211 if(function_table[i].function == NULL){
05212
05213 if(debug)
05214 printf("@@@@ NULL for action: %s\n",action);
05215 return DC_ERROR;
05216 }
05217 functiondigits = digits + strlen(vp->name);
05218 return (*function_table[i].function)(myrpt, param, functiondigits, command_source, mylink);
05219 }
05220
05221
05222 static void handle_link_data(struct rpt *myrpt, struct rpt_link *mylink,
05223 char *str)
05224 {
05225 char tmp[512],cmd[300] = "",dest[300],src[300],c;
05226 int seq, res;
05227 struct rpt_link *l;
05228 struct ast_frame wf;
05229
05230 wf.frametype = AST_FRAME_TEXT;
05231 wf.subclass = 0;
05232 wf.offset = 0;
05233 wf.mallocd = 0;
05234 wf.datalen = strlen(str) + 1;
05235 wf.samples = 0;
05236
05237 strncpy(tmp,str,sizeof(tmp) - 1);
05238
05239 if (!strcmp(tmp,discstr))
05240 {
05241 mylink->disced = 1;
05242 mylink->retries = mylink->max_retries + 1;
05243 ast_softhangup(mylink->chan,AST_SOFTHANGUP_DEV);
05244 return;
05245 }
05246 if (tmp[0] == 'L')
05247 {
05248 rpt_mutex_lock(&myrpt->lock);
05249 strcpy(mylink->linklist,tmp + 2);
05250 time(&mylink->linklistreceived);
05251 rpt_mutex_unlock(&myrpt->lock);
05252 if (debug > 6) ast_log(LOG_NOTICE,"@@@@ node %s recieved node list %s from node %s\n",
05253 myrpt->name,tmp,mylink->name);
05254 return;
05255 }
05256 if (sscanf(tmp,"%s %s %s %d %c",cmd,dest,src,&seq,&c) != 5)
05257 {
05258 ast_log(LOG_WARNING, "Unable to parse link string %s\n",str);
05259 return;
05260 }
05261 if (strcmp(cmd,"D"))
05262 {
05263 ast_log(LOG_WARNING, "Unable to parse link string %s\n",str);
05264 return;
05265 }
05266 if (dest[0] == '0')
05267 {
05268 strcpy(dest,myrpt->name);
05269 }
05270
05271
05272 if (strcmp(dest,myrpt->name))
05273 {
05274 l = myrpt->links.next;
05275
05276 while(l != &myrpt->links)
05277 {
05278 if (l->name[0] == '0')
05279 {
05280 l = l->next;
05281 continue;
05282 }
05283
05284 if ((l == mylink) || (!strcmp(l->name,mylink->name)))
05285 {
05286 l = l->next;
05287 continue;
05288 }
05289
05290 if (!strcmp(l->name,dest))
05291 {
05292
05293 if (strcmp(l->name,src)) {
05294 wf.data = str;
05295 if (l->chan) ast_write(l->chan,&wf);
05296 }
05297 return;
05298 }
05299 l = l->next;
05300 }
05301 l = myrpt->links.next;
05302
05303 while(l != &myrpt->links)
05304 {
05305 if (l->name[0] == '0')
05306 {
05307 l = l->next;
05308 continue;
05309 }
05310
05311 if ((l == mylink) || (!strcmp(l->name,mylink->name)))
05312 {
05313 l = l->next;
05314 continue;
05315 }
05316
05317 if (strcmp(l->name,src)) {
05318 wf.data = str;
05319 if (l->chan) ast_write(l->chan,&wf);
05320 }
05321 l = l->next;
05322 }
05323 return;
05324 }
05325 if (myrpt->p.archivedir)
05326 {
05327 char str[100];
05328
05329 sprintf(str,"DTMF,%s,%c",mylink->name,c);
05330 donodelog(myrpt,str);
05331 }
05332 c = func_xlat(myrpt,c,&myrpt->p.outxlat);
05333 if (!c) return;
05334 rpt_mutex_lock(&myrpt->lock);
05335 if (c == myrpt->p.endchar) myrpt->stopgen = 1;
05336 if (myrpt->callmode == 1)
05337 {
05338 myrpt->exten[myrpt->cidx++] = c;
05339 myrpt->exten[myrpt->cidx] = 0;
05340
05341 if (ast_exists_extension(myrpt->pchannel,myrpt->patchcontext,myrpt->exten,1,NULL))
05342 {
05343 myrpt->callmode = 2;
05344 if(!myrpt->patchquiet){
05345 rpt_mutex_unlock(&myrpt->lock);
05346 rpt_telemetry(myrpt,PROC,NULL);
05347 rpt_mutex_lock(&myrpt->lock);
05348 }
05349 }
05350
05351 if (!ast_canmatch_extension(myrpt->pchannel,myrpt->patchcontext,myrpt->exten,1,NULL))
05352 {
05353
05354 myrpt->callmode = 4;
05355 }
05356 }
05357 if (c == myrpt->p.funcchar)
05358 {
05359 myrpt->rem_dtmfidx = 0;
05360 myrpt->rem_dtmfbuf[myrpt->rem_dtmfidx] = 0;
05361 time(&myrpt->rem_dtmf_time);
05362 rpt_mutex_unlock(&myrpt->lock);
05363 return;
05364 }
05365 else if (myrpt->rem_dtmfidx < 0)
05366 {
05367 if ((myrpt->callmode == 2) || (myrpt->callmode == 3))
05368 {
05369 myrpt->mydtmf = c;
05370 }
05371 if (myrpt->p.propagate_dtmf) do_dtmf_local(myrpt,c);
05372 if (myrpt->p.propagate_phonedtmf) do_dtmf_phone(myrpt,mylink,c);
05373 rpt_mutex_unlock(&myrpt->lock);
05374 return;
05375 }
05376 else if ((c != myrpt->p.endchar) && (myrpt->rem_dtmfidx >= 0))
05377 {
05378 time(&myrpt->rem_dtmf_time);
05379 if (myrpt->rem_dtmfidx < MAXDTMF)
05380 {
05381 myrpt->rem_dtmfbuf[myrpt->rem_dtmfidx++] = c;
05382 myrpt->rem_dtmfbuf[myrpt->rem_dtmfidx] = 0;
05383
05384 rpt_mutex_unlock(&myrpt->lock);
05385 strncpy(cmd, myrpt->rem_dtmfbuf, sizeof(cmd) - 1);
05386 res = collect_function_digits(myrpt, cmd, SOURCE_LNK, mylink);
05387 rpt_mutex_lock(&myrpt->lock);
05388
05389 switch(res){
05390
05391 case DC_INDETERMINATE:
05392 break;
05393
05394 case DC_REQ_FLUSH:
05395 myrpt->rem_dtmfidx = 0;
05396 myrpt->rem_dtmfbuf[0] = 0;
05397 break;
05398
05399
05400 case DC_COMPLETE:
05401 case DC_COMPLETEQUIET:
05402 myrpt->totalexecdcommands++;
05403 myrpt->dailyexecdcommands++;
05404 strncpy(myrpt->lastdtmfcommand, cmd, MAXDTMF-1);
05405 myrpt->lastdtmfcommand[MAXDTMF-1] = '\0';
05406 myrpt->rem_dtmfbuf[0] = 0;
05407 myrpt->rem_dtmfidx = -1;
05408 myrpt->rem_dtmf_time = 0;
05409 break;
05410
05411 case DC_ERROR:
05412 default:
05413 myrpt->rem_dtmfbuf[0] = 0;
05414 myrpt->rem_dtmfidx = -1;
05415 myrpt->rem_dtmf_time = 0;
05416 break;
05417 }
05418 }
05419
05420 }
05421 rpt_mutex_unlock(&myrpt->lock);
05422 return;
05423 }
05424
05425 static void handle_link_phone_dtmf(struct rpt *myrpt, struct rpt_link *mylink,
05426 char c)
05427 {
05428
05429 char cmd[300];
05430 int res;
05431
05432 if (myrpt->p.archivedir)
05433 {
05434 char str[100];
05435
05436 sprintf(str,"DTMF(P),%s,%c",mylink->name,c);
05437 donodelog(myrpt,str);
05438 }
05439 rpt_mutex_lock(&myrpt->lock);
05440 if (c == myrpt->p.endchar)
05441 {
05442 if (mylink->lastrx)
05443 {
05444 mylink->lastrx = 0;
05445 rpt_mutex_unlock(&myrpt->lock);
05446 return;
05447 }
05448 myrpt->stopgen = 1;
05449 if (myrpt->cmdnode[0])
05450 {
05451 myrpt->cmdnode[0] = 0;
05452 myrpt->dtmfidx = -1;
05453 myrpt->dtmfbuf[0] = 0;
05454 rpt_mutex_unlock(&myrpt->lock);
05455 rpt_telemetry(myrpt,COMPLETE,NULL);
05456 return;
05457 }
05458 }
05459 if (myrpt->cmdnode[0])
05460 {
05461 rpt_mutex_unlock(&myrpt->lock);
05462 send_link_dtmf(myrpt,c);
05463 return;
05464 }
05465 if (myrpt->callmode == 1)
05466 {
05467 myrpt->exten[myrpt->cidx++] = c;
05468 myrpt->exten[myrpt->cidx] = 0;
05469
05470 if (ast_exists_extension(myrpt->pchannel,myrpt->patchcontext,myrpt->exten,1,NULL))
05471 {
05472 myrpt->callmode = 2;
05473 if(!myrpt->patchquiet){
05474 rpt_mutex_unlock(&myrpt->lock);
05475 rpt_telemetry(myrpt,PROC,NULL);
05476 rpt_mutex_lock(&myrpt->lock);
05477 }
05478 }
05479
05480 if (!ast_canmatch_extension(myrpt->pchannel,myrpt->patchcontext,myrpt->exten,1,NULL))
05481 {
05482
05483 myrpt->callmode = 4;
05484 }
05485 }
05486 if ((myrpt->callmode == 2) || (myrpt->callmode == 3))
05487 {
05488 myrpt->mydtmf = c;
05489 }
05490 if (c == myrpt->p.funcchar)
05491 {
05492 myrpt->rem_dtmfidx = 0;
05493 myrpt->rem_dtmfbuf[myrpt->rem_dtmfidx] = 0;
05494 time(&myrpt->rem_dtmf_time);
05495 rpt_mutex_unlock(&myrpt->lock);
05496 return;
05497 }
05498 else if ((c != myrpt->p.endchar) && (myrpt->rem_dtmfidx >= 0))
05499 {
05500 time(&myrpt->rem_dtmf_time);
05501 if (myrpt->rem_dtmfidx < MAXDTMF)
05502 {
05503 myrpt->rem_dtmfbuf[myrpt->rem_dtmfidx++] = c;
05504 myrpt->rem_dtmfbuf[myrpt->rem_dtmfidx] = 0;
05505
05506 rpt_mutex_unlock(&myrpt->lock);
05507 strncpy(cmd, myrpt->rem_dtmfbuf, sizeof(cmd) - 1);
05508 switch(mylink->phonemode)
05509 {
05510 case 1:
05511 res = collect_function_digits(myrpt, cmd,
05512 SOURCE_PHONE, mylink);
05513 break;
05514 case 2:
05515 res = collect_function_digits(myrpt, cmd,
05516 SOURCE_DPHONE,mylink);
05517 break;
05518 default:
05519 res = collect_function_digits(myrpt, cmd,
05520 SOURCE_LNK, mylink);
05521 break;
05522 }
05523
05524 rpt_mutex_lock(&myrpt->lock);
05525
05526 switch(res){
05527
05528 case DC_INDETERMINATE:
05529 break;
05530
05531 case DC_DOKEY:
05532 mylink->lastrx = 1;
05533 break;
05534
05535 case DC_REQ_FLUSH:
05536 myrpt->rem_dtmfidx = 0;
05537 myrpt->rem_dtmfbuf[0] = 0;
05538 break;
05539
05540
05541 case DC_COMPLETE:
05542 case DC_COMPLETEQUIET:
05543 myrpt->totalexecdcommands++;
05544 myrpt->dailyexecdcommands++;
05545 strncpy(myrpt->lastdtmfcommand, cmd, MAXDTMF-1);
05546 myrpt->lastdtmfcommand[MAXDTMF-1] = '\0';
05547 myrpt->rem_dtmfbuf[0] = 0;
05548 myrpt->rem_dtmfidx = -1;
05549 myrpt->rem_dtmf_time = 0;
05550 break;
05551
05552 case DC_ERROR:
05553 default:
05554 myrpt->rem_dtmfbuf[0] = 0;
05555 myrpt->rem_dtmfidx = -1;
05556 myrpt->rem_dtmf_time = 0;
05557 break;
05558 }
05559 }
05560
05561 }
05562 rpt_mutex_unlock(&myrpt->lock);
05563 return;
05564 }
05565
05566
05567
05568
05569
05570
05571
05572
05573
05574
05575
05576
05577
05578
05579
05580
05581
05582
05583
05584
05585
05586
05587
05588
05589
05590
05591
05592
05593
05594
05595
05596
05597 static int rbi_mhztoband(char *str)
05598 {
05599 int i;
05600
05601 i = atoi(str) / 10;
05602 switch(i)
05603 {
05604 case 2:
05605 return 10;
05606 case 5:
05607 return 11;
05608 case 14:
05609 return 2;
05610 case 22:
05611 return 3;
05612 case 44:
05613 return 4;
05614 case 124:
05615 return 0;
05616 case 125:
05617 return 1;
05618 case 126:
05619 return 8;
05620 case 127:
05621 return 5;
05622 case 128:
05623 return 6;
05624 case 129:
05625 return 7;
05626 default:
05627 break;
05628 }
05629 return -1;
05630 }
05631
05632
05633 static int rbi_pltocode(char *str)
05634 {
05635 int i;
05636 char *s;
05637
05638 s = strchr(str,'.');
05639 i = 0;
05640 if (s) i = atoi(s + 1);
05641 i += atoi(str) * 10;
05642 switch(i)
05643 {
05644 case 670:
05645 return 0;
05646 case 719:
05647 return 1;
05648 case 744:
05649 return 2;
05650 case 770:
05651 return 3;
05652 case 797:
05653 return 4;
05654 case 825:
05655 return 5;
05656 case 854:
05657 return 6;
05658 case 885:
05659 return 7;
05660 case 915:
05661 return 8;
05662 case 948:
05663 return 9;
05664 case 974:
05665 return 10;
05666 case 1000:
05667 return 11;
05668 case 1035:
05669 return 12;
05670 case 1072:
05671 return 13;
05672 case 1109:
05673 return 14;
05674 case 1148:
05675 return 15;
05676 case 1188:
05677 return 16;
05678 case 1230:
05679 return 17;
05680 case 1273:
05681 return 18;
05682 case 1318:
05683 return 19;
05684 case 1365:
05685 return 20;
05686 case 1413:
05687 return 21;
05688 case 1462:
05689 return 22;
05690 case 1514:
05691 return 23;
05692 case 1567:
05693 return 24;
05694 case 1622:
05695 return 25;
05696 case 1679:
05697 return 26;
05698 case 1738:
05699 return 27;
05700 case 1799:
05701 return 28;
05702 case 1862:
05703 return 29;
05704 case 1928:
05705 return 30;
05706 case 2035:
05707 return 31;
05708 case 2107:
05709 return 32;
05710 case 2181:
05711 return 33;
05712 case 2257:
05713 return 34;
05714 case 2336:
05715 return 35;
05716 case 2418:
05717 return 36;
05718 case 2503:
05719 return 37;
05720 }
05721 return -1;
05722 }
05723
05724
05725
05726
05727
05728 static void rbi_out_parallel(struct rpt *myrpt,unsigned char *data)
05729 {
05730 int i,j;
05731 unsigned char od,d;
05732 static volatile long long delayvar;
05733
05734 for(i = 0 ; i < 5 ; i++){
05735 od = *data++;
05736 for(j = 0 ; j < 8 ; j++){
05737 d = od & 1;
05738 outb(d,myrpt->p.iobase);
05739
05740 for(delayvar = 1; delayvar < 15000; delayvar++);
05741 od >>= 1;
05742 outb(d | 2,myrpt->p.iobase);
05743
05744 for(delayvar = 1; delayvar < 30000; delayvar++);
05745 outb(d,myrpt->p.iobase);
05746
05747 for(delayvar = 1; delayvar < 10000; delayvar++);
05748 }
05749 }
05750
05751 for(delayvar = 1; delayvar < 50000; delayvar++);
05752 }
05753
05754 static void rbi_out(struct rpt *myrpt,unsigned char *data)
05755 {
05756 struct zt_radio_param r;
05757
05758 memset(&r,0,sizeof(struct zt_radio_param));
05759 r.radpar = ZT_RADPAR_REMMODE;
05760 r.data = ZT_RADPAR_REM_RBI1;
05761
05762 if (ioctl(myrpt->rxchannel->fds[0],ZT_RADIO_SETPARAM,&r) == -1)
05763 {
05764 rbi_out_parallel(myrpt,data);
05765 return;
05766 }
05767 r.radpar = ZT_RADPAR_REMCOMMAND;
05768 memcpy(&r.data,data,5);
05769 if (ioctl(myrpt->rxchannel->fds[0],ZT_RADIO_SETPARAM,&r) == -1)
05770 {
05771 ast_log(LOG_WARNING,"Cannot send RBI command for channel %s\n",myrpt->rxchannel->name);
05772 return;
05773 }
05774 }
05775
05776 static int serial_remote_io(struct rpt *myrpt, unsigned char *txbuf, int txbytes,
05777 unsigned char *rxbuf, int rxmaxbytes, int asciiflag)
05778 {
05779 int i,j,index,oldmode,olddata;
05780 struct zt_radio_param prm;
05781 char c;
05782
05783 if(debug){
05784 printf("String output was: ");
05785 for(i = 0; i < txbytes; i++)
05786 printf("%02X ", (unsigned char ) txbuf[i]);
05787 printf("\n");
05788 }
05789 if (myrpt->iofd > 0)
05790 {
05791 if (rxmaxbytes && rxbuf) tcflush(myrpt->iofd,TCIFLUSH);
05792 if (write(myrpt->iofd,txbuf,txbytes) != txbytes) return -1;
05793 if ((!rxmaxbytes) || (rxbuf == NULL)) return(0);
05794 memset(rxbuf,0,rxmaxbytes);
05795 for(i = 0; i < rxmaxbytes; i++)
05796 {
05797 j = read(myrpt->iofd,&c,1);
05798 if (j < 1) return(i);
05799 rxbuf[i] = c;
05800 if (asciiflag & 1)
05801 {
05802 rxbuf[i + 1] = 0;
05803 if (c == '\r') break;
05804 }
05805 }
05806 if(debug){
05807 printf("String returned was: ");
05808 for(j = 0; j < i; j++)
05809 printf("%02X ", (unsigned char ) rxbuf[j]);
05810 printf("\n");
05811 }
05812 return(i);
05813 }
05814
05815 prm.radpar = ZT_RADPAR_UIOMODE;
05816 if (ioctl(myrpt->rxchannel->fds[0],ZT_RADIO_GETPARAM,&prm) == -1) return -1;
05817 oldmode = prm.data;
05818 prm.radpar = ZT_RADPAR_UIODATA;
05819 if (ioctl(myrpt->rxchannel->fds[0],ZT_RADIO_GETPARAM,&prm) == -1) return -1;
05820 olddata = prm.data;
05821 prm.radpar = ZT_RADPAR_REMMODE;
05822 if (asciiflag & 1) prm.data = ZT_RADPAR_REM_SERIAL_ASCII;
05823 else prm.data = ZT_RADPAR_REM_SERIAL;
05824 if (ioctl(myrpt->rxchannel->fds[0],ZT_RADIO_SETPARAM,&prm) == -1) return -1;
05825 if (asciiflag & 2)
05826 {
05827 i = ZT_ONHOOK;
05828 if (ioctl(myrpt->rxchannel->fds[0],ZT_HOOK,&i) == -1) return -1;
05829 usleep(100000);
05830 }
05831 prm.radpar = ZT_RADPAR_REMCOMMAND;
05832 prm.data = rxmaxbytes;
05833 memcpy(prm.buf,txbuf,txbytes);
05834 prm.index = txbytes;
05835 if (ioctl(myrpt->rxchannel->fds[0],ZT_RADIO_SETPARAM,&prm) == -1) return -1;
05836 if (rxbuf)
05837 {
05838 *rxbuf = 0;
05839 memcpy(rxbuf,prm.buf,prm.index);
05840 }
05841 index = prm.index;
05842 prm.radpar = ZT_RADPAR_REMMODE;
05843 prm.data = ZT_RADPAR_REM_NONE;
05844 if (ioctl(myrpt->rxchannel->fds[0],ZT_RADIO_SETPARAM,&prm) == -1) return -1;
05845 if (asciiflag & 2)
05846 {
05847 i = ZT_OFFHOOK;
05848 if (ioctl(myrpt->rxchannel->fds[0],ZT_HOOK,&i) == -1) return -1;
05849 }
05850 prm.radpar = ZT_RADPAR_UIOMODE;
05851 prm.data = oldmode;
05852 if (ioctl(myrpt->rxchannel->fds[0],ZT_RADIO_SETPARAM,&prm) == -1) return -1;
05853 prm.radpar = ZT_RADPAR_UIODATA;
05854 prm.data = olddata;
05855 if (ioctl(myrpt->rxchannel->fds[0],ZT_RADIO_SETPARAM,&prm) == -1) return -1;
05856 return(index);
05857 }
05858
05859 static int civ_cmd(struct rpt *myrpt,unsigned char *cmd, int cmdlen)
05860 {
05861 unsigned char rxbuf[100];
05862 int i,rv ;
05863
05864 rv = serial_remote_io(myrpt,cmd,cmdlen,rxbuf,cmdlen + 6,0);
05865 if (rv == -1) return(-1);
05866 if (rv != (cmdlen + 6)) return(1);
05867 for(i = 0; i < 6; i++)
05868 if (rxbuf[i] != cmd[i]) return(1);
05869 if (rxbuf[cmdlen] != 0xfe) return(1);
05870 if (rxbuf[cmdlen + 1] != 0xfe) return(1);
05871 if (rxbuf[cmdlen + 4] != 0xfb) return(1);
05872 if (rxbuf[cmdlen + 5] != 0xfd) return(1);
05873 return(0);
05874 }
05875
05876 static int sendkenwood(struct rpt *myrpt,char *txstr, char *rxstr)
05877 {
05878 int i;
05879
05880 if (debug) printf("Send to kenwood: %s\n",txstr);
05881 i = serial_remote_io(myrpt, (unsigned char *)txstr, strlen(txstr),
05882 (unsigned char *)rxstr,RAD_SERIAL_BUFLEN - 1,3);
05883 if (i < 0) return -1;
05884 if ((i > 0) && (rxstr[i - 1] == '\r'))
05885 rxstr[i-- - 1] = 0;
05886 if (debug) printf("Got from kenwood: %s\n",rxstr);
05887 return(i);
05888 }
05889
05890
05891 static int kenwood_pltocode(char *str)
05892 {
05893 int i;
05894 char *s;
05895
05896 s = strchr(str,'.');
05897 i = 0;
05898 if (s) i = atoi(s + 1);
05899 i += atoi(str) * 10;
05900 switch(i)
05901 {
05902 case 670:
05903 return 1;
05904 case 719:
05905 return 3;
05906 case 744:
05907 return 4;
05908 case 770:
05909 return 5;
05910 case 797:
05911 return 6;
05912 case 825:
05913 return 7;
05914 case 854:
05915 return 8;
05916 case 885:
05917 return 9;
05918 case 915:
05919 return 10;
05920 case 948:
05921 return 11;
05922 case 974:
05923 return 12;
05924 case 1000:
05925 return 13;
05926 case 1035:
05927 return 14;
05928 case 1072:
05929 return 15;
05930 case 1109:
05931 return 16;
05932 case 1148:
05933 return 17;
05934 case 1188:
05935 return 18;
05936 case 1230:
05937 return 19;
05938 case 1273:
05939 return 20;
05940 case 1318:
05941 return 21;
05942 case 1365:
05943 return 22;
05944 case 1413:
05945 return 23;
05946 case 1462:
05947 return 24;
05948 case 1514:
05949 return 25;
05950 case 1567:
05951 return 26;
05952 case 1622:
05953 return 27;
05954 case 1679:
05955 return 28;
05956 case 1738:
05957 return 29;
05958 case 1799:
05959 return 30;
05960 case 1862:
05961 return 31;
05962 case 1928:
05963 return 32;
05964 case 2035:
05965 return 33;
05966 case 2107:
05967 return 34;
05968 case 2181:
05969 return 35;
05970 case 2257:
05971 return 36;
05972 case 2336:
05973 return 37;
05974 case 2418:
05975 return 38;
05976 case 2503:
05977 return 39;
05978 }
05979 return -1;
05980 }
05981
05982 static int sendrxkenwood(struct rpt *myrpt, char *txstr, char *rxstr,
05983 char *cmpstr)
05984 {
05985 int i,j;
05986
05987 for(i = 0;i < KENWOOD_RETRIES;i++)
05988 {
05989 j = sendkenwood(myrpt,txstr,rxstr);
05990 if (j < 0) return(j);
05991 if (j == 0) continue;
05992 if (!strncmp(rxstr,cmpstr,strlen(cmpstr))) return(0);
05993 }
05994 return(-1);
05995 }
05996
05997 static int setkenwood(struct rpt *myrpt)
05998 {
05999 char rxstr[RAD_SERIAL_BUFLEN],txstr[RAD_SERIAL_BUFLEN],freq[20];
06000 char mhz[MAXREMSTR],offset[20],band,decimals[MAXREMSTR],band1,band2;
06001
06002 int offsets[] = {0,2,1};
06003 int powers[] = {2,1,0};
06004
06005 if (sendrxkenwood(myrpt,"VMC 0,0\r",rxstr,"VMC") < 0) return -1;
06006 split_freq(mhz, decimals, myrpt->freq);
06007 if (atoi(mhz) > 400)
06008 {
06009 band = '6';
06010 band1 = '1';
06011 band2 = '5';
06012 strcpy(offset,"005000000");
06013 }
06014 else
06015 {
06016 band = '2';
06017 band1 = '0';
06018 band2 = '2';
06019 strcpy(offset,"000600000");
06020 }
06021 strcpy(freq,"000000");
06022 strncpy(freq,decimals,strlen(decimals));
06023 sprintf(txstr,"VW %c,%05d%s,0,%d,0,%d,%d,,%02d,,%02d,%s\r",
06024 band,atoi(mhz),freq,offsets[(int)myrpt->offset],
06025 (myrpt->txplon != 0),(myrpt->rxplon != 0),
06026 kenwood_pltocode(myrpt->txpl),kenwood_pltocode(myrpt->rxpl),
06027 offset);
06028 if (sendrxkenwood(myrpt,txstr,rxstr,"VW") < 0) return -1;
06029 sprintf(txstr,"RBN %c\r",band2);
06030 if (sendrxkenwood(myrpt,txstr,rxstr,"RBN") < 0) return -1;
06031 sprintf(txstr,"PC %c,%d\r",band1,powers[(int)myrpt->powerlevel]);
06032 if (sendrxkenwood(myrpt,txstr,rxstr,"PC") < 0) return -1;
06033 return 0;
06034 }
06035
06036 static int setrbi(struct rpt *myrpt)
06037 {
06038 char tmp[MAXREMSTR] = "",*s;
06039 unsigned char rbicmd[5];
06040 int band,txoffset = 0,txpower = 0,rxpl;
06041
06042
06043 if (!myrpt->remote) return(0);
06044
06045 if (strncmp(myrpt->remote,remote_rig_rbi,3)) return(0);
06046 if (setrbi_check(myrpt) == -1) return(-1);
06047 strncpy(tmp, myrpt->freq, sizeof(tmp) - 1);
06048 s = strchr(tmp,'.');
06049
06050
06051 if (s == NULL){
06052 if(debug)
06053 printf("@@@@ Frequency needs a decimal\n");
06054 return -1;
06055 }
06056
06057 *s++ = 0;
06058 if (strlen(tmp) < 2){
06059 if(debug)
06060 printf("@@@@ Bad MHz digits: %s\n", tmp);
06061 return -1;
06062 }
06063
06064 if (strlen(s) < 3){
06065 if(debug)
06066 printf("@@@@ Bad KHz digits: %s\n", s);
06067 return -1;
06068 }
06069
06070 if ((s[2] != '0') && (s[2] != '5')){
06071 if(debug)
06072 printf("@@@@ KHz must end in 0 or 5: %c\n", s[2]);
06073 return -1;
06074 }
06075
06076 band = rbi_mhztoband(tmp);
06077 if (band == -1){
06078 if(debug)
06079 printf("@@@@ Bad Band: %s\n", tmp);
06080 return -1;
06081 }
06082
06083 rxpl = rbi_pltocode(myrpt->rxpl);
06084
06085 if (rxpl == -1){
06086 if(debug)
06087 printf("@@@@ Bad TX PL: %s\n", myrpt->rxpl);
06088 return -1;
06089 }
06090
06091
06092 switch(myrpt->offset)
06093 {
06094 case REM_MINUS:
06095 txoffset = 0;
06096 break;
06097 case REM_PLUS:
06098 txoffset = 0x10;
06099 break;
06100 case REM_SIMPLEX:
06101 txoffset = 0x20;
06102 break;
06103 }
06104 switch(myrpt->powerlevel)
06105 {
06106 case REM_LOWPWR:
06107 txpower = 0;
06108 break;
06109 case REM_MEDPWR:
06110 txpower = 0x20;
06111 break;
06112 case REM_HIPWR:
06113 txpower = 0x10;
06114 break;
06115 }
06116 rbicmd[0] = 0;
06117 rbicmd[1] = band | txpower | 0xc0;
06118 rbicmd[2] = (*(s - 2) - '0') | txoffset | 0x80;
06119 if (s[2] == '5') rbicmd[2] |= 0x40;
06120 rbicmd[3] = ((*s - '0') << 4) + (s[1] - '0');
06121 rbicmd[4] = rxpl;
06122 if (myrpt->txplon) rbicmd[4] |= 0x40;
06123 if (myrpt->rxplon) rbicmd[4] |= 0x80;
06124 rbi_out(myrpt,rbicmd);
06125 return 0;
06126 }
06127
06128 static int setrbi_check(struct rpt *myrpt)
06129 {
06130 char tmp[MAXREMSTR] = "",*s;
06131 int band,txpl;
06132
06133
06134 if (!myrpt->remote) return(0);
06135
06136 if (strncmp(myrpt->remote,remote_rig_rbi,3)) return(0);
06137 strncpy(tmp, myrpt->freq, sizeof(tmp) - 1);
06138 s = strchr(tmp,'.');
06139
06140
06141 if (s == NULL){
06142 if(debug)
06143 printf("@@@@ Frequency needs a decimal\n");
06144 return -1;
06145 }
06146
06147 *s++ = 0;
06148 if (strlen(tmp) < 2){
06149 if(debug)
06150 printf("@@@@ Bad MHz digits: %s\n", tmp);
06151 return -1;
06152 }
06153
06154 if (strlen(s) < 3){
06155 if(debug)
06156 printf("@@@@ Bad KHz digits: %s\n", s);
06157 return -1;
06158 }
06159
06160 if ((s[2] != '0') && (s[2] != '5')){
06161 if(debug)
06162 printf("@@@@ KHz must end in 0 or 5: %c\n", s[2]);
06163 return -1;
06164 }
06165
06166 band = rbi_mhztoband(tmp);
06167 if (band == -1){
06168 if(debug)
06169 printf("@@@@ Bad Band: %s\n", tmp);
06170 return -1;
06171 }
06172
06173 txpl = rbi_pltocode(myrpt->txpl);
06174
06175 if (txpl == -1){
06176 if(debug)
06177 printf("@@@@ Bad TX PL: %s\n", myrpt->txpl);
06178 return -1;
06179 }
06180 return 0;
06181 }
06182
06183 static int check_freq_kenwood(int m, int d, int *defmode)
06184 {
06185 int dflmd = REM_MODE_FM;
06186
06187 if (m == 144){
06188 if(d < 10100)
06189 return -1;
06190 }
06191 else if((m >= 145) && (m < 148)){
06192 ;
06193 }
06194 else if((m >= 430) && (m < 450)){
06195 ;
06196 }
06197 else
06198 return -1;
06199
06200 if(defmode)
06201 *defmode = dflmd;
06202
06203
06204 return 0;
06205 }
06206
06207
06208
06209
06210
06211 static int check_freq_rbi(int m, int d, int *defmode)
06212 {
06213 int dflmd = REM_MODE_FM;
06214
06215 if(m == 50){
06216 if(d < 10100)
06217 return -1;
06218 }
06219 else if((m >= 51) && ( m < 54)){
06220 ;
06221 }
06222 else if(m == 144){
06223 if(d < 10100)
06224 return -1;
06225 }
06226 else if((m >= 145) && (m < 148)){
06227 ;
06228 }
06229 else if((m >= 222) && (m < 225)){
06230 ;
06231 }
06232 else if((m >= 430) && (m < 450)){
06233 ;
06234 }
06235 else if((m >= 1240) && (m < 1300)){
06236 ;
06237 }
06238 else
06239 return -1;
06240
06241 if(defmode)
06242 *defmode = dflmd;
06243
06244
06245 return 0;
06246 }
06247
06248
06249
06250
06251
06252 static int decimals2int(char *fraction)
06253 {
06254 int i;
06255 char len = strlen(fraction);
06256 int multiplier = 100000;
06257 int res = 0;
06258
06259 if(!len)
06260 return 0;
06261 for( i = 0 ; i < len ; i++, multiplier /= 10)
06262 res += (fraction[i] - '0') * multiplier;
06263 return res;
06264 }
06265
06266
06267
06268
06269
06270
06271 static int split_freq(char *mhz, char *decimals, char *freq)
06272 {
06273 char freq_copy[MAXREMSTR];
06274 char *decp;
06275
06276 decp = strchr(strncpy(freq_copy, freq, MAXREMSTR),'.');
06277 if(decp){
06278 *decp++ = 0;
06279 strncpy(mhz, freq_copy, MAXREMSTR);
06280 strcpy(decimals, "00000");
06281 strncpy(decimals, decp, strlen(decp));
06282 decimals[5] = 0;
06283 return 0;
06284 }
06285 else
06286 return -1;
06287
06288 }
06289
06290
06291
06292
06293
06294 static int split_ctcss_freq(char *hertz, char *decimal, char *freq)
06295 {
06296 char freq_copy[MAXREMSTR];
06297 char *decp;
06298
06299 decp = strchr(strncpy(freq_copy, freq, MAXREMSTR),'.');
06300 if(decp){
06301 *decp++ = 0;
06302 strncpy(hertz, freq_copy, MAXREMSTR);
06303 strncpy(decimal, decp, strlen(decp));
06304 decimal[strlen(decp)] = '\0';
06305 return 0;
06306 }
06307 else
06308 return -1;
06309 }
06310
06311
06312
06313
06314
06315
06316
06317
06318
06319
06320
06321 static int check_freq_ft897(int m, int d, int *defmode)
06322 {
06323 int dflmd = REM_MODE_FM;
06324
06325 if(m == 1){
06326 dflmd = REM_MODE_LSB;
06327 if(d < 80000)
06328 return -1;
06329 }
06330 else if(m == 3){
06331 dflmd = REM_MODE_LSB;
06332 if(d < 50000)
06333 return -1;
06334 }
06335 else if(m == 7){
06336 dflmd = REM_MODE_LSB;
06337 if(d > 30000)
06338 return -1;
06339 }
06340 else if(m == 14){
06341 dflmd = REM_MODE_USB;
06342 if(d > 35000)
06343 return -1;
06344 }
06345 else if(m == 18){
06346 dflmd = REM_MODE_USB;
06347 if((d < 6800) || (d > 16800))
06348 return -1;
06349 }
06350 else if(m == 21){
06351 dflmd = REM_MODE_USB;
06352 if((d < 20000) || (d > 45000))
06353 return -1;
06354 }
06355 else if(m == 24){
06356 dflmd = REM_MODE_USB;
06357 if((d < 89000) || (d > 99000))
06358 return -1;
06359 }
06360 else if(m == 28){
06361 dflmd = REM_MODE_USB;
06362 }
06363 else if(m == 29){
06364 if(d >= 51000)
06365 dflmd = REM_MODE_FM;
06366 else
06367 dflmd = REM_MODE_USB;
06368 if(d > 70000)
06369 return -1;
06370 }
06371 else if(m == 50){
06372 if(d >= 30000)
06373 dflmd = REM_MODE_FM;
06374 else
06375 dflmd = REM_MODE_USB;
06376
06377 }
06378 else if((m >= 51) && ( m < 54)){
06379 dflmd = REM_MODE_FM;
06380 }
06381 else if(m == 144){
06382 if(d >= 30000)
06383 dflmd = REM_MODE_FM;
06384 else
06385 dflmd = REM_MODE_USB;
06386 }
06387 else if((m >= 145) && (m < 148)){
06388 dflmd = REM_MODE_FM;
06389 }
06390 else if((m >= 430) && (m < 450)){
06391 if(m < 438)
06392 dflmd = REM_MODE_USB;
06393 else
06394 dflmd = REM_MODE_FM;
06395 ;
06396 }
06397 else
06398 return -1;
06399
06400 if(defmode)
06401 *defmode = dflmd;
06402
06403 return 0;
06404 }
06405
06406
06407
06408
06409
06410 static int set_freq_ft897(struct rpt *myrpt, char *newfreq)
06411 {
06412 unsigned char cmdstr[5];
06413 int fd,m,d;
06414 char mhz[MAXREMSTR];
06415 char decimals[MAXREMSTR];
06416
06417 fd = 0;
06418 if(debug)
06419 printf("New frequency: %s\n",newfreq);
06420
06421 if(split_freq(mhz, decimals, newfreq))
06422 return -1;
06423
06424 m = atoi(mhz);
06425 d = atoi(decimals);
06426
06427
06428
06429 cmdstr[0] = ((m / 100) << 4) + ((m % 100)/10);
06430 cmdstr[1] = ((m % 10) << 4) + (d / 10000);
06431 cmdstr[2] = (((d % 10000)/1000) << 4) + ((d % 1000)/ 100);
06432 cmdstr[3] = (((d % 100)/10) << 4) + (d % 10);
06433 cmdstr[4] = 0x01;
06434
06435 return serial_remote_io(myrpt, cmdstr, 5, NULL, 0, 0);
06436
06437 }
06438
06439
06440
06441 static int simple_command_ft897(struct rpt *myrpt, char command)
06442 {
06443 unsigned char cmdstr[5];
06444
06445 memset(cmdstr, 0, 5);
06446
06447 cmdstr[4] = command;
06448
06449 return serial_remote_io(myrpt, cmdstr, 5, NULL, 0, 0);
06450
06451 }
06452
06453
06454
06455 static int set_offset_ft897(struct rpt *myrpt, char offset)
06456 {
06457 unsigned char cmdstr[5];
06458
06459 memset(cmdstr, 0, 5);
06460
06461 switch(offset){
06462 case REM_SIMPLEX:
06463 cmdstr[0] = 0x89;
06464 break;
06465
06466 case REM_MINUS:
06467 cmdstr[0] = 0x09;
06468 break;
06469
06470 case REM_PLUS:
06471 cmdstr[0] = 0x49;
06472 break;
06473
06474 default:
06475 return -1;
06476 }
06477
06478 cmdstr[4] = 0x09;
06479
06480 return serial_remote_io(myrpt, cmdstr, 5, NULL, 0, 0);
06481 }
06482
06483
06484
06485 static int set_mode_ft897(struct rpt *myrpt, char newmode)
06486 {
06487 unsigned char cmdstr[5];
06488
06489 memset(cmdstr, 0, 5);
06490
06491 switch(newmode){
06492 case REM_MODE_FM:
06493 cmdstr[0] = 0x08;
06494 break;
06495
06496 case REM_MODE_USB:
06497 cmdstr[0] = 0x01;
06498 break;
06499
06500 case REM_MODE_LSB:
06501 cmdstr[0] = 0x00;
06502 break;
06503
06504 case REM_MODE_AM:
06505 cmdstr[0] = 0x04;
06506 break;
06507
06508 default:
06509 return -1;
06510 }
06511 cmdstr[4] = 0x07;
06512
06513 return serial_remote_io(myrpt, cmdstr, 5, NULL, 0, 0);
06514 }
06515
06516
06517
06518 static int set_ctcss_mode_ft897(struct rpt *myrpt, char txplon, char rxplon)
06519 {
06520 unsigned char cmdstr[5];
06521
06522 memset(cmdstr, 0, 5);
06523
06524 if(rxplon && txplon)
06525 cmdstr[0] = 0x2A;
06526 else if (!rxplon && txplon)
06527 cmdstr[0] = 0x4A;
06528 else if (rxplon && !txplon)
06529 cmdstr[0] = 0x3A;
06530 else
06531 cmdstr[0] = 0x8A;
06532
06533 cmdstr[4] = 0x0A;
06534
06535 return serial_remote_io(myrpt, cmdstr, 5, NULL, 0, 0);
06536 }
06537
06538
06539
06540
06541 static int set_ctcss_freq_ft897(struct rpt *myrpt, char *txtone, char *rxtone)
06542 {
06543 unsigned char cmdstr[5];
06544 char hertz[MAXREMSTR],decimal[MAXREMSTR];
06545 int h,d;
06546
06547 memset(cmdstr, 0, 5);
06548
06549 if(split_ctcss_freq(hertz, decimal, txtone))
06550 return -1;
06551
06552 h = atoi(hertz);
06553 d = atoi(decimal);
06554
06555 cmdstr[0] = ((h / 100) << 4) + (h % 100)/ 10;
06556 cmdstr[1] = ((h % 10) << 4) + (d % 10);
06557
06558 if(rxtone){
06559
06560 if(split_ctcss_freq(hertz, decimal, rxtone))
06561 return -1;
06562
06563 h = atoi(hertz);
06564 d = atoi(decimal);
06565
06566 cmdstr[2] = ((h / 100) << 4) + (h % 100)/ 10;
06567 cmdstr[3] = ((h % 10) << 4) + (d % 10);
06568 }
06569 cmdstr[4] = 0x0B;
06570
06571 return serial_remote_io(myrpt, cmdstr, 5, NULL, 0, 0);
06572 }
06573
06574
06575
06576 static int set_ft897(struct rpt *myrpt)
06577 {
06578 int res;
06579
06580 if(debug)
06581 printf("@@@@ lock on\n");
06582
06583 res = simple_command_ft897(myrpt, 0x00);
06584
06585 if(debug)
06586 printf("@@@@ ptt off\n");
06587
06588 if(!res)
06589 res = simple_command_ft897(myrpt, 0x88);
06590
06591 if(debug)
06592 printf("Modulation mode\n");
06593
06594 if(!res)
06595 res = set_mode_ft897(myrpt, myrpt->remmode);
06596
06597 if(debug)
06598 printf("Split off\n");
06599
06600 if(!res)
06601 simple_command_ft897(myrpt, 0x82);
06602
06603 if(debug)
06604 printf("Frequency\n");
06605
06606 if(!res)
06607 res = set_freq_ft897(myrpt, myrpt->freq);
06608 if((myrpt->remmode == REM_MODE_FM)){
06609 if(debug)
06610 printf("Offset\n");
06611 if(!res)
06612 res = set_offset_ft897(myrpt, myrpt->offset);
06613 if((!res)&&(myrpt->rxplon || myrpt->txplon)){
06614 if(debug)
06615 printf("CTCSS tone freqs.\n");
06616 res = set_ctcss_freq_ft897(myrpt, myrpt->txpl, myrpt->rxpl);
06617 }
06618 if(!res){
06619 if(debug)
06620 printf("CTCSS mode\n");
06621 res = set_ctcss_mode_ft897(myrpt, myrpt->txplon, myrpt->rxplon);
06622 }
06623 }
06624 if((myrpt->remmode == REM_MODE_USB)||(myrpt->remmode == REM_MODE_LSB)){
06625 if(debug)
06626 printf("Clarifier off\n");
06627 simple_command_ft897(myrpt, 0x85);
06628 }
06629 return res;
06630 }
06631
06632 static int closerem_ft897(struct rpt *myrpt)
06633 {
06634 simple_command_ft897(myrpt, 0x88);
06635 return 0;
06636 }
06637
06638
06639
06640
06641
06642
06643
06644 static int multimode_bump_freq_ft897(struct rpt *myrpt, int interval)
06645 {
06646 int m,d;
06647 char mhz[MAXREMSTR], decimals[MAXREMSTR];
06648
06649 if(debug)
06650 printf("Before bump: %s\n", myrpt->freq);
06651
06652 if(split_freq(mhz, decimals, myrpt->freq))
06653 return -1;
06654
06655 m = atoi(mhz);
06656 d = atoi(decimals);
06657
06658 d += (interval / 10);
06659 if(d < 0){
06660 m--;
06661 d += 100000;
06662 }
06663 else if(d >= 100000){
06664 m++;
06665 d -= 100000;
06666 }
06667
06668 if(check_freq_ft897(m, d, NULL)){
06669 if(debug)
06670 printf("Bump freq invalid\n");
06671 return -1;
06672 }
06673
06674 snprintf(myrpt->freq, MAXREMSTR, "%d.%05d", m, d);
06675
06676 if(debug)
06677 printf("After bump: %s\n", myrpt->freq);
06678
06679 return set_freq_ft897(myrpt, myrpt->freq);
06680 }
06681
06682
06683
06684
06685
06686
06687
06688
06689
06690
06691
06692 static int check_freq_ic706(int m, int d, int *defmode)
06693 {
06694 int dflmd = REM_MODE_FM;
06695
06696 if(m == 1){
06697 dflmd = REM_MODE_LSB;
06698 if(d < 80000)
06699 return -1;
06700 }
06701 else if(m == 3){
06702 dflmd = REM_MODE_LSB;
06703 if(d < 50000)
06704 return -1;
06705 }
06706 else if(m == 7){
06707 dflmd = REM_MODE_LSB;
06708 if(d > 30000)
06709 return -1;
06710 }
06711 else if(m == 14){
06712 dflmd = REM_MODE_USB;
06713 if(d > 35000)
06714 return -1;
06715 }
06716 else if(m == 18){
06717 dflmd = REM_MODE_USB;
06718 if((d < 6800) || (d > 16800))
06719 return -1;
06720 }
06721 else if(m == 21){
06722 dflmd = REM_MODE_USB;
06723 if((d < 20000) || (d > 45000))
06724 return -1;
06725 }
06726 else if(m == 24){
06727 dflmd = REM_MODE_USB;
06728 if((d < 89000) || (d > 99000))
06729 return -1;
06730 }
06731 else if(m == 28){
06732 dflmd = REM_MODE_USB;
06733 }
06734 else if(m == 29){
06735 if(d >= 51000)
06736 dflmd = REM_MODE_FM;
06737 else
06738 dflmd = REM_MODE_USB;
06739 if(d > 70000)
06740 return -1;
06741 }
06742 else if(m == 50){
06743 if(d >= 30000)
06744 dflmd = REM_MODE_FM;
06745 else
06746 dflmd = REM_MODE_USB;
06747
06748 }
06749 else if((m >= 51) && ( m < 54)){
06750 dflmd = REM_MODE_FM;
06751 }
06752 else if(m == 144){
06753 if(d >= 30000)
06754 dflmd = REM_MODE_FM;
06755 else
06756 dflmd = REM_MODE_USB;
06757 }
06758 else if((m >= 145) && (m < 148)){
06759 dflmd = REM_MODE_FM;
06760 }
06761 else if((m >= 430) && (m < 450)){
06762 if(m < 438)
06763 dflmd = REM_MODE_USB;
06764 else
06765 dflmd = REM_MODE_FM;
06766 ;
06767 }
06768 else
06769 return -1;
06770
06771 if(defmode)
06772 *defmode = dflmd;
06773
06774 return 0;
06775 }
06776
06777
06778 static int ic706_pltocode(char *str)
06779 {
06780 int i;
06781 char *s;
06782
06783 s = strchr(str,'.');
06784 i = 0;
06785 if (s) i = atoi(s + 1);
06786 i += atoi(str) * 10;
06787 switch(i)
06788 {
06789 case 670:
06790 return 0;
06791 case 693:
06792 return 1;
06793 case 719:
06794 return 2;
06795 case 744:
06796 return 3;
06797 case 770:
06798 return 4;
06799 case 797:
06800 return 5;
06801 case 825:
06802 return 6;
06803 case 854:
06804 return 7;
06805 case 885:
06806 return 8;
06807 case 915:
06808 return 9;
06809 case 948:
06810 return 10;
06811 case 974:
06812 return 11;
06813 case 1000:
06814 return 12;
06815 case 1035:
06816 return 13;
06817 case 1072:
06818 return 14;
06819 case 1109:
06820 return 15;
06821 case 1148:
06822 return 16;
06823 case 1188:
06824 return 17;
06825 case 1230:
06826 return 18;
06827 case 1273:
06828 return 19;
06829 case 1318:
06830 return 20;
06831 case 1365:
06832 return 21;
06833 case 1413:
06834 return 22;
06835 case 1462:
06836 return 23;
06837 case 1514:
06838 return 24;
06839 case 1567:
06840 return 25;
06841 case 1598:
06842 return 26;
06843 case 1622:
06844 return 27;
06845 case 1655:
06846 return 28;
06847 case 1679:
06848 return 29;
06849 case 1713:
06850 return 30;
06851 case 1738:
06852 return 31;
06853 case 1773:
06854 return 32;
06855 case 1799:
06856 return 33;
06857 case 1835:
06858 return 34;
06859 case 1862:
06860 return 35;
06861 case 1899:
06862 return 36;
06863 case 1928:
06864 return 37;
06865 case 1966:
06866 return 38;
06867 case 1995:
06868 return 39;
06869 case 2035:
06870 return 40;
06871 case 2065:
06872 return 41;
06873 case 2107:
06874 return 42;
06875 case 2181:
06876 return 43;
06877 case 2257:
06878 return 44;
06879 case 2291:
06880 return 45;
06881 case 2336:
06882 return 46;
06883 case 2418:
06884 return 47;
06885 case 2503:
06886 return 48;
06887 case 2541:
06888 return 49;
06889 }
06890 return -1;
06891 }
06892
06893
06894
06895 static int simple_command_ic706(struct rpt *myrpt, char command, char subcommand)
06896 {
06897 unsigned char cmdstr[10];
06898
06899 cmdstr[0] = cmdstr[1] = 0xfe;
06900 cmdstr[2] = myrpt->p.civaddr;
06901 cmdstr[3] = 0xe0;
06902 cmdstr[4] = command;
06903 cmdstr[5] = subcommand;
06904 cmdstr[6] = 0xfd;
06905
06906 return(civ_cmd(myrpt,cmdstr,7));
06907 }
06908
06909
06910
06911
06912
06913 static int set_freq_ic706(struct rpt *myrpt, char *newfreq)
06914 {
06915 unsigned char cmdstr[20];
06916 char mhz[MAXREMSTR], decimals[MAXREMSTR];
06917 int fd,m,d;
06918
06919 fd = 0;
06920 if(debug)
06921 printf("New frequency: %s\n",newfreq);
06922
06923 if(split_freq(mhz, decimals, newfreq))
06924 return -1;
06925
06926 m = atoi(mhz);
06927 d = atoi(decimals);
06928
06929
06930
06931 cmdstr[0] = cmdstr[1] = 0xfe;
06932 cmdstr[2] = myrpt->p.civaddr;
06933 cmdstr[3] = 0xe0;
06934 cmdstr[4] = 5;
06935 cmdstr[5] = ((d % 10) << 4);
06936 cmdstr[6] = (((d % 1000)/ 100) << 4) + ((d % 100)/10);
06937 cmdstr[7] = ((d / 10000) << 4) + ((d % 10000)/1000);
06938 cmdstr[8] = (((m % 100)/10) << 4) + (m % 10);
06939 cmdstr[9] = (m / 100);
06940 cmdstr[10] = 0xfd;
06941
06942 return(civ_cmd(myrpt,cmdstr,11));
06943 }
06944
06945
06946
06947 static int set_offset_ic706(struct rpt *myrpt, char offset)
06948 {
06949 unsigned char c;
06950
06951 switch(offset){
06952 case REM_SIMPLEX:
06953 c = 0x10;
06954 break;
06955
06956 case REM_MINUS:
06957 c = 0x11;
06958 break;
06959
06960 case REM_PLUS:
06961 c = 0x12;
06962 break;
06963
06964 default:
06965 return -1;
06966 }
06967
06968 return simple_command_ic706(myrpt,0x0f,c);
06969
06970 }
06971
06972
06973
06974 static int set_mode_ic706(struct rpt *myrpt, char newmode)
06975 {
06976 unsigned char c;
06977
06978 switch(newmode){
06979 case REM_MODE_FM:
06980 c = 5;
06981 break;
06982
06983 case REM_MODE_USB:
06984 c = 1;
06985 break;
06986
06987 case REM_MODE_LSB:
06988 c = 0;
06989 break;
06990
06991 case REM_MODE_AM:
06992 c = 2;
06993 break;
06994
06995 default:
06996 return -1;
06997 }
06998 return simple_command_ic706(myrpt,6,c);
06999 }
07000
07001
07002
07003 static int set_ctcss_mode_ic706(struct rpt *myrpt, char txplon, char rxplon)
07004 {
07005 unsigned char cmdstr[10];
07006 int rv;
07007
07008 cmdstr[0] = cmdstr[1] = 0xfe;
07009 cmdstr[2] = myrpt->p.civaddr;
07010 cmdstr[3] = 0xe0;
07011 cmdstr[4] = 0x16;
07012 cmdstr[5] = 0x42;
07013 cmdstr[6] = (txplon != 0);
07014 cmdstr[7] = 0xfd;
07015
07016 rv = civ_cmd(myrpt,cmdstr,8);
07017 if (rv) return(-1);
07018
07019 cmdstr[0] = cmdstr[1] = 0xfe;
07020 cmdstr[2] = myrpt->p.civaddr;
07021 cmdstr[3] = 0xe0;
07022 cmdstr[4] = 0x16;
07023 cmdstr[5] = 0x43;
07024 cmdstr[6] = (rxplon != 0);
07025 cmdstr[7] = 0xfd;
07026
07027 return(civ_cmd(myrpt,cmdstr,8));
07028 }
07029
07030 #if 0
07031
07032
07033 static int set_ctcss_freq_ic706(struct rpt *myrpt, char *txtone, char *rxtone)
07034 {
07035 unsigned char cmdstr[10];
07036 char hertz[MAXREMSTR],decimal[MAXREMSTR];
07037 int h,d,rv;
07038
07039 memset(cmdstr, 0, 5);
07040
07041 if(split_ctcss_freq(hertz, decimal, txtone))
07042 return -1;
07043
07044 h = atoi(hertz);
07045 d = atoi(decimal);
07046
07047 cmdstr[0] = cmdstr[1] = 0xfe;
07048 cmdstr[2] = myrpt->p.civaddr;
07049 cmdstr[3] = 0xe0;
07050 cmdstr[4] = 0x1b;
07051 cmdstr[5] = 0;
07052 cmdstr[6] = ((h / 100) << 4) + (h % 100)/ 10;
07053 cmdstr[7] = ((h % 10) << 4) + (d % 10);
07054 cmdstr[8] = 0xfd;
07055
07056 rv = civ_cmd(myrpt,cmdstr,9);
07057 if (rv) return(-1);
07058
07059 if (!rxtone) return(0);
07060
07061 if(split_ctcss_freq(hertz, decimal, rxtone))
07062 return -1;
07063
07064 h = atoi(hertz);
07065 d = atoi(decimal);
07066
07067 cmdstr[0] = cmdstr[1] = 0xfe;
07068 cmdstr[2] = myrpt->p.civaddr;
07069 cmdstr[3] = 0xe0;
07070 cmdstr[4] = 0x1b;
07071 cmdstr[5] = 1;
07072 cmdstr[6] = ((h / 100) << 4) + (h % 100)/ 10;
07073 cmdstr[7] = ((h % 10) << 4) + (d % 10);
07074 cmdstr[8] = 0xfd;
07075 return(civ_cmd(myrpt,cmdstr,9));
07076 }
07077 #endif
07078
07079 static int vfo_ic706(struct rpt *myrpt)
07080 {
07081 unsigned char cmdstr[10];
07082
07083 cmdstr[0] = cmdstr[1] = 0xfe;
07084 cmdstr[2] = myrpt->p.civaddr;
07085 cmdstr[3] = 0xe0;
07086 cmdstr[4] = 7;
07087 cmdstr[5] = 0xfd;
07088
07089 return(civ_cmd(myrpt,cmdstr,6));
07090 }
07091
07092 static int mem2vfo_ic706(struct rpt *myrpt)
07093 {
07094 unsigned char cmdstr[10];
07095
07096 cmdstr[0] = cmdstr[1] = 0xfe;
07097 cmdstr[2] = myrpt->p.civaddr;
07098 cmdstr[3] = 0xe0;
07099 cmdstr[4] = 0x0a;
07100 cmdstr[5] = 0xfd;
07101
07102 return(civ_cmd(myrpt,cmdstr,6));
07103 }
07104
07105 static int select_mem_ic706(struct rpt *myrpt, int slot)
07106 {
07107 unsigned char cmdstr[10];
07108
07109 cmdstr[0] = cmdstr[1] = 0xfe;
07110 cmdstr[2] = myrpt->p.civaddr;
07111 cmdstr[3] = 0xe0;
07112 cmdstr[4] = 8;
07113 cmdstr[5] = 0;
07114 cmdstr[6] = ((slot / 10) << 4) + (slot % 10);
07115 cmdstr[7] = 0xfd;
07116
07117 return(civ_cmd(myrpt,cmdstr,8));
07118 }
07119
07120 static int set_ic706(struct rpt *myrpt)
07121 {
07122 int res = 0,i;
07123
07124 if(debug)
07125 printf("Set to VFO A\n");
07126
07127 if (!res)
07128 res = simple_command_ic706(myrpt,7,0);
07129
07130
07131 if((myrpt->remmode == REM_MODE_FM))
07132 {
07133 i = ic706_pltocode(myrpt->rxpl);
07134 if (i == -1) return -1;
07135 if(debug)
07136 printf("Select memory number\n");
07137 if (!res)
07138 res = select_mem_ic706(myrpt,i + IC706_PL_MEMORY_OFFSET);
07139 if(debug)
07140 printf("Transfer memory to VFO\n");
07141 if (!res)
07142 res = mem2vfo_ic706(myrpt);
07143 }
07144
07145 if(debug)
07146 printf("Set to VFO\n");
07147
07148 if (!res)
07149 res = vfo_ic706(myrpt);
07150
07151 if(debug)
07152 printf("Modulation mode\n");
07153
07154 if (!res)
07155 res = set_mode_ic706(myrpt, myrpt->remmode);
07156
07157 if(debug)
07158 printf("Split off\n");
07159
07160 if(!res)
07161 simple_command_ic706(myrpt, 0x82,0);
07162
07163 if(debug)
07164 printf("Frequency\n");
07165
07166 if(!res)
07167 res = set_freq_ic706(myrpt, myrpt->freq);
07168 if((myrpt->remmode == REM_MODE_FM)){
07169 if(debug)
07170 printf("Offset\n");
07171 if(!res)
07172 res = set_offset_ic706(myrpt, myrpt->offset);
07173 if(!res){
07174 if(debug)
07175 printf("CTCSS mode\n");
07176 res = set_ctcss_mode_ic706(myrpt, myrpt->txplon, myrpt->rxplon);
07177 }
07178 }
07179 return res;
07180 }
07181
07182
07183
07184
07185
07186
07187
07188 static int multimode_bump_freq_ic706(struct rpt *myrpt, int interval)
07189 {
07190 int m,d;
07191 char mhz[MAXREMSTR], decimals[MAXREMSTR];
07192 unsigned char cmdstr[20];
07193
07194 if(debug)
07195 printf("Before bump: %s\n", myrpt->freq);
07196
07197 if(split_freq(mhz, decimals, myrpt->freq))
07198 return -1;
07199
07200 m = atoi(mhz);
07201 d = atoi(decimals);
07202
07203 d += (interval / 10);
07204 if(d < 0){
07205 m--;
07206 d += 100000;
07207 }
07208 else if(d >= 100000){
07209 m++;
07210 d -= 100000;
07211 }
07212
07213 if(check_freq_ic706(m, d, NULL)){
07214 if(debug)
07215 printf("Bump freq invalid\n");
07216 return -1;
07217 }
07218
07219 snprintf(myrpt->freq, MAXREMSTR, "%d.%05d", m, d);
07220
07221 if(debug)
07222 printf("After bump: %s\n", myrpt->freq);
07223
07224
07225
07226 cmdstr[0] = cmdstr[1] = 0xfe;
07227 cmdstr[2] = myrpt->p.civaddr;
07228 cmdstr[3] = 0xe0;
07229 cmdstr[4] = 0;
07230 cmdstr[5] = ((d % 10) << 4);
07231 cmdstr[6] = (((d % 1000)/ 100) << 4) + ((d % 100)/10);
07232 cmdstr[7] = ((d / 10000) << 4) + ((d % 10000)/1000);
07233 cmdstr[8] = (((m % 100)/10) << 4) + (m % 10);
07234 cmdstr[9] = (m / 100);
07235 cmdstr[10] = 0xfd;
07236
07237 return(serial_remote_io(myrpt,cmdstr,11,NULL,0,0));
07238 }
07239
07240
07241
07242
07243
07244
07245
07246 static int setrem(struct rpt *myrpt)
07247 {
07248 char str[300];
07249 char *offsets[] = {"MINUS","SIMPLEX","PLUS"};
07250 char *powerlevels[] = {"LOW","MEDIUM","HIGH"};
07251 char *modes[] = {"FM","USB","LSB","AM"};
07252 int res = -1;
07253
07254 if (myrpt->p.archivedir)
07255 {
07256 sprintf(str,"FREQ,%s,%s,%s,%s,%s,%s,%d,%d",myrpt->freq,
07257 modes[(int)myrpt->remmode],
07258 myrpt->txpl,myrpt->rxpl,offsets[(int)myrpt->offset],
07259 powerlevels[(int)myrpt->powerlevel],myrpt->txplon,
07260 myrpt->rxplon);
07261 donodelog(myrpt,str);
07262 }
07263 if(!strcmp(myrpt->remote, remote_rig_ft897))
07264 {
07265 rpt_telemetry(myrpt,SETREMOTE,NULL);
07266 res = 0;
07267 }
07268 if(!strcmp(myrpt->remote, remote_rig_ic706))
07269 {
07270 rpt_telemetry(myrpt,SETREMOTE,NULL);
07271 res = 0;
07272 }
07273 else if(!strcmp(myrpt->remote, remote_rig_rbi))
07274 {
07275 res = setrbi_check(myrpt);
07276 if (!res)
07277 {
07278 rpt_telemetry(myrpt,SETREMOTE,NULL);
07279 res = 0;
07280 }
07281 }
07282 else if(!strcmp(myrpt->remote, remote_rig_kenwood)) {
07283 rpt_telemetry(myrpt,SETREMOTE,NULL);
07284 res = 0;
07285 }
07286 else
07287 res = 0;
07288
07289 if (res < 0) ast_log(LOG_ERROR,"Unable to send remote command on node %s\n",myrpt->name);
07290
07291 return res;
07292 }
07293
07294 static int closerem(struct rpt *myrpt)
07295 {
07296 if(!strcmp(myrpt->remote, remote_rig_ft897))
07297 return closerem_ft897(myrpt);
07298 else
07299 return 0;
07300 }
07301
07302
07303
07304
07305
07306 static int check_freq(struct rpt *myrpt, int m, int d, int *defmode)
07307 {
07308 if(!strcmp(myrpt->remote, remote_rig_ft897))
07309 return check_freq_ft897(m, d, defmode);
07310 else if(!strcmp(myrpt->remote, remote_rig_ic706))
07311 return check_freq_ic706(m, d, defmode);
07312 else if(!strcmp(myrpt->remote, remote_rig_rbi))
07313 return check_freq_rbi(m, d, defmode);
07314 else if(!strcmp(myrpt->remote, remote_rig_kenwood))
07315 return check_freq_kenwood(m, d, defmode);
07316 else
07317 return -1;
07318 }
07319
07320
07321
07322
07323
07324 static char check_tx_freq(struct rpt *myrpt)
07325 {
07326 int i;
07327 int radio_mhz, radio_decimals, ulimit_mhz, ulimit_decimals, llimit_mhz, llimit_decimals;
07328 char radio_mhz_char[MAXREMSTR];
07329 char radio_decimals_char[MAXREMSTR];
07330 char limit_mhz_char[MAXREMSTR];
07331 char limit_decimals_char[MAXREMSTR];
07332 char limits[256];
07333 char *limit_ranges[40];
07334 struct ast_variable *limitlist;
07335
07336
07337
07338
07339 if(!myrpt->p.txlimitsstanzaname || !myrpt->loginuser[0] || !myrpt->loginlevel[0]){
07340 if(debug > 3){
07341 ast_log(LOG_NOTICE, "No tx band table defined, or no user logged in\n");
07342 }
07343 return 1;
07344 }
07345
07346
07347 limitlist = ast_variable_browse(myrpt->cfg, myrpt->p.txlimitsstanzaname);
07348
07349 if(!limitlist){
07350 ast_log(LOG_WARNING, "No entries in %s band table stanza\n", myrpt->p.txlimitsstanzaname);
07351 return 0;
07352 }
07353
07354 split_freq(radio_mhz_char, radio_decimals_char, myrpt->freq);
07355 radio_mhz = atoi(radio_mhz_char);
07356 radio_decimals = decimals2int(radio_decimals_char);
07357
07358
07359 if(debug > 3){
07360 ast_log(LOG_NOTICE, "Login User = %s, login level = %s\n", myrpt->loginuser, myrpt->loginlevel);
07361 }
07362
07363
07364
07365 for(;limitlist; limitlist=limitlist->next){
07366 if(!strcmp(limitlist->name, myrpt->loginlevel))
07367 break;
07368 }
07369
07370 if(!limitlist){
07371 ast_log(LOG_WARNING, "Can't find %s entry in band table stanza %s\n", myrpt->loginlevel, myrpt->p.txlimitsstanzaname);
07372 return 0;
07373 }
07374
07375 if(debug > 3){
07376 ast_log(LOG_NOTICE, "Auth %s = %s\n", limitlist->name, limitlist->value);
07377 }
07378
07379
07380
07381 strncpy(limits, limitlist->value, 256);
07382 limits[255] = 0;
07383 finddelim(limits, limit_ranges, 40);
07384 for(i = 0; i < 40 && limit_ranges[i] ; i++){
07385 char range[40];
07386 char *r,*s;
07387 strncpy(range, limit_ranges[i], 40);
07388 range[39] = 0;
07389 if(debug > 3){
07390 ast_log(LOG_NOTICE, "Checking to see if %s is within limits of %s\n", myrpt->freq, range);
07391 }
07392
07393 r = strchr(range, '-');
07394 if(!r){
07395 ast_log(LOG_WARNING, "Malformed range in %s tx band table entry\n", limitlist->name);
07396 return 0;
07397 }
07398 *r++ = 0;
07399 s = eatwhite(range);
07400 r = eatwhite(r);
07401 split_freq(limit_mhz_char, limit_decimals_char, s);
07402 llimit_mhz = atoi(limit_mhz_char);
07403 llimit_decimals = decimals2int(limit_decimals_char);
07404 split_freq(limit_mhz_char, limit_decimals_char, r);
07405 ulimit_mhz = atoi(limit_mhz_char);
07406 ulimit_decimals = decimals2int(limit_decimals_char);
07407
07408 if((radio_mhz >= llimit_mhz) && (radio_mhz <= ulimit_mhz)){
07409 if(radio_mhz == llimit_mhz){
07410 if(radio_decimals >= llimit_decimals){
07411 if(llimit_mhz == ulimit_mhz){
07412 if(radio_decimals <= ulimit_decimals){
07413 return 1;
07414 }
07415 else{
07416 if(debug > 3)
07417 ast_log(LOG_NOTICE, "Invalid TX frequency, debug msg 1\n");
07418 return 0;
07419 }
07420 }
07421 else{
07422 return 1;
07423 }
07424 }
07425 else{
07426 if(debug > 3)
07427 ast_log(LOG_NOTICE, "Invalid TX frequency, debug msg 2\n");
07428 return 0;
07429 }
07430 }
07431 else if(radio_mhz == ulimit_mhz){
07432 if(radio_decimals <= ulimit_decimals){
07433 return 1;
07434 }
07435 else{
07436 if(debug > 3)
07437 ast_log(LOG_NOTICE, "Invalid TX frequency, debug msg 3\n");
07438 return 0;
07439 }
07440 }
07441 else
07442 return 1;
07443 }
07444 }
07445 if(debug > 3)
07446 ast_log(LOG_NOTICE, "Invalid TX frequency, debug msg 4\n");
07447 return 0;
07448 }
07449
07450
07451
07452
07453
07454
07455 static int multimode_bump_freq(struct rpt *myrpt, int interval)
07456 {
07457 if(!strcmp(myrpt->remote, remote_rig_ft897))
07458 return multimode_bump_freq_ft897(myrpt, interval);
07459 else if(!strcmp(myrpt->remote, remote_rig_ic706))
07460 return multimode_bump_freq_ic706(myrpt, interval);
07461 else
07462 return -1;
07463 }
07464
07465
07466
07467
07468
07469
07470 static void stop_scan(struct rpt *myrpt)
07471 {
07472 myrpt->hfscanstop = 1;
07473 rpt_telemetry(myrpt,SCAN,0);
07474 }
07475
07476
07477
07478
07479
07480
07481 static int service_scan(struct rpt *myrpt)
07482 {
07483 int res, interval;
07484 char mhz[MAXREMSTR], decimals[MAXREMSTR], k10=0i, k100=0;
07485
07486 switch(myrpt->hfscanmode){
07487
07488 case HF_SCAN_DOWN_SLOW:
07489 interval = -10;
07490 break;
07491
07492 case HF_SCAN_DOWN_QUICK:
07493 interval = -50;
07494 break;
07495
07496 case HF_SCAN_DOWN_FAST:
07497 interval = -200;
07498 break;
07499
07500 case HF_SCAN_UP_SLOW:
07501 interval = 10;
07502 break;
07503
07504 case HF_SCAN_UP_QUICK:
07505 interval = 50;
07506 break;
07507
07508 case HF_SCAN_UP_FAST:
07509 interval = 200;
07510 break;
07511
07512 default:
07513 myrpt->hfscanmode = 0;
07514 return -1;
07515 }
07516
07517 res = split_freq(mhz, decimals, myrpt->freq);
07518
07519 if(!res){
07520 k100 =decimals[0];
07521 k10 = decimals[1];
07522 res = multimode_bump_freq(myrpt, interval);
07523 }
07524
07525 if(!res)
07526 res = split_freq(mhz, decimals, myrpt->freq);
07527
07528
07529 if(res){
07530 myrpt->hfscanmode = 0;
07531 myrpt->hfscanstatus = -2;
07532 return -1;
07533 }
07534
07535
07536 if(k10 != decimals[1]){
07537 int myhund = (interval < 0) ? k100 : decimals[0];
07538 int myten = (interval < 0) ? k10 : decimals[1];
07539 myrpt->hfscanstatus = (myten == '0') ? (myhund - '0') * 100 : (myten - '0') * 10;
07540 } else myrpt->hfscanstatus = 0;
07541 return res;
07542
07543 }
07544
07545
07546
07547
07548
07549
07550
07551
07552 static int retreive_memory(struct rpt *myrpt, char *memory)
07553 {
07554 char tmp[30], *s, *s1, *val;
07555
07556 val = (char *) ast_variable_retrieve(myrpt->cfg, myrpt->p.memory, memory);
07557 if (!val){
07558 return -1;
07559 }
07560 strncpy(tmp,val,sizeof(tmp) - 1);
07561 tmp[sizeof(tmp)-1] = 0;
07562
07563 s = strchr(tmp,',');
07564 if (!s)
07565 return 1;
07566 *s++ = 0;
07567 s1 = strchr(s,',');
07568 if (!s1)
07569 return 1;
07570 *s1++ = 0;
07571 strncpy(myrpt->freq, tmp, sizeof(myrpt->freq) - 1);
07572 strncpy(myrpt->rxpl, s, sizeof(myrpt->rxpl) - 1);
07573 strncpy(myrpt->txpl, s, sizeof(myrpt->rxpl) - 1);
07574 myrpt->remmode = REM_MODE_FM;
07575 myrpt->offset = REM_SIMPLEX;
07576 myrpt->powerlevel = REM_MEDPWR;
07577 myrpt->txplon = myrpt->rxplon = 0;
07578 while(*s1){
07579 switch(*s1++){
07580 case 'A':
07581 case 'a':
07582 strcpy(myrpt->rxpl, "100.0");
07583 strcpy(myrpt->txpl, "100.0");
07584 myrpt->remmode = REM_MODE_AM;
07585 break;
07586 case 'B':
07587 case 'b':
07588 strcpy(myrpt->rxpl, "100.0");
07589 strcpy(myrpt->txpl, "100.0");
07590 myrpt->remmode = REM_MODE_LSB;
07591 break;
07592 case 'F':
07593 myrpt->remmode = REM_MODE_FM;
07594 break;
07595 case 'L':
07596 case 'l':
07597 myrpt->powerlevel = REM_LOWPWR;
07598 break;
07599 case 'H':
07600 case 'h':
07601 myrpt->powerlevel = REM_HIPWR;
07602 break;
07603
07604 case 'M':
07605 case 'm':
07606 myrpt->powerlevel = REM_MEDPWR;
07607 break;
07608
07609 case '-':
07610 myrpt->offset = REM_MINUS;
07611 break;
07612
07613 case '+':
07614 myrpt->offset = REM_PLUS;
07615 break;
07616
07617 case 'S':
07618 case 's':
07619 myrpt->offset = REM_SIMPLEX;
07620 break;
07621
07622 case 'T':
07623 case 't':
07624 myrpt->txplon = 1;
07625 break;
07626
07627 case 'R':
07628 case 'r':
07629 myrpt->rxplon = 1;
07630 break;
07631
07632 case 'U':
07633 case 'u':
07634 strcpy(myrpt->rxpl, "100.0");
07635 strcpy(myrpt->txpl, "100.0");
07636 myrpt->remmode = REM_MODE_USB;
07637 break;
07638 default:
07639 return 1;
07640 }
07641 }
07642 return 0;
07643 }
07644
07645
07646
07647
07648
07649
07650
07651 static int function_remote(struct rpt *myrpt, char *param, char *digitbuf, int command_source, struct rpt_link *mylink)
07652 {
07653 char *s,*s1,*s2;
07654 int i,j,p,r,ht,k,l,ls2,m,d,offset,offsave, modesave, defmode;
07655 char multimode = 0;
07656 char oc,*cp,*cp1,*cp2;
07657 char tmp[20], freq[20] = "", savestr[20] = "";
07658 char mhz[MAXREMSTR], decimals[MAXREMSTR];
07659
07660 if((!param) || (command_source == SOURCE_RPT) || (command_source == SOURCE_LNK))
07661 return DC_ERROR;
07662
07663 p = myatoi(param);
07664
07665 if ((p != 99) && (p != 5) && (p != 140) && myrpt->p.authlevel &&
07666 (!myrpt->loginlevel[0])) return DC_ERROR;
07667 multimode = multimode_capable(myrpt);
07668
07669 switch(p){
07670
07671 case 1:
07672 if(strlen(digitbuf) < 2)
07673 break;
07674
07675 for(i = 0 ; i < 2 ; i++){
07676 if((digitbuf[i] < '0') || (digitbuf[i] > '9'))
07677 return DC_ERROR;
07678 }
07679
07680 r = retreive_memory(myrpt, digitbuf);
07681 if (r < 0){
07682 rpt_telemetry(myrpt,MEMNOTFOUND,NULL);
07683 return DC_COMPLETE;
07684 }
07685 if (r > 0){
07686 return DC_ERROR;
07687 }
07688 if (setrem(myrpt) == -1) return DC_ERROR;
07689 return DC_COMPLETE;
07690
07691 case 2:
07692
07693
07694 for(i = 0, j = 0, k = 0, l = 0 ; digitbuf[i] ; i++){
07695 if(digitbuf[i] == '*'){
07696 j++;
07697 continue;
07698 }
07699 if((digitbuf[i] < '0') || (digitbuf[i] > '9'))
07700 goto invalid_freq;
07701 else{
07702 if(j == 0)
07703 l++;
07704 if(j == 1)
07705 k++;
07706 }
07707 }
07708
07709 i = strlen(digitbuf) - 1;
07710 if(multimode){
07711 if((j > 2) || (l > 3) || (k > 6))
07712 goto invalid_freq;
07713 }
07714 else{
07715 if((j > 2) || (l > 4) || (k > 3))
07716 goto invalid_freq;
07717 }
07718
07719
07720
07721 if(j < 2)
07722 break;
07723
07724
07725
07726 strncpy(tmp, digitbuf ,sizeof(tmp) - 1);
07727
07728 s = tmp;
07729 s1 = strsep(&s, "*");
07730 s2 = strsep(&s,"*");
07731 ls2 = strlen(s2);
07732
07733 switch(ls2){
07734 case 1:
07735 ht = 0;
07736 k = 100 * atoi(s2);
07737 break;
07738
07739 case 2:
07740 ht = 0;
07741 k = 10 * atoi(s2);
07742 break;
07743
07744 case 3:
07745 if(!multimode){
07746 if((s2[2] != '0')&&(s2[2] != '5'))
07747 goto invalid_freq;
07748 }
07749 ht = 0;
07750 k = atoi(s2);
07751 break;
07752 case 4:
07753 k = atoi(s2)/10;
07754 ht = 10 * (atoi(s2+(ls2-1)));
07755 break;
07756
07757 case 5:
07758 k = atoi(s2)/100;
07759 ht = (atoi(s2+(ls2-2)));
07760 break;
07761
07762 default:
07763 goto invalid_freq;
07764 }
07765
07766
07767
07768 snprintf(freq, sizeof(freq), "%s.%03d%02d",s1, k, ht);
07769
07770 if(debug)
07771 printf("New frequency: %s\n", freq);
07772
07773 split_freq(mhz, decimals, freq);
07774 m = atoi(mhz);
07775 d = atoi(decimals);
07776
07777 if(check_freq(myrpt, m, d, &defmode))
07778 goto invalid_freq;
07779
07780
07781 if((defmode == REM_MODE_FM) && (digitbuf[i] == '*'))
07782 break;
07783
07784
07785 offset = REM_SIMPLEX;
07786
07787 if(defmode == REM_MODE_FM){
07788 oc = *s;
07789
07790 if (oc){
07791 switch(oc){
07792 case '1':
07793 offset = REM_MINUS;
07794 break;
07795
07796 case '2':
07797 offset = REM_SIMPLEX;
07798 break;
07799
07800 case '3':
07801 offset = REM_PLUS;
07802 break;
07803
07804 default:
07805 goto invalid_freq;
07806 }
07807 }
07808 }
07809 offsave = myrpt->offset;
07810 modesave = myrpt->remmode;
07811 strncpy(savestr, myrpt->freq, sizeof(savestr) - 1);
07812 strncpy(myrpt->freq, freq, sizeof(myrpt->freq) - 1);
07813 myrpt->offset = offset;
07814 myrpt->remmode = defmode;
07815
07816 if (setrem(myrpt) == -1){
07817 myrpt->offset = offsave;
07818 myrpt->remmode = modesave;
07819 strncpy(myrpt->freq, savestr, sizeof(myrpt->freq) - 1);
07820 goto invalid_freq;
07821 }
07822
07823 return DC_COMPLETE;
07824
07825 invalid_freq:
07826 rpt_telemetry(myrpt,INVFREQ,NULL);
07827 return DC_ERROR;
07828
07829 case 3:
07830 for(i = 0, j = 0, k = 0, l = 0 ; digitbuf[i] ; i++){
07831 if(digitbuf[i] == '*'){
07832 j++;
07833 continue;
07834 }
07835 if((digitbuf[i] < '0') || (digitbuf[i] > '9'))
07836 return DC_ERROR;
07837 else{
07838 if(j)
07839 l++;
07840 else
07841 k++;
07842 }
07843 }
07844 if((j > 1) || (k > 3) || (l > 1))
07845 return DC_ERROR;
07846 i = strlen(digitbuf) - 1;
07847 if((j != 1) || (k < 2)|| (l != 1))
07848 break;
07849 if(debug)
07850 printf("PL digits entered %s\n", digitbuf);
07851
07852 strncpy(tmp, digitbuf, sizeof(tmp) - 1);
07853
07854 s = strchr(tmp,'*');
07855 if(s)
07856 *s = '.';
07857 strncpy(savestr, myrpt->rxpl, sizeof(savestr) - 1);
07858 strncpy(myrpt->rxpl, tmp, sizeof(myrpt->rxpl) - 1);
07859 if(!strcmp(myrpt->remote, remote_rig_rbi))
07860 {
07861 strncpy(myrpt->txpl, tmp, sizeof(myrpt->txpl) - 1);
07862 }
07863 if (setrem(myrpt) == -1){
07864 strncpy(myrpt->rxpl, savestr, sizeof(myrpt->rxpl) - 1);
07865 return DC_ERROR;
07866 }
07867
07868
07869 return DC_COMPLETE;
07870
07871 case 4:
07872
07873 if(!strcmp(myrpt->remote, remote_rig_rbi))
07874 return DC_ERROR;
07875 if(!strcmp(myrpt->remote, remote_rig_ic706))
07876 return DC_ERROR;
07877 for(i = 0, j = 0, k = 0, l = 0 ; digitbuf[i] ; i++){
07878 if(digitbuf[i] == '*'){
07879 j++;
07880 continue;
07881 }
07882 if((digitbuf[i] < '0') || (digitbuf[i] > '9'))
07883 return DC_ERROR;
07884 else{
07885 if(j)
07886 l++;
07887 else
07888 k++;
07889 }
07890 }
07891 if((j > 1) || (k > 3) || (l > 1))
07892 return DC_ERROR;
07893 i = strlen(digitbuf) - 1;
07894 if((j != 1) || (k < 2)|| (l != 1))
07895 break;
07896 if(debug)
07897 printf("PL digits entered %s\n", digitbuf);
07898
07899 strncpy(tmp, digitbuf, sizeof(tmp) - 1);
07900
07901 s = strchr(tmp,'*');
07902 if(s)
07903 *s = '.';
07904 strncpy(savestr, myrpt->txpl, sizeof(savestr) - 1);
07905 strncpy(myrpt->txpl, tmp, sizeof(myrpt->txpl) - 1);
07906
07907 if (setrem(myrpt) == -1){
07908 strncpy(myrpt->txpl, savestr, sizeof(myrpt->txpl) - 1);
07909 return DC_ERROR;
07910 }
07911
07912
07913 return DC_COMPLETE;
07914
07915
07916 case 6:
07917 if(strlen(digitbuf) < 1)
07918 break;
07919
07920 if(!multimode)
07921 return DC_ERROR;
07922
07923 switch(*digitbuf){
07924 case '1':
07925 split_freq(mhz, decimals, myrpt->freq);
07926 m=atoi(mhz);
07927 if(m < 29)
07928 return DC_ERROR;
07929 myrpt->remmode = REM_MODE_FM;
07930
07931 rpt_telemetry(myrpt,REMMODE,NULL);
07932 break;
07933
07934 case '2':
07935 myrpt->remmode = REM_MODE_USB;
07936 rpt_telemetry(myrpt,REMMODE,NULL);
07937 break;
07938
07939 case '3':
07940 myrpt->remmode = REM_MODE_LSB;
07941 rpt_telemetry(myrpt,REMMODE,NULL);
07942 break;
07943
07944 case '4':
07945 myrpt->remmode = REM_MODE_AM;
07946 rpt_telemetry(myrpt,REMMODE,NULL);
07947 break;
07948
07949 default:
07950 return DC_ERROR;
07951 }
07952
07953 if(setrem(myrpt))
07954 return DC_ERROR;
07955 return DC_COMPLETEQUIET;
07956 case 99:
07957
07958 if (myrpt->loginlevel[0])
07959 return DC_ERROR;
07960 *myrpt->loginuser = 0;
07961 myrpt->loginlevel[0] = 0;
07962 cp = strdup(param);
07963 cp1 = strchr(cp,',');
07964 ast_mutex_lock(&myrpt->lock);
07965 if (cp1)
07966 {
07967 *cp1 = 0;
07968 cp2 = strchr(cp1 + 1,',');
07969 if (cp2)
07970 {
07971 *cp2 = 0;
07972 strncpy(myrpt->loginlevel,cp2 + 1,
07973 sizeof(myrpt->loginlevel) - 1);
07974 }
07975 strncpy(myrpt->loginuser,cp1 + 1,sizeof(myrpt->loginuser));
07976 ast_mutex_unlock(&myrpt->lock);
07977 if (myrpt->p.archivedir)
07978 {
07979 char str[100];
07980
07981 sprintf(str,"LOGIN,%s,%s",
07982 myrpt->loginuser,myrpt->loginlevel);
07983 donodelog(myrpt,str);
07984 }
07985 if (debug)
07986 printf("loginuser %s level %s\n",myrpt->loginuser,myrpt->loginlevel);
07987 rpt_telemetry(myrpt,REMLOGIN,NULL);
07988 }
07989 free(cp);
07990 return DC_COMPLETEQUIET;
07991 case 100:
07992 myrpt->rxplon = 0;
07993 setrem(myrpt);
07994 rpt_telemetry(myrpt,REMXXX,(void *)p);
07995 return DC_COMPLETEQUIET;
07996 case 101:
07997 myrpt->rxplon = 1;
07998 setrem(myrpt);
07999 rpt_telemetry(myrpt,REMXXX,(void *)p);
08000 return DC_COMPLETEQUIET;
08001 case 102:
08002 myrpt->txplon = 0;
08003 setrem(myrpt);
08004 rpt_telemetry(myrpt,REMXXX,(void *)p);
08005 return DC_COMPLETEQUIET;
08006 case 103:
08007 myrpt->txplon = 1;
08008 setrem(myrpt);
08009 rpt_telemetry(myrpt,REMXXX,(void *)p);
08010 return DC_COMPLETEQUIET;
08011 case 104:
08012 if(!strcmp(myrpt->remote, remote_rig_ic706))
08013 return DC_ERROR;
08014 myrpt->powerlevel = REM_LOWPWR;
08015 setrem(myrpt);
08016 rpt_telemetry(myrpt,REMXXX,(void *)p);
08017 return DC_COMPLETEQUIET;
08018 case 105:
08019 if(!strcmp(myrpt->remote, remote_rig_ic706))
08020 return DC_ERROR;
08021 myrpt->powerlevel = REM_MEDPWR;
08022 setrem(myrpt);
08023 rpt_telemetry(myrpt,REMXXX,(void *)p);
08024 return DC_COMPLETEQUIET;
08025 case 106:
08026 if(!strcmp(myrpt->remote, remote_rig_ic706))
08027 return DC_ERROR;
08028 myrpt->powerlevel = REM_HIPWR;
08029 setrem(myrpt);
08030 rpt_telemetry(myrpt,REMXXX,(void *)p);
08031 return DC_COMPLETEQUIET;
08032 case 107:
08033 multimode_bump_freq(myrpt, -20);
08034 return DC_COMPLETE;
08035 case 108:
08036 multimode_bump_freq(myrpt, -100);
08037 return DC_COMPLETE;
08038 case 109:
08039 multimode_bump_freq(myrpt, -500);
08040 return DC_COMPLETE;
08041 case 110:
08042 multimode_bump_freq(myrpt, 20);
08043 return DC_COMPLETE;
08044 case 111:
08045 multimode_bump_freq(myrpt, 100);
08046 return DC_COMPLETE;
08047 case 112:
08048 multimode_bump_freq(myrpt, 500);
08049 return DC_COMPLETE;
08050 case 113:
08051 myrpt->scantimer = REM_SCANTIME;
08052 myrpt->hfscanmode = HF_SCAN_DOWN_SLOW;
08053 rpt_telemetry(myrpt,REMXXX,(void *)p);
08054 return DC_COMPLETEQUIET;
08055 case 114:
08056 myrpt->scantimer = REM_SCANTIME;
08057 myrpt->hfscanmode = HF_SCAN_DOWN_QUICK;
08058 rpt_telemetry(myrpt,REMXXX,(void *)p);
08059 return DC_COMPLETEQUIET;
08060 case 115:
08061 myrpt->scantimer = REM_SCANTIME;
08062 myrpt->hfscanmode = HF_SCAN_DOWN_FAST;
08063 rpt_telemetry(myrpt,REMXXX,(void *)p);
08064 return DC_COMPLETEQUIET;
08065 case 116:
08066 myrpt->scantimer = REM_SCANTIME;
08067 myrpt->hfscanmode = HF_SCAN_UP_SLOW;
08068 rpt_telemetry(myrpt,REMXXX,(void *)p);
08069 return DC_COMPLETEQUIET;
08070 case 117:
08071 myrpt->scantimer = REM_SCANTIME;
08072 myrpt->hfscanmode = HF_SCAN_UP_QUICK;
08073 rpt_telemetry(myrpt,REMXXX,(void *)p);
08074 return DC_COMPLETEQUIET;
08075 case 118:
08076 myrpt->scantimer = REM_SCANTIME;
08077 myrpt->hfscanmode = HF_SCAN_UP_FAST;
08078 rpt_telemetry(myrpt,REMXXX,(void *)p);
08079 return DC_COMPLETEQUIET;
08080 case 119:
08081
08082 if((!myrpt->tunerequest) &&
08083 ((!strcmp(myrpt->remote, remote_rig_ft897) ||
08084 !strcmp(myrpt->remote, remote_rig_ic706)) )) {
08085 myrpt->remotetx = 0;
08086 ast_indicate(myrpt->txchannel,AST_CONTROL_RADIO_UNKEY);
08087 myrpt->tunerequest = 1;
08088 rpt_telemetry(myrpt,TUNE,NULL);
08089 return DC_COMPLETEQUIET;
08090 }
08091 return DC_ERROR;
08092 case 5:
08093 rpt_telemetry(myrpt,REMLONGSTATUS,NULL);
08094 return DC_COMPLETEQUIET;
08095 case 140:
08096 rpt_telemetry(myrpt,REMSHORTSTATUS,NULL);
08097 return DC_COMPLETEQUIET;
08098 case 200:
08099 case 201:
08100 case 202:
08101 case 203:
08102 case 204:
08103 case 205:
08104 case 206:
08105 case 207:
08106 case 208:
08107 case 209:
08108 case 210:
08109 case 211:
08110 case 212:
08111 case 213:
08112 case 214:
08113 case 215:
08114 do_dtmf_local(myrpt,remdtmfstr[p - 200]);
08115 return DC_COMPLETEQUIET;
08116 default:
08117 break;
08118 }
08119 return DC_INDETERMINATE;
08120 }
08121
08122
08123 static int handle_remote_dtmf_digit(struct rpt *myrpt,char c, char *keyed, int phonemode)
08124 {
08125 time_t now;
08126 int ret,res = 0,src;
08127
08128 time(&myrpt->last_activity_time);
08129
08130 if(myrpt->hfscanmode){
08131 stop_scan(myrpt);
08132 return 0;
08133 }
08134
08135 time(&now);
08136
08137 if ((myrpt->dtmf_time_rem + DTMF_TIMEOUT) < now)
08138 {
08139 myrpt->dtmfidx = -1;
08140 myrpt->dtmfbuf[0] = 0;
08141 myrpt->dtmf_time_rem = 0;
08142 }
08143
08144 if (myrpt->dtmfidx == -1)
08145 {
08146
08147 if (c != myrpt->p.funcchar)
08148 {
08149 if (!myrpt->p.propagate_dtmf)
08150 {
08151 rpt_mutex_lock(&myrpt->lock);
08152 do_dtmf_local(myrpt,c);
08153 rpt_mutex_unlock(&myrpt->lock);
08154 }
08155 return 0;
08156 }
08157 myrpt->dtmfidx = 0;
08158 myrpt->dtmfbuf[0] = 0;
08159 myrpt->dtmf_time_rem = now;
08160 return 0;
08161 }
08162
08163 if (myrpt->dtmfidx >= MAXDTMF)
08164 {
08165 myrpt->dtmfidx = 0;
08166 myrpt->dtmfbuf[0] = 0;
08167 myrpt->dtmf_time_rem = now;
08168 }
08169 if (c == myrpt->p.funcchar)
08170 {
08171
08172 if ((myrpt->dtmfidx < 1) ||
08173 (myrpt->dtmfbuf[myrpt->dtmfidx - 1] == myrpt->p.funcchar))
08174 {
08175 myrpt->dtmfidx = 0;
08176 myrpt->dtmfbuf[0] = 0;
08177 myrpt->dtmf_time_rem = now;
08178 return 0;
08179 }
08180 }
08181 myrpt->dtmfbuf[myrpt->dtmfidx++] = c;
08182 myrpt->dtmfbuf[myrpt->dtmfidx] = 0;
08183 myrpt->dtmf_time_rem = now;
08184
08185
08186 src = SOURCE_RMT;
08187 if (phonemode > 1) src = SOURCE_DPHONE;
08188 else if (phonemode) src = SOURCE_PHONE;
08189 ret = collect_function_digits(myrpt, myrpt->dtmfbuf, src, NULL);
08190
08191 switch(ret){
08192
08193 case DC_INDETERMINATE:
08194 res = 0;
08195 break;
08196
08197 case DC_DOKEY:
08198 if (keyed) *keyed = 1;
08199 res = 0;
08200 break;
08201
08202 case DC_REQ_FLUSH:
08203 myrpt->dtmfidx = 0;
08204 myrpt->dtmfbuf[0] = 0;
08205 res = 0;
08206 break;
08207
08208
08209 case DC_COMPLETE:
08210 res = 1;
08211 case DC_COMPLETEQUIET:
08212 myrpt->totalexecdcommands++;
08213 myrpt->dailyexecdcommands++;
08214 strncpy(myrpt->lastdtmfcommand, myrpt->dtmfbuf, MAXDTMF-1);
08215 myrpt->lastdtmfcommand[MAXDTMF-1] = '\0';
08216 myrpt->dtmfbuf[0] = 0;
08217 myrpt->dtmfidx = -1;
08218 myrpt->dtmf_time_rem = 0;
08219 break;
08220
08221 case DC_ERROR:
08222 default:
08223 myrpt->dtmfbuf[0] = 0;
08224 myrpt->dtmfidx = -1;
08225 myrpt->dtmf_time_rem = 0;
08226 res = 0;
08227 break;
08228 }
08229
08230 return res;
08231 }
08232
08233 static int handle_remote_data(struct rpt *myrpt, char *str)
08234 {
08235 char tmp[300],cmd[300],dest[300],src[300],c;
08236 int seq,res;
08237
08238
08239 strncpy(tmp,str,sizeof(tmp) - 1);
08240 if (!strcmp(tmp,discstr)) return 0;
08241 if (sscanf(tmp,"%s %s %s %d %c",cmd,dest,src,&seq,&c) != 5)
08242 {
08243 ast_log(LOG_WARNING, "Unable to parse link string %s\n",str);
08244 return 0;
08245 }
08246 if (strcmp(cmd,"D"))
08247 {
08248 ast_log(LOG_WARNING, "Unable to parse link string %s\n",str);
08249 return 0;
08250 }
08251
08252 if (strcmp(dest,myrpt->name)) return 0;
08253 if (myrpt->p.archivedir)
08254 {
08255 char str[100];
08256
08257 sprintf(str,"DTMF,%c",c);
08258 donodelog(myrpt,str);
08259 }
08260 c = func_xlat(myrpt,c,&myrpt->p.outxlat);
08261 if (!c) return(0);
08262 res = handle_remote_dtmf_digit(myrpt,c, NULL, 0);
08263 if (res != 1)
08264 return res;
08265 rpt_telemetry(myrpt,COMPLETE,NULL);
08266 return 0;
08267 }
08268
08269 static int handle_remote_phone_dtmf(struct rpt *myrpt, char c, char *keyed, int phonemode)
08270 {
08271 int res;
08272
08273
08274 if (keyed && *keyed && (c == myrpt->p.endchar))
08275 {
08276 *keyed = 0;
08277 return DC_INDETERMINATE;
08278 }
08279
08280 if (myrpt->p.archivedir)
08281 {
08282 char str[100];
08283
08284 sprintf(str,"DTMF(P),%c",c);
08285 donodelog(myrpt,str);
08286 }
08287 res = handle_remote_dtmf_digit(myrpt,c,keyed, phonemode);
08288 if (res != 1)
08289 return res;
08290 rpt_telemetry(myrpt,COMPLETE,NULL);
08291 return 0;
08292 }
08293
08294 static int attempt_reconnect(struct rpt *myrpt, struct rpt_link *l)
08295 {
08296 char *val, *s, *s1, *s2, *tele;
08297 char tmp[300], deststr[300] = "";
08298
08299 val = node_lookup(myrpt,l->name);
08300 if (!val)
08301 {
08302 fprintf(stderr,"attempt_reconnect: cannot find node %s\n",l->name);
08303 return -1;
08304 }
08305
08306 rpt_mutex_lock(&myrpt->lock);
08307
08308 remque((struct qelem *) l);
08309 rpt_mutex_unlock(&myrpt->lock);
08310 strncpy(tmp,val,sizeof(tmp) - 1);
08311 s = tmp;
08312 s1 = strsep(&s,",");
08313 s2 = strsep(&s,",");
08314 snprintf(deststr, sizeof(deststr), "IAX2/%s", s1);
08315 tele = strchr(deststr, '/');
08316 if (!tele) {
08317 fprintf(stderr,"attempt_reconnect:Dial number (%s) must be in format tech/number\n",deststr);
08318 return -1;
08319 }
08320 *tele++ = 0;
08321 l->elaptime = 0;
08322 l->connecttime = 0;
08323 l->thisconnected = 0;
08324 l->chan = ast_request(deststr, AST_FORMAT_SLINEAR, tele,NULL);
08325 if (l->chan){
08326 ast_set_read_format(l->chan, AST_FORMAT_SLINEAR);
08327 ast_set_write_format(l->chan, AST_FORMAT_SLINEAR);
08328 l->chan->whentohangup = 0;
08329 l->chan->appl = "Apprpt";
08330 l->chan->data = "(Remote Rx)";
08331 if (option_verbose > 2)
08332 ast_verbose(VERBOSE_PREFIX_3 "rpt (attempt_reconnect) initiating call to %s/%s on %s\n",
08333 deststr, tele, l->chan->name);
08334 if(l->chan->cid.cid_num)
08335 free(l->chan->cid.cid_num);
08336 l->chan->cid.cid_num = strdup(myrpt->name);
08337 ast_call(l->chan,tele,999);
08338
08339 }
08340 else
08341 {
08342 if (option_verbose > 2)
08343 ast_verbose(VERBOSE_PREFIX_3 "Unable to place call to %s/%s on %s\n",
08344 deststr,tele,l->chan->name);
08345 return -1;
08346 }
08347 rpt_mutex_lock(&myrpt->lock);
08348
08349 insque((struct qelem *)l,(struct qelem *)myrpt->links.next);
08350 rpt_mutex_unlock(&myrpt->lock);
08351 ast_log(LOG_NOTICE,"Reconnect Attempt to %s in process\n",l->name);
08352 return 0;
08353 }
08354
08355
08356 static void local_dtmf_helper(struct rpt *myrpt,char c)
08357 {
08358 int res;
08359 pthread_attr_t attr;
08360 char cmd[MAXDTMF+1] = "";
08361
08362 if (myrpt->p.archivedir)
08363 {
08364 char str[100];
08365
08366 sprintf(str,"DTMF,MAIN,%c",c);
08367 donodelog(myrpt,str);
08368 }
08369 if (c == myrpt->p.endchar)
08370 {
08371
08372 if (myrpt->p.simple && myrpt->callmode)
08373 {
08374 rpt_mutex_lock(&myrpt->lock);
08375 myrpt->callmode = 0;
08376 rpt_mutex_unlock(&myrpt->lock);
08377 rpt_telemetry(myrpt,TERM,NULL);
08378 return;
08379 }
08380 rpt_mutex_lock(&myrpt->lock);
08381 myrpt->stopgen = 1;
08382 if (myrpt->cmdnode[0])
08383 {
08384 myrpt->cmdnode[0] = 0;
08385 myrpt->dtmfidx = -1;
08386 myrpt->dtmfbuf[0] = 0;
08387 rpt_mutex_unlock(&myrpt->lock);
08388 rpt_telemetry(myrpt,COMPLETE,NULL);
08389 }
08390 else
08391 {
08392 rpt_mutex_unlock(&myrpt->lock);
08393 if (myrpt->p.propagate_phonedtmf)
08394 do_dtmf_phone(myrpt,NULL,c);
08395 }
08396 return;
08397 }
08398 rpt_mutex_lock(&myrpt->lock);
08399 if (myrpt->cmdnode[0])
08400 {
08401 rpt_mutex_unlock(&myrpt->lock);
08402 send_link_dtmf(myrpt,c);
08403 return;
08404 }
08405 if (!myrpt->p.simple)
08406 {
08407 if (c == myrpt->p.funcchar)
08408 {
08409 myrpt->dtmfidx = 0;
08410 myrpt->dtmfbuf[myrpt->dtmfidx] = 0;
08411 rpt_mutex_unlock(&myrpt->lock);
08412 time(&myrpt->dtmf_time);
08413 return;
08414 }
08415 else if ((c != myrpt->p.endchar) && (myrpt->dtmfidx >= 0))
08416 {
08417 time(&myrpt->dtmf_time);
08418
08419 if (myrpt->dtmfidx < MAXDTMF)
08420 {
08421 myrpt->dtmfbuf[myrpt->dtmfidx++] = c;
08422 myrpt->dtmfbuf[myrpt->dtmfidx] = 0;
08423
08424 strncpy(cmd, myrpt->dtmfbuf, sizeof(cmd) - 1);
08425
08426 rpt_mutex_unlock(&myrpt->lock);
08427 res = collect_function_digits(myrpt, cmd, SOURCE_RPT, NULL);
08428 rpt_mutex_lock(&myrpt->lock);
08429 switch(res){
08430 case DC_INDETERMINATE:
08431 break;
08432 case DC_REQ_FLUSH:
08433 myrpt->dtmfidx = 0;
08434 myrpt->dtmfbuf[0] = 0;
08435 break;
08436 case DC_COMPLETE:
08437 case DC_COMPLETEQUIET:
08438 myrpt->totalexecdcommands++;
08439 myrpt->dailyexecdcommands++;
08440 strncpy(myrpt->lastdtmfcommand, cmd, MAXDTMF-1);
08441 myrpt->lastdtmfcommand[MAXDTMF-1] = '\0';
08442 myrpt->dtmfbuf[0] = 0;
08443 myrpt->dtmfidx = -1;
08444 myrpt->dtmf_time = 0;
08445 break;
08446
08447 case DC_ERROR:
08448 default:
08449 myrpt->dtmfbuf[0] = 0;
08450 myrpt->dtmfidx = -1;
08451 myrpt->dtmf_time = 0;
08452 break;
08453 }
08454 if(res != DC_INDETERMINATE) {
08455 rpt_mutex_unlock(&myrpt->lock);
08456 return;
08457 }
08458 }
08459 }
08460 }
08461 else
08462 {
08463 if ((!myrpt->callmode) && (c == myrpt->p.funcchar))
08464 {
08465 myrpt->callmode = 1;
08466 myrpt->patchnoct = 0;
08467 myrpt->patchquiet = 0;
08468 myrpt->patchfarenddisconnect = 0;
08469 myrpt->patchdialtime = 0;
08470 strncpy(myrpt->patchcontext, myrpt->p.ourcontext, MAXPATCHCONTEXT);
08471 myrpt->cidx = 0;
08472 myrpt->exten[myrpt->cidx] = 0;
08473 rpt_mutex_unlock(&myrpt->lock);
08474 pthread_attr_init(&attr);
08475 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
08476 ast_pthread_create(&myrpt->rpt_call_thread,&attr,rpt_call,(void *)myrpt);
08477 return;
08478 }
08479 }
08480 if (myrpt->callmode == 1)
08481 {
08482 myrpt->exten[myrpt->cidx++] = c;
08483 myrpt->exten[myrpt->cidx] = 0;
08484
08485 if (ast_exists_extension(myrpt->pchannel,myrpt->patchcontext,myrpt->exten,1,NULL))
08486 {
08487 myrpt->callmode = 2;
08488 rpt_mutex_unlock(&myrpt->lock);
08489 if(!myrpt->patchquiet)
08490 rpt_telemetry(myrpt,PROC,NULL);
08491 return;
08492 }
08493
08494 if (!ast_canmatch_extension(myrpt->pchannel,myrpt->patchcontext,myrpt->exten,1,NULL))
08495 {
08496
08497 myrpt->callmode = 4;
08498 }
08499 rpt_mutex_unlock(&myrpt->lock);
08500 return;
08501 }
08502 if ((myrpt->callmode == 2) || (myrpt->callmode == 3))
08503 {
08504 myrpt->mydtmf = c;
08505 }
08506 rpt_mutex_unlock(&myrpt->lock);
08507 if ((myrpt->dtmfidx < 0) && myrpt->p.propagate_phonedtmf)
08508 do_dtmf_phone(myrpt,NULL,c);
08509 return;
08510 }
08511
08512
08513
08514
08515 static void queue_id(struct rpt *myrpt)
08516 {
08517 if(myrpt->p.idtime){
08518 myrpt->mustid = myrpt->tailid = 0;
08519 myrpt->idtimer = myrpt->p.idtime;
08520 rpt_mutex_unlock(&myrpt->lock);
08521 rpt_telemetry(myrpt,ID,NULL);
08522 rpt_mutex_lock(&myrpt->lock);
08523 }
08524 }
08525
08526
08527
08528
08529 static void do_scheduler(struct rpt *myrpt)
08530 {
08531 int i,res;
08532 struct tm tmnow;
08533 struct ast_variable *skedlist;
08534 char *strs[5],*vp,*val,value[100];
08535
08536 memcpy(&myrpt->lasttv, &myrpt->curtv, sizeof(struct timeval));
08537
08538 if( (res = gettimeofday(&myrpt->curtv, NULL)) < 0)
08539 ast_log(LOG_NOTICE, "Scheduler gettime of day returned: %s\n", strerror(res));
08540
08541
08542
08543 if(myrpt->lasttv.tv_sec == myrpt->curtv.tv_sec)
08544 return;
08545
08546 rpt_localtime(&myrpt->curtv.tv_sec, &tmnow);
08547
08548
08549
08550 if((tmnow.tm_hour == 0)&&(tmnow.tm_min == 0)&&(tmnow.tm_sec == 0)){
08551 myrpt->dailykeyups = 0;
08552 myrpt->dailytxtime = 0;
08553 myrpt->dailykerchunks = 0;
08554 myrpt->dailyexecdcommands = 0;
08555 }
08556
08557 if(tmnow.tm_sec != 0)
08558 return;
08559
08560
08561
08562
08563
08564
08565 if (myrpt->remote)
08566 return;
08567
08568
08569
08570 if(myrpt->p.s[myrpt->p.sysstate_cur].schedulerdisable){
08571 if(debug > 6)
08572 ast_log(LOG_NOTICE, "Scheduler disabled\n");
08573 return;
08574 }
08575
08576 if(!myrpt->p.skedstanzaname){
08577 if(debug > 6)
08578 ast_log(LOG_NOTICE,"No stanza for scheduler in rpt.conf\n");
08579 return;
08580 }
08581
08582
08583 skedlist = ast_variable_browse(myrpt->cfg, myrpt->p.skedstanzaname);
08584
08585 if(debug > 6){
08586 ast_log(LOG_NOTICE, "Time now: %02d:%02d %02d %02d %02d\n",
08587 tmnow.tm_hour,tmnow.tm_min,tmnow.tm_mday,tmnow.tm_mon + 1, tmnow.tm_wday);
08588 }
08589
08590 for(; skedlist; skedlist = skedlist->next){
08591 if(debug > 6)
08592 ast_log(LOG_NOTICE, "Scheduler entry %s = %s being considered\n",skedlist->name, skedlist->value);
08593 strncpy(value,skedlist->value,99);
08594 value[99] = 0;
08595
08596 for( i = 0, vp = value ; i < 5; i++){
08597 if(!*vp)
08598 break;
08599 while((*vp == ' ') || (*vp == 0x09))
08600 vp++;
08601 strs[i] = vp;
08602 while((*vp != ' ') && (*vp != 0x09) && (*vp != 0))
08603 vp++;
08604 if(*vp)
08605 *vp++ = 0;
08606 }
08607 if(debug > 6)
08608 ast_log(LOG_NOTICE, "i = %d, min = %s, hour = %s, mday=%s, mon=%s, wday=%s\n",i,
08609 strs[0], strs[1], strs[2], strs[3], strs[4]);
08610 if(i == 5){
08611 if((*strs[0] != '*')&&(atoi(strs[0]) != tmnow.tm_min))
08612 continue;
08613 if((*strs[1] != '*')&&(atoi(strs[1]) != tmnow.tm_hour))
08614 continue;
08615 if((*strs[2] != '*')&&(atoi(strs[2]) != tmnow.tm_mday))
08616 continue;
08617 if((*strs[3] != '*')&&(atoi(strs[3]) != tmnow.tm_mon + 1))
08618 continue;
08619 if(atoi(strs[4]) == 7)
08620 strs[4] = "0";
08621 if((*strs[4] != '*')&&(atoi(strs[4]) != tmnow.tm_wday))
08622 continue;
08623 if(debug)
08624 ast_log(LOG_NOTICE, "Executing scheduler entry %s = %s\n", skedlist->name, skedlist->value);
08625 if(atoi(skedlist->name) == 0)
08626 return;
08627 val = (char *) ast_variable_retrieve(myrpt->cfg, myrpt->p.macro, skedlist->name);
08628 if (!val){
08629 ast_log(LOG_WARNING,"Scheduler could not find macro %s\n",skedlist->name);
08630 return;
08631 }
08632 if ((MAXMACRO - strlen(myrpt->macrobuf)) < strlen(val)){
08633 ast_log(LOG_WARNING, "Scheduler could not execute macro %s: Macro buffer full\n",
08634 skedlist->name);
08635 return;
08636 }
08637 myrpt->macrotimer = MACROTIME;
08638 strncat(myrpt->macrobuf,val,MAXMACRO - 1);
08639 }
08640 else{
08641 ast_log(LOG_WARNING,"Malformed scheduler entry in rpt.conf: %s = %s\n",
08642 skedlist->name, skedlist->value);
08643 }
08644 }
08645
08646 }
08647
08648
08649
08650 static void *rpt(void *this)
08651 {
08652 struct rpt *myrpt = (struct rpt *)this;
08653 char *tele,*idtalkover,c;
08654 int ms = MSWAIT,i,lasttx=0,val,remrx=0,identqueued,othertelemqueued;
08655 int tailmessagequeued,ctqueued,dtmfed;
08656 struct ast_channel *who;
08657 ZT_CONFINFO ci;
08658 time_t t;
08659 struct rpt_link *l,*m;
08660 struct rpt_tele *telem;
08661 char tmpstr[300],lstr[MAXLINKLIST];
08662
08663
08664 if (myrpt->p.archivedir) mkdir(myrpt->p.archivedir,0600);
08665 sprintf(tmpstr,"%s/%s",myrpt->p.archivedir,myrpt->name);
08666 mkdir(tmpstr,0600);
08667 rpt_mutex_lock(&myrpt->lock);
08668
08669 telem = myrpt->tele.next;
08670 while(telem != &myrpt->tele)
08671 {
08672 ast_softhangup(telem->chan,AST_SOFTHANGUP_DEV);
08673 telem = telem->next;
08674 }
08675 rpt_mutex_unlock(&myrpt->lock);
08676
08677 for(i = 0; i < nrpts; i++)
08678 {
08679 if (&rpt_vars[i] == myrpt)
08680 {
08681 load_rpt_vars(i,0);
08682 break;
08683 }
08684 }
08685 rpt_mutex_lock(&myrpt->lock);
08686 strncpy(tmpstr,myrpt->rxchanname,sizeof(tmpstr) - 1);
08687 tele = strchr(tmpstr,'/');
08688 if (!tele)
08689 {
08690 fprintf(stderr,"rpt:Rxchannel Dial number (%s) must be in format tech/number\n",myrpt->rxchanname);
08691 rpt_mutex_unlock(&myrpt->lock);
08692 myrpt->rpt_thread = AST_PTHREADT_STOP;
08693 pthread_exit(NULL);
08694 }
08695 *tele++ = 0;
08696 myrpt->rxchannel = ast_request(tmpstr,AST_FORMAT_SLINEAR,tele,NULL);
08697 if (myrpt->rxchannel)
08698 {
08699 if (myrpt->rxchannel->_state == AST_STATE_BUSY)
08700 {
08701 fprintf(stderr,"rpt:Sorry unable to obtain Rx channel\n");
08702 rpt_mutex_unlock(&myrpt->lock);
08703 ast_hangup(myrpt->rxchannel);
08704 myrpt->rpt_thread = AST_PTHREADT_STOP;
08705 pthread_exit(NULL);
08706 }
08707 ast_set_read_format(myrpt->rxchannel,AST_FORMAT_SLINEAR);
08708 ast_set_write_format(myrpt->rxchannel,AST_FORMAT_SLINEAR);
08709 myrpt->rxchannel->whentohangup = 0;
08710 myrpt->rxchannel->appl = "Apprpt";
08711 myrpt->rxchannel->data = "(Repeater Rx)";
08712 if (option_verbose > 2)
08713 ast_verbose(VERBOSE_PREFIX_3 "rpt (Rx) initiating call to %s/%s on %s\n",
08714 tmpstr,tele,myrpt->rxchannel->name);
08715 ast_call(myrpt->rxchannel,tele,999);
08716 if (myrpt->rxchannel->_state != AST_STATE_UP)
08717 {
08718 rpt_mutex_unlock(&myrpt->lock);
08719 ast_hangup(myrpt->rxchannel);
08720 myrpt->rpt_thread = AST_PTHREADT_STOP;
08721 pthread_exit(NULL);
08722 }
08723 }
08724 else
08725 {
08726 fprintf(stderr,"rpt:Sorry unable to obtain Rx channel\n");
08727 rpt_mutex_unlock(&myrpt->lock);
08728 myrpt->rpt_thread = AST_PTHREADT_STOP;
08729 pthread_exit(NULL);
08730 }
08731 if (myrpt->txchanname)
08732 {
08733 strncpy(tmpstr,myrpt->txchanname,sizeof(tmpstr) - 1);
08734 tele = strchr(tmpstr,'/');
08735 if (!tele)
08736 {
08737 fprintf(stderr,"rpt:Txchannel Dial number (%s) must be in format tech/number\n",myrpt->txchanname);
08738 rpt_mutex_unlock(&myrpt->lock);
08739 ast_hangup(myrpt->rxchannel);
08740 myrpt->rpt_thread = AST_PTHREADT_STOP;
08741 pthread_exit(NULL);
08742 }
08743 *tele++ = 0;
08744 myrpt->txchannel = ast_request(tmpstr,AST_FORMAT_SLINEAR,tele,NULL);
08745 if (myrpt->txchannel)
08746 {
08747 if (myrpt->txchannel->_state == AST_STATE_BUSY)
08748 {
08749 fprintf(stderr,"rpt:Sorry unable to obtain Tx channel\n");
08750 rpt_mutex_unlock(&myrpt->lock);
08751 ast_hangup(myrpt->txchannel);
08752 ast_hangup(myrpt->rxchannel);
08753 myrpt->rpt_thread = AST_PTHREADT_STOP;
08754 pthread_exit(NULL);
08755 }
08756 ast_set_read_format(myrpt->txchannel,AST_FORMAT_SLINEAR);
08757 ast_set_write_format(myrpt->txchannel,AST_FORMAT_SLINEAR);
08758 myrpt->txchannel->whentohangup = 0;
08759 myrpt->txchannel->appl = "Apprpt";
08760 myrpt->txchannel->data = "(Repeater Tx)";
08761 if (option_verbose > 2)
08762 ast_verbose(VERBOSE_PREFIX_3 "rpt (Tx) initiating call to %s/%s on %s\n",
08763 tmpstr,tele,myrpt->txchannel->name);
08764 ast_call(myrpt->txchannel,tele,999);
08765 if (myrpt->rxchannel->_state != AST_STATE_UP)
08766 {
08767 rpt_mutex_unlock(&myrpt->lock);
08768 ast_hangup(myrpt->rxchannel);
08769 ast_hangup(myrpt->txchannel);
08770 myrpt->rpt_thread = AST_PTHREADT_STOP;
08771 pthread_exit(NULL);
08772 }
08773 }
08774 else
08775 {
08776 fprintf(stderr,"rpt:Sorry unable to obtain Tx channel\n");
08777 rpt_mutex_unlock(&myrpt->lock);
08778 ast_hangup(myrpt->rxchannel);
08779 myrpt->rpt_thread = AST_PTHREADT_STOP;
08780 pthread_exit(NULL);
08781 }
08782 }
08783 else
08784 {
08785 myrpt->txchannel = myrpt->rxchannel;
08786 }
08787 ast_indicate(myrpt->txchannel,AST_CONTROL_RADIO_KEY);
08788 ast_indicate(myrpt->txchannel,AST_CONTROL_RADIO_UNKEY);
08789
08790 myrpt->pchannel = ast_request("zap",AST_FORMAT_SLINEAR,"pseudo",NULL);
08791 if (!myrpt->pchannel)
08792 {
08793 fprintf(stderr,"rpt:Sorry unable to obtain pseudo channel\n");
08794 rpt_mutex_unlock(&myrpt->lock);
08795 if (myrpt->txchannel != myrpt->rxchannel)
08796 ast_hangup(myrpt->txchannel);
08797 ast_hangup(myrpt->rxchannel);
08798 myrpt->rpt_thread = AST_PTHREADT_STOP;
08799 pthread_exit(NULL);
08800 }
08801
08802 myrpt->monchannel = ast_request("zap",AST_FORMAT_SLINEAR,"pseudo",NULL);
08803 if (!myrpt->monchannel)
08804 {
08805 fprintf(stderr,"rpt:Sorry unable to obtain pseudo channel\n");
08806 rpt_mutex_unlock(&myrpt->lock);
08807 if (myrpt->txchannel != myrpt->rxchannel)
08808 ast_hangup(myrpt->txchannel);
08809 ast_hangup(myrpt->rxchannel);
08810 myrpt->rpt_thread = AST_PTHREADT_STOP;
08811 pthread_exit(NULL);
08812 }
08813 ast_set_read_format(myrpt->monchannel,AST_FORMAT_SLINEAR);
08814 ast_set_write_format(myrpt->monchannel,AST_FORMAT_SLINEAR);
08815
08816 ci.chan = 0;
08817 ci.confno = -1;
08818 ci.confmode = ZT_CONF_CONF | ZT_CONF_LISTENER;
08819
08820 if (ioctl(myrpt->txchannel->fds[0],ZT_SETCONF,&ci) == -1)
08821 {
08822 ast_log(LOG_WARNING, "Unable to set conference mode to Announce\n");
08823 rpt_mutex_unlock(&myrpt->lock);
08824 ast_hangup(myrpt->pchannel);
08825 ast_hangup(myrpt->monchannel);
08826 if (myrpt->txchannel != myrpt->rxchannel)
08827 ast_hangup(myrpt->txchannel);
08828 ast_hangup(myrpt->rxchannel);
08829 myrpt->rpt_thread = AST_PTHREADT_STOP;
08830 pthread_exit(NULL);
08831 }
08832
08833 myrpt->txconf = ci.confno;
08834
08835 ci.chan = 0;
08836 ci.confno = -1;
08837 ci.confmode = ((myrpt->p.duplex == 2) || (myrpt->p.duplex == 4)) ? ZT_CONF_CONFANNMON :
08838 (ZT_CONF_CONF | ZT_CONF_LISTENER | ZT_CONF_TALKER);
08839
08840 if (ioctl(myrpt->pchannel->fds[0],ZT_SETCONF,&ci) == -1)
08841 {
08842 ast_log(LOG_WARNING, "Unable to set conference mode to Announce\n");
08843 rpt_mutex_unlock(&myrpt->lock);
08844 ast_hangup(myrpt->pchannel);
08845 ast_hangup(myrpt->monchannel);
08846 if (myrpt->txchannel != myrpt->rxchannel)
08847 ast_hangup(myrpt->txchannel);
08848 ast_hangup(myrpt->rxchannel);
08849 myrpt->rpt_thread = AST_PTHREADT_STOP;
08850 pthread_exit(NULL);
08851 }
08852
08853 myrpt->conf = ci.confno;
08854
08855 ci.chan = 0;
08856 if (strstr(myrpt->txchannel->name,"pseudo") == NULL)
08857 {
08858
08859 if (ioctl(myrpt->txchannel->fds[0],ZT_CHANNO,&ci.confno) == -1)
08860 {
08861 ast_log(LOG_WARNING, "Unable to set tx channel's chan number\n");
08862 rpt_mutex_unlock(&myrpt->lock);
08863 ast_hangup(myrpt->pchannel);
08864 ast_hangup(myrpt->monchannel);
08865 if (myrpt->txchannel != myrpt->rxchannel)
08866 ast_hangup(myrpt->txchannel);
08867 ast_hangup(myrpt->rxchannel);
08868 myrpt->rpt_thread = AST_PTHREADT_STOP;
08869 pthread_exit(NULL);
08870 }
08871 ci.confmode = ZT_CONF_MONITORTX;
08872 }
08873 else
08874 {
08875 ci.confno = myrpt->txconf;
08876 ci.confmode = ZT_CONF_CONFANNMON;
08877 }
08878
08879 if (ioctl(myrpt->monchannel->fds[0],ZT_SETCONF,&ci) == -1)
08880 {
08881 ast_log(LOG_WARNING, "Unable to set conference mode for monitor\n");
08882 rpt_mutex_unlock(&myrpt->lock);
08883 ast_hangup(myrpt->pchannel);
08884 ast_hangup(myrpt->monchannel);
08885 if (myrpt->txchannel != myrpt->rxchannel)
08886 ast_hangup(myrpt->txchannel);
08887 ast_hangup(myrpt->rxchannel);
08888 myrpt->rpt_thread = AST_PTHREADT_STOP;
08889 pthread_exit(NULL);
08890 }
08891
08892 myrpt->txpchannel = ast_request("zap",AST_FORMAT_SLINEAR,"pseudo",NULL);
08893 if (!myrpt->txpchannel)
08894 {
08895 fprintf(stderr,"rpt:Sorry unable to obtain pseudo channel\n");
08896 rpt_mutex_unlock(&myrpt->lock);
08897 ast_hangup(myrpt->pchannel);
08898 ast_hangup(myrpt->monchannel);
08899 if (myrpt->txchannel != myrpt->rxchannel)
08900 ast_hangup(myrpt->txchannel);
08901 ast_hangup(myrpt->rxchannel);
08902 myrpt->rpt_thread = AST_PTHREADT_STOP;
08903 pthread_exit(NULL);
08904 }
08905
08906 ci.chan = 0;
08907 ci.confno = myrpt->txconf;
08908 ci.confmode = ZT_CONF_CONF | ZT_CONF_TALKER ;
08909
08910 if (ioctl(myrpt->txpchannel->fds[0],ZT_SETCONF,&ci) == -1)
08911 {
08912 ast_log(LOG_WARNING, "Unable to set conference mode to Announce\n");
08913 rpt_mutex_unlock(&myrpt->lock);
08914 ast_hangup(myrpt->txpchannel);
08915 ast_hangup(myrpt->monchannel);
08916 if (myrpt->txchannel != myrpt->rxchannel)
08917 ast_hangup(myrpt->txchannel);
08918 ast_hangup(myrpt->rxchannel);
08919 myrpt->rpt_thread = AST_PTHREADT_STOP;
08920 pthread_exit(NULL);
08921 }
08922
08923
08924
08925 myrpt->links.next = &myrpt->links;
08926 myrpt->links.prev = &myrpt->links;
08927 myrpt->tailtimer = 0;
08928 myrpt->totimer = 0;
08929 myrpt->tmsgtimer = myrpt->p.tailmessagetime;
08930 myrpt->idtimer = myrpt->p.politeid;
08931 myrpt->mustid = myrpt->tailid = 0;
08932 myrpt->callmode = 0;
08933 myrpt->tounkeyed = 0;
08934 myrpt->tonotify = 0;
08935 myrpt->retxtimer = 0;
08936 myrpt->rerxtimer = 0;
08937 myrpt->skedtimer = 0;
08938 myrpt->tailevent = 0;
08939 lasttx = 0;
08940 myrpt->keyed = 0;
08941 idtalkover = (char *) ast_variable_retrieve(myrpt->cfg, myrpt->name, "idtalkover");
08942 myrpt->dtmfidx = -1;
08943 myrpt->dtmfbuf[0] = 0;
08944 myrpt->rem_dtmfidx = -1;
08945 myrpt->rem_dtmfbuf[0] = 0;
08946 myrpt->dtmf_time = 0;
08947 myrpt->rem_dtmf_time = 0;
08948 myrpt->disgorgetime = 0;
08949 myrpt->lastnodewhichkeyedusup[0] = '\0';
08950 myrpt->dailytxtime = 0;
08951 myrpt->totaltxtime = 0;
08952 myrpt->dailykeyups = 0;
08953 myrpt->totalkeyups = 0;
08954 myrpt->dailykerchunks = 0;
08955 myrpt->totalkerchunks = 0;
08956 myrpt->dailyexecdcommands = 0;
08957 myrpt->totalexecdcommands = 0;
08958 myrpt->timeouts = 0;
08959 myrpt->exten[0] = '\0';
08960 myrpt->lastdtmfcommand[0] = '\0';
08961 if (myrpt->p.startupmacro)
08962 {
08963 snprintf(myrpt->macrobuf,MAXMACRO - 1,"PPPP%s",myrpt->p.startupmacro);
08964 }
08965 rpt_mutex_unlock(&myrpt->lock);
08966 val = 1;
08967 ast_channel_setoption(myrpt->rxchannel,AST_OPTION_RELAXDTMF,&val,sizeof(char),0);
08968 val = 1;
08969 ast_channel_setoption(myrpt->rxchannel,AST_OPTION_TONE_VERIFY,&val,sizeof(char),0);
08970 if (myrpt->p.archivedir) donodelog(myrpt,"STARTUP");
08971 dtmfed = 0;
08972 while (ms >= 0)
08973 {
08974 struct ast_frame *f,*f1,*f2;
08975 struct ast_channel *cs[300],*cs1[300];
08976 int totx=0,elap=0,n,x,toexit=0;
08977
08978
08979 if((myrpt->disgorgetime) && (time(NULL) >= myrpt->disgorgetime)){
08980 struct rpt_link *zl;
08981 struct rpt_tele *zt;
08982
08983 myrpt->disgorgetime = 0;
08984 ast_log(LOG_NOTICE,"********** Variable Dump Start (app_rpt) **********\n");
08985 ast_log(LOG_NOTICE,"totx = %d\n",totx);
08986 ast_log(LOG_NOTICE,"remrx = %d\n",remrx);
08987 ast_log(LOG_NOTICE,"lasttx = %d\n",lasttx);
08988 ast_log(LOG_NOTICE,"elap = %d\n",elap);
08989 ast_log(LOG_NOTICE,"toexit = %d\n",toexit);
08990
08991 ast_log(LOG_NOTICE,"myrpt->keyed = %d\n",myrpt->keyed);
08992 ast_log(LOG_NOTICE,"myrpt->localtx = %d\n",myrpt->localtx);
08993 ast_log(LOG_NOTICE,"myrpt->callmode = %d\n",myrpt->callmode);
08994 ast_log(LOG_NOTICE,"myrpt->mustid = %d\n",myrpt->mustid);
08995 ast_log(LOG_NOTICE,"myrpt->tounkeyed = %d\n",myrpt->tounkeyed);
08996 ast_log(LOG_NOTICE,"myrpt->tonotify = %d\n",myrpt->tonotify);
08997 ast_log(LOG_NOTICE,"myrpt->retxtimer = %ld\n",myrpt->retxtimer);
08998 ast_log(LOG_NOTICE,"myrpt->totimer = %d\n",myrpt->totimer);
08999 ast_log(LOG_NOTICE,"myrpt->tailtimer = %d\n",myrpt->tailtimer);
09000 ast_log(LOG_NOTICE,"myrpt->tailevent = %d\n",myrpt->tailevent);
09001
09002 zl = myrpt->links.next;
09003 while(zl != &myrpt->links){
09004 ast_log(LOG_NOTICE,"*** Link Name: %s ***\n",zl->name);
09005 ast_log(LOG_NOTICE," link->lasttx %d\n",zl->lasttx);
09006 ast_log(LOG_NOTICE," link->lastrx %d\n",zl->lastrx);
09007 ast_log(LOG_NOTICE," link->connected %d\n",zl->connected);
09008 ast_log(LOG_NOTICE," link->hasconnected %d\n",zl->hasconnected);
09009 ast_log(LOG_NOTICE," link->outbound %d\n",zl->outbound);
09010 ast_log(LOG_NOTICE," link->disced %d\n",zl->disced);
09011 ast_log(LOG_NOTICE," link->killme %d\n",zl->killme);
09012 ast_log(LOG_NOTICE," link->disctime %ld\n",zl->disctime);
09013 ast_log(LOG_NOTICE," link->retrytimer %ld\n",zl->retrytimer);
09014 ast_log(LOG_NOTICE," link->retries = %d\n",zl->retries);
09015 ast_log(LOG_NOTICE," link->reconnects = %d\n",zl->reconnects);
09016 zl = zl->next;
09017 }
09018
09019 zt = myrpt->tele.next;
09020 if(zt != &myrpt->tele)
09021 ast_log(LOG_NOTICE,"*** Telemetry Queue ***\n");
09022 while(zt != &myrpt->tele){
09023 ast_log(LOG_NOTICE," Telemetry mode: %d\n",zt->mode);
09024 zt = zt->next;
09025 }
09026 ast_log(LOG_NOTICE,"******* Variable Dump End (app_rpt) *******\n");
09027
09028 }
09029
09030
09031 if (myrpt->reload)
09032 {
09033 struct rpt_tele *telem;
09034
09035 rpt_mutex_lock(&myrpt->lock);
09036 telem = myrpt->tele.next;
09037 while(telem != &myrpt->tele)
09038 {
09039 ast_softhangup(telem->chan,AST_SOFTHANGUP_DEV);
09040 telem = telem->next;
09041 }
09042 myrpt->reload = 0;
09043 rpt_mutex_unlock(&myrpt->lock);
09044 usleep(10000);
09045
09046 for(i = 0; i < nrpts; i++)
09047 {
09048 if (&rpt_vars[i] == myrpt)
09049 {
09050 load_rpt_vars(i,0);
09051 break;
09052 }
09053 }
09054 }
09055
09056 rpt_mutex_lock(&myrpt->lock);
09057 if (ast_check_hangup(myrpt->rxchannel)) break;
09058 if (ast_check_hangup(myrpt->txchannel)) break;
09059 if (ast_check_hangup(myrpt->pchannel)) break;
09060 if (ast_check_hangup(myrpt->monchannel)) break;
09061 if (ast_check_hangup(myrpt->txpchannel)) break;
09062
09063
09064 myrpt->localtx = myrpt->keyed;
09065
09066 l = myrpt->links.next;
09067 remrx = 0;
09068 while(l != &myrpt->links)
09069 {
09070 if (l->lastrx){
09071 remrx = 1;
09072 if(l->name[0] != '0')
09073 strcpy(myrpt->lastnodewhichkeyedusup, l->name);
09074 }
09075 l = l->next;
09076 }
09077
09078 if(myrpt->p.idtime)
09079 myrpt->mustid |= (myrpt->idtimer) && (myrpt->keyed || remrx) ;
09080
09081 totx = myrpt->callmode;
09082
09083 if (myrpt->p.duplex > 1)
09084 {
09085 totx = totx || myrpt->localtx;
09086 }
09087
09088 identqueued = 0;
09089 othertelemqueued = 0;
09090 tailmessagequeued = 0;
09091 ctqueued = 0;
09092 telem = myrpt->tele.next;
09093 while(telem != &myrpt->tele)
09094 {
09095 if((telem->mode == ID) || (telem->mode == IDTALKOVER)){
09096 identqueued = 1;
09097 }
09098 else if(telem->mode == TAILMSG)
09099 {
09100 tailmessagequeued = 1;
09101 }
09102 else
09103 {
09104 if ((telem->mode != UNKEY) && (telem->mode != LINKUNKEY))
09105 othertelemqueued = 1;
09106 else
09107 ctqueued = 1;
09108 }
09109 telem = telem->next;
09110 }
09111
09112
09113 if (!myrpt->p.notelemtx) totx = totx || othertelemqueued;
09114
09115 myrpt->exttx = totx;
09116 totx = totx || myrpt->dtmf_local_timer;
09117
09118 if (myrpt->p.duplex < 2) myrpt->exttx = myrpt->exttx || myrpt->localtx;
09119
09120 totx = totx || remrx;
09121
09122 if (myrpt->p.duplex > 0)
09123 totx = totx || identqueued || ctqueued;
09124
09125 if (myrpt->p.duplex > 1)
09126 {
09127 totx = totx || (myrpt->dtmfidx > -1) ||
09128 myrpt->cmdnode[0];
09129 }
09130
09131 if (!totx)
09132 {
09133 myrpt->totimer = myrpt->p.totime;
09134 myrpt->tounkeyed = 0;
09135 myrpt->tonotify = 0;
09136 }
09137 else{
09138 myrpt->tailtimer = myrpt->p.s[myrpt->p.sysstate_cur].alternatetail ?
09139 myrpt->p.althangtime :
09140 myrpt->p.hangtime;
09141 }
09142
09143 totx = totx && myrpt->totimer;
09144
09145 if ((!myrpt->totimer) && (!myrpt->tonotify))
09146 {
09147 myrpt->tonotify = 1;
09148 myrpt->timeouts++;
09149 rpt_mutex_unlock(&myrpt->lock);
09150 rpt_telemetry(myrpt,TIMEOUT,NULL);
09151 rpt_mutex_lock(&myrpt->lock);
09152 }
09153
09154
09155 if ((!totx) && (!myrpt->totimer) && (!myrpt->tounkeyed) && (!myrpt->keyed))
09156 {
09157 myrpt->tounkeyed = 1;
09158 }
09159 if ((!totx) && (!myrpt->totimer) && myrpt->tounkeyed && myrpt->keyed)
09160 {
09161 myrpt->totimer = myrpt->p.totime;
09162 myrpt->tounkeyed = 0;
09163 myrpt->tonotify = 0;
09164 rpt_mutex_unlock(&myrpt->lock);
09165 continue;
09166 }
09167
09168 if ((!totx) && (!myrpt->totimer) && (myrpt->callmode == 4))
09169 {
09170 myrpt->callmode = 0;
09171 }
09172
09173 if (!myrpt->totimer) myrpt->tailtimer = 0;
09174
09175 if (myrpt->totimer) totx = totx || myrpt->tailtimer;
09176
09177
09178 if ((myrpt->keyed || remrx) && ((identqueued && idtalkover) || (tailmessagequeued))) {
09179 int hasid = 0,hastalkover = 0;
09180
09181 telem = myrpt->tele.next;
09182 while(telem != &myrpt->tele){
09183 if(telem->mode == ID){
09184 if (telem->chan) ast_softhangup(telem->chan, AST_SOFTHANGUP_DEV);
09185 hasid = 1;
09186 }
09187 if(telem->mode == TAILMSG){
09188 if (telem->chan) ast_softhangup(telem->chan, AST_SOFTHANGUP_DEV);
09189 }
09190 if (telem->mode == IDTALKOVER) hastalkover = 1;
09191 telem = telem->next;
09192 }
09193 rpt_mutex_unlock(&myrpt->lock);
09194 if (hasid && (!hastalkover)) rpt_telemetry(myrpt, IDTALKOVER, NULL);
09195 rpt_mutex_lock(&myrpt->lock);
09196 }
09197
09198
09199
09200
09201
09202 if(myrpt->mustid && (!myrpt->idtimer))
09203 queue_id(myrpt);
09204
09205 if ((myrpt->p.idtime && totx && (!myrpt->exttx) &&
09206 (myrpt->idtimer <= myrpt->p.politeid) && myrpt->tailtimer))
09207 {
09208 myrpt->tailid = 1;
09209 }
09210
09211
09212
09213 if(myrpt->tailevent){
09214 myrpt->tailevent = 0;
09215 if(myrpt->tailid){
09216 totx = 1;
09217 queue_id(myrpt);
09218 }
09219 else if ((myrpt->p.tailmessages[0]) &&
09220 (myrpt->p.tailmessagetime) && (myrpt->tmsgtimer == 0)){
09221 totx = 1;
09222 myrpt->tmsgtimer = myrpt->p.tailmessagetime;
09223 rpt_mutex_unlock(&myrpt->lock);
09224 rpt_telemetry(myrpt, TAILMSG, NULL);
09225 rpt_mutex_lock(&myrpt->lock);
09226 }
09227 }
09228
09229
09230
09231
09232 if (myrpt->p.duplex > 0) totx = totx || (myrpt->tele.next != &myrpt->tele);
09233 if (totx && (!lasttx))
09234 {
09235 char mydate[100],myfname[100];
09236 time_t myt;
09237
09238 if (myrpt->monstream) ast_closestream(myrpt->monstream);
09239 if (myrpt->p.archivedir)
09240 {
09241 long blocksleft;
09242
09243 time(&myt);
09244 strftime(mydate,sizeof(mydate) - 1,"%Y%m%d%H%M%S",
09245 localtime(&myt));
09246 sprintf(myfname,"%s/%s/%s",myrpt->p.archivedir,
09247 myrpt->name,mydate);
09248 myrpt->monstream = ast_writefile(myfname,"wav49",
09249 "app_rpt Air Archive",O_CREAT | O_APPEND,0,0600);
09250 if (myrpt->p.monminblocks)
09251 {
09252 blocksleft = diskavail(myrpt);
09253 if (blocksleft >= myrpt->p.monminblocks)
09254 donodelog(myrpt,"TXKEY,MAIN");
09255 } else donodelog(myrpt,"TXKEY,MAIN");
09256 }
09257 lasttx = 1;
09258 myrpt->dailykeyups++;
09259 myrpt->totalkeyups++;
09260 rpt_mutex_unlock(&myrpt->lock);
09261 ast_indicate(myrpt->txchannel,AST_CONTROL_RADIO_KEY);
09262 rpt_mutex_lock(&myrpt->lock);
09263 }
09264 totx = totx && !myrpt->p.s[myrpt->p.sysstate_cur].txdisable;
09265 if ((!totx) && lasttx)
09266 {
09267 if (myrpt->monstream) ast_closestream(myrpt->monstream);
09268 myrpt->monstream = NULL;
09269
09270 lasttx = 0;
09271 rpt_mutex_unlock(&myrpt->lock);
09272 ast_indicate(myrpt->txchannel,AST_CONTROL_RADIO_UNKEY);
09273 rpt_mutex_lock(&myrpt->lock);
09274 donodelog(myrpt,"TXUNKEY,MAIN");
09275 }
09276 time(&t);
09277
09278 if ((!myrpt->cmdnode[0]) && (myrpt->dtmfidx >= 0) && ((myrpt->dtmf_time + DTMF_TIMEOUT) < t))
09279 {
09280 myrpt->dtmfidx = -1;
09281 myrpt->dtmfbuf[0] = 0;
09282 }
09283
09284 if ((myrpt->rem_dtmfidx >= 0) && ((myrpt->rem_dtmf_time + DTMF_TIMEOUT) < t))
09285 {
09286 myrpt->rem_dtmfidx = -1;
09287 myrpt->rem_dtmfbuf[0] = 0;
09288 }
09289
09290
09291
09292 l = myrpt->links.next;
09293 while(l != &myrpt->links)
09294 {
09295 if (l->killme)
09296 {
09297
09298 remque((struct qelem *) l);
09299 if (!strcmp(myrpt->cmdnode,l->name))
09300 myrpt->cmdnode[0] = 0;
09301 rpt_mutex_unlock(&myrpt->lock);
09302
09303 if (l->chan) ast_hangup(l->chan);
09304 ast_hangup(l->pchan);
09305 free(l);
09306 rpt_mutex_lock(&myrpt->lock);
09307
09308 l = myrpt->links.next;
09309 continue;
09310 }
09311 l = l->next;
09312 }
09313 n = 0;
09314 cs[n++] = myrpt->rxchannel;
09315 cs[n++] = myrpt->pchannel;
09316 cs[n++] = myrpt->monchannel;
09317 cs[n++] = myrpt->txpchannel;
09318 if (myrpt->txchannel != myrpt->rxchannel) cs[n++] = myrpt->txchannel;
09319 l = myrpt->links.next;
09320 while(l != &myrpt->links)
09321 {
09322 if ((!l->killme) && (!l->disctime) && l->chan)
09323 {
09324 cs[n++] = l->chan;
09325 cs[n++] = l->pchan;
09326 }
09327 l = l->next;
09328 }
09329 rpt_mutex_unlock(&myrpt->lock);
09330 ms = MSWAIT;
09331 for(x = 0; x < n; x++)
09332 {
09333 int s = -(-x - myrpt->scram - 1) % n;
09334 cs1[x] = cs[s];
09335 }
09336 myrpt->scram++;
09337 who = ast_waitfor_n(cs1,n,&ms);
09338 if (who == NULL) ms = 0;
09339 elap = MSWAIT - ms;
09340 rpt_mutex_lock(&myrpt->lock);
09341 l = myrpt->links.next;
09342 while(l != &myrpt->links)
09343 {
09344 if (l->linklisttimer)
09345 {
09346 l->linklisttimer -= elap;
09347 if (l->linklisttimer < 0) l->linklisttimer = 0;
09348 }
09349 if ((!l->linklisttimer) && (l->name[0] != '0') && (!l->isremote))
09350 {
09351 struct ast_frame lf;
09352
09353 memset(&lf,0,sizeof(lf));
09354 lf.frametype = AST_FRAME_TEXT;
09355 lf.subclass = 0;
09356 lf.offset = 0;
09357 lf.mallocd = 0;
09358 lf.samples = 0;
09359 l->linklisttimer = LINKLISTTIME;
09360 strcpy(lstr,"L ");
09361 __mklinklist(myrpt,l,lstr + 2);
09362 if (l->chan)
09363 {
09364 lf.datalen = strlen(lstr) + 1;
09365 lf.data = lstr;
09366 ast_write(l->chan,&lf);
09367 if (debug > 6) ast_log(LOG_NOTICE,
09368 "@@@@ node %s sent node string %s to node %s\n",
09369 myrpt->name,lstr,l->name);
09370 }
09371 }
09372 #ifndef OLDKEY
09373 if ((l->retxtimer += elap) >= REDUNDANT_TX_TIME)
09374 {
09375 l->retxtimer = 0;
09376 if (l->chan && l->phonemode == 0)
09377 {
09378 if (l->lasttx)
09379 ast_indicate(l->chan,AST_CONTROL_RADIO_KEY);
09380 else
09381 ast_indicate(l->chan,AST_CONTROL_RADIO_UNKEY);
09382 }
09383 }
09384 if ((l->rerxtimer += elap) >= (REDUNDANT_TX_TIME * 5))
09385 {
09386 if (debug == 7) printf("@@@@ rx un-key\n");
09387 l->lastrx = 0;
09388 l->rerxtimer = 0;
09389 if(myrpt->p.duplex)
09390 rpt_telemetry(myrpt,LINKUNKEY,l);
09391 if (myrpt->p.archivedir)
09392 {
09393 char str[100];
09394
09395 l->lastrx1 = 0;
09396 sprintf(str,"RXUNKEY(T),%s",l->name);
09397 donodelog(myrpt,str);
09398 }
09399 }
09400 #endif
09401 if (l->disctime)
09402 {
09403 l->disctime -= elap;
09404 if (l->disctime <= 0)
09405 l->disctime = 0;
09406 }
09407
09408 if (l->retrytimer)
09409 {
09410 l->retrytimer -= elap;
09411 if (l->retrytimer < 0) l->retrytimer = 0;
09412 }
09413
09414
09415 l->connecttime += elap;
09416
09417
09418 if (l->elaptime < 0)
09419 {
09420 l = l->next;
09421 continue;
09422 }
09423 l->elaptime += elap;
09424
09425 if ((l->elaptime > MAXCONNECTTIME) &&
09426 ((!l->chan) || (l->chan->_state != AST_STATE_UP)))
09427 {
09428 l->elaptime = 0;
09429 rpt_mutex_unlock(&myrpt->lock);
09430 if (l->chan) ast_softhangup(l->chan,AST_SOFTHANGUP_DEV);
09431 rpt_mutex_lock(&myrpt->lock);
09432 break;
09433 }
09434 if ((!l->chan) && (!l->retrytimer) && l->outbound &&
09435 (l->retries++ < l->max_retries) && (l->hasconnected))
09436 {
09437 if (l->chan) ast_hangup(l->chan);
09438 l->chan = 0;
09439 rpt_mutex_unlock(&myrpt->lock);
09440 if ((l->name[0] != '0') && (!l->isremote))
09441 {
09442 if (attempt_reconnect(myrpt,l) == -1)
09443 {
09444 l->retrytimer = RETRY_TIMER_MS;
09445 }
09446 }
09447 else
09448 {
09449 l->retrytimer = l->max_retries + 1;
09450 }
09451
09452 rpt_mutex_lock(&myrpt->lock);
09453 break;
09454 }
09455 if ((!l->chan) && (!l->retrytimer) && l->outbound &&
09456 (l->retries >= l->max_retries))
09457 {
09458
09459 remque((struct qelem *) l);
09460 if (!strcmp(myrpt->cmdnode,l->name))
09461 myrpt->cmdnode[0] = 0;
09462 rpt_mutex_unlock(&myrpt->lock);
09463 if (l->name[0] != '0')
09464 {
09465 if (!l->hasconnected)
09466 rpt_telemetry(myrpt,CONNFAIL,l);
09467 else rpt_telemetry(myrpt,REMDISC,l);
09468 }
09469 if (myrpt->p.archivedir)
09470 {
09471 char str[100];
09472
09473 if (!l->hasconnected)
09474 sprintf(str,"LINKFAIL,%s",l->name);
09475 else
09476 sprintf(str,"LINKDISC,%s",l->name);
09477 donodelog(myrpt,str);
09478 }
09479
09480 ast_hangup(l->pchan);
09481 free(l);
09482 rpt_mutex_lock(&myrpt->lock);
09483 break;
09484 }
09485 if ((!l->chan) && (!l->disctime) && (!l->outbound))
09486 {
09487
09488 remque((struct qelem *) l);
09489 if (!strcmp(myrpt->cmdnode,l->name))
09490 myrpt->cmdnode[0] = 0;
09491 rpt_mutex_unlock(&myrpt->lock);
09492 if (l->name[0] != '0')
09493 {
09494 rpt_telemetry(myrpt,REMDISC,l);
09495 }
09496 if (myrpt->p.archivedir)
09497 {
09498 char str[100];
09499
09500 sprintf(str,"LINKDISC,%s",l->name);
09501 donodelog(myrpt,str);
09502 }
09503
09504 ast_hangup(l->pchan);
09505 free(l);
09506 rpt_mutex_lock(&myrpt->lock);
09507 break;
09508 }
09509 l = l->next;
09510 }
09511 if(totx){
09512 myrpt->dailytxtime += elap;
09513 myrpt->totaltxtime += elap;
09514 }
09515 i = myrpt->tailtimer;
09516 if (myrpt->tailtimer) myrpt->tailtimer -= elap;
09517 if (myrpt->tailtimer < 0) myrpt->tailtimer = 0;
09518 if((i) && (myrpt->tailtimer == 0))
09519 myrpt->tailevent = 1;
09520 if ((!myrpt->p.s[myrpt->p.sysstate_cur].totdisable) && myrpt->totimer) myrpt->totimer -= elap;
09521 if (myrpt->totimer < 0) myrpt->totimer = 0;
09522 if (myrpt->idtimer) myrpt->idtimer -= elap;
09523 if (myrpt->idtimer < 0) myrpt->idtimer = 0;
09524 if (myrpt->tmsgtimer) myrpt->tmsgtimer -= elap;
09525 if (myrpt->tmsgtimer < 0) myrpt->tmsgtimer = 0;
09526
09527 if (myrpt->macrotimer) myrpt->macrotimer -= elap;
09528 if (myrpt->macrotimer < 0) myrpt->macrotimer = 0;
09529
09530 if (myrpt->dtmf_local_timer)
09531 {
09532 if (myrpt->dtmf_local_timer > 1) myrpt->dtmf_local_timer -= elap;
09533 if (myrpt->dtmf_local_timer < 1) myrpt->dtmf_local_timer = 1;
09534 }
09535 do_dtmf_local(myrpt,0);
09536
09537 if (myrpt->skedtimer <= 0){
09538 myrpt->skedtimer = 200;
09539 do_scheduler(myrpt);
09540 }
09541 else
09542 myrpt->skedtimer -=elap;
09543 if (!ms)
09544 {
09545 rpt_mutex_unlock(&myrpt->lock);
09546 continue;
09547 }
09548 c = myrpt->macrobuf[0];
09549 time(&t);
09550 if (c && (!myrpt->macrotimer) &&
09551 starttime && (t > (starttime + START_DELAY)))
09552 {
09553 myrpt->macrotimer = MACROTIME;
09554 memmove(myrpt->macrobuf,myrpt->macrobuf + 1,MAXMACRO - 1);
09555 if ((c == 'p') || (c == 'P'))
09556 myrpt->macrotimer = MACROPTIME;
09557 rpt_mutex_unlock(&myrpt->lock);
09558 if (myrpt->p.archivedir)
09559 {
09560 char str[100];
09561
09562 sprintf(str,"DTMF(M),MAIN,%c",c);
09563 donodelog(myrpt,str);
09564 }
09565 local_dtmf_helper(myrpt,c);
09566 } else rpt_mutex_unlock(&myrpt->lock);
09567 if (who == myrpt->rxchannel)
09568 {
09569 int ismuted;
09570
09571 f = ast_read(myrpt->rxchannel);
09572 if (!f)
09573 {
09574 if (debug) printf("@@@@ rpt:Hung Up\n");
09575 break;
09576 }
09577 if (f->frametype == AST_FRAME_VOICE)
09578 {
09579 #ifdef _MDC_DECODE_H_
09580 unsigned char ubuf[2560];
09581 short *sp;
09582 int n;
09583 #endif
09584
09585 if ((!myrpt->localtx) && (!myrpt->p.linktolink)) {
09586 memset(f->data,0,f->datalen);
09587 }
09588
09589 #ifdef _MDC_DECODE_H_
09590 sp = (short *) f->data;
09591
09592 for(n = 0; n < f->datalen / 2; n++)
09593 {
09594 ubuf[n] = (*sp++ >> 8) + 128;
09595 }
09596 n = mdc_decoder_process_samples(myrpt->mdc,ubuf,f->datalen / 2);
09597 if (n == 1)
09598 {
09599 unsigned char op,arg;
09600 unsigned short unitID;
09601
09602 mdc_decoder_get_packet(myrpt->mdc,&op,&arg,&unitID);
09603 if (debug > 2)
09604 {
09605 ast_log(LOG_NOTICE,"Got (single-length) packet:\n");
09606 ast_log(LOG_NOTICE,"op: %02x, arg: %02x, UnitID: %04x\n",
09607 op & 255,arg & 255,unitID);
09608 }
09609 if ((op == 1) && (arg == 0))
09610 {
09611 myrpt->lastunit = unitID;
09612 }
09613 }
09614 if ((debug > 2) && (i == 2))
09615 {
09616 unsigned char op,arg,ex1,ex2,ex3,ex4;
09617 unsigned short unitID;
09618
09619 mdc_decoder_get_double_packet(myrpt->mdc,&op,&arg,&unitID,
09620 &ex1,&ex2,&ex3,&ex4);
09621 ast_log(LOG_NOTICE,"Got (double-length) packet:\n");
09622 ast_log(LOG_NOTICE,"op: %02x, arg: %02x, UnitID: %04x\n",
09623 op & 255,arg & 255,unitID);
09624 ast_log(LOG_NOTICE,"ex1: %02x, ex2: %02x, ex3: %02x, ex4: %02x\n",
09625 ex1 & 255, ex2 & 255, ex3 & 255, ex4 & 255);
09626 }
09627 #endif
09628 #ifdef __RPT_NOTCH
09629
09630 rpt_filter(myrpt,f->data,f->datalen / 2);
09631 #endif
09632 if (ioctl(myrpt->rxchannel->fds[0], ZT_GETCONFMUTE, &ismuted) == -1)
09633 {
09634 ismuted = 0;
09635 }
09636 if (dtmfed) ismuted = 1;
09637 dtmfed = 0;
09638 if (ismuted)
09639 {
09640 memset(f->data,0,f->datalen);
09641 if (myrpt->lastf1)
09642 memset(myrpt->lastf1->data,0,myrpt->lastf1->datalen);
09643 if (myrpt->lastf2)
09644 memset(myrpt->lastf2->data,0,myrpt->lastf2->datalen);
09645 }
09646 if (f) f2 = ast_frdup(f);
09647 else f2 = NULL;
09648 f1 = myrpt->lastf2;
09649 myrpt->lastf2 = myrpt->lastf1;
09650 myrpt->lastf1 = f2;
09651 if (ismuted)
09652 {
09653 if (myrpt->lastf1)
09654 memset(myrpt->lastf1->data,0,myrpt->lastf1->datalen);
09655 if (myrpt->lastf2)
09656 memset(myrpt->lastf2->data,0,myrpt->lastf2->datalen);
09657 }
09658 if (f1)
09659 {
09660 ast_write(myrpt->pchannel,f1);
09661 ast_frfree(f1);
09662 }
09663 }
09664 #ifndef OLD_ASTERISK
09665 else if (f->frametype == AST_FRAME_DTMF_BEGIN)
09666 {
09667 if (myrpt->lastf1)
09668 memset(myrpt->lastf1->data,0,myrpt->lastf1->datalen);
09669 if (myrpt->lastf2)
09670 memset(myrpt->lastf2->data,0,myrpt->lastf2->datalen);
09671 dtmfed = 1;
09672 }
09673 #endif
09674 else if (f->frametype == AST_FRAME_DTMF)
09675 {
09676 c = (char) f->subclass;
09677 ast_frfree(f);
09678 if (myrpt->lastf1)
09679 memset(myrpt->lastf1->data,0,myrpt->lastf1->datalen);
09680 if (myrpt->lastf2)
09681 memset(myrpt->lastf2->data,0,myrpt->lastf2->datalen);
09682 dtmfed = 1;
09683 if (!myrpt->keyed) continue;
09684 c = func_xlat(myrpt,c,&myrpt->p.inxlat);
09685 if (c) local_dtmf_helper(myrpt,c);
09686 continue;
09687 }
09688 else if (f->frametype == AST_FRAME_CONTROL)
09689 {
09690 if (f->subclass == AST_CONTROL_HANGUP)
09691 {
09692 if (debug) printf("@@@@ rpt:Hung Up\n");
09693 ast_frfree(f);
09694 break;
09695 }
09696
09697 if (f->subclass == AST_CONTROL_RADIO_KEY)
09698 {
09699 if ((!lasttx) || (myrpt->p.duplex > 1) || (myrpt->p.linktolink))
09700 {
09701 if (debug == 7) printf("@@@@ rx key\n");
09702 myrpt->keyed = 1;
09703 }
09704 if (myrpt->p.archivedir)
09705 {
09706 donodelog(myrpt,"RXKEY,MAIN");
09707 }
09708 }
09709
09710 if (f->subclass == AST_CONTROL_RADIO_UNKEY)
09711 {
09712 if ((!lasttx) || (myrpt->p.duplex > 1) || (myrpt->p.linktolink))
09713 {
09714 if (debug == 7) printf("@@@@ rx un-key\n");
09715 if(myrpt->p.duplex && myrpt->keyed) {
09716 rpt_telemetry(myrpt,UNKEY,NULL);
09717 }
09718 }
09719 myrpt->keyed = 0;
09720 if (myrpt->p.archivedir)
09721 {
09722 donodelog(myrpt,"RXUNKEY,MAIN");
09723 }
09724 }
09725 }
09726 ast_frfree(f);
09727 continue;
09728 }
09729 if (who == myrpt->pchannel)
09730 {
09731 f = ast_read(myrpt->pchannel);
09732 if (!f)
09733 {
09734 if (debug) printf("@@@@ rpt:Hung Up\n");
09735 break;
09736 }
09737 if (f->frametype == AST_FRAME_VOICE)
09738 {
09739 ast_write(myrpt->txpchannel,f);
09740 }
09741 if (f->frametype == AST_FRAME_CONTROL)
09742 {
09743 if (f->subclass == AST_CONTROL_HANGUP)
09744 {
09745 if (debug) printf("@@@@ rpt:Hung Up\n");
09746 ast_frfree(f);
09747 break;
09748 }
09749 }
09750 ast_frfree(f);
09751 continue;
09752 }
09753 if (who == myrpt->txchannel)
09754 {
09755 f = ast_read(myrpt->txchannel);
09756 if (!f)
09757 {
09758 if (debug) printf("@@@@ rpt:Hung Up\n");
09759 break;
09760 }
09761 if (f->frametype == AST_FRAME_CONTROL)
09762 {
09763 if (f->subclass == AST_CONTROL_HANGUP)
09764 {
09765 if (debug) printf("@@@@ rpt:Hung Up\n");
09766 ast_frfree(f);
09767 break;
09768 }
09769 }
09770 ast_frfree(f);
09771 continue;
09772 }
09773 toexit = 0;
09774 rpt_mutex_lock(&myrpt->lock);
09775 l = myrpt->links.next;
09776 while(l != &myrpt->links)
09777 {
09778 if (l->disctime)
09779 {
09780 l = l->next;
09781 continue;
09782 }
09783 if (who == l->chan)
09784 {
09785 int remnomute;
09786
09787 remrx = 0;
09788
09789 m = myrpt->links.next;
09790 while(m != &myrpt->links)
09791 {
09792
09793 if ((m != l) && (m->lastrx)) remrx = 1;
09794 m = m->next;
09795 }
09796 rpt_mutex_unlock(&myrpt->lock);
09797 remnomute = myrpt->localtx &&
09798 (!(myrpt->cmdnode[0] ||
09799 (myrpt->dtmfidx > -1)));
09800 totx = (((l->isremote) ? (remnomute) :
09801 myrpt->exttx) || remrx) && l->mode;
09802 if (l->phonemode == 0 && l->chan && (l->lasttx != totx))
09803 {
09804 if (totx)
09805 {
09806 ast_indicate(l->chan,AST_CONTROL_RADIO_KEY);
09807 }
09808 else
09809 {
09810 ast_indicate(l->chan,AST_CONTROL_RADIO_UNKEY);
09811 }
09812 if (myrpt->p.archivedir)
09813 {
09814 char str[100];
09815
09816 if (totx)
09817 sprintf(str,"TXKEY,%s",l->name);
09818 else
09819 sprintf(str,"TXUNKEY,%s",l->name);
09820 donodelog(myrpt,str);
09821 }
09822 }
09823 l->lasttx = totx;
09824 f = ast_read(l->chan);
09825 if (!f)
09826 {
09827 rpt_mutex_lock(&myrpt->lock);
09828 __kickshort(myrpt);
09829 rpt_mutex_unlock(&myrpt->lock);
09830 if ((!l->disced) && (!l->outbound))
09831 {
09832 if ((l->name[0] == '0') || l->isremote)
09833 l->disctime = 1;
09834 else
09835 l->disctime = DISC_TIME;
09836 rpt_mutex_lock(&myrpt->lock);
09837 ast_hangup(l->chan);
09838 l->chan = 0;
09839 break;
09840 }
09841
09842 if (l->retrytimer)
09843 {
09844 ast_hangup(l->chan);
09845 l->chan = 0;
09846 rpt_mutex_lock(&myrpt->lock);
09847 break;
09848 }
09849 if (l->outbound && (l->retries++ < l->max_retries) && (l->hasconnected))
09850 {
09851 rpt_mutex_lock(&myrpt->lock);
09852 if (l->chan) ast_hangup(l->chan);
09853 l->chan = 0;
09854 l->hasconnected = 1;
09855 l->retrytimer = RETRY_TIMER_MS;
09856 l->elaptime = 0;
09857 l->connecttime = 0;
09858 l->thisconnected = 0;
09859 break;
09860 }
09861 rpt_mutex_lock(&myrpt->lock);
09862
09863 remque((struct qelem *) l);
09864 if (!strcmp(myrpt->cmdnode,l->name))
09865 myrpt->cmdnode[0] = 0;
09866 __kickshort(myrpt);
09867 rpt_mutex_unlock(&myrpt->lock);
09868 if (!l->hasconnected)
09869 rpt_telemetry(myrpt,CONNFAIL,l);
09870 else if (l->disced != 2) rpt_telemetry(myrpt,REMDISC,l);
09871 if (myrpt->p.archivedir)
09872 {
09873 char str[100];
09874
09875 if (!l->hasconnected)
09876 sprintf(str,"LINKFAIL,%s",l->name);
09877 else
09878 sprintf(str,"LINKDISC,%s",l->name);
09879 donodelog(myrpt,str);
09880 }
09881 if (l->lastf1) ast_frfree(l->lastf1);
09882 l->lastf1 = NULL;
09883 if (l->lastf2) ast_frfree(l->lastf2);
09884 l->lastf2 = NULL;
09885
09886 ast_hangup(l->chan);
09887 ast_hangup(l->pchan);
09888 free(l);
09889 rpt_mutex_lock(&myrpt->lock);
09890 break;
09891 }
09892 if (f->frametype == AST_FRAME_VOICE)
09893 {
09894 int ismuted;
09895
09896 if (l->phonemode)
09897 {
09898 if (ioctl(l->chan->fds[0], ZT_GETCONFMUTE, &ismuted) == -1)
09899 {
09900 ismuted = 0;
09901 }
09902
09903 ismuted |= (!l->lastrx);
09904 if (l->dtmfed && l->phonemode) ismuted = 1;
09905 l->dtmfed = 0;
09906 if (ismuted)
09907 {
09908 memset(f->data,0,f->datalen);
09909 if (l->lastf1)
09910 memset(l->lastf1->data,0,l->lastf1->datalen);
09911 if (l->lastf2)
09912 memset(l->lastf2->data,0,l->lastf2->datalen);
09913 }
09914 if (f) f2 = ast_frdup(f);
09915 else f2 = NULL;
09916 f1 = l->lastf2;
09917 l->lastf2 = l->lastf1;
09918 l->lastf1 = f2;
09919 if (ismuted)
09920 {
09921 if (l->lastf1)
09922 memset(l->lastf1->data,0,l->lastf1->datalen);
09923 if (l->lastf2)
09924 memset(l->lastf2->data,0,l->lastf2->datalen);
09925 }
09926 if (f1)
09927 {
09928 ast_write(l->pchan,f1);
09929 ast_frfree(f1);
09930 }
09931 }
09932 else
09933 {
09934 if (!l->lastrx)
09935 memset(f->data,0,f->datalen);
09936 ast_write(l->pchan,f);
09937 }
09938 }
09939 #ifndef OLD_ASTERISK
09940 else if (f->frametype == AST_FRAME_DTMF_BEGIN)
09941 {
09942 if (l->lastf1)
09943 memset(l->lastf1->data,0,l->lastf1->datalen);
09944 if (l->lastf2)
09945 memset(l->lastf2->data,0,l->lastf2->datalen);
09946 l->dtmfed = 1;
09947 }
09948 #endif
09949
09950 if (f->frametype == AST_FRAME_TEXT)
09951 {
09952 handle_link_data(myrpt,l,f->data);
09953 }
09954 if (f->frametype == AST_FRAME_DTMF)
09955 {
09956 if (l->lastf1)
09957 memset(l->lastf1->data,0,l->lastf1->datalen);
09958 if (l->lastf2)
09959 memset(l->lastf2->data,0,l->lastf2->datalen);
09960 l->dtmfed = 1;
09961 handle_link_phone_dtmf(myrpt,l,f->subclass);
09962 }
09963 if (f->frametype == AST_FRAME_CONTROL)
09964 {
09965 if (f->subclass == AST_CONTROL_ANSWER)
09966 {
09967 char lconnected = l->connected;
09968
09969 __kickshort(myrpt);
09970 l->connected = 1;
09971 l->hasconnected = 1;
09972 l->thisconnected = 1;
09973 l->elaptime = -1;
09974 if (!l->isremote) l->retries = 0;
09975 if (!lconnected)
09976 {
09977 rpt_telemetry(myrpt,CONNECTED,l);
09978 if (myrpt->p.archivedir)
09979 {
09980 char str[100];
09981
09982 if (l->mode)
09983 sprintf(str,"LINKTRX,%s",l->name);
09984 else
09985 sprintf(str,"LINKMONITOR,%s",l->name);
09986 donodelog(myrpt,str);
09987 }
09988 }
09989 else
09990 l->reconnects++;
09991 }
09992
09993 if (f->subclass == AST_CONTROL_RADIO_KEY)
09994 {
09995 if (debug == 7 ) printf("@@@@ rx key\n");
09996 l->lastrx = 1;
09997 l->rerxtimer = 0;
09998 if (myrpt->p.archivedir && (!l->lastrx1))
09999 {
10000 char str[100];
10001
10002 l->lastrx1 = 1;
10003 sprintf(str,"RXKEY,%s",l->name);
10004 donodelog(myrpt,str);
10005 }
10006 }
10007
10008 if (f->subclass == AST_CONTROL_RADIO_UNKEY)
10009 {
10010 if (debug == 7) printf("@@@@ rx un-key\n");
10011 l->lastrx = 0;
10012 l->rerxtimer = 0;
10013 if(myrpt->p.duplex)
10014 rpt_telemetry(myrpt,LINKUNKEY,l);
10015 if (myrpt->p.archivedir && (l->lastrx1))
10016 {
10017 char str[100];
10018
10019 l->lastrx1 = 0;
10020 sprintf(str,"RXUNKEY,%s",l->name);
10021 donodelog(myrpt,str);
10022 }
10023 }
10024 if (f->subclass == AST_CONTROL_HANGUP)
10025 {
10026 ast_frfree(f);
10027 rpt_mutex_lock(&myrpt->lock);
10028 __kickshort(myrpt);
10029 rpt_mutex_unlock(&myrpt->lock);
10030 if ((!l->outbound) && (!l->disced))
10031 {
10032 if ((l->name[0] == '0') || l->isremote)
10033 l->disctime = 1;
10034 else
10035 l->disctime = DISC_TIME;
10036 rpt_mutex_lock(&myrpt->lock);
10037 ast_hangup(l->chan);
10038 l->chan = 0;
10039 break;
10040 }
10041 if (l->retrytimer)
10042 {
10043 if (l->chan) ast_hangup(l->chan);
10044 l->chan = 0;
10045 rpt_mutex_lock(&myrpt->lock);
10046 break;
10047 }
10048 if (l->outbound && (l->retries++ < l->max_retries) && (l->hasconnected))
10049 {
10050 rpt_mutex_lock(&myrpt->lock);
10051 if (l->chan) ast_hangup(l->chan);
10052 l->chan = 0;
10053 l->hasconnected = 1;
10054 l->elaptime = 0;
10055 l->retrytimer = RETRY_TIMER_MS;
10056 l->connecttime = 0;
10057 l->thisconnected = 0;
10058 break;
10059 }
10060 rpt_mutex_lock(&myrpt->lock);
10061
10062 remque((struct qelem *) l);
10063 if (!strcmp(myrpt->cmdnode,l->name))
10064 myrpt->cmdnode[0] = 0;
10065 __kickshort(myrpt);
10066 rpt_mutex_unlock(&myrpt->lock);
10067 if (!l->hasconnected)
10068 rpt_telemetry(myrpt,CONNFAIL,l);
10069 else if (l->disced != 2) rpt_telemetry(myrpt,REMDISC,l);
10070 if (myrpt->p.archivedir)
10071 {
10072 char str[100];
10073
10074 if (!l->hasconnected)
10075 sprintf(str,"LINKFAIL,%s",l->name);
10076 else
10077 sprintf(str,"LINKDISC,%s",l->name);
10078 donodelog(myrpt,str);
10079 }
10080 if (l->lastf1) ast_frfree(l->lastf1);
10081 l->lastf1 = NULL;
10082 if (l->lastf2) ast_frfree(l->lastf2);
10083 l->lastf2 = NULL;
10084
10085 ast_hangup(l->chan);
10086 ast_hangup(l->pchan);
10087 free(l);
10088 rpt_mutex_lock(&myrpt->lock);
10089 break;
10090 }
10091 }
10092 ast_frfree(f);
10093 rpt_mutex_lock(&myrpt->lock);
10094 break;
10095 }
10096 if (who == l->pchan)
10097 {
10098 rpt_mutex_unlock(&myrpt->lock);
10099 f = ast_read(l->pchan);
10100 if (!f)
10101 {
10102 if (debug) printf("@@@@ rpt:Hung Up\n");
10103 toexit = 1;
10104 rpt_mutex_lock(&myrpt->lock);
10105 break;
10106 }
10107 if (f->frametype == AST_FRAME_VOICE)
10108 {
10109 if (l->chan) ast_write(l->chan,f);
10110 }
10111 if (f->frametype == AST_FRAME_CONTROL)
10112 {
10113 if (f->subclass == AST_CONTROL_HANGUP)
10114 {
10115 if (debug) printf("@@@@ rpt:Hung Up\n");
10116 ast_frfree(f);
10117 toexit = 1;
10118 rpt_mutex_lock(&myrpt->lock);
10119 break;
10120 }
10121 }
10122 ast_frfree(f);
10123 rpt_mutex_lock(&myrpt->lock);
10124 break;
10125 }
10126 l = l->next;
10127 }
10128 rpt_mutex_unlock(&myrpt->lock);
10129 if (toexit) break;
10130 if (who == myrpt->monchannel)
10131 {
10132 f = ast_read(myrpt->monchannel);
10133 if (!f)
10134 {
10135 if (debug) printf("@@@@ rpt:Hung Up\n");
10136 break;
10137 }
10138 if (f->frametype == AST_FRAME_VOICE)
10139 {
10140 if (myrpt->monstream)
10141 ast_writestream(myrpt->monstream,f);
10142 }
10143 if (f->frametype == AST_FRAME_CONTROL)
10144 {
10145 if (f->subclass == AST_CONTROL_HANGUP)
10146 {
10147 if (debug) printf("@@@@ rpt:Hung Up\n");
10148 ast_frfree(f);
10149 break;
10150 }
10151 }
10152 ast_frfree(f);
10153 continue;
10154 }
10155 if (who == myrpt->txpchannel)
10156 {
10157 f = ast_read(myrpt->txpchannel);
10158 if (!f)
10159 {
10160 if (debug) printf("@@@@ rpt:Hung Up\n");
10161 break;
10162 }
10163 if (f->frametype == AST_FRAME_CONTROL)
10164 {
10165 if (f->subclass == AST_CONTROL_HANGUP)
10166 {
10167 if (debug) printf("@@@@ rpt:Hung Up\n");
10168 ast_frfree(f);
10169 break;
10170 }
10171 }
10172 ast_frfree(f);
10173 continue;
10174 }
10175 }
10176 usleep(100000);
10177 ast_hangup(myrpt->pchannel);
10178 ast_hangup(myrpt->monchannel);
10179 ast_hangup(myrpt->txpchannel);
10180 if (myrpt->txchannel != myrpt->rxchannel) ast_hangup(myrpt->txchannel);
10181 if (myrpt->lastf1) ast_frfree(myrpt->lastf1);
10182 myrpt->lastf1 = NULL;
10183 if (myrpt->lastf2) ast_frfree(myrpt->lastf2);
10184 myrpt->lastf2 = NULL;
10185 ast_hangup(myrpt->rxchannel);
10186 rpt_mutex_lock(&myrpt->lock);
10187 l = myrpt->links.next;
10188 while(l != &myrpt->links)
10189 {
10190 struct rpt_link *ll = l;
10191
10192 remque((struct qelem *) l);
10193
10194 if (l->chan) ast_hangup(l->chan);
10195 ast_hangup(l->pchan);
10196 l = l->next;
10197 free(ll);
10198 }
10199 rpt_mutex_unlock(&myrpt->lock);
10200 if (debug) printf("@@@@ rpt:Hung up channel\n");
10201 myrpt->rpt_thread = AST_PTHREADT_STOP;
10202 pthread_exit(NULL);
10203 return NULL;
10204 }
10205
10206
10207 static void *rpt_master(void *ignore)
10208 {
10209 int i,n;
10210 pthread_attr_t attr;
10211 struct ast_config *cfg;
10212 char *this,*val;
10213
10214
10215 nodelog.next = nodelog.prev = &nodelog;
10216
10217 this = NULL;
10218 n = 0;
10219 rpt_vars[n].cfg = ast_config_load("rpt.conf");
10220 cfg = rpt_vars[n].cfg;
10221 if (!cfg) {
10222 ast_log(LOG_NOTICE, "Unable to open radio repeater configuration rpt.conf. Radio Repeater disabled.\n");
10223 pthread_exit(NULL);
10224 }
10225 while((this = ast_category_browse(cfg,this)) != NULL)
10226 {
10227 for(i = 0 ; i < strlen(this) ; i++){
10228 if((this[i] < '0') || (this[i] > '9'))
10229 break;
10230 }
10231 if(i != strlen(this)) continue;
10232 memset(&rpt_vars[n],0,sizeof(rpt_vars[n]));
10233 rpt_vars[n].name = strdup(this);
10234 val = (char *) ast_variable_retrieve(cfg,this,"rxchannel");
10235 if (val) rpt_vars[n].rxchanname = strdup(val);
10236 val = (char *) ast_variable_retrieve(cfg,this,"txchannel");
10237 if (val) rpt_vars[n].txchanname = strdup(val);
10238 val = (char *) ast_variable_retrieve(cfg,this,"remote");
10239 if (val) rpt_vars[n].remote = strdup(val);
10240 ast_mutex_init(&rpt_vars[n].lock);
10241 ast_mutex_init(&rpt_vars[n].remlock);
10242 rpt_vars[n].tele.next = &rpt_vars[n].tele;
10243 rpt_vars[n].tele.prev = &rpt_vars[n].tele;
10244 rpt_vars[n].rpt_thread = AST_PTHREADT_NULL;
10245 rpt_vars[n].tailmessagen = 0;
10246 #ifdef _MDC_DECODE_H_
10247 rpt_vars[n].mdc = mdc_decoder_new(8000);
10248 #endif
10249 n++;
10250 }
10251 nrpts = n;
10252 ast_config_destroy(cfg);
10253
10254
10255 for(i = 0; i < n; i++)
10256 {
10257 load_rpt_vars(i,1);
10258
10259
10260 if (rpt_vars[i].remote)
10261 {
10262 if(retreive_memory(&rpt_vars[i],"init")){
10263 strncpy(rpt_vars[i].freq, "146.580", sizeof(rpt_vars[i].freq) - 1);
10264 strncpy(rpt_vars[i].rxpl, "100.0", sizeof(rpt_vars[i].rxpl) - 1);
10265
10266 strncpy(rpt_vars[i].txpl, "100.0", sizeof(rpt_vars[i].txpl) - 1);
10267 rpt_vars[i].remmode = REM_MODE_FM;
10268 rpt_vars[i].offset = REM_SIMPLEX;
10269 rpt_vars[i].powerlevel = REM_MEDPWR;
10270 }
10271 continue;
10272 }
10273 if (!rpt_vars[i].p.ident)
10274 {
10275 ast_log(LOG_WARNING,"Did not specify ident for node %s\n",rpt_vars[i].name);
10276 ast_config_destroy(cfg);
10277 pthread_exit(NULL);
10278 }
10279 pthread_attr_init(&attr);
10280 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
10281 ast_pthread_create(&rpt_vars[i].rpt_thread,&attr,rpt,(void *) &rpt_vars[i]);
10282 }
10283 usleep(500000);
10284 time(&starttime);
10285 for(;;)
10286 {
10287
10288 for(i = 0; i < n; i++)
10289 {
10290 int rv;
10291 if (rpt_vars[i].remote) continue;
10292 if (rpt_vars[i].rpt_thread == AST_PTHREADT_STOP)
10293 rv = -1;
10294 else
10295 rv = pthread_kill(rpt_vars[i].rpt_thread,0);
10296 if (rv)
10297 {
10298 if(time(NULL) - rpt_vars[i].lastthreadrestarttime <= 15)
10299 {
10300 if(rpt_vars[i].threadrestarts >= 5)
10301 {
10302 ast_log(LOG_ERROR,"Continual RPT thread restarts, killing Asterisk\n");
10303 exit(1);
10304 }
10305 else
10306 {
10307 ast_log(LOG_NOTICE,"RPT thread restarted on %s\n",rpt_vars[i].name);
10308 rpt_vars[i].threadrestarts++;
10309 }
10310 }
10311 else
10312 rpt_vars[i].threadrestarts = 0;
10313
10314 rpt_vars[i].lastthreadrestarttime = time(NULL);
10315 pthread_attr_init(&attr);
10316 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
10317 ast_pthread_create(&rpt_vars[i].rpt_thread,&attr,rpt,(void *) &rpt_vars[i]);
10318 ast_log(LOG_WARNING, "rpt_thread restarted on node %s\n", rpt_vars[i].name);
10319 }
10320
10321 }
10322 for(;;)
10323 {
10324 struct nodelog *nodep;
10325 char *space,datestr[100],fname[300];
10326 int fd;
10327
10328 ast_mutex_lock(&nodeloglock);
10329 nodep = nodelog.next;
10330 if(nodep == &nodelog)
10331 {
10332 ast_mutex_unlock(&nodeloglock);
10333 break;
10334 }
10335 remque((struct qelem *)nodep);
10336 ast_mutex_unlock(&nodeloglock);
10337 space = strchr(nodep->str,' ');
10338 if (!space)
10339 {
10340 free(nodep);
10341 continue;
10342 }
10343 *space = 0;
10344 strftime(datestr,sizeof(datestr) - 1,"%Y%m%d",
10345 localtime(&nodep->timestamp));
10346 sprintf(fname,"%s/%s/%s.txt",nodep->archivedir,
10347 nodep->str,datestr);
10348 fd = open(fname,O_WRONLY | O_CREAT | O_APPEND,0600);
10349 if (fd == -1)
10350 {
10351 ast_log(LOG_ERROR,"Cannot open node log file %s for write",space + 1);
10352 free(nodep);
10353 continue;
10354 }
10355 if (write(fd,space + 1,strlen(space + 1)) !=
10356 strlen(space + 1))
10357 {
10358 ast_log(LOG_ERROR,"Cannot write node log file %s for write",space + 1);
10359 free(nodep);
10360 continue;
10361 }
10362 close(fd);
10363 free(nodep);
10364 }
10365 usleep(2000000);
10366 }
10367 ast_config_destroy(cfg);
10368 pthread_exit(NULL);
10369 }
10370
10371 static int rpt_exec(struct ast_channel *chan, void *data)
10372 {
10373 int res=-1,i,rem_totx,rem_rx,remkeyed,n,phone_mode = 0;
10374 int iskenwood_pci4,authtold,authreq,setting,notremming,reming;
10375 int ismuted,dtmfed;
10376 #ifdef OLD_ASTERISK
10377 struct localuser *u;
10378 #endif
10379 char tmp[256], keyed = 0,keyed1 = 0;
10380 char *options,*stringp,*tele,c;
10381 struct rpt *myrpt;
10382 struct ast_frame *f,*f1,*f2;
10383 struct ast_channel *who;
10384 struct ast_channel *cs[20];
10385 struct rpt_link *l;
10386 ZT_CONFINFO ci;
10387 ZT_PARAMS par;
10388 int ms,elap,nullfd;
10389 time_t t,last_timeout_warning;
10390 struct zt_radio_param z;
10391 struct rpt_tele *telem;
10392
10393 nullfd = open("/dev/null",O_RDWR);
10394 if (ast_strlen_zero(data)) {
10395 ast_log(LOG_WARNING, "Rpt requires an argument (system node)\n");
10396 return -1;
10397 }
10398 strncpy(tmp, (char *)data, sizeof(tmp)-1);
10399 time(&t);
10400
10401 if (t < starttime) t = starttime + START_DELAY;
10402 if ((!starttime) || (t < (starttime + START_DELAY)))
10403 {
10404 ast_log(LOG_NOTICE,"Node %s rejecting call: too soon!\n",tmp);
10405 ast_safe_sleep(chan,3000);
10406 return -1;
10407 }
10408 stringp=tmp;
10409 strsep(&stringp, "|");
10410 options = stringp;
10411 myrpt = NULL;
10412
10413 for(i = 0; i < nrpts; i++)
10414 {
10415
10416 if (!strcmp(tmp,rpt_vars[i].name))
10417 {
10418 myrpt = &rpt_vars[i];
10419 break;
10420 }
10421 }
10422 if (myrpt == NULL)
10423 {
10424 ast_log(LOG_WARNING, "Cannot find specified system node %s\n",tmp);
10425 return -1;
10426 }
10427
10428 if(myrpt->p.s[myrpt->p.sysstate_cur].txdisable){
10429 ast_log(LOG_NOTICE, "Connect attempt to node %s with tx disabled", myrpt->name);
10430 return -1;
10431 }
10432
10433
10434 if (options && ((*options == 'P') || (*options == 'D') || (*options == 'R')))
10435 {
10436 int val;
10437
10438 phone_mode = 1;
10439 if (*options == 'D') phone_mode = 2;
10440 ast_set_callerid(chan,"0","app_rpt user","0");
10441 val = 1;
10442 ast_channel_setoption(chan,AST_OPTION_TONE_VERIFY,&val,sizeof(char),0);
10443 }
10444 else
10445 {
10446 if (strncmp(chan->name,"IAX2",4))
10447 {
10448 ast_log(LOG_WARNING, "We only accept links via IAX2!!\n");
10449 return -1;
10450 }
10451 }
10452 if (options && (*options == 'R'))
10453 {
10454
10455
10456 char *return_context;
10457 int l, m, lot, timeout = 0;
10458 char tmp[256],*template;
10459 char *working, *context, *exten, *priority;
10460 char *s,*orig_s;
10461
10462
10463 rpt_mutex_lock(&myrpt->lock);
10464 m = myrpt->callmode;
10465 rpt_mutex_unlock(&myrpt->lock);
10466
10467 if ((!myrpt->p.nobusyout) && m)
10468 {
10469 if (chan->_state != AST_STATE_UP)
10470 {
10471 ast_indicate(chan,AST_CONTROL_BUSY);
10472 }
10473 while(ast_safe_sleep(chan,10000) != -1);
10474 return -1;
10475 }
10476
10477 if (chan->_state != AST_STATE_UP)
10478 {
10479 ast_answer(chan);
10480 }
10481
10482 l=strlen(options)+2;
10483 orig_s=malloc(l);
10484 if(!orig_s) {
10485 ast_log(LOG_WARNING, "Out of memory\n");
10486 return -1;
10487 }
10488 s=orig_s;
10489 strncpy(s,options,l);
10490
10491 template=strsep(&s,"|");
10492 if(!template) {
10493 ast_log(LOG_WARNING, "An announce template must be defined\n");
10494 free(orig_s);
10495 return -1;
10496 }
10497
10498 if(s) {
10499 timeout = atoi(strsep(&s, "|"));
10500 timeout *= 1000;
10501 }
10502
10503 return_context = s;
10504
10505 if(return_context != NULL) {
10506
10507
10508 working = return_context;
10509 context = strsep(&working, "|");
10510 exten = strsep(&working, "|");
10511 if(!exten) {
10512
10513 priority = context;
10514 exten = NULL;
10515 context = NULL;
10516 } else {
10517 priority = strsep(&working, "|");
10518 if(!priority) {
10519
10520 priority = exten;
10521 exten = context;
10522 context = NULL;
10523 }
10524 }
10525 if(atoi(priority) < 0) {
10526 ast_log(LOG_WARNING, "Priority '%s' must be a number > 0\n", priority);
10527 free(orig_s);
10528 return -1;
10529 }
10530
10531 chan->priority = atoi(priority);
10532 #ifdef OLD_ASTERISK
10533 if(exten && strcasecmp(exten, "BYEXTENSION"))
10534 #else
10535 if(exten)
10536 #endif
10537 strncpy(chan->exten, exten, sizeof(chan->exten)-1);
10538 if(context)
10539 strncpy(chan->context, context, sizeof(chan->context)-1);
10540 } else {
10541 chan->priority++;
10542 }
10543
10544 if(option_verbose > 2) {
10545 ast_verbose( VERBOSE_PREFIX_3 "Return Context: (%s,%s,%d) ID: %s\n", chan->context,chan->exten, chan->priority, chan->cid.cid_num);
10546 if(!ast_exists_extension(chan, chan->context, chan->exten, chan->priority, chan->cid.cid_num)) {
10547 ast_verbose( VERBOSE_PREFIX_3 "Warning: Return Context Invalid, call will return to default|s\n");
10548 }
10549 }
10550
10551
10552
10553
10554 ast_masq_park_call(chan, NULL, timeout, &lot);
10555
10556 if (option_verbose > 2) ast_verbose( VERBOSE_PREFIX_3 "Call Parking Called, lot: %d, timeout: %d, context: %s\n", lot, timeout, return_context);
10557
10558 snprintf(tmp,sizeof(tmp) - 1,"%d,%s",lot,template + 1);
10559
10560 rpt_telemetry(myrpt,REV_PATCH,tmp);
10561
10562 free(orig_s);
10563
10564 return 0;
10565
10566 }
10567
10568 if (!options)
10569 {
10570 struct ast_hostent ahp;
10571 struct hostent *hp;
10572 struct in_addr ia;
10573 char hisip[100],nodeip[100],*val, *s, *s1, *s2, *b,*b1;
10574
10575
10576 if (!chan->cid.cid_num)
10577 {
10578 ast_log(LOG_WARNING, "Doesnt have callerid on %s\n",tmp);
10579 return -1;
10580 }
10581
10582
10583 memset(hisip,0,sizeof(hisip));
10584 pbx_substitute_variables_helper(chan,"${IAXPEER(CURRENTCHANNEL)}",hisip,sizeof(hisip) - 1);
10585 if (!hisip[0])
10586 {
10587 ast_log(LOG_WARNING, "Link IP address cannot be determined!!\n");
10588 return -1;
10589 }
10590
10591 ast_callerid_parse(chan->cid.cid_num,&b,&b1);
10592 ast_shrink_phone_number(b1);
10593 if (!strcmp(myrpt->name,b1))
10594 {
10595 ast_log(LOG_WARNING, "Trying to link to self!!\n");
10596 return -1;
10597 }
10598
10599 if (*b1 < '1')
10600 {
10601 ast_log(LOG_WARNING, "Node %s Invalid for connection here!!\n",b1);
10602 return -1;
10603 }
10604
10605
10606
10607 val = node_lookup(myrpt,b1);
10608 if (!val)
10609 {
10610 ast_log(LOG_WARNING, "Reported node %s cannot be found!!\n",b1);
10611 return -1;
10612 }
10613 strncpy(tmp,val,sizeof(tmp) - 1);
10614 s = tmp;
10615 s1 = strsep(&s,",");
10616 s2 = strsep(&s,",");
10617 if (!s2)
10618 {
10619 ast_log(LOG_WARNING, "Reported node %s not in correct format!!\n",b1);
10620 return -1;
10621 }
10622 if (strcmp(s2,"NONE")) {
10623 hp = ast_gethostbyname(s2, &ahp);
10624 if (!hp)
10625 {
10626 ast_log(LOG_WARNING, "Reported node %s, name %s cannot be found!!\n",b1,s2);
10627 return -1;
10628 }
10629 memcpy(&ia,hp->h_addr,sizeof(in_addr_t));
10630 #ifdef OLD_ASTERISK
10631 ast_inet_ntoa(nodeip,sizeof(nodeip) - 1,ia);
10632 #else
10633 strncpy(nodeip,ast_inet_ntoa(ia),sizeof(nodeip) - 1);
10634 #endif
10635 if (strcmp(hisip,nodeip))
10636 {
10637 char *s3 = strchr(s1,'@');
10638 if (s3) s1 = s3 + 1;
10639 s3 = strchr(s1,'/');
10640 if (s3) *s3 = 0;
10641 hp = ast_gethostbyname(s1, &ahp);
10642 if (!hp)
10643 {
10644 ast_log(LOG_WARNING, "Reported node %s, name %s cannot be found!!\n",b1,s1);
10645 return -1;
10646 }
10647 memcpy(&ia,hp->h_addr,sizeof(in_addr_t));
10648 #ifdef OLD_ASTERISK
10649 ast_inet_ntoa(nodeip,sizeof(nodeip) - 1,ia);
10650 #else
10651 strncpy(nodeip,ast_inet_ntoa(ia),sizeof(nodeip) - 1);
10652 #endif
10653 if (strcmp(hisip,nodeip))
10654 {
10655 ast_log(LOG_WARNING, "Node %s IP %s does not match link IP %s!!\n",b1,nodeip,hisip);
10656 return -1;
10657 }
10658 }
10659 }
10660 }
10661
10662
10663 if (!myrpt->remote)
10664 {
10665
10666 char *b,*b1;
10667 int reconnects = 0;
10668
10669
10670 if (!chan->cid.cid_num)
10671 {
10672 ast_log(LOG_WARNING, "Doesnt have callerid on %s\n",tmp);
10673 return -1;
10674 }
10675
10676 ast_callerid_parse(chan->cid.cid_num,&b,&b1);
10677 ast_shrink_phone_number(b1);
10678 if (!strcmp(myrpt->name,b1))
10679 {
10680 ast_log(LOG_WARNING, "Trying to link to self!!\n");
10681 return -1;
10682 }
10683 rpt_mutex_lock(&myrpt->lock);
10684 l = myrpt->links.next;
10685
10686 while(l != &myrpt->links)
10687 {
10688 if (l->name[0] == '0')
10689 {
10690 l = l->next;
10691 continue;
10692 }
10693
10694 if (!strcmp(l->name,b1)) break;
10695 l = l->next;
10696 }
10697
10698 if (l != &myrpt->links)
10699 {
10700 l->killme = 1;
10701 l->retries = l->max_retries + 1;
10702 l->disced = 2;
10703 reconnects = l->reconnects;
10704 reconnects++;
10705 rpt_mutex_unlock(&myrpt->lock);
10706 usleep(500000);
10707 } else
10708 rpt_mutex_unlock(&myrpt->lock);
10709
10710 l = malloc(sizeof(struct rpt_link));
10711 if (!l)
10712 {
10713 ast_log(LOG_WARNING, "Unable to malloc\n");
10714 pthread_exit(NULL);
10715 }
10716
10717 memset((char *)l,0,sizeof(struct rpt_link));
10718 l->mode = 1;
10719 strncpy(l->name,b1,MAXNODESTR - 1);
10720 l->isremote = 0;
10721 l->chan = chan;
10722 l->connected = 1;
10723 l->thisconnected = 1;
10724 l->hasconnected = 1;
10725 l->reconnects = reconnects;
10726 l->phonemode = phone_mode;
10727 l->lastf1 = NULL;
10728 l->lastf2 = NULL;
10729 l->dtmfed = 0;
10730 ast_set_read_format(l->chan,AST_FORMAT_SLINEAR);
10731 ast_set_write_format(l->chan,AST_FORMAT_SLINEAR);
10732
10733 l->pchan = ast_request("zap",AST_FORMAT_SLINEAR,"pseudo",NULL);
10734 if (!l->pchan)
10735 {
10736 fprintf(stderr,"rpt:Sorry unable to obtain pseudo channel\n");
10737 pthread_exit(NULL);
10738 }
10739 ast_set_read_format(l->pchan,AST_FORMAT_SLINEAR);
10740 ast_set_write_format(l->pchan,AST_FORMAT_SLINEAR);
10741
10742 ci.chan = 0;
10743 ci.confno = myrpt->conf;
10744 ci.confmode = ZT_CONF_CONF | ZT_CONF_LISTENER | ZT_CONF_TALKER;
10745
10746 if (ioctl(l->pchan->fds[0],ZT_SETCONF,&ci) == -1)
10747 {
10748 ast_log(LOG_WARNING, "Unable to set conference mode to Announce\n");
10749 pthread_exit(NULL);
10750 }
10751 rpt_mutex_lock(&myrpt->lock);
10752 if (phone_mode > 1) l->lastrx = 1;
10753 l->max_retries = MAX_RETRIES;
10754
10755 insque((struct qelem *)l,(struct qelem *)myrpt->links.next);
10756 __kickshort(myrpt);
10757 rpt_mutex_unlock(&myrpt->lock);
10758 if (chan->_state != AST_STATE_UP) {
10759 ast_answer(chan);
10760 }
10761 if (myrpt->p.archivedir)
10762 {
10763 char str[100];
10764
10765 if (l->phonemode)
10766 sprintf(str,"LINK(P),%s",l->name);
10767 else
10768 sprintf(str,"LINK,%s",l->name);
10769 donodelog(myrpt,str);
10770 }
10771 return AST_PBX_KEEPALIVE;
10772 }
10773
10774 rpt_mutex_lock(&myrpt->lock);
10775
10776 if (myrpt->remoteon)
10777 {
10778 rpt_mutex_unlock(&myrpt->lock);
10779 usleep(500000);
10780 if (myrpt->remoteon)
10781 {
10782 ast_log(LOG_WARNING, "Trying to use busy link on %s\n",tmp);
10783 return -1;
10784 }
10785 rpt_mutex_lock(&myrpt->lock);
10786 }
10787 if ((!strcmp(myrpt->remote, remote_rig_rbi)) &&
10788 (ioperm(myrpt->p.iobase,1,1) == -1))
10789 {
10790 rpt_mutex_unlock(&myrpt->lock);
10791 ast_log(LOG_WARNING, "Cant get io permission on IO port %x hex\n",myrpt->p.iobase);
10792 return -1;
10793 }
10794 myrpt->remoteon = 1;
10795 #ifdef OLD_ASTERISK
10796 LOCAL_USER_ADD(u);
10797 #endif
10798 rpt_mutex_unlock(&myrpt->lock);
10799
10800 for(i = 0; i < nrpts; i++)
10801 {
10802 if (&rpt_vars[i] == myrpt)
10803 {
10804 load_rpt_vars(i,0);
10805 break;
10806 }
10807 }
10808 rpt_mutex_lock(&myrpt->lock);
10809 tele = strchr(myrpt->rxchanname,'/');
10810 if (!tele)
10811 {
10812 fprintf(stderr,"rpt:Dial number must be in format tech/number\n");
10813 rpt_mutex_unlock(&myrpt->lock);
10814 pthread_exit(NULL);
10815 }
10816 *tele++ = 0;
10817 myrpt->rxchannel = ast_request(myrpt->rxchanname,AST_FORMAT_SLINEAR,tele,NULL);
10818 if (myrpt->rxchannel)
10819 {
10820 ast_set_read_format(myrpt->rxchannel,AST_FORMAT_SLINEAR);
10821 ast_set_write_format(myrpt->rxchannel,AST_FORMAT_SLINEAR);
10822 myrpt->rxchannel->whentohangup = 0;
10823 myrpt->rxchannel->appl = "Apprpt";
10824 myrpt->rxchannel->data = "(Link Rx)";
10825 if (option_verbose > 2)
10826 ast_verbose(VERBOSE_PREFIX_3 "rpt (Rx) initiating call to %s/%s on %s\n",
10827 myrpt->rxchanname,tele,myrpt->rxchannel->name);
10828 rpt_mutex_unlock(&myrpt->lock);
10829 ast_call(myrpt->rxchannel,tele,999);
10830 rpt_mutex_lock(&myrpt->lock);
10831 }
10832 else
10833 {
10834 fprintf(stderr,"rpt:Sorry unable to obtain Rx channel\n");
10835 rpt_mutex_unlock(&myrpt->lock);
10836 pthread_exit(NULL);
10837 }
10838 *--tele = '/';
10839 if (myrpt->txchanname)
10840 {
10841 tele = strchr(myrpt->txchanname,'/');
10842 if (!tele)
10843 {
10844 fprintf(stderr,"rpt:Dial number must be in format tech/number\n");
10845 rpt_mutex_unlock(&myrpt->lock);
10846 ast_hangup(myrpt->rxchannel);
10847 pthread_exit(NULL);
10848 }
10849 *tele++ = 0;
10850 myrpt->txchannel = ast_request(myrpt->txchanname,AST_FORMAT_SLINEAR,tele,NULL);
10851 if (myrpt->txchannel)
10852 {
10853 ast_set_read_format(myrpt->txchannel,AST_FORMAT_SLINEAR);
10854 ast_set_write_format(myrpt->txchannel,AST_FORMAT_SLINEAR);
10855 myrpt->txchannel->whentohangup = 0;
10856 myrpt->txchannel->appl = "Apprpt";
10857 myrpt->txchannel->data = "(Link Tx)";
10858 if (option_verbose > 2)
10859 ast_verbose(VERBOSE_PREFIX_3 "rpt (Tx) initiating call to %s/%s on %s\n",
10860 myrpt->txchanname,tele,myrpt->txchannel->name);
10861 rpt_mutex_unlock(&myrpt->lock);
10862 ast_call(myrpt->txchannel,tele,999);
10863 rpt_mutex_lock(&myrpt->lock);
10864 }
10865 else
10866 {
10867 fprintf(stderr,"rpt:Sorry unable to obtain Tx channel\n");
10868 rpt_mutex_unlock(&myrpt->lock);
10869 ast_hangup(myrpt->rxchannel);
10870 pthread_exit(NULL);
10871 }
10872 *--tele = '/';
10873 }
10874 else
10875 {
10876 myrpt->txchannel = myrpt->rxchannel;
10877 }
10878
10879 myrpt->pchannel = ast_request("zap",AST_FORMAT_SLINEAR,"pseudo",NULL);
10880 if (!myrpt->pchannel)
10881 {
10882 fprintf(stderr,"rpt:Sorry unable to obtain pseudo channel\n");
10883 rpt_mutex_unlock(&myrpt->lock);
10884 if (myrpt->txchannel != myrpt->rxchannel)
10885 ast_hangup(myrpt->txchannel);
10886 ast_hangup(myrpt->rxchannel);
10887 pthread_exit(NULL);
10888 }
10889 ast_set_read_format(myrpt->pchannel,AST_FORMAT_SLINEAR);
10890 ast_set_write_format(myrpt->pchannel,AST_FORMAT_SLINEAR);
10891
10892 ci.chan = 0;
10893 ci.confno = -1;
10894 ci.confmode = ZT_CONF_CONFANNMON ;
10895
10896 if (ioctl(myrpt->pchannel->fds[0],ZT_SETCONF,&ci) == -1)
10897 {
10898 ast_log(LOG_WARNING, "Unable to set conference mode to Announce\n");
10899 rpt_mutex_unlock(&myrpt->lock);
10900 ast_hangup(myrpt->pchannel);
10901 if (myrpt->txchannel != myrpt->rxchannel)
10902 ast_hangup(myrpt->txchannel);
10903 ast_hangup(myrpt->rxchannel);
10904 pthread_exit(NULL);
10905 }
10906
10907 myrpt->iofd = -1;
10908 if (myrpt->p.ioport && ((myrpt->iofd = openserial(myrpt->p.ioport)) == -1))
10909 {
10910 rpt_mutex_unlock(&myrpt->lock);
10911 ast_hangup(myrpt->pchannel);
10912 if (myrpt->txchannel != myrpt->rxchannel)
10913 ast_hangup(myrpt->txchannel);
10914 ast_hangup(myrpt->rxchannel);
10915 pthread_exit(NULL);
10916 }
10917 iskenwood_pci4 = 0;
10918 memset(&z,0,sizeof(z));
10919 if (myrpt->iofd < 1)
10920 {
10921 z.radpar = ZT_RADPAR_REMMODE;
10922 z.data = ZT_RADPAR_REM_NONE;
10923 res = ioctl(myrpt->txchannel->fds[0],ZT_RADIO_SETPARAM,&z);
10924
10925 if ((!res) && (!strcmp(myrpt->remote,remote_rig_kenwood)))
10926 {
10927 z.radpar = ZT_RADPAR_UIOMODE;
10928 z.data = 1;
10929 if (ioctl(myrpt->txchannel->fds[0],ZT_RADIO_SETPARAM,&z) == -1)
10930 {
10931 ast_log(LOG_ERROR,"Cannot set UIOMODE\n");
10932 return -1;
10933 }
10934 z.radpar = ZT_RADPAR_UIODATA;
10935 z.data = 3;
10936 if (ioctl(myrpt->txchannel->fds[0],ZT_RADIO_SETPARAM,&z) == -1)
10937 {
10938 ast_log(LOG_ERROR,"Cannot set UIODATA\n");
10939 return -1;
10940 }
10941 i = ZT_OFFHOOK;
10942 if (ioctl(myrpt->txchannel->fds[0],ZT_HOOK,&i) == -1)
10943 {
10944 ast_log(LOG_ERROR,"Cannot set hook\n");
10945 return -1;
10946 }
10947 iskenwood_pci4 = 1;
10948 }
10949 }
10950 i = ZT_ONHOOK;
10951 ioctl(myrpt->txchannel->fds[0],ZT_HOOK,&i);
10952
10953 if ((myrpt->iofd < 1) && (!res) &&
10954 (!strcmp(myrpt->remote,remote_rig_ft897) ||
10955 (!strcmp(myrpt->remote,remote_rig_ic706))))
10956 {
10957 z.radpar = ZT_RADPAR_UIOMODE;
10958 z.data = 1;
10959 if (ioctl(myrpt->txchannel->fds[0],ZT_RADIO_SETPARAM,&z) == -1)
10960 {
10961 ast_log(LOG_ERROR,"Cannot set UIOMODE\n");
10962 return -1;
10963 }
10964 z.radpar = ZT_RADPAR_UIODATA;
10965 z.data = 3;
10966 if (ioctl(myrpt->txchannel->fds[0],ZT_RADIO_SETPARAM,&z) == -1)
10967 {
10968 ast_log(LOG_ERROR,"Cannot set UIODATA\n");
10969 return -1;
10970 }
10971 }
10972
10973 myrpt->conf = myrpt->txconf = ci.confno;
10974 myrpt->remoterx = 0;
10975 myrpt->remotetx = 0;
10976 myrpt->retxtimer = 0;
10977 myrpt->rerxtimer = 0;
10978 myrpt->remoteon = 1;
10979 myrpt->dtmfidx = -1;
10980 myrpt->dtmfbuf[0] = 0;
10981 myrpt->dtmf_time_rem = 0;
10982 myrpt->hfscanmode = 0;
10983 myrpt->hfscanstatus = 0;
10984 if (myrpt->p.startupmacro)
10985 {
10986 snprintf(myrpt->macrobuf,MAXMACRO - 1,"PPPP%s",myrpt->p.startupmacro);
10987 }
10988 time(&myrpt->start_time);
10989 myrpt->last_activity_time = myrpt->start_time;
10990 last_timeout_warning = 0;
10991 myrpt->reload = 0;
10992 myrpt->tele.next = &myrpt->tele;
10993 myrpt->tele.prev = &myrpt->tele;
10994 rpt_mutex_unlock(&myrpt->lock);
10995 ast_set_write_format(chan, AST_FORMAT_SLINEAR);
10996 ast_set_read_format(chan, AST_FORMAT_SLINEAR);
10997 rem_rx = 0;
10998 remkeyed = 0;
10999
11000 if (myrpt->remote && (myrpt->rxchannel == myrpt->txchannel))
11001 {
11002 i = 128;
11003 ioctl(myrpt->rxchannel->fds[0],ZT_ECHOCANCEL,&i);
11004 }
11005 if (chan->_state != AST_STATE_UP) {
11006 ast_answer(chan);
11007 }
11008
11009 if (ioctl(myrpt->rxchannel->fds[0],ZT_GET_PARAMS,&par) != -1)
11010 {
11011 if (par.rxisoffhook)
11012 {
11013 ast_indicate(chan,AST_CONTROL_RADIO_KEY);
11014 myrpt->remoterx = 1;
11015 remkeyed = 1;
11016 }
11017 }
11018 if (myrpt->p.archivedir)
11019 {
11020 char mycmd[100],mydate[100],*b,*b1;
11021 time_t myt;
11022 long blocksleft;
11023
11024
11025 mkdir(myrpt->p.archivedir,0600);
11026 sprintf(mycmd,"%s/%s",myrpt->p.archivedir,myrpt->name);
11027 mkdir(mycmd,0600);
11028 time(&myt);
11029 strftime(mydate,sizeof(mydate) - 1,"%Y%m%d%H%M%S",
11030 localtime(&myt));
11031 sprintf(mycmd,"mixmonitor start %s %s/%s/%s.wav49 a",chan->name,
11032 myrpt->p.archivedir,myrpt->name,mydate);
11033 if (myrpt->p.monminblocks)
11034 {
11035 blocksleft = diskavail(myrpt);
11036 if (myrpt->p.remotetimeout)
11037 {
11038 blocksleft -= (myrpt->p.remotetimeout *
11039 MONITOR_DISK_BLOCKS_PER_MINUTE) / 60;
11040 }
11041 if (blocksleft >= myrpt->p.monminblocks)
11042 ast_cli_command(nullfd,mycmd);
11043 } else ast_cli_command(nullfd,mycmd);
11044
11045 if (!chan->cid.cid_num)
11046 {
11047 b1 = "0";
11048 } else {
11049 ast_callerid_parse(chan->cid.cid_num,&b,&b1);
11050 ast_shrink_phone_number(b1);
11051 }
11052 sprintf(mycmd,"CONNECT,%s",b1);
11053 donodelog(myrpt,mycmd);
11054 }
11055 myrpt->loginuser[0] = 0;
11056 myrpt->loginlevel[0] = 0;
11057 myrpt->authtelltimer = 0;
11058 myrpt->authtimer = 0;
11059 authtold = 0;
11060 authreq = 0;
11061 if (myrpt->p.authlevel > 1) authreq = 1;
11062 setrem(myrpt);
11063 n = 0;
11064 dtmfed = 0;
11065 cs[n++] = chan;
11066 cs[n++] = myrpt->rxchannel;
11067 cs[n++] = myrpt->pchannel;
11068 if (myrpt->rxchannel != myrpt->txchannel)
11069 cs[n++] = myrpt->txchannel;
11070
11071 for(;;)
11072 {
11073 if (ast_check_hangup(chan)) break;
11074 if (ast_check_hangup(myrpt->rxchannel)) break;
11075 notremming = 0;
11076 setting = 0;
11077 reming = 0;
11078 telem = myrpt->tele.next;
11079 while(telem != &myrpt->tele)
11080 {
11081 if (telem->mode == SETREMOTE) setting = 1;
11082 if ((telem->mode == SETREMOTE) ||
11083 (telem->mode == SCAN) ||
11084 (telem->mode == TUNE)) reming = 1;
11085 else notremming = 1;
11086 telem = telem->next;
11087 }
11088 if (myrpt->reload)
11089 {
11090 myrpt->reload = 0;
11091
11092 for(i = 0; i < nrpts; i++)
11093 {
11094 if (&rpt_vars[i] == myrpt)
11095 {
11096 load_rpt_vars(i,0);
11097 break;
11098 }
11099 }
11100 }
11101 time(&t);
11102 if (myrpt->p.remotetimeout)
11103 {
11104 time_t r;
11105
11106 r = (t - myrpt->start_time);
11107 if (r >= myrpt->p.remotetimeout)
11108 {
11109 sayfile(chan,"rpt/node");
11110 ast_say_character_str(chan,myrpt->name,NULL,chan->language);
11111 sayfile(chan,"rpt/timeout");
11112 ast_safe_sleep(chan,1000);
11113 break;
11114 }
11115 if ((myrpt->p.remotetimeoutwarning) &&
11116 (r >= (myrpt->p.remotetimeout -
11117 myrpt->p.remotetimeoutwarning)) &&
11118 (r <= (myrpt->p.remotetimeout -
11119 myrpt->p.remotetimeoutwarningfreq)))
11120 {
11121 if (myrpt->p.remotetimeoutwarningfreq)
11122 {
11123 if ((t - last_timeout_warning) >=
11124 myrpt->p.remotetimeoutwarningfreq)
11125 {
11126 time(&last_timeout_warning);
11127 rpt_telemetry(myrpt,TIMEOUT_WARNING,0);
11128 }
11129 }
11130 else
11131 {
11132 if (!last_timeout_warning)
11133 {
11134 time(&last_timeout_warning);
11135 rpt_telemetry(myrpt,TIMEOUT_WARNING,0);
11136 }
11137 }
11138 }
11139 }
11140 if (myrpt->p.remoteinacttimeout && myrpt->last_activity_time)
11141 {
11142 time_t r;
11143
11144 r = (t - myrpt->last_activity_time);
11145 if (r >= myrpt->p.remoteinacttimeout)
11146 {
11147 sayfile(chan,"rpt/node");
11148 ast_say_character_str(chan,myrpt->name,NULL,chan->language);
11149 sayfile(chan,"rpt/timeout");
11150 ast_safe_sleep(chan,1000);
11151 break;
11152 }
11153 if ((myrpt->p.remotetimeoutwarning) &&
11154 (r >= (myrpt->p.remoteinacttimeout -
11155 myrpt->p.remotetimeoutwarning)) &&
11156 (r <= (myrpt->p.remoteinacttimeout -
11157 myrpt->p.remotetimeoutwarningfreq)))
11158 {
11159 if (myrpt->p.remotetimeoutwarningfreq)
11160 {
11161 if ((t - last_timeout_warning) >=
11162 myrpt->p.remotetimeoutwarningfreq)
11163 {
11164 time(&last_timeout_warning);
11165 rpt_telemetry(myrpt,ACT_TIMEOUT_WARNING,0);
11166 }
11167 }
11168 else
11169 {
11170 if (!last_timeout_warning)
11171 {
11172 time(&last_timeout_warning);
11173 rpt_telemetry(myrpt,ACT_TIMEOUT_WARNING,0);
11174 }
11175 }
11176 }
11177 }
11178 ms = MSWAIT;
11179 who = ast_waitfor_n(cs,n,&ms);
11180 if (who == NULL) ms = 0;
11181 elap = MSWAIT - ms;
11182 if (myrpt->macrotimer) myrpt->macrotimer -= elap;
11183 if (myrpt->macrotimer < 0) myrpt->macrotimer = 0;
11184 if (!ms) continue;
11185
11186 if (myrpt->dtmf_local_timer)
11187 {
11188 if (myrpt->dtmf_local_timer > 1) myrpt->dtmf_local_timer -= elap;
11189 if (myrpt->dtmf_local_timer < 1) myrpt->dtmf_local_timer = 1;
11190 }
11191 rpt_mutex_lock(&myrpt->lock);
11192 do_dtmf_local(myrpt,0);
11193 rpt_mutex_unlock(&myrpt->lock);
11194 rem_totx = myrpt->dtmf_local_timer && (!phone_mode);
11195 rem_totx |= keyed && (!myrpt->tunerequest);
11196 rem_rx = (remkeyed && (!setting)) || (myrpt->tele.next != &myrpt->tele);
11197 if(!strcmp(myrpt->remote, remote_rig_ic706))
11198 rem_totx |= myrpt->tunerequest;
11199 if (keyed && (!keyed1))
11200 {
11201 keyed1 = 1;
11202 }
11203
11204 if (!keyed && (keyed1))
11205 {
11206 time_t myt;
11207
11208 keyed1 = 0;
11209 time(&myt);
11210
11211 if ((myrpt->p.authlevel) &&
11212 (!myrpt->loginlevel[0]) &&
11213 (myt > (t + 3)))
11214 {
11215 authreq = 1;
11216 authtold = 0;
11217 myrpt->authtelltimer = AUTHTELLTIME - AUTHTXTIME;
11218 }
11219 }
11220
11221
11222 if (rem_rx && (!myrpt->remoterx))
11223 {
11224 myrpt->remoterx = 1;
11225 ast_indicate(chan,AST_CONTROL_RADIO_KEY);
11226 }
11227 if ((!rem_rx) && (myrpt->remoterx))
11228 {
11229 myrpt->remoterx = 0;
11230 ast_indicate(chan,AST_CONTROL_RADIO_UNKEY);
11231 }
11232
11233 if (authreq && (!myrpt->loginlevel[0]))
11234 {
11235 if ((!authtold) && ((myrpt->authtelltimer += elap)
11236 >= AUTHTELLTIME))
11237 {
11238 authtold = 1;
11239 rpt_telemetry(myrpt,LOGINREQ,NULL);
11240 }
11241 if ((myrpt->authtimer += elap) >= AUTHLOGOUTTIME)
11242 {
11243 break;
11244 }
11245 }
11246 #ifndef OLDKEY
11247 if ((myrpt->retxtimer += elap) >= REDUNDANT_TX_TIME)
11248 {
11249 myrpt->retxtimer = 0;
11250 if ((myrpt->remoterx) && (!myrpt->remotetx))
11251 ast_indicate(chan,AST_CONTROL_RADIO_KEY);
11252 else
11253 ast_indicate(chan,AST_CONTROL_RADIO_UNKEY);
11254 }
11255
11256 if ((myrpt->rerxtimer += elap) >= (REDUNDANT_TX_TIME * 2))
11257 {
11258 keyed = 0;
11259 myrpt->rerxtimer = 0;
11260 }
11261 #endif
11262 if (rem_totx && (!myrpt->remotetx))
11263 {
11264
11265 if ((!myrpt->p.authlevel) || myrpt->loginlevel[0])
11266 {
11267 myrpt->remotetx = 1;
11268 if((myrpt->remtxfreqok = check_tx_freq(myrpt)))
11269 {
11270 time(&myrpt->last_activity_time);
11271 if (iskenwood_pci4)
11272 {
11273 z.radpar = ZT_RADPAR_UIODATA;
11274 z.data = 1;
11275 if (ioctl(myrpt->txchannel->fds[0],ZT_RADIO_SETPARAM,&z) == -1)
11276 {
11277 ast_log(LOG_ERROR,"Cannot set UIODATA\n");
11278 return -1;
11279 }
11280 }
11281 else
11282 {
11283 ast_indicate(myrpt->txchannel,AST_CONTROL_RADIO_KEY);
11284 }
11285 if (myrpt->p.archivedir) donodelog(myrpt,"TXKEY");
11286 }
11287 }
11288 }
11289 if ((!rem_totx) && myrpt->remotetx)
11290 {
11291 myrpt->remotetx = 0;
11292 if(!myrpt->remtxfreqok){
11293 rpt_telemetry(myrpt,UNAUTHTX,NULL);
11294 }
11295 if (iskenwood_pci4)
11296 {
11297 z.radpar = ZT_RADPAR_UIODATA;
11298 z.data = 3;
11299 if (ioctl(myrpt->txchannel->fds[0],ZT_RADIO_SETPARAM,&z) == -1)
11300 {
11301 ast_log(LOG_ERROR,"Cannot set UIODATA\n");
11302 return -1;
11303 }
11304 }
11305 else
11306 {
11307 ast_indicate(myrpt->txchannel,AST_CONTROL_RADIO_UNKEY);
11308 }
11309 if (myrpt->p.archivedir) donodelog(myrpt,"TXUNKEY");
11310 }
11311 if (myrpt->hfscanmode){
11312 myrpt->scantimer -= elap;
11313 if(myrpt->scantimer <= 0){
11314 if (!reming)
11315 {
11316 myrpt->scantimer = REM_SCANTIME;
11317 rpt_telemetry(myrpt,SCAN,0);
11318 } else myrpt->scantimer = 1;
11319 }
11320 }
11321 rpt_mutex_lock(&myrpt->lock);
11322 c = myrpt->macrobuf[0];
11323 if (c && (!myrpt->macrotimer))
11324 {
11325 myrpt->macrotimer = MACROTIME;
11326 memmove(myrpt->macrobuf,myrpt->macrobuf + 1,MAXMACRO - 1);
11327 if ((c == 'p') || (c == 'P'))
11328 myrpt->macrotimer = MACROPTIME;
11329 rpt_mutex_unlock(&myrpt->lock);
11330 if (myrpt->p.archivedir)
11331 {
11332 char str[100];
11333 sprintf(str,"DTMF(M),%c",c);
11334 donodelog(myrpt,str);
11335 }
11336 if (handle_remote_dtmf_digit(myrpt,c,&keyed,0) == -1) break;
11337 continue;
11338 } else rpt_mutex_unlock(&myrpt->lock);
11339 if (who == chan)
11340 {
11341 f = ast_read(chan);
11342 if (!f)
11343 {
11344 if (debug) printf("@@@@ link:Hung Up\n");
11345 break;
11346 }
11347 if (f->frametype == AST_FRAME_VOICE)
11348 {
11349 if (ioctl(chan->fds[0], ZT_GETCONFMUTE, &ismuted) == -1)
11350 {
11351 ismuted = 0;
11352 }
11353
11354 ismuted |= (!myrpt->remotetx);
11355 if (dtmfed && phone_mode) ismuted = 1;
11356 dtmfed = 0;
11357 if (ismuted)
11358 {
11359 memset(f->data,0,f->datalen);
11360 if (myrpt->lastf1)
11361 memset(myrpt->lastf1->data,0,myrpt->lastf1->datalen);
11362 if (myrpt->lastf2)
11363 memset(myrpt->lastf2->data,0,myrpt->lastf2->datalen);
11364 }
11365 if (f) f2 = ast_frdup(f);
11366 else f2 = NULL;
11367 f1 = myrpt->lastf2;
11368 myrpt->lastf2 = myrpt->lastf1;
11369 myrpt->lastf1 = f2;
11370 if (ismuted)
11371 {
11372 if (myrpt->lastf1)
11373 memset(myrpt->lastf1->data,0,myrpt->lastf1->datalen);
11374 if (myrpt->lastf2)
11375 memset(myrpt->lastf2->data,0,myrpt->lastf2->datalen);
11376 }
11377 if (f1)
11378 {
11379 if (phone_mode)
11380 ast_write(myrpt->txchannel,f1);
11381 else
11382 ast_write(myrpt->txchannel,f);
11383 ast_frfree(f1);
11384 }
11385 }
11386 #ifndef OLD_ASTERISK
11387 else if (f->frametype == AST_FRAME_DTMF_BEGIN)
11388 {
11389 if (myrpt->lastf1)
11390 memset(myrpt->lastf1->data,0,myrpt->lastf1->datalen);
11391 if (myrpt->lastf2)
11392 memset(myrpt->lastf2->data,0,myrpt->lastf2->datalen);
11393 dtmfed = 1;
11394 }
11395 #endif
11396 if (f->frametype == AST_FRAME_DTMF)
11397 {
11398 if (myrpt->lastf1)
11399 memset(myrpt->lastf1->data,0,myrpt->lastf1->datalen);
11400 if (myrpt->lastf2)
11401 memset(myrpt->lastf2->data,0,myrpt->lastf2->datalen);
11402 dtmfed = 1;
11403 if (handle_remote_phone_dtmf(myrpt,f->subclass,&keyed,phone_mode) == -1)
11404 {
11405 if (debug) printf("@@@@ rpt:Hung Up\n");
11406 ast_frfree(f);
11407 break;
11408 }
11409 }
11410 if (f->frametype == AST_FRAME_TEXT)
11411 {
11412 if (handle_remote_data(myrpt,f->data) == -1)
11413 {
11414 if (debug) printf("@@@@ rpt:Hung Up\n");
11415 ast_frfree(f);
11416 break;
11417 }
11418 }
11419 if (f->frametype == AST_FRAME_CONTROL)
11420 {
11421 if (f->subclass == AST_CONTROL_HANGUP)
11422 {
11423 if (debug) printf("@@@@ rpt:Hung Up\n");
11424 ast_frfree(f);
11425 break;
11426 }
11427
11428 if (f->subclass == AST_CONTROL_RADIO_KEY)
11429 {
11430 if (debug == 7) printf("@@@@ rx key\n");
11431 keyed = 1;
11432 myrpt->rerxtimer = 0;
11433 }
11434
11435 if (f->subclass == AST_CONTROL_RADIO_UNKEY)
11436 {
11437 myrpt->rerxtimer = 0;
11438 if (debug == 7) printf("@@@@ rx un-key\n");
11439 keyed = 0;
11440 }
11441 }
11442 ast_frfree(f);
11443 continue;
11444 }
11445 if (who == myrpt->rxchannel)
11446 {
11447 f = ast_read(myrpt->rxchannel);
11448 if (!f)
11449 {
11450 if (debug) printf("@@@@ link:Hung Up\n");
11451 break;
11452 }
11453 if (f->frametype == AST_FRAME_VOICE)
11454 {
11455 int myreming = 0;
11456
11457 if(!strcmp(myrpt->remote, remote_rig_kenwood))
11458 myreming = reming;
11459
11460 if (myreming || (!remkeyed) ||
11461 ((myrpt->remote) && (myrpt->remotetx)) ||
11462 ((myrpt->remmode != REM_MODE_FM) &&
11463 notremming))
11464 memset(f->data,0,f->datalen);
11465 ast_write(myrpt->pchannel,f);
11466 }
11467 else if (f->frametype == AST_FRAME_CONTROL)
11468 {
11469 if (f->subclass == AST_CONTROL_HANGUP)
11470 {
11471 if (debug) printf("@@@@ rpt:Hung Up\n");
11472 ast_frfree(f);
11473 break;
11474 }
11475
11476 if (f->subclass == AST_CONTROL_RADIO_KEY)
11477 {
11478 if (debug == 7) printf("@@@@ remote rx key\n");
11479 if (!myrpt->remotetx)
11480 {
11481 remkeyed = 1;
11482 }
11483 }
11484
11485 if (f->subclass == AST_CONTROL_RADIO_UNKEY)
11486 {
11487 if (debug == 7) printf("@@@@ remote rx un-key\n");
11488 if (!myrpt->remotetx)
11489 {
11490 remkeyed = 0;
11491 }
11492 }
11493 }
11494 ast_frfree(f);
11495 continue;
11496 }
11497 if (who == myrpt->pchannel)
11498 {
11499 f = ast_read(myrpt->pchannel);
11500 if (!f)
11501 {
11502 if (debug) printf("@@@@ link:Hung Up\n");
11503 break;
11504 }
11505 if (f->frametype == AST_FRAME_VOICE)
11506 {
11507 ast_write(chan,f);
11508 }
11509 if (f->frametype == AST_FRAME_CONTROL)
11510 {
11511 if (f->subclass == AST_CONTROL_HANGUP)
11512 {
11513 if (debug) printf("@@@@ rpt:Hung Up\n");
11514 ast_frfree(f);
11515 break;
11516 }
11517 }
11518 ast_frfree(f);
11519 continue;
11520 }
11521 if ((myrpt->rxchannel != myrpt->txchannel) &&
11522 (who == myrpt->txchannel))
11523 {
11524 f = ast_read(myrpt->txchannel);
11525 if (!f)
11526 {
11527 if (debug) printf("@@@@ link:Hung Up\n");
11528 break;
11529 }
11530 if (f->frametype == AST_FRAME_CONTROL)
11531 {
11532 if (f->subclass == AST_CONTROL_HANGUP)
11533 {
11534 if (debug) printf("@@@@ rpt:Hung Up\n");
11535 ast_frfree(f);
11536 break;
11537 }
11538 }
11539 ast_frfree(f);
11540 continue;
11541 }
11542 }
11543 if (myrpt->p.archivedir)
11544 {
11545 char mycmd[100],*b,*b1;
11546
11547
11548 if (!chan->cid.cid_num)
11549 {
11550 b1 = "0";
11551 } else {
11552 ast_callerid_parse(chan->cid.cid_num,&b,&b1);
11553 ast_shrink_phone_number(b1);
11554 }
11555 sprintf(mycmd,"DISCONNECT,%s",b1);
11556 donodelog(myrpt,mycmd);
11557 }
11558
11559 while(myrpt->tele.next != &myrpt->tele) usleep(100000);
11560 sprintf(tmp,"mixmonitor stop %s",chan->name);
11561 ast_cli_command(nullfd,tmp);
11562 close(nullfd);
11563 rpt_mutex_lock(&myrpt->lock);
11564 myrpt->hfscanmode = 0;
11565 myrpt->hfscanstatus = 0;
11566 myrpt->remoteon = 0;
11567 rpt_mutex_unlock(&myrpt->lock);
11568 if (myrpt->lastf1) ast_frfree(myrpt->lastf1);
11569 myrpt->lastf1 = NULL;
11570 if (myrpt->lastf2) ast_frfree(myrpt->lastf2);
11571 myrpt->lastf2 = NULL;
11572 if (iskenwood_pci4)
11573 {
11574 z.radpar = ZT_RADPAR_UIOMODE;
11575 z.data = 3;
11576 if (ioctl(myrpt->txchannel->fds[0],ZT_RADIO_SETPARAM,&z) == -1)
11577 {
11578 ast_log(LOG_ERROR,"Cannot set UIOMODE\n");
11579 return -1;
11580 }
11581 z.radpar = ZT_RADPAR_UIODATA;
11582 z.data = 3;
11583 if (ioctl(myrpt->txchannel->fds[0],ZT_RADIO_SETPARAM,&z) == -1)
11584 {
11585 ast_log(LOG_ERROR,"Cannot set UIODATA\n");
11586 return -1;
11587 }
11588 i = ZT_OFFHOOK;
11589 if (ioctl(myrpt->txchannel->fds[0],ZT_HOOK,&i) == -1)
11590 {
11591 ast_log(LOG_ERROR,"Cannot set hook\n");
11592 return -1;
11593 }
11594 }
11595 if (myrpt->iofd) close(myrpt->iofd);
11596 myrpt->iofd = -1;
11597 ast_hangup(myrpt->pchannel);
11598 if (myrpt->rxchannel != myrpt->txchannel) ast_hangup(myrpt->txchannel);
11599 ast_hangup(myrpt->rxchannel);
11600 closerem(myrpt);
11601 #ifdef OLD_ASTERISK
11602 LOCAL_USER_REMOVE(u);
11603 #endif
11604 return res;
11605 }
11606
11607 #ifdef OLD_ASTERISK
11608 int unload_module()
11609 #else
11610 static int unload_module(void)
11611 #endif
11612 {
11613 int i;
11614
11615 #ifdef OLD_ASTERISK
11616 STANDARD_HANGUP_LOCALUSERS;
11617 #endif
11618 for(i = 0; i < nrpts; i++) {
11619 if (!strcmp(rpt_vars[i].name,rpt_vars[i].p.nodes)) continue;
11620 ast_mutex_destroy(&rpt_vars[i].lock);
11621 ast_mutex_destroy(&rpt_vars[i].remlock);
11622 }
11623 i = ast_unregister_application(app);
11624
11625
11626 ast_cli_unregister(&cli_debug);
11627 ast_cli_unregister(&cli_dump);
11628 ast_cli_unregister(&cli_stats);
11629 ast_cli_unregister(&cli_lstats);
11630 ast_cli_unregister(&cli_nodes);
11631 ast_cli_unregister(&cli_reload);
11632 ast_cli_unregister(&cli_restart);
11633 ast_cli_unregister(&cli_fun);
11634
11635 return i;
11636 }
11637
11638 #ifdef OLD_ASTERISK
11639 int load_module()
11640 #else
11641 static int load_module(void)
11642 #endif
11643 {
11644 ast_pthread_create(&rpt_master_thread,NULL,rpt_master,NULL);
11645
11646
11647 ast_cli_register(&cli_debug);
11648 ast_cli_register(&cli_dump);
11649 ast_cli_register(&cli_stats);
11650 ast_cli_register(&cli_lstats);
11651 ast_cli_register(&cli_nodes);
11652 ast_cli_register(&cli_reload);
11653 ast_cli_register(&cli_restart);
11654 ast_cli_register(&cli_fun);
11655
11656 return ast_register_application(app, rpt_exec, synopsis, descrip);
11657 }
11658
11659 #ifdef OLD_ASTERISK
11660 char *description()
11661 {
11662 return tdesc;
11663 }
11664 int usecount(void)
11665 {
11666 int res;
11667 STANDARD_USECOUNT(res);
11668 return res;
11669 }
11670
11671 char *key()
11672 {
11673 return ASTERISK_GPL_KEY;
11674 }
11675 #endif
11676
11677 #ifdef OLD_ASTERISK
11678 int reload()
11679 #else
11680 static int reload(void)
11681 #endif
11682 {
11683 int n;
11684
11685 for(n = 0; n < nrpts; n++) rpt_vars[n].reload = 1;
11686 return(0);
11687 }
11688
11689 #ifndef OLD_ASTERISK
11690
11691 AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_DEFAULT, "Radio Repeater/Remote Base Application",
11692 .load = load_module,
11693 .unload = unload_module,
11694 .reload = reload,
11695 );
11696
11697 #endif
11698