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