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