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