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