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