00001 #define NEW_ASTERISK
00002
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
00156
00157
00158
00159
00160
00161
00162
00163
00164
00165
00166
00167
00168
00169
00170
00171 #ifdef OLD_ASTERISK
00172 #define ast_free free
00173 #define ast_malloc malloc
00174 #define ast_strdup strdup
00175 #endif
00176
00177
00178 #define MAXDTMF 32
00179 #define MAXMACRO 2048
00180 #define MAXLINKLIST 512
00181 #define LINKLISTTIME 10000
00182 #define LINKLISTSHORTTIME 200
00183 #define LINKPOSTTIME 30000
00184 #define LINKPOSTSHORTTIME 200
00185 #define KEYPOSTTIME 30000
00186 #define KEYPOSTSHORTTIME 200
00187 #define MACROTIME 100
00188 #define MACROPTIME 500
00189 #define DTMF_TIMEOUT 3
00190 #define KENWOOD_RETRIES 5
00191 #define TOPKEYN 32
00192 #define TOPKEYWAIT 3
00193 #define TOPKEYMAXSTR 30
00194
00195 #define AUTHTELLTIME 7000
00196 #define AUTHTXTIME 1000
00197 #define AUTHLOGOUTTIME 25000
00198
00199 #ifdef __RPT_NOTCH
00200 #define MAXFILTERS 10
00201 #endif
00202
00203 #define DISC_TIME 10000
00204 #define MAX_RETRIES 5
00205 #define MAX_RETRIES_PERM 1000000000
00206
00207 #define REDUNDANT_TX_TIME 2000
00208
00209 #define RETRY_TIMER_MS 5000
00210
00211 #define PATCH_DIALPLAN_TIMEOUT 1500
00212
00213 #ifdef OLD_ASTERISK
00214 #define START_DELAY 10
00215 #else
00216 #define START_DELAY 2
00217 #endif
00218
00219 #define RPT_LOCKOUT_SECS 10
00220
00221 #define MAXPEERSTR 31
00222 #define MAXREMSTR 15
00223
00224 #define DELIMCHR ','
00225 #define QUOTECHR 34
00226
00227 #define MONITOR_DISK_BLOCKS_PER_MINUTE 38
00228
00229 #define DEFAULT_MONITOR_MIN_DISK_BLOCKS 10000
00230 #define DEFAULT_REMOTE_INACT_TIMEOUT (15 * 60)
00231 #define DEFAULT_REMOTE_TIMEOUT (60 * 60)
00232 #define DEFAULT_REMOTE_TIMEOUT_WARNING (3 * 60)
00233 #define DEFAULT_REMOTE_TIMEOUT_WARNING_FREQ 30
00234
00235 #define NODES "nodes"
00236 #define EXTNODES "extnodes"
00237 #define MEMORY "memory"
00238 #define MACRO "macro"
00239 #define FUNCTIONS "functions"
00240 #define TELEMETRY "telemetry"
00241 #define MORSE "morse"
00242 #define TONEMACRO "tonemacro"
00243 #define FUNCCHAR '*'
00244 #define ENDCHAR '#'
00245 #define EXTNODEFILE "/var/lib/asterisk/rpt_extnodes"
00246 #define NODENAMES "rpt/nodenames"
00247 #define PARROTFILE "/tmp/parrot_%s_%u"
00248
00249 #define PARROTTIME 1000
00250
00251 #define DEFAULT_IOBASE 0x378
00252
00253 #define DEFAULT_CIV_ADDR 0x58
00254
00255 #define MAXCONNECTTIME 5000
00256
00257 #define MAXNODESTR 300
00258
00259 #define MAXNODELEN 16
00260
00261 #define MAXIDENTLEN 32
00262
00263 #define MAXPATCHCONTEXT 100
00264
00265 #define ACTIONSIZE 32
00266
00267 #define TELEPARAMSIZE 256
00268
00269 #define REM_SCANTIME 100
00270
00271 #define DTMF_LOCAL_TIME 250
00272 #define DTMF_LOCAL_STARTTIME 500
00273
00274 #define IC706_PL_MEMORY_OFFSET 50
00275
00276 #define VOX_ON_DEBOUNCE_COUNT 3
00277 #define VOX_OFF_DEBOUNCE_COUNT 20
00278 #define VOX_MAX_THRESHOLD 10000.0
00279 #define VOX_MIN_THRESHOLD 3000.0
00280 #define VOX_TIMEOUT_MS 5000
00281 #define VOX_RECOVER_MS 500
00282 #define SIMPLEX_PATCH_DELAY 25
00283 #define SIMPLEX_PHONE_DELAY 25
00284
00285 #define STATPOST_PROGRAM "/usr/bin/wget,-q,--output-document=/dev/null,--no-check-certificate"
00286
00287 #define ALLOW_LOCAL_CHANNELS
00288
00289 enum {REM_OFF,REM_MONITOR,REM_TX};
00290
00291 enum{ID,PROC,TERM,COMPLETE,UNKEY,REMDISC,REMALREADY,REMNOTFOUND,REMGO,
00292 CONNECTED,CONNFAIL,STATUS,TIMEOUT,ID1, STATS_TIME, PLAYBACK,
00293 STATS_VERSION, IDTALKOVER, ARB_ALPHA, TEST_TONE, REV_PATCH,
00294 TAILMSG, MACRO_NOTFOUND, MACRO_BUSY, LASTNODEKEY, FULLSTATUS,
00295 MEMNOTFOUND, INVFREQ, REMMODE, REMLOGIN, REMXXX, REMSHORTSTATUS,
00296 REMLONGSTATUS, LOGINREQ, SCAN, SCANSTAT, TUNE, SETREMOTE, TOPKEY,
00297 TIMEOUT_WARNING, ACT_TIMEOUT_WARNING, LINKUNKEY, UNAUTHTX, PARROT,
00298 STATS_TIME_LOCAL};
00299
00300
00301 enum {REM_SIMPLEX,REM_MINUS,REM_PLUS};
00302
00303 enum {REM_LOWPWR,REM_MEDPWR,REM_HIPWR};
00304
00305 enum {DC_INDETERMINATE, DC_REQ_FLUSH, DC_ERROR, DC_COMPLETE, DC_COMPLETEQUIET, DC_DOKEY};
00306
00307 enum {SOURCE_RPT, SOURCE_LNK, SOURCE_RMT, SOURCE_PHONE, SOURCE_DPHONE, SOURCE_ALT};
00308
00309 enum {DLY_TELEM, DLY_ID, DLY_UNKEY, DLY_CALLTERM, DLY_COMP, DLY_LINKUNKEY, DLY_PARROT};
00310
00311 enum {REM_MODE_FM,REM_MODE_USB,REM_MODE_LSB,REM_MODE_AM};
00312
00313 enum {HF_SCAN_OFF,HF_SCAN_DOWN_SLOW,HF_SCAN_DOWN_QUICK,
00314 HF_SCAN_DOWN_FAST,HF_SCAN_UP_SLOW,HF_SCAN_UP_QUICK,HF_SCAN_UP_FAST};
00315
00316 #include "asterisk.h"
00317
00318 ASTERISK_FILE_VERSION(__FILE__, "$Revision: 328209 $")
00319
00320 #include <signal.h>
00321 #include <stdio.h>
00322 #include <stdint.h>
00323 #include <unistd.h>
00324 #include <string.h>
00325 #include <stdlib.h>
00326 #include <search.h>
00327 #include <sys/types.h>
00328 #include <sys/stat.h>
00329 #include <errno.h>
00330 #include <dirent.h>
00331 #include <ctype.h>
00332 #include <sys/stat.h>
00333 #include <sys/time.h>
00334 #include <sys/file.h>
00335 #include <sys/ioctl.h>
00336 #ifdef HAVE_SYS_IO_H
00337 #include <sys/io.h>
00338 #endif
00339 #include <sys/vfs.h>
00340 #include <math.h>
00341 #include <dahdi/user.h>
00342 #include <dahdi/tonezone.h>
00343 #include <netinet/in.h>
00344 #include <arpa/inet.h>
00345
00346 #include "asterisk/utils.h"
00347 #include "asterisk/lock.h"
00348 #include "asterisk/file.h"
00349 #include "asterisk/logger.h"
00350 #include "asterisk/channel.h"
00351 #include "asterisk/callerid.h"
00352 #include "asterisk/pbx.h"
00353 #include "asterisk/module.h"
00354 #include "asterisk/translate.h"
00355 #include "asterisk/features.h"
00356 #include "asterisk/options.h"
00357 #include "asterisk/cli.h"
00358 #include "asterisk/config.h"
00359 #include "asterisk/say.h"
00360 #include "asterisk/localtime.h"
00361 #include "asterisk/cdr.h"
00362 #include "asterisk/options.h"
00363 #include "asterisk/manager.h"
00364 #include "asterisk/app.h"
00365
00366 #include <termios.h>
00367
00368 #ifdef NEW_ASTERISK
00369 struct ast_flags config_flags = { CONFIG_FLAG_WITHCOMMENTS };
00370 #endif
00371
00372
00373
00374 int ast_playtones_start(struct ast_channel *chan, int vol, const char* tonelist, int interruptible);
00375
00376 void ast_playtones_stop(struct ast_channel *chan);
00377
00378 static char *tdesc = "Radio Repeater / Remote Base version 0.115 5/12/2008";
00379
00380 static char *app = "Rpt";
00381
00382 static char *synopsis = "Radio Repeater/Remote Base Control System";
00383
00384 static char *descrip =
00385 " Rpt(nodename[|options][|M][|*]): \n"
00386 " Radio Remote Link or Remote Base Link Endpoint Process.\n"
00387 "\n"
00388 " Not specifying an option puts it in normal endpoint mode (where source\n"
00389 " IP and nodename are verified).\n"
00390 "\n"
00391 " Options are as follows:\n"
00392 "\n"
00393 " X - Normal endpoint mode WITHOUT security check. Only specify\n"
00394 " this if you have checked security already (like with an IAX2\n"
00395 " user/password or something).\n"
00396 "\n"
00397 " Rannounce-string[|timeout[|timeout-destination]] - Amateur Radio\n"
00398 " Reverse Autopatch. Caller is put on hold, and announcement (as\n"
00399 " specified by the 'announce-string') is played on radio system.\n"
00400 " Users of radio system can access autopatch, dial specified\n"
00401 " code, and pick up call. Announce-string is list of names of\n"
00402 " recordings, or \"PARKED\" to substitute code for un-parking,\n"
00403 " or \"NODE\" to substitute node number.\n"
00404 "\n"
00405 " P - Phone Control mode. This allows a regular phone user to have\n"
00406 " full control and audio access to the radio system. For the\n"
00407 " user to have DTMF control, the 'phone_functions' parameter\n"
00408 " must be specified for the node in 'rpt.conf'. An additional\n"
00409 " function (cop,6) must be listed so that PTT control is available.\n"
00410 "\n"
00411 " D - Dumb Phone Control mode. This allows a regular phone user to\n"
00412 " have full control and audio access to the radio system. In this\n"
00413 " mode, the PTT is activated for the entire length of the call.\n"
00414 " For the user to have DTMF control (not generally recomended in\n"
00415 " this mode), the 'dphone_functions' parameter must be specified\n"
00416 " for the node in 'rpt.conf'. Otherwise no DTMF control will be\n"
00417 " available to the phone user.\n"
00418 "\n"
00419 " S - Simplex Dumb Phone Control mode. This allows a regular phone user\n"
00420 " audio-only access to the radio system. In this mode, the\n"
00421 " transmitter is toggled on and off when the phone user presses the\n"
00422 " funcchar (*) key on the telephone set. In addition, the transmitter\n"
00423 " will turn off if the endchar (#) key is pressed. When a user first\n"
00424 " calls in, the transmitter will be off, and the user can listen for\n"
00425 " radio traffic. When the user wants to transmit, they press the *\n"
00426 " key, start talking, then press the * key again or the # key to turn\n"
00427 " the transmitter off. No other functions can be executed by the\n"
00428 " user on the phone when this mode is selected. Note: If your\n"
00429 " radio system is full-duplex, we recommend using either P or D\n"
00430 " modes as they provide more flexibility.\n"
00431 "\n"
00432 " q - Query Status. Sets channel variables and returns + 101 in plan.\n"
00433 "\n"
00434 " M - Memory Channel Steer as MXX where XX is the memory channel number.\n"
00435 "\n"
00436 " * - Alt Macro to execute (e.g. *7 for status)\n"
00437 "\n";
00438 ;
00439
00440 static int debug = 0;
00441 static int nrpts = 0;
00442
00443 static const char remdtmfstr[] = "0123456789*#ABCD";
00444
00445 enum {TOP_TOP,TOP_WON,WON_BEFREAD,BEFREAD_AFTERREAD};
00446
00447 int max_chan_stat [] = {22000,1000,22000,100,22000,2000,22000};
00448
00449 #define NRPTSTAT 7
00450
00451 struct rpt_chan_stat
00452 {
00453 struct timeval last;
00454 long long total;
00455 unsigned long count;
00456 unsigned long largest;
00457 struct timeval largest_time;
00458 };
00459
00460 char *discstr = "!!DISCONNECT!!";
00461 char *newkeystr = "!NEWKEY!";
00462 static char *remote_rig_ft897="ft897";
00463 static char *remote_rig_rbi="rbi";
00464 static char *remote_rig_kenwood="kenwood";
00465 static char *remote_rig_tm271="tm271";
00466 static char *remote_rig_ic706="ic706";
00467 static char *remote_rig_rtx150="rtx150";
00468 static char *remote_rig_rtx450="rtx450";
00469 static char *remote_rig_ppp16="ppp16";
00470
00471 #define ISRIG_RTX(x) ((!strcmp(x,remote_rig_rtx150)) || (!strcmp(x,remote_rig_rtx450)))
00472 #define IS_XPMR(x) (!strncasecmp(x->rxchanname,"rad",3))
00473
00474 #ifdef OLD_ASTERISK
00475 STANDARD_LOCAL_USER;
00476 LOCAL_USER_DECL;
00477 #endif
00478
00479 #define MSWAIT 200
00480 #define HANGTIME 5000
00481 #define TOTIME 180000
00482 #define IDTIME 300000
00483 #define MAXRPTS 20
00484 #define MAX_STAT_LINKS 32
00485 #define POLITEID 30000
00486 #define FUNCTDELAY 1500
00487
00488 #define MAXXLAT 20
00489 #define MAXXLATTIME 3
00490
00491 #define MAX_SYSSTATES 10
00492
00493 struct vox {
00494 float speech_energy;
00495 float noise_energy;
00496 int enacount;
00497 char voxena;
00498 char lastvox;
00499 int offdebcnt;
00500 int ondebcnt;
00501 } ;
00502
00503 #define mymax(x,y) ((x > y) ? x : y)
00504 #define mymin(x,y) ((x < y) ? x : y)
00505
00506 struct rpt_topkey
00507 {
00508 char node[TOPKEYMAXSTR];
00509 int timesince;
00510 int keyed;
00511 } ;
00512
00513 struct rpt_xlat
00514 {
00515 char funccharseq[MAXXLAT];
00516 char endcharseq[MAXXLAT];
00517 char passchars[MAXXLAT];
00518 int funcindex;
00519 int endindex;
00520 time_t lastone;
00521 } ;
00522
00523 static time_t starttime = 0;
00524
00525 static pthread_t rpt_master_thread;
00526
00527 struct rpt;
00528
00529 struct rpt_link
00530 {
00531 struct rpt_link *next;
00532 struct rpt_link *prev;
00533 char mode;
00534 char isremote;
00535 char phonemode;
00536 char phonevox;
00537 char name[MAXNODESTR];
00538 char lasttx;
00539 char lasttx1;
00540 char lastrx;
00541 char lastrealrx;
00542 char lastrx1;
00543 char connected;
00544 char hasconnected;
00545 char perma;
00546 char thisconnected;
00547 char outbound;
00548 char disced;
00549 char killme;
00550 long elaptime;
00551 long disctime;
00552 long retrytimer;
00553 long retxtimer;
00554 long rerxtimer;
00555 int retries;
00556 int max_retries;
00557 int reconnects;
00558 long long connecttime;
00559 struct ast_channel *chan;
00560 struct ast_channel *pchan;
00561 char linklist[MAXLINKLIST];
00562 time_t linklistreceived;
00563 long linklisttimer;
00564 int dtmfed;
00565 int linkunkeytocttimer;
00566 struct timeval lastlinktv;
00567 struct ast_frame *lastf1,*lastf2;
00568 struct rpt_chan_stat chan_stat[NRPTSTAT];
00569 struct vox vox;
00570 char wasvox;
00571 int voxtotimer;
00572 char voxtostate;
00573 char newkey;
00574 #ifdef OLD_ASTERISK
00575 AST_LIST_HEAD(, ast_frame) rxq;
00576 #else
00577 AST_LIST_HEAD_NOLOCK(, ast_frame) rxq;
00578 #endif
00579 } ;
00580
00581 struct rpt_lstat
00582 {
00583 struct rpt_lstat *next;
00584 struct rpt_lstat *prev;
00585 char peer[MAXPEERSTR];
00586 char name[MAXNODESTR];
00587 char mode;
00588 char outbound;
00589 char reconnects;
00590 char thisconnected;
00591 long long connecttime;
00592 struct rpt_chan_stat chan_stat[NRPTSTAT];
00593 } ;
00594
00595 struct rpt_tele
00596 {
00597 struct rpt_tele *next;
00598 struct rpt_tele *prev;
00599 struct rpt *rpt;
00600 struct ast_channel *chan;
00601 int mode;
00602 struct rpt_link mylink;
00603 char param[TELEPARAMSIZE];
00604 intptr_t submode;
00605 uintptr_t parrot;
00606 pthread_t threadid;
00607 } ;
00608
00609 struct function_table_tag
00610 {
00611 char action[ACTIONSIZE];
00612 int (*function)(struct rpt *myrpt, char *param, char *digitbuf,
00613 int command_source, struct rpt_link *mylink);
00614 } ;
00615
00616
00617
00618 struct morse_bits
00619 {
00620 int len;
00621 int ddcomb;
00622 } ;
00623
00624 struct telem_defaults
00625 {
00626 char name[20];
00627 char value[80];
00628 } ;
00629
00630
00631 struct sysstate
00632 {
00633 char txdisable;
00634 char totdisable;
00635 char linkfundisable;
00636 char autopatchdisable;
00637 char schedulerdisable;
00638 char userfundisable;
00639 char alternatetail;
00640 };
00641
00642
00643 #define CMD_DEPTH 1
00644 #define CMD_STATE_IDLE 0
00645 #define CMD_STATE_BUSY 1
00646 #define CMD_STATE_READY 2
00647 #define CMD_STATE_EXECUTING 3
00648
00649 struct rpt_cmd_struct
00650 {
00651 int state;
00652 int functionNumber;
00653 char param[MAXDTMF];
00654 char digits[MAXDTMF];
00655 int command_source;
00656 };
00657
00658 static struct rpt
00659 {
00660 ast_mutex_t lock;
00661 ast_mutex_t remlock;
00662 ast_mutex_t statpost_lock;
00663 struct ast_config *cfg;
00664 char reload;
00665 char xlink;
00666 unsigned int statpost_seqno;
00667
00668 char *name;
00669 char *rxchanname;
00670 char *txchanname;
00671 char remote;
00672 char *remoterig;
00673 struct rpt_chan_stat chan_stat[NRPTSTAT];
00674 unsigned int scram;
00675
00676 struct {
00677 char *ourcontext;
00678 char *ourcallerid;
00679 char *acctcode;
00680 char *ident;
00681 char *tonezone;
00682 char simple;
00683 char *functions;
00684 char *link_functions;
00685 char *phone_functions;
00686 char *dphone_functions;
00687 char *alt_functions;
00688 char *nodes;
00689 char *extnodes;
00690 char *extnodefile;
00691 int hangtime;
00692 int althangtime;
00693 int totime;
00694 int idtime;
00695 int tailmessagetime;
00696 int tailsquashedtime;
00697 int duplex;
00698 int politeid;
00699 char *tailmessages[500];
00700 int tailmessagemax;
00701 char *memory;
00702 char *macro;
00703 char *tonemacro;
00704 char *startupmacro;
00705 int iobase;
00706 char *ioport;
00707 char funcchar;
00708 char endchar;
00709 char nobusyout;
00710 char notelemtx;
00711 char propagate_dtmf;
00712 char propagate_phonedtmf;
00713 char linktolink;
00714 unsigned char civaddr;
00715 struct rpt_xlat inxlat;
00716 struct rpt_xlat outxlat;
00717 char *archivedir;
00718 int authlevel;
00719 char *csstanzaname;
00720 char *skedstanzaname;
00721 char *txlimitsstanzaname;
00722 long monminblocks;
00723 int remoteinacttimeout;
00724 int remotetimeout;
00725 int remotetimeoutwarning;
00726 int remotetimeoutwarningfreq;
00727 int sysstate_cur;
00728 struct sysstate s[MAX_SYSSTATES];
00729 char parrotmode;
00730 int parrottime;
00731 char *rptnode;
00732 char remote_mars;
00733 int voxtimeout_ms;
00734 int voxrecover_ms;
00735 int simplexpatchdelay;
00736 int simplexphonedelay;
00737 char *statpost_program;
00738 char *statpost_url;
00739 } p;
00740 struct rpt_link links;
00741 int unkeytocttimer;
00742 time_t lastkeyedtime;
00743 time_t lasttxkeyedtime;
00744 char keyed;
00745 char txkeyed;
00746 char exttx;
00747 char localtx;
00748 char remoterx;
00749 char remotetx;
00750 char remoteon;
00751 char remtxfreqok;
00752 char tounkeyed;
00753 char tonotify;
00754 char dtmfbuf[MAXDTMF];
00755 char macrobuf[MAXMACRO];
00756 char rem_dtmfbuf[MAXDTMF];
00757 char lastdtmfcommand[MAXDTMF];
00758 char cmdnode[50];
00759 char nowchan;
00760 char waschan;
00761 char bargechan;
00762 char macropatch;
00763 char parrotstate;
00764 int parrottimer;
00765 unsigned int parrotcnt;
00766 struct ast_channel *rxchannel,*txchannel, *monchannel, *parrotchannel;
00767 struct ast_channel *pchannel,*txpchannel, *dahdirxchannel, *dahditxchannel;
00768 struct ast_channel *voxchannel;
00769 struct ast_frame *lastf1,*lastf2;
00770 struct rpt_tele tele;
00771 struct timeval lasttv,curtv;
00772 pthread_t rpt_call_thread,rpt_thread;
00773 time_t dtmf_time,rem_dtmf_time,dtmf_time_rem;
00774 int calldigittimer;
00775 int tailtimer,totimer,idtimer,txconf,conf,callmode,cidx,scantimer,tmsgtimer,skedtimer;
00776 int mustid,tailid;
00777 int tailevent;
00778 int telemrefcount;
00779 int dtmfidx,rem_dtmfidx;
00780 int dailytxtime,dailykerchunks,totalkerchunks,dailykeyups,totalkeyups,timeouts;
00781 int totalexecdcommands, dailyexecdcommands;
00782 long retxtimer;
00783 long rerxtimer;
00784 long long totaltxtime;
00785 char mydtmf;
00786 char exten[AST_MAX_EXTENSION];
00787 char freq[MAXREMSTR],rxpl[MAXREMSTR],txpl[MAXREMSTR];
00788 char offset;
00789 char powerlevel;
00790 char txplon;
00791 char rxplon;
00792 char remmode;
00793 char tunerequest;
00794 char hfscanmode;
00795 int hfscanstatus;
00796 char hfscanstop;
00797 char lastlinknode[MAXNODESTR];
00798 char savednodes[MAXNODESTR];
00799 int stopgen;
00800 char patchfarenddisconnect;
00801 char patchnoct;
00802 char patchquiet;
00803 char patchcontext[MAXPATCHCONTEXT];
00804 int patchdialtime;
00805 int macro_longest;
00806 int phone_longestfunc;
00807 int alt_longestfunc;
00808 int dphone_longestfunc;
00809 int link_longestfunc;
00810 int longestfunc;
00811 int longestnode;
00812 int threadrestarts;
00813 int tailmessagen;
00814 time_t disgorgetime;
00815 time_t lastthreadrestarttime;
00816 long macrotimer;
00817 char lastnodewhichkeyedusup[MAXNODESTR];
00818 int dtmf_local_timer;
00819 char dtmf_local_str[100];
00820 struct ast_filestream *monstream,*parrotstream;
00821 char loginuser[50];
00822 char loginlevel[10];
00823 long authtelltimer;
00824 long authtimer;
00825 int iofd;
00826 time_t start_time,last_activity_time;
00827 char lasttone[32];
00828 struct rpt_tele *active_telem;
00829 struct rpt_topkey topkey[TOPKEYN];
00830 int topkeystate;
00831 time_t topkeytime;
00832 int topkeylong;
00833 struct vox vox;
00834 char wasvox;
00835 int voxtotimer;
00836 char voxtostate;
00837 int linkposttimer;
00838 int keyposttimer;
00839 char newkey;
00840 char inpadtest;
00841 #ifdef OLD_ASTERISK
00842 AST_LIST_HEAD(, ast_frame) txq;
00843 #else
00844 AST_LIST_HEAD_NOLOCK(, ast_frame) txq;
00845 #endif
00846 char txrealkeyed;
00847 #ifdef __RPT_NOTCH
00848 struct rptfilter
00849 {
00850 char desc[100];
00851 float x0;
00852 float x1;
00853 float x2;
00854 float y0;
00855 float y1;
00856 float y2;
00857 float gain;
00858 float const0;
00859 float const1;
00860 float const2;
00861 } filters[MAXFILTERS];
00862 #endif
00863 #ifdef _MDC_DECODE_H_
00864 mdc_decoder_t *mdc;
00865 unsigned short lastunit;
00866 #endif
00867 struct rpt_cmd_struct cmdAction;
00868 } rpt_vars[MAXRPTS];
00869
00870 struct nodelog {
00871 struct nodelog *next;
00872 struct nodelog *prev;
00873 time_t timestamp;
00874 char archivedir[MAXNODESTR];
00875 char str[MAXNODESTR * 2];
00876 } nodelog;
00877
00878 static int service_scan(struct rpt *myrpt);
00879 static int set_mode_ft897(struct rpt *myrpt, char newmode);
00880 static int set_mode_ic706(struct rpt *myrpt, char newmode);
00881 static int simple_command_ft897(struct rpt *myrpt, char command);
00882 static int setrem(struct rpt *myrpt);
00883 static int setrtx_check(struct rpt *myrpt);
00884 static int channel_revert(struct rpt *myrpt);
00885 static int channel_steer(struct rpt *myrpt, char *data);
00886
00887 AST_MUTEX_DEFINE_STATIC(nodeloglock);
00888
00889 AST_MUTEX_DEFINE_STATIC(nodelookuplock);
00890
00891 #ifdef APP_RPT_LOCK_DEBUG
00892
00893 #warning COMPILING WITH LOCK-DEBUGGING ENABLED!!
00894
00895 #define MAXLOCKTHREAD 100
00896
00897 #define rpt_mutex_lock(x) _rpt_mutex_lock(x,myrpt,__LINE__)
00898 #define rpt_mutex_unlock(x) _rpt_mutex_unlock(x,myrpt,__LINE__)
00899
00900 struct lockthread
00901 {
00902 pthread_t id;
00903 int lockcount;
00904 int lastlock;
00905 int lastunlock;
00906 } lockthreads[MAXLOCKTHREAD];
00907
00908
00909 struct by_lightning
00910 {
00911 int line;
00912 struct timeval tv;
00913 struct rpt *rpt;
00914 struct lockthread lockthread;
00915 } lock_ring[32];
00916
00917 int lock_ring_index = 0;
00918
00919 AST_MUTEX_DEFINE_STATIC(locklock);
00920
00921 static struct lockthread *get_lockthread(pthread_t id)
00922 {
00923 int i;
00924
00925 for(i = 0; i < MAXLOCKTHREAD; i++)
00926 {
00927 if (lockthreads[i].id == id) return(&lockthreads[i]);
00928 }
00929 return(NULL);
00930 }
00931
00932 static struct lockthread *put_lockthread(pthread_t id)
00933 {
00934 int i;
00935
00936 for(i = 0; i < MAXLOCKTHREAD; i++)
00937 {
00938 if (lockthreads[i].id == id)
00939 return(&lockthreads[i]);
00940 }
00941 for(i = 0; i < MAXLOCKTHREAD; i++)
00942 {
00943 if (!lockthreads[i].id)
00944 {
00945 lockthreads[i].lockcount = 0;
00946 lockthreads[i].lastlock = 0;
00947 lockthreads[i].lastunlock = 0;
00948 lockthreads[i].id = id;
00949 return(&lockthreads[i]);
00950 }
00951 }
00952 return(NULL);
00953 }
00954
00955
00956 static void rpt_mutex_spew(void)
00957 {
00958 struct by_lightning lock_ring_copy[32];
00959 int lock_ring_index_copy;
00960 int i,j;
00961 long long diff;
00962 char a[100];
00963 struct timeval lasttv;
00964
00965 ast_mutex_lock(&locklock);
00966 memcpy(&lock_ring_copy, &lock_ring, sizeof(lock_ring_copy));
00967 lock_ring_index_copy = lock_ring_index;
00968 ast_mutex_unlock(&locklock);
00969
00970 lasttv.tv_sec = lasttv.tv_usec = 0;
00971 for(i = 0 ; i < 32 ; i++)
00972 {
00973 j = (i + lock_ring_index_copy) % 32;
00974 strftime(a,sizeof(a) - 1,"%m/%d/%Y %H:%M:%S",
00975 localtime(&lock_ring_copy[j].tv.tv_sec));
00976 diff = 0;
00977 if(lasttv.tv_sec)
00978 {
00979 diff = (lock_ring_copy[j].tv.tv_sec - lasttv.tv_sec)
00980 * 1000000;
00981 diff += (lock_ring_copy[j].tv.tv_usec - lasttv.tv_usec);
00982 }
00983 lasttv.tv_sec = lock_ring_copy[j].tv.tv_sec;
00984 lasttv.tv_usec = lock_ring_copy[j].tv.tv_usec;
00985 if (!lock_ring_copy[j].tv.tv_sec) continue;
00986 if (lock_ring_copy[j].line < 0)
00987 {
00988 ast_log(LOG_NOTICE,"LOCKDEBUG [#%d] UNLOCK app_rpt.c:%d node %s pid %x diff %lld us at %s.%06d\n",
00989 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);
00990 }
00991 else
00992 {
00993 ast_log(LOG_NOTICE,"LOCKDEBUG [#%d] LOCK app_rpt.c:%d node %s pid %x diff %lld us at %s.%06d\n",
00994 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);
00995 }
00996 }
00997 }
00998
00999
01000 static void _rpt_mutex_lock(ast_mutex_t *lockp, struct rpt *myrpt, int line)
01001 {
01002 struct lockthread *t;
01003 pthread_t id;
01004
01005 id = pthread_self();
01006 ast_mutex_lock(&locklock);
01007 t = put_lockthread(id);
01008 if (!t)
01009 {
01010 ast_mutex_unlock(&locklock);
01011 return;
01012 }
01013 if (t->lockcount)
01014 {
01015 int lastline = t->lastlock;
01016 ast_mutex_unlock(&locklock);
01017 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);
01018 rpt_mutex_spew();
01019 return;
01020 }
01021 t->lastlock = line;
01022 t->lockcount = 1;
01023 gettimeofday(&lock_ring[lock_ring_index].tv, NULL);
01024 lock_ring[lock_ring_index].rpt = myrpt;
01025 memcpy(&lock_ring[lock_ring_index].lockthread,t,sizeof(struct lockthread));
01026 lock_ring[lock_ring_index++].line = line;
01027 if(lock_ring_index == 32)
01028 lock_ring_index = 0;
01029 ast_mutex_unlock(&locklock);
01030 ast_mutex_lock(lockp);
01031 }
01032
01033
01034 static void _rpt_mutex_unlock(ast_mutex_t *lockp, struct rpt *myrpt, int line)
01035 {
01036 struct lockthread *t;
01037 pthread_t id;
01038
01039 id = pthread_self();
01040 ast_mutex_lock(&locklock);
01041 t = put_lockthread(id);
01042 if (!t)
01043 {
01044 ast_mutex_unlock(&locklock);
01045 return;
01046 }
01047 if (!t->lockcount)
01048 {
01049 int lastline = t->lastunlock;
01050 ast_mutex_unlock(&locklock);
01051 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);
01052 rpt_mutex_spew();
01053 return;
01054 }
01055 t->lastunlock = line;
01056 t->lockcount = 0;
01057 gettimeofday(&lock_ring[lock_ring_index].tv, NULL);
01058 lock_ring[lock_ring_index].rpt = myrpt;
01059 memcpy(&lock_ring[lock_ring_index].lockthread,t,sizeof(struct lockthread));
01060 lock_ring[lock_ring_index++].line = -line;
01061 if(lock_ring_index == 32)
01062 lock_ring_index = 0;
01063 ast_mutex_unlock(&locklock);
01064 ast_mutex_unlock(lockp);
01065 }
01066
01067 #else
01068
01069 #define rpt_mutex_lock(x) ast_mutex_lock(x)
01070 #define rpt_mutex_unlock(x) ast_mutex_unlock(x)
01071
01072 #endif
01073
01074
01075
01076
01077
01078 static int multimode_capable(struct rpt *myrpt)
01079 {
01080 if(!strcmp(myrpt->remoterig, remote_rig_ft897))
01081 return 1;
01082 if(!strcmp(myrpt->remoterig, remote_rig_ic706))
01083 return 1;
01084 return 0;
01085 }
01086
01087 static void voxinit_rpt(struct rpt *myrpt,char enable)
01088 {
01089
01090 myrpt->vox.speech_energy = 0.0;
01091 myrpt->vox.noise_energy = 0.0;
01092 myrpt->vox.enacount = 0;
01093 myrpt->vox.voxena = 0;
01094 if (!enable) myrpt->vox.voxena = -1;
01095 myrpt->vox.lastvox = 0;
01096 myrpt->vox.ondebcnt = VOX_ON_DEBOUNCE_COUNT;
01097 myrpt->vox.offdebcnt = VOX_OFF_DEBOUNCE_COUNT;
01098 myrpt->wasvox = 0;
01099 myrpt->voxtotimer = 0;
01100 myrpt->voxtostate = 0;
01101 }
01102
01103 static void voxinit_link(struct rpt_link *mylink,char enable)
01104 {
01105
01106 mylink->vox.speech_energy = 0.0;
01107 mylink->vox.noise_energy = 0.0;
01108 mylink->vox.enacount = 0;
01109 mylink->vox.voxena = 0;
01110 if (!enable) mylink->vox.voxena = -1;
01111 mylink->vox.lastvox = 0;
01112 mylink->vox.ondebcnt = VOX_ON_DEBOUNCE_COUNT;
01113 mylink->vox.offdebcnt = VOX_OFF_DEBOUNCE_COUNT;
01114 mylink->wasvox = 0;
01115 mylink->voxtotimer = 0;
01116 mylink->voxtostate = 0;
01117 }
01118
01119 static int dovox(struct vox *v,short *buf,int bs)
01120 {
01121
01122 int i;
01123 float esquare = 0.0;
01124 float energy = 0.0;
01125 float threshold = 0.0;
01126
01127 if (v->voxena < 0) return(v->lastvox);
01128 for(i = 0; i < bs; i++)
01129 {
01130 esquare += (float) buf[i] * (float) buf[i];
01131 }
01132 energy = sqrt(esquare);
01133
01134 if (energy >= v->speech_energy)
01135 v->speech_energy += (energy - v->speech_energy) / 4;
01136 else
01137 v->speech_energy += (energy - v->speech_energy) / 64;
01138
01139 if (energy >= v->noise_energy)
01140 v->noise_energy += (energy - v->noise_energy) / 64;
01141 else
01142 v->noise_energy += (energy - v->noise_energy) / 4;
01143
01144 if (v->voxena) threshold = v->speech_energy / 8;
01145 else
01146 {
01147 threshold = mymax(v->speech_energy / 16,v->noise_energy * 2);
01148 threshold = mymin(threshold,VOX_MAX_THRESHOLD);
01149 }
01150 threshold = mymax(threshold,VOX_MIN_THRESHOLD);
01151 if (energy > threshold)
01152 {
01153 if (v->voxena) v->noise_energy *= 0.75;
01154 v->voxena = 1;
01155 } else v->voxena = 0;
01156 if (v->lastvox != v->voxena)
01157 {
01158 if (v->enacount++ >= ((v->lastvox) ? v->offdebcnt : v->ondebcnt))
01159 {
01160 v->lastvox = v->voxena;
01161 v->enacount = 0;
01162 }
01163 } else v->enacount = 0;
01164 return(v->lastvox);
01165 }
01166
01167
01168
01169
01170
01171
01172
01173
01174
01175 static int rpt_do_debug(int fd, int argc, const char * const *argv);
01176 static int rpt_do_dump(int fd, int argc, const char * const *argv);
01177 static int rpt_do_stats(int fd, int argc, const char * const *argv);
01178 static int rpt_do_lstats(int fd, int argc, const char * const *argv);
01179 static int rpt_do_nodes(int fd, int argc, const char * const *argv);
01180 static int rpt_do_local_nodes(int fd, int argc, const char * const *argv);
01181 static int rpt_do_reload(int fd, int argc, const char * const *argv);
01182 static int rpt_do_restart(int fd, int argc, const char * const *argv);
01183 static int rpt_do_fun(int fd, int argc, const char * const *argv);
01184 static int rpt_do_fun1(int fd, int argc, const char * const *argv);
01185 static int rpt_do_cmd(int fd, int argc, const char * const *argv);
01186
01187 static char debug_usage[] =
01188 "Usage: rpt debug level {0-7}\n"
01189 " Enables debug messages in app_rpt\n";
01190
01191 static char dump_usage[] =
01192 "Usage: rpt dump <nodename>\n"
01193 " Dumps struct debug info to log\n";
01194
01195 static char dump_stats[] =
01196 "Usage: rpt stats <nodename>\n"
01197 " Dumps node statistics to console\n";
01198
01199 static char dump_lstats[] =
01200 "Usage: rpt lstats <nodename>\n"
01201 " Dumps link statistics to console\n";
01202
01203 static char dump_nodes[] =
01204 "Usage: rpt nodes <nodename>\n"
01205 " Dumps a list of directly and indirectly connected nodes to the console\n";
01206
01207 static char usage_local_nodes[] =
01208 "Usage: rpt localnodes\n"
01209 " Dumps a list of the locally configured node numbers to the console.\n";
01210
01211 static char reload_usage[] =
01212 "Usage: rpt reload\n"
01213 " Reloads app_rpt running config parameters\n";
01214
01215 static char restart_usage[] =
01216 "Usage: rpt restart\n"
01217 " Restarts app_rpt\n";
01218
01219 static char fun_usage[] =
01220 "Usage: rpt fun <nodename> <command>\n"
01221 " Send a DTMF function to a node\n";
01222
01223 static char cmd_usage[] =
01224 "Usage: rpt cmd <nodename> <cmd-name> <cmd-index> <cmd-args.\n"
01225 " Send a command to a node.\n i.e. rpt cmd 2000 ilink 3 2001\n";
01226
01227 #ifndef NEW_ASTERISK
01228
01229 static struct ast_cli_entry cli_debug =
01230 { { "rpt", "debug", "level" }, rpt_do_debug,
01231 "Enable app_rpt debugging", debug_usage };
01232
01233 static struct ast_cli_entry cli_dump =
01234 { { "rpt", "dump" }, rpt_do_dump,
01235 "Dump app_rpt structs for debugging", dump_usage };
01236
01237 static struct ast_cli_entry cli_stats =
01238 { { "rpt", "stats" }, rpt_do_stats,
01239 "Dump node statistics", dump_stats };
01240
01241 static struct ast_cli_entry cli_nodes =
01242 { { "rpt", "nodes" }, rpt_do_nodes,
01243 "Dump node list", dump_nodes };
01244
01245 static struct ast_cli_entry cli_local_nodes =
01246 { { "rpt", "localnodes" }, rpt_do_local_nodes,
01247 "Dump list of local node numbers", usage_local_nodes };
01248
01249 static struct ast_cli_entry cli_lstats =
01250 { { "rpt", "lstats" }, rpt_do_lstats,
01251 "Dump link statistics", dump_lstats };
01252
01253 static struct ast_cli_entry cli_reload =
01254 { { "rpt", "reload" }, rpt_do_reload,
01255 "Reload app_rpt config", reload_usage };
01256
01257 static struct ast_cli_entry cli_restart =
01258 { { "rpt", "restart" }, rpt_do_restart,
01259 "Restart app_rpt", restart_usage };
01260
01261 static struct ast_cli_entry cli_fun =
01262 { { "rpt", "fun" }, rpt_do_fun,
01263 "Execute a DTMF function", fun_usage };
01264
01265 static struct ast_cli_entry cli_fun1 =
01266 { { "rpt", "fun1" }, rpt_do_fun1,
01267 "Execute a DTMF function", fun_usage };
01268
01269 static struct ast_cli_entry cli_cmd =
01270 { { "rpt", "cmd" }, rpt_do_cmd,
01271 "Execute a DTMF function", cmd_usage };
01272
01273 #endif
01274
01275
01276
01277
01278
01279
01280 static struct telem_defaults tele_defs[] = {
01281 {"ct1","|t(350,0,100,3072)(500,0,100,3072)(660,0,100,3072)"},
01282 {"ct2","|t(660,880,150,3072)"},
01283 {"ct3","|t(440,0,150,3072)"},
01284 {"ct4","|t(550,0,150,3072)"},
01285 {"ct5","|t(660,0,150,3072)"},
01286 {"ct6","|t(880,0,150,3072)"},
01287 {"ct7","|t(660,440,150,3072)"},
01288 {"ct8","|t(700,1100,150,3072)"},
01289 {"remotemon","|t(1600,0,75,2048)"},
01290 {"remotetx","|t(2000,0,75,2048)(0,0,75,0)(1600,0,75,2048)"},
01291 {"cmdmode","|t(900,904,200,2048)"},
01292 {"functcomplete","|t(1000,0,100,2048)(0,0,100,0)(1000,0,100,2048)"}
01293 } ;
01294
01295
01296
01297
01298
01299 static int setrbi(struct rpt *myrpt);
01300 static int set_ft897(struct rpt *myrpt);
01301 static int set_ic706(struct rpt *myrpt);
01302 static int setkenwood(struct rpt *myrpt);
01303 static int set_tm271(struct rpt *myrpt);
01304 static int setrbi_check(struct rpt *myrpt);
01305
01306
01307
01308
01309
01310
01311
01312 static int function_ilink(struct rpt *myrpt, char *param, char *digitbuf, int command_source, struct rpt_link *mylink);
01313 static int function_autopatchup(struct rpt *myrpt, char *param, char *digitbuf, int command_source, struct rpt_link *mylink);
01314 static int function_autopatchdn(struct rpt *myrpt, char *param, char *digitbuf, int command_source, struct rpt_link *mylink);
01315 static int function_status(struct rpt *myrpt, char *param, char *digitbuf, int command_source, struct rpt_link *mylink);
01316 static int function_cop(struct rpt *myrpt, char *param, char *digitbuf, int command_source, struct rpt_link *mylink);
01317 static int function_remote(struct rpt *myrpt, char *param, char *digitbuf, int command_source, struct rpt_link *mylink);
01318 static int function_macro(struct rpt *myrpt, char *param, char *digitbuf, int command_source, struct rpt_link *mylink);
01319 static int function_playback(struct rpt *myrpt, char *param, char *digitbuf, int command_source, struct rpt_link *mylink);
01320
01321
01322
01323
01324 static struct function_table_tag function_table[] = {
01325 {"cop", function_cop},
01326 {"autopatchup", function_autopatchup},
01327 {"autopatchdn", function_autopatchdn},
01328 {"ilink", function_ilink},
01329 {"status", function_status},
01330 {"remote", function_remote},
01331 {"macro", function_macro},
01332 {"playback", function_playback}
01333 } ;
01334
01335 static long diskavail(struct rpt *myrpt)
01336 {
01337 struct statfs statfsbuf;
01338
01339 if (!myrpt->p.archivedir) return(0);
01340 if (statfs(myrpt->p.archivedir,&statfsbuf) == -1)
01341 {
01342 ast_log(LOG_WARNING,"Cannot get filesystem size for %s node %s\n",
01343 myrpt->p.archivedir,myrpt->name);
01344 return(-1);
01345 }
01346 return(statfsbuf.f_bavail);
01347 }
01348
01349 static void flush_telem(struct rpt *myrpt)
01350 {
01351 struct rpt_tele *telem;
01352 if(debug > 2)
01353 ast_log(LOG_NOTICE, "flush_telem()!!");
01354 rpt_mutex_lock(&myrpt->lock);
01355 telem = myrpt->tele.next;
01356 while(telem != &myrpt->tele)
01357 {
01358 if (telem->mode != SETREMOTE) ast_softhangup(telem->chan,AST_SOFTHANGUP_DEV);
01359 telem = telem->next;
01360 }
01361 rpt_mutex_unlock(&myrpt->lock);
01362 }
01363
01364
01365
01366 static int priority_jump(struct rpt *myrpt, struct ast_channel *chan)
01367 {
01368 int res=0;
01369
01370
01371 if (ast_goto_if_exists(chan, chan->context, chan->exten, chan->priority + 101) == 0){
01372 res = 0;
01373 } else {
01374 res = -1;
01375 }
01376 return res;
01377 }
01378
01379
01380 static int linkcount(struct rpt *myrpt)
01381 {
01382 struct rpt_link *l;
01383 char *reverse_patch_state;
01384 int numoflinks;
01385
01386 reverse_patch_state = "DOWN";
01387 numoflinks = 0;
01388 l = myrpt->links.next;
01389 while(l && (l != &myrpt->links)){
01390 if(numoflinks >= MAX_STAT_LINKS){
01391 ast_log(LOG_WARNING,
01392 "maximum number of links exceeds %d in rpt_do_stats()!",MAX_STAT_LINKS);
01393 break;
01394 }
01395
01396
01397
01398
01399
01400 numoflinks++;
01401
01402 l = l->next;
01403 }
01404 ast_log(LOG_NOTICE, "numoflinks=%i\n",numoflinks);
01405 return numoflinks;
01406 }
01407
01408
01409
01410
01411
01412
01413 static int retreive_memory(struct rpt *myrpt, char *memory)
01414 {
01415 char tmp[30], *s, *s1, *val;
01416
01417 if (debug)ast_log(LOG_NOTICE, "memory=%s block=%s\n",memory,myrpt->p.memory);
01418
01419 val = (char *) ast_variable_retrieve(myrpt->cfg, myrpt->p.memory, memory);
01420 if (!val){
01421 return -1;
01422 }
01423 strncpy(tmp,val,sizeof(tmp) - 1);
01424 tmp[sizeof(tmp)-1] = 0;
01425
01426 s = strchr(tmp,',');
01427 if (!s)
01428 return 1;
01429 *s++ = 0;
01430 s1 = strchr(s,',');
01431 if (!s1)
01432 return 1;
01433 *s1++ = 0;
01434 strncpy(myrpt->freq, tmp, sizeof(myrpt->freq) - 1);
01435 strncpy(myrpt->rxpl, s, sizeof(myrpt->rxpl) - 1);
01436 strncpy(myrpt->txpl, s, sizeof(myrpt->rxpl) - 1);
01437 myrpt->remmode = REM_MODE_FM;
01438 myrpt->offset = REM_SIMPLEX;
01439 myrpt->powerlevel = REM_MEDPWR;
01440 myrpt->txplon = myrpt->rxplon = 0;
01441 while(*s1){
01442 switch(*s1++){
01443 case 'A':
01444 case 'a':
01445 strcpy(myrpt->rxpl, "100.0");
01446 strcpy(myrpt->txpl, "100.0");
01447 myrpt->remmode = REM_MODE_AM;
01448 break;
01449 case 'B':
01450 case 'b':
01451 strcpy(myrpt->rxpl, "100.0");
01452 strcpy(myrpt->txpl, "100.0");
01453 myrpt->remmode = REM_MODE_LSB;
01454 break;
01455 case 'F':
01456 myrpt->remmode = REM_MODE_FM;
01457 break;
01458 case 'L':
01459 case 'l':
01460 myrpt->powerlevel = REM_LOWPWR;
01461 break;
01462 case 'H':
01463 case 'h':
01464 myrpt->powerlevel = REM_HIPWR;
01465 break;
01466
01467 case 'M':
01468 case 'm':
01469 myrpt->powerlevel = REM_MEDPWR;
01470 break;
01471
01472 case '-':
01473 myrpt->offset = REM_MINUS;
01474 break;
01475
01476 case '+':
01477 myrpt->offset = REM_PLUS;
01478 break;
01479
01480 case 'S':
01481 case 's':
01482 myrpt->offset = REM_SIMPLEX;
01483 break;
01484
01485 case 'T':
01486 case 't':
01487 myrpt->txplon = 1;
01488 break;
01489
01490 case 'R':
01491 case 'r':
01492 myrpt->rxplon = 1;
01493 break;
01494
01495 case 'U':
01496 case 'u':
01497 strcpy(myrpt->rxpl, "100.0");
01498 strcpy(myrpt->txpl, "100.0");
01499 myrpt->remmode = REM_MODE_USB;
01500 break;
01501 default:
01502 return 1;
01503 }
01504 }
01505 return 0;
01506 }
01507
01508
01509
01510 static void birdbath(struct rpt *myrpt)
01511 {
01512 struct rpt_tele *telem;
01513 if(debug > 2)
01514 ast_log(LOG_NOTICE, "birdbath!!");
01515 rpt_mutex_lock(&myrpt->lock);
01516 telem = myrpt->tele.next;
01517 while(telem != &myrpt->tele)
01518 {
01519 if (telem->mode == PARROT) ast_softhangup(telem->chan,AST_SOFTHANGUP_DEV);
01520 telem = telem->next;
01521 }
01522 rpt_mutex_unlock(&myrpt->lock);
01523 }
01524
01525 static void do_dtmf_phone(struct rpt *myrpt, struct rpt_link *mylink, char c)
01526 {
01527 struct rpt_link *l;
01528
01529 l = myrpt->links.next;
01530
01531 while(l != &myrpt->links)
01532 {
01533 if (!l->phonemode)
01534 {
01535 l = l->next;
01536 continue;
01537 }
01538
01539 if (mylink && (l == mylink))
01540 {
01541 l = l->next;
01542 continue;
01543 }
01544 #ifdef NEW_ASTERISK
01545 if (l->chan) ast_senddigit(l->chan,c,0);
01546 #else
01547 if (l->chan) ast_senddigit(l->chan,c);
01548 #endif
01549 l = l->next;
01550 }
01551 return;
01552 }
01553
01554
01555 static void donodelog(struct rpt *myrpt,char *str)
01556 {
01557 struct nodelog *nodep;
01558 char datestr[100];
01559
01560 if (!myrpt->p.archivedir) return;
01561 nodep = (struct nodelog *)ast_malloc(sizeof(struct nodelog));
01562 if (nodep == NULL)
01563 {
01564 ast_log(LOG_ERROR,"Cannot get memory for node log");
01565 return;
01566 }
01567 time(&nodep->timestamp);
01568 strncpy(nodep->archivedir,myrpt->p.archivedir,
01569 sizeof(nodep->archivedir) - 1);
01570 strftime(datestr,sizeof(datestr) - 1,"%Y%m%d%H%M%S",
01571 localtime(&nodep->timestamp));
01572 snprintf(nodep->str,sizeof(nodep->str) - 1,"%s %s,%s\n",
01573 myrpt->name,datestr,str);
01574 ast_mutex_lock(&nodeloglock);
01575 insque((struct qelem *) nodep, (struct qelem *) nodelog.prev);
01576 ast_mutex_unlock(&nodeloglock);
01577 }
01578
01579
01580 static void do_dtmf_local(struct rpt *myrpt, char c)
01581 {
01582 int i;
01583 char digit;
01584 static const char* dtmf_tones[] = {
01585 "!941+1336/200,!0/200",
01586 "!697+1209/200,!0/200",
01587 "!697+1336/200,!0/200",
01588 "!697+1477/200,!0/200",
01589 "!770+1209/200,!0/200",
01590 "!770+1336/200,!0/200",
01591 "!770+1477/200,!0/200",
01592 "!852+1209/200,!0/200",
01593 "!852+1336/200,!0/200",
01594 "!852+1477/200,!0/200",
01595 "!697+1633/200,!0/200",
01596 "!770+1633/200,!0/200",
01597 "!852+1633/200,!0/200",
01598 "!941+1633/200,!0/200",
01599 "!941+1209/200,!0/200",
01600 "!941+1477/200,!0/200" };
01601
01602
01603 if (c)
01604 {
01605 snprintf(myrpt->dtmf_local_str + strlen(myrpt->dtmf_local_str),sizeof(myrpt->dtmf_local_str) - 1,"%c",c);
01606 if (!myrpt->dtmf_local_timer)
01607 myrpt->dtmf_local_timer = DTMF_LOCAL_STARTTIME;
01608 }
01609
01610 if (myrpt->dtmf_local_timer == 1)
01611 {
01612 if(debug > 6)
01613 ast_log(LOG_NOTICE,"time out dtmf_local_timer=%i\n",myrpt->dtmf_local_timer);
01614
01615
01616 if (myrpt->dtmf_local_str[0])
01617 {
01618 digit = myrpt->dtmf_local_str[0];
01619 myrpt->dtmf_local_str[0] = 0;
01620 for(i = 1; myrpt->dtmf_local_str[i]; i++)
01621 {
01622 myrpt->dtmf_local_str[i - 1] =
01623 myrpt->dtmf_local_str[i];
01624 }
01625 myrpt->dtmf_local_str[i - 1] = 0;
01626 myrpt->dtmf_local_timer = DTMF_LOCAL_TIME;
01627 rpt_mutex_unlock(&myrpt->lock);
01628 if (digit >= '0' && digit <='9')
01629 ast_playtones_start(myrpt->txchannel, 0, dtmf_tones[digit-'0'], 0);
01630 else if (digit >= 'A' && digit <= 'D')
01631 ast_playtones_start(myrpt->txchannel, 0, dtmf_tones[digit-'A'+10], 0);
01632 else if (digit == '*')
01633 ast_playtones_start(myrpt->txchannel, 0, dtmf_tones[14], 0);
01634 else if (digit == '#')
01635 ast_playtones_start(myrpt->txchannel, 0, dtmf_tones[15], 0);
01636 else {
01637
01638 ast_log(LOG_DEBUG, "Unable to generate DTMF tone '%c' for '%s'\n", digit, myrpt->txchannel->name);
01639 }
01640 rpt_mutex_lock(&myrpt->lock);
01641 }
01642 else
01643 {
01644 myrpt->dtmf_local_timer = 0;
01645 }
01646 }
01647 }
01648
01649 static int setdtr(int fd, int enable)
01650 {
01651 struct termios mode;
01652
01653 if (fd < 0) return -1;
01654 if (tcgetattr(fd, &mode)) {
01655 ast_log(LOG_WARNING, "Unable to get serial parameters for dtr: %s\n", strerror(errno));
01656 return -1;
01657 }
01658 if (enable)
01659 {
01660 cfsetspeed(&mode, B9600);
01661 }
01662 else
01663 {
01664 cfsetspeed(&mode, B0);
01665 usleep(100000);
01666 }
01667 if (tcsetattr(fd, TCSADRAIN, &mode)) {
01668 ast_log(LOG_WARNING, "Unable to set serial parameters for dtr: %s\n", strerror(errno));
01669 return -1;
01670 }
01671 if (enable) usleep(100000);
01672 return 0;
01673 }
01674
01675 static int openserial(struct rpt *myrpt,char *fname)
01676 {
01677 struct termios mode;
01678 int fd;
01679
01680 fd = open(fname,O_RDWR);
01681 if (fd == -1)
01682 {
01683 ast_log(LOG_WARNING,"Cannot open serial port %s\n",fname);
01684 return -1;
01685 }
01686 memset(&mode, 0, sizeof(mode));
01687 if (tcgetattr(fd, &mode)) {
01688 ast_log(LOG_WARNING, "Unable to get serial parameters on %s: %s\n", fname, strerror(errno));
01689 return -1;
01690 }
01691 #ifndef SOLARIS
01692 cfmakeraw(&mode);
01693 #else
01694 mode.c_iflag &= ~(IGNBRK|BRKINT|PARMRK|ISTRIP
01695 |INLCR|IGNCR|ICRNL|IXON);
01696 mode.c_lflag &= ~(ECHO|ECHONL|ICANON|ISIG|IEXTEN);
01697 mode.c_cflag &= ~(CSIZE|PARENB|CRTSCTS);
01698 mode.c_cflag |= CS8;
01699 mode.c_cc[VTIME] = 3;
01700 mode.c_cc[VMIN] = 1;
01701 #endif
01702
01703 cfsetispeed(&mode, B9600);
01704 cfsetospeed(&mode, B9600);
01705 if (tcsetattr(fd, TCSANOW, &mode))
01706 ast_log(LOG_WARNING, "Unable to set serial parameters on %s: %s\n", fname, strerror(errno));
01707 if(!strcmp(myrpt->remoterig, remote_rig_kenwood)) setdtr(fd,0);
01708 usleep(100000);
01709 if (debug)ast_log(LOG_NOTICE,"Opened serial port %s\n",fname);
01710 return(fd);
01711 }
01712
01713 static void mdc1200_notify(struct rpt *myrpt,char *fromnode, unsigned int unit)
01714 {
01715 if (!fromnode)
01716 {
01717 ast_verbose("Got MDC-1200 ID %04X from local system (%s)\n",
01718 unit,myrpt->name);
01719 }
01720 else
01721 {
01722 ast_verbose("Got MDC-1200 ID %04X from node %s (%s)\n",
01723 unit,fromnode,myrpt->name);
01724 }
01725 }
01726
01727 #ifdef _MDC_DECODE_H_
01728
01729 static void mdc1200_send(struct rpt *myrpt, unsigned int unit)
01730 {
01731 struct rpt_link *l;
01732 struct ast_frame wf;
01733 char str[200];
01734
01735
01736 sprintf(str,"I %s %04X",myrpt->name,unit);
01737
01738 wf.frametype = AST_FRAME_TEXT;
01739 wf.subclass.integer = 0;
01740 wf.offset = 0;
01741 wf.mallocd = 0;
01742 wf.datalen = strlen(str) + 1;
01743 wf.samples = 0;
01744
01745
01746 l = myrpt->links.next;
01747
01748 while(l != &myrpt->links)
01749 {
01750 if (l->name[0] == '0')
01751 {
01752 l = l->next;
01753 continue;
01754 }
01755 wf.data = str;
01756 if (l->chan) ast_write(l->chan,&wf);
01757 l = l->next;
01758 }
01759 return;
01760 }
01761
01762 #endif
01763
01764 static char func_xlat(struct rpt *myrpt,char c,struct rpt_xlat *xlat)
01765 {
01766 time_t now;
01767 int gotone;
01768
01769 time(&now);
01770 gotone = 0;
01771
01772 if ((now - xlat->lastone) > MAXXLATTIME)
01773 {
01774 xlat->funcindex = xlat->endindex = 0;
01775 }
01776 if (xlat->funccharseq[0] && (c == xlat->funccharseq[xlat->funcindex++]))
01777 {
01778 time(&xlat->lastone);
01779 gotone = 1;
01780 if (!xlat->funccharseq[xlat->funcindex])
01781 {
01782 xlat->funcindex = xlat->endindex = 0;
01783 return(myrpt->p.funcchar);
01784 }
01785 } else xlat->funcindex = 0;
01786 if (xlat->endcharseq[0] && (c == xlat->endcharseq[xlat->endindex++]))
01787 {
01788 time(&xlat->lastone);
01789 gotone = 1;
01790 if (!xlat->endcharseq[xlat->endindex])
01791 {
01792 xlat->funcindex = xlat->endindex = 0;
01793 return(myrpt->p.endchar);
01794 }
01795 } else xlat->endindex = 0;
01796
01797 if (gotone) return(0);
01798
01799 if (!xlat->passchars[0]) return(c);
01800
01801 if (strchr(xlat->passchars,c)) return(c);
01802 return(0);
01803 }
01804
01805
01806
01807
01808
01809 static char *eatwhite(char *s)
01810 {
01811 while((*s == ' ') || (*s == 0x09)){
01812 if(!*s)
01813 break;
01814 s++;
01815 }
01816 return s;
01817 }
01818
01819
01820
01821
01822
01823
01824
01825
01826
01827
01828
01829 static int finddelim(char *str, char *strp[], int limit)
01830 {
01831 int i,l,inquo;
01832
01833 inquo = 0;
01834 i = 0;
01835 strp[i++] = str;
01836 if (!*str)
01837 {
01838 strp[0] = 0;
01839 return(0);
01840 }
01841 for(l = 0; *str && (l < limit) ; str++)
01842 {
01843 if (*str == QUOTECHR)
01844 {
01845 if (inquo)
01846 {
01847 *str = 0;
01848 inquo = 0;
01849 }
01850 else
01851 {
01852 strp[i - 1] = str + 1;
01853 inquo = 1;
01854 }
01855 }
01856 if ((*str == DELIMCHR) && (!inquo))
01857 {
01858 *str = 0;
01859 l++;
01860 strp[i++] = str + 1;
01861 }
01862 }
01863 strp[i] = 0;
01864 return(i);
01865
01866 }
01867
01868
01869
01870 static int send_usb_txt(struct rpt *myrpt, char *txt)
01871 {
01872 struct ast_frame wf;
01873
01874 if (debug)ast_log(LOG_NOTICE, "send_usb_txt %s\n",txt);
01875 wf.frametype = AST_FRAME_TEXT;
01876 wf.subclass.integer = 0;
01877 wf.offset = 0;
01878 wf.mallocd = 0;
01879 wf.datalen = strlen(txt) + 1;
01880 wf.data.ptr = txt;
01881 wf.samples = 0;
01882 ast_write(myrpt->txchannel,&wf);
01883 return 0;
01884 }
01885
01886 static void __mklinklist(struct rpt *myrpt, struct rpt_link *mylink, char *buf)
01887 {
01888 struct rpt_link *l;
01889 char mode;
01890 int i,spos;
01891
01892 buf[0] = 0;
01893 if (myrpt->remote) return;
01894
01895 for(l = myrpt->links.next; l != &myrpt->links; l = l->next)
01896 {
01897
01898 if (l->name[0] == '0') continue;
01899
01900 if (l == mylink) continue;
01901 if (mylink && (!strcmp(l->name,mylink->name))) continue;
01902
01903 mode = 'T';
01904 if (!l->mode) mode = 'R';
01905 if (!l->thisconnected) mode = 'C';
01906 spos = strlen(buf);
01907 if (spos)
01908 {
01909 strcat(buf,",");
01910 spos++;
01911 }
01912
01913 if (l->linklist[0])
01914 {
01915 snprintf(buf + spos,MAXLINKLIST - spos,
01916 "%c%s,%s",mode,l->name,l->linklist);
01917 }
01918 else
01919 {
01920 snprintf(buf + spos,MAXLINKLIST - spos,
01921 "%c%s",mode,l->name);
01922 }
01923
01924 if (mode == 'T') continue;
01925
01926 for(i = spos; buf[i]; i++)
01927 {
01928 if (buf[i] == 'T') buf[i] = mode;
01929 if ((buf[i] == 'R') && (mode == 'C')) buf[i] = mode;
01930 }
01931 }
01932 return;
01933 }
01934
01935
01936 static void __kickshort(struct rpt *myrpt)
01937 {
01938 struct rpt_link *l;
01939
01940 for(l = myrpt->links.next; l != &myrpt->links; l = l->next)
01941 {
01942
01943 if (l->name[0] == '0') continue;
01944 l->linklisttimer = LINKLISTSHORTTIME;
01945 }
01946 myrpt->linkposttimer = LINKPOSTSHORTTIME;
01947 return;
01948 }
01949
01950 static void statpost(struct rpt *myrpt,char *pairs)
01951 {
01952 char *str,*astr;
01953 char *astrs[100];
01954 int n,pid;
01955 time_t now;
01956 unsigned int seq;
01957
01958 if (!myrpt->p.statpost_url) return;
01959 str = ast_malloc(strlen(pairs) + strlen(myrpt->p.statpost_url) + 200);
01960 astr = ast_strdup(myrpt->p.statpost_program);
01961 if ((!str) || (!astr)) {
01962 ast_free(str);
01963 ast_free(astr);
01964 return;
01965 }
01966 n = finddelim(astr,astrs,100);
01967 if (n < 1) {
01968 ast_free(str);
01969 ast_free(astr);
01970 return;
01971 }
01972 ast_mutex_lock(&myrpt->statpost_lock);
01973 seq = ++myrpt->statpost_seqno;
01974 ast_mutex_unlock(&myrpt->statpost_lock);
01975 astrs[n++] = str;
01976 astrs[n] = NULL;
01977 time(&now);
01978 sprintf(str,"%s?node=%s&time=%u&seqno=%u",myrpt->p.statpost_url,
01979 myrpt->name,(unsigned int) now,seq);
01980 if (pairs) sprintf(str + strlen(str),"&%s",pairs);
01981 if (!(pid = ast_safe_fork(0)))
01982 {
01983 execv(astrs[0],astrs);
01984 ast_log(LOG_ERROR, "exec of %s failed.\n", astrs[0]);
01985 perror("asterisk");
01986 exit(0);
01987 }
01988 ast_free(astr);
01989 ast_free(str);
01990 return;
01991 }
01992
01993 static char *node_lookup(struct rpt *myrpt,char *digitbuf)
01994 {
01995
01996 char *val;
01997 int longestnode,j;
01998 struct stat mystat;
01999 static time_t last = 0;
02000 static struct ast_config *ourcfg = NULL;
02001 struct ast_variable *vp;
02002
02003
02004 val = (char *) ast_variable_retrieve(myrpt->cfg, myrpt->p.nodes, digitbuf);
02005 if (val) return(val);
02006 ast_mutex_lock(&nodelookuplock);
02007
02008 if (stat(myrpt->p.extnodefile,&mystat) == -1)
02009 {
02010 if (ourcfg) ast_config_destroy(ourcfg);
02011 ourcfg = NULL;
02012 ast_mutex_unlock(&nodelookuplock);
02013 return(NULL);
02014 }
02015
02016 if (mystat.st_mtime > last)
02017 {
02018 if (ourcfg) ast_config_destroy(ourcfg);
02019 #ifdef NEW_ASTERISK
02020 ourcfg = ast_config_load(myrpt->p.extnodefile,config_flags);
02021 #else
02022 ourcfg = ast_config_load(myrpt->p.extnodefile);
02023 #endif
02024
02025 if (!ourcfg || ourcfg == CONFIG_STATUS_FILEINVALID)
02026 {
02027 ast_mutex_unlock(&nodelookuplock);
02028 return(NULL);
02029 }
02030
02031 last = mystat.st_mtime;
02032
02033
02034 longestnode = 0;
02035 vp = ast_variable_browse(myrpt->cfg, myrpt->p.nodes);
02036 while(vp){
02037 j = strlen(vp->name);
02038 if (j > longestnode)
02039 longestnode = j;
02040 vp = vp->next;
02041 }
02042
02043 vp = ast_variable_browse(ourcfg, myrpt->p.extnodes);
02044 while(vp){
02045 j = strlen(vp->name);
02046 if (j > longestnode)
02047 longestnode = j;
02048 vp = vp->next;
02049 }
02050
02051 myrpt->longestnode = longestnode;
02052 }
02053 val = NULL;
02054 if (ourcfg)
02055 val = (char *) ast_variable_retrieve(ourcfg, myrpt->p.extnodes, digitbuf);
02056 ast_mutex_unlock(&nodelookuplock);
02057 return(val);
02058 }
02059
02060
02061
02062
02063
02064
02065 static int matchkeyword(char *string, char **param, char *keywords[])
02066 {
02067 int i,ls;
02068 for( i = 0 ; keywords[i] ; i++){
02069 ls = strlen(keywords[i]);
02070 if(!ls){
02071 *param = NULL;
02072 return 0;
02073 }
02074 if(!strncmp(string, keywords[i], ls)){
02075 if(param)
02076 *param = string + ls;
02077 return i + 1;
02078 }
02079 }
02080 *param = NULL;
02081 return 0;
02082 }
02083
02084
02085
02086
02087
02088
02089 static char *skipchars(char *string, char *charlist)
02090 {
02091 int i;
02092 while(*string){
02093 for(i = 0; charlist[i] ; i++){
02094 if(*string == charlist[i]){
02095 string++;
02096 break;
02097 }
02098 }
02099 if(!charlist[i])
02100 return string;
02101 }
02102 return string;
02103 }
02104
02105 static int myatoi(const char *str)
02106 {
02107 int ret;
02108
02109 if (!str) {
02110 return -1;
02111 }
02112
02113
02114 if (sscanf(str, "%30i", &ret) != 1) {
02115 return -1;
02116 }
02117
02118 return ret;
02119 }
02120
02121 static int mycompar(const void *a, const void *b)
02122 {
02123 char **x = (char **) a;
02124 char **y = (char **) b;
02125 int xoff,yoff;
02126
02127 if ((**x < '0') || (**x > '9')) xoff = 1; else xoff = 0;
02128 if ((**y < '0') || (**y > '9')) yoff = 1; else yoff = 0;
02129 return(strcmp((*x) + xoff,(*y) + yoff));
02130 }
02131
02132 static int topcompar(const void *a, const void *b)
02133 {
02134 struct rpt_topkey *x = (struct rpt_topkey *) a;
02135 struct rpt_topkey *y = (struct rpt_topkey *) b;
02136
02137 return(x->timesince - y->timesince);
02138 }
02139
02140 #ifdef __RPT_NOTCH
02141
02142
02143 static void rpt_filter(struct rpt *myrpt, volatile short *buf, int len)
02144 {
02145 int i,j;
02146 struct rptfilter *f;
02147
02148 for(i = 0; i < len; i++)
02149 {
02150 for(j = 0; j < MAXFILTERS; j++)
02151 {
02152 f = &myrpt->filters[j];
02153 if (!*f->desc) continue;
02154 f->x0 = f->x1; f->x1 = f->x2;
02155 f->x2 = ((float)buf[i]) / f->gain;
02156 f->y0 = f->y1; f->y1 = f->y2;
02157 f->y2 = (f->x0 + f->x2) + f->const0 * f->x1
02158 + (f->const1 * f->y0) + (f->const2 * f->y1);
02159 buf[i] = (short)f->y2;
02160 }
02161 }
02162 }
02163
02164 #endif
02165
02166
02167
02168
02169
02170
02171
02172
02173
02174
02175
02176
02177
02178
02179
02180
02181
02182
02183 #ifdef NEW_ASTERISK
02184 static void rpt_localtime( time_t * t, struct ast_tm *lt)
02185 {
02186 struct timeval when;
02187
02188 when.tv_sec = *t;
02189 when.tv_usec = 0;
02190 ast_localtime(&when, lt, NULL);
02191 }
02192
02193 #else
02194 static void rpt_localtime( time_t * t, struct tm *lt)
02195 {
02196 #ifdef OLD_ASTERISK
02197 localtime_r(t, lt);
02198 #else
02199 ast_localtime(t, lt, NULL);
02200 #endif
02201 }
02202 #endif
02203
02204
02205
02206
02207 static int retrieve_astcfgint(struct rpt *myrpt,char *category, char *name, int min, int max, int defl)
02208 {
02209 char *var;
02210 int ret;
02211 char include_zero = 0;
02212
02213 if(min < 0){
02214 min = -min;
02215 include_zero = 1;
02216 }
02217
02218 var = (char *) ast_variable_retrieve(myrpt->cfg, category, name);
02219 if(var){
02220 ret = myatoi(var);
02221 if(include_zero && !ret)
02222 return 0;
02223 if(ret < min)
02224 ret = min;
02225 if(ret > max)
02226 ret = max;
02227 }
02228 else
02229 ret = defl;
02230 return ret;
02231 }
02232
02233
02234 static void load_rpt_vars(int n,int init)
02235 {
02236 char *this,*val;
02237 int i,j,longestnode;
02238 struct ast_variable *vp;
02239 struct ast_config *cfg;
02240 char *strs[100];
02241 char s1[256];
02242 static char *cs_keywords[] = {"rptena","rptdis","apena","apdis","lnkena","lnkdis","totena","totdis","skena","skdis",
02243 "ufena","ufdis","atena","atdis",NULL};
02244
02245 if (option_verbose > 2)
02246 ast_verbose(VERBOSE_PREFIX_3 "%s config for repeater %s\n",
02247 (init) ? "Loading initial" : "Re-Loading",rpt_vars[n].name);
02248 ast_mutex_lock(&rpt_vars[n].lock);
02249 if (rpt_vars[n].cfg) ast_config_destroy(rpt_vars[n].cfg);
02250 #ifdef NEW_ASTERISK
02251 cfg = ast_config_load("rpt.conf",config_flags);
02252 #else
02253 cfg = ast_config_load("rpt.conf");
02254 #endif
02255 if (!cfg || cfg == CONFIG_STATUS_FILEINVALID) {
02256 ast_mutex_unlock(&rpt_vars[n].lock);
02257 ast_log(LOG_NOTICE, "Unable to open radio repeater configuration rpt.conf. Radio Repeater disabled.\n");
02258 pthread_exit(NULL);
02259 }
02260 rpt_vars[n].cfg = cfg;
02261 this = rpt_vars[n].name;
02262 memset(&rpt_vars[n].p,0,sizeof(rpt_vars[n].p));
02263 if (init)
02264 {
02265 char *cp;
02266 int savearea = (char *)&rpt_vars[n].p - (char *)&rpt_vars[n];
02267
02268 cp = (char *) &rpt_vars[n].p;
02269 memset(cp + sizeof(rpt_vars[n].p),0,
02270 sizeof(rpt_vars[n]) - (sizeof(rpt_vars[n].p) + savearea));
02271 rpt_vars[n].tele.next = &rpt_vars[n].tele;
02272 rpt_vars[n].tele.prev = &rpt_vars[n].tele;
02273 rpt_vars[n].rpt_thread = AST_PTHREADT_NULL;
02274 rpt_vars[n].tailmessagen = 0;
02275 }
02276 #ifdef __RPT_NOTCH
02277
02278 memset(&rpt_vars[n].filters,0,sizeof(rpt_vars[n].filters));
02279 #endif
02280 val = (char *) ast_variable_retrieve(cfg,this,"context");
02281 if (val) rpt_vars[n].p.ourcontext = val;
02282 else rpt_vars[n].p.ourcontext = this;
02283 val = (char *) ast_variable_retrieve(cfg,this,"callerid");
02284 if (val) rpt_vars[n].p.ourcallerid = val;
02285 val = (char *) ast_variable_retrieve(cfg,this,"accountcode");
02286 if (val) rpt_vars[n].p.acctcode = val;
02287 val = (char *) ast_variable_retrieve(cfg,this,"idrecording");
02288 if (val) rpt_vars[n].p.ident = val;
02289 val = (char *) ast_variable_retrieve(cfg,this,"hangtime");
02290 if (val) rpt_vars[n].p.hangtime = atoi(val);
02291 else rpt_vars[n].p.hangtime = HANGTIME;
02292 val = (char *) ast_variable_retrieve(cfg,this,"althangtime");
02293 if (val) rpt_vars[n].p.althangtime = atoi(val);
02294 else rpt_vars[n].p.althangtime = HANGTIME;
02295 val = (char *) ast_variable_retrieve(cfg,this,"totime");
02296 if (val) rpt_vars[n].p.totime = atoi(val);
02297 else rpt_vars[n].p.totime = TOTIME;
02298 val = (char *) ast_variable_retrieve(cfg,this,"voxtimeout");
02299 if (val) rpt_vars[n].p.voxtimeout_ms = atoi(val);
02300 else rpt_vars[n].p.voxtimeout_ms = VOX_TIMEOUT_MS;
02301 val = (char *) ast_variable_retrieve(cfg,this,"voxrecover");
02302 if (val) rpt_vars[n].p.voxrecover_ms = atoi(val);
02303 else rpt_vars[n].p.voxrecover_ms = VOX_RECOVER_MS;
02304 val = (char *) ast_variable_retrieve(cfg,this,"simplexpatchdelay");
02305 if (val) rpt_vars[n].p.simplexpatchdelay = atoi(val);
02306 else rpt_vars[n].p.simplexpatchdelay = SIMPLEX_PATCH_DELAY;
02307 val = (char *) ast_variable_retrieve(cfg,this,"simplexphonedelay");
02308 if (val) rpt_vars[n].p.simplexphonedelay = atoi(val);
02309 else rpt_vars[n].p.simplexphonedelay = SIMPLEX_PHONE_DELAY;
02310 val = (char *) ast_variable_retrieve(cfg,this,"statpost_program");
02311 if (val) rpt_vars[n].p.statpost_program = val;
02312 else rpt_vars[n].p.statpost_program = STATPOST_PROGRAM;
02313 rpt_vars[n].p.statpost_url =
02314 (char *) ast_variable_retrieve(cfg,this,"statpost_url");
02315 rpt_vars[n].p.tailmessagetime = retrieve_astcfgint(&rpt_vars[n],this, "tailmessagetime", 0, 2400000, 0);
02316 rpt_vars[n].p.tailsquashedtime = retrieve_astcfgint(&rpt_vars[n],this, "tailsquashedtime", 0, 2400000, 0);
02317 rpt_vars[n].p.duplex = retrieve_astcfgint(&rpt_vars[n],this,"duplex",0,4,2);
02318 rpt_vars[n].p.idtime = retrieve_astcfgint(&rpt_vars[n],this, "idtime", -60000, 2400000, IDTIME);
02319 rpt_vars[n].p.politeid = retrieve_astcfgint(&rpt_vars[n],this, "politeid", 30000, 300000, POLITEID);
02320 val = (char *) ast_variable_retrieve(cfg,this,"tonezone");
02321 if (val) rpt_vars[n].p.tonezone = val;
02322 rpt_vars[n].p.tailmessages[0] = 0;
02323 rpt_vars[n].p.tailmessagemax = 0;
02324 val = (char *) ast_variable_retrieve(cfg,this,"tailmessagelist");
02325 if (val) rpt_vars[n].p.tailmessagemax = finddelim(val, rpt_vars[n].p.tailmessages, 500);
02326 val = (char *) ast_variable_retrieve(cfg,this,"memory");
02327 if (!val) val = MEMORY;
02328 rpt_vars[n].p.memory = val;
02329 val = (char *) ast_variable_retrieve(cfg,this,"macro");
02330 if (!val) val = MACRO;
02331 rpt_vars[n].p.macro = val;
02332 val = (char *) ast_variable_retrieve(cfg,this,"tonemacro");
02333 if (!val) val = TONEMACRO;
02334 rpt_vars[n].p.tonemacro = val;
02335 val = (char *) ast_variable_retrieve(cfg,this,"startup_macro");
02336 if (val) rpt_vars[n].p.startupmacro = val;
02337 val = (char *) ast_variable_retrieve(cfg,this,"iobase");
02338
02339
02340
02341 if ((!val) || (sscanf(val,"%30i",&rpt_vars[n].p.iobase) != 1))
02342 rpt_vars[n].p.iobase = DEFAULT_IOBASE;
02343 val = (char *) ast_variable_retrieve(cfg,this,"ioport");
02344 rpt_vars[n].p.ioport = val;
02345 val = (char *) ast_variable_retrieve(cfg,this,"functions");
02346 if (!val)
02347 {
02348 val = FUNCTIONS;
02349 rpt_vars[n].p.simple = 1;
02350 }
02351 rpt_vars[n].p.functions = val;
02352 val = (char *) ast_variable_retrieve(cfg,this,"link_functions");
02353 if (val) rpt_vars[n].p.link_functions = val;
02354 else
02355 rpt_vars[n].p.link_functions = rpt_vars[n].p.functions;
02356 val = (char *) ast_variable_retrieve(cfg,this,"phone_functions");
02357 if (val) rpt_vars[n].p.phone_functions = val;
02358 val = (char *) ast_variable_retrieve(cfg,this,"dphone_functions");
02359 if (val) rpt_vars[n].p.dphone_functions = val;
02360 val = (char *) ast_variable_retrieve(cfg,this,"alt_functions");
02361 if (val) rpt_vars[n].p.alt_functions = val;
02362 val = (char *) ast_variable_retrieve(cfg,this,"funcchar");
02363 if (!val) rpt_vars[n].p.funcchar = FUNCCHAR; else
02364 rpt_vars[n].p.funcchar = *val;
02365 val = (char *) ast_variable_retrieve(cfg,this,"endchar");
02366 if (!val) rpt_vars[n].p.endchar = ENDCHAR; else
02367 rpt_vars[n].p.endchar = *val;
02368 val = (char *) ast_variable_retrieve(cfg,this,"nobusyout");
02369 if (val) rpt_vars[n].p.nobusyout = ast_true(val);
02370 val = (char *) ast_variable_retrieve(cfg,this,"notelemtx");
02371 if (val) rpt_vars[n].p.notelemtx = ast_true(val);
02372 val = (char *) ast_variable_retrieve(cfg,this,"propagate_dtmf");
02373 if (val) rpt_vars[n].p.propagate_dtmf = ast_true(val);
02374 val = (char *) ast_variable_retrieve(cfg,this,"propagate_phonedtmf");
02375 if (val) rpt_vars[n].p.propagate_phonedtmf = ast_true(val);
02376 val = (char *) ast_variable_retrieve(cfg,this,"linktolink");
02377 if (val) rpt_vars[n].p.linktolink = ast_true(val);
02378 val = (char *) ast_variable_retrieve(cfg,this,"nodes");
02379 if (!val) val = NODES;
02380 rpt_vars[n].p.nodes = val;
02381 val = (char *) ast_variable_retrieve(cfg,this,"extnodes");
02382 if (!val) val = EXTNODES;
02383 rpt_vars[n].p.extnodes = val;
02384 val = (char *) ast_variable_retrieve(cfg,this,"extnodefile");
02385 if (!val) val = EXTNODEFILE;
02386 rpt_vars[n].p.extnodefile = val;
02387 val = (char *) ast_variable_retrieve(cfg,this,"archivedir");
02388 if (val) rpt_vars[n].p.archivedir = val;
02389 val = (char *) ast_variable_retrieve(cfg,this,"authlevel");
02390 if (val) rpt_vars[n].p.authlevel = atoi(val);
02391 else rpt_vars[n].p.authlevel = 0;
02392 val = (char *) ast_variable_retrieve(cfg,this,"parrot");
02393 if (val) rpt_vars[n].p.parrotmode = ast_true(val) * 2;
02394 else rpt_vars[n].p.parrotmode = 0;
02395 val = (char *) ast_variable_retrieve(cfg,this,"parrottime");
02396 if (val) rpt_vars[n].p.parrottime = atoi(val);
02397 else rpt_vars[n].p.parrottime = PARROTTIME;
02398 val = (char *) ast_variable_retrieve(cfg,this,"rptnode");
02399 rpt_vars[n].p.rptnode = val;
02400 val = (char *) ast_variable_retrieve(cfg,this,"mars");
02401 if (val) rpt_vars[n].p.remote_mars = atoi(val);
02402 else rpt_vars[n].p.remote_mars = 0;
02403 val = (char *) ast_variable_retrieve(cfg,this,"monminblocks");
02404 if (val) rpt_vars[n].p.monminblocks = atol(val);
02405 else rpt_vars[n].p.monminblocks = DEFAULT_MONITOR_MIN_DISK_BLOCKS;
02406 val = (char *) ast_variable_retrieve(cfg,this,"remote_inact_timeout");
02407 if (val) rpt_vars[n].p.remoteinacttimeout = atoi(val);
02408 else rpt_vars[n].p.remoteinacttimeout = DEFAULT_REMOTE_INACT_TIMEOUT;
02409 val = (char *) ast_variable_retrieve(cfg,this,"civaddr");
02410 if (val) rpt_vars[n].p.civaddr = atoi(val);
02411 else rpt_vars[n].p.civaddr = DEFAULT_CIV_ADDR;
02412 val = (char *) ast_variable_retrieve(cfg,this,"remote_timeout");
02413 if (val) rpt_vars[n].p.remotetimeout = atoi(val);
02414 else rpt_vars[n].p.remotetimeout = DEFAULT_REMOTE_TIMEOUT;
02415 val = (char *) ast_variable_retrieve(cfg,this,"remote_timeout_warning");
02416 if (val) rpt_vars[n].p.remotetimeoutwarning = atoi(val);
02417 else rpt_vars[n].p.remotetimeoutwarning = DEFAULT_REMOTE_TIMEOUT_WARNING;
02418 val = (char *) ast_variable_retrieve(cfg,this,"remote_timeout_warning_freq");
02419 if (val) rpt_vars[n].p.remotetimeoutwarningfreq = atoi(val);
02420 else rpt_vars[n].p.remotetimeoutwarningfreq = DEFAULT_REMOTE_TIMEOUT_WARNING_FREQ;
02421 #ifdef __RPT_NOTCH
02422 val = (char *) ast_variable_retrieve(cfg,this,"rxnotch");
02423 if (val) {
02424 i = finddelim(val,strs,MAXFILTERS * 2);
02425 i &= ~1;
02426 if (i >= 2) for(j = 0; j < i; j += 2)
02427 {
02428 rpt_mknotch(atof(strs[j]),atof(strs[j + 1]),
02429 &rpt_vars[n].filters[j >> 1].gain,
02430 &rpt_vars[n].filters[j >> 1].const0,
02431 &rpt_vars[n].filters[j >> 1].const1,
02432 &rpt_vars[n].filters[j >> 1].const2);
02433 sprintf(rpt_vars[n].filters[j >> 1].desc,"%s Hz, BW = %s",
02434 strs[j],strs[j + 1]);
02435 }
02436
02437 }
02438 #endif
02439 val = (char *) ast_variable_retrieve(cfg,this,"inxlat");
02440 if (val) {
02441 memset(&rpt_vars[n].p.inxlat,0,sizeof(struct rpt_xlat));
02442 i = finddelim(val,strs,3);
02443 if (i) strncpy(rpt_vars[n].p.inxlat.funccharseq,strs[0],MAXXLAT - 1);
02444 if (i > 1) strncpy(rpt_vars[n].p.inxlat.endcharseq,strs[1],MAXXLAT - 1);
02445 if (i > 2) strncpy(rpt_vars[n].p.inxlat.passchars,strs[2],MAXXLAT - 1);
02446 }
02447 val = (char *) ast_variable_retrieve(cfg,this,"outxlat");
02448 if (val) {
02449 memset(&rpt_vars[n].p.outxlat,0,sizeof(struct rpt_xlat));
02450 i = finddelim(val,strs,3);
02451 if (i) strncpy(rpt_vars[n].p.outxlat.funccharseq,strs[0],MAXXLAT - 1);
02452 if (i > 1) strncpy(rpt_vars[n].p.outxlat.endcharseq,strs[1],MAXXLAT - 1);
02453 if (i > 2) strncpy(rpt_vars[n].p.outxlat.passchars,strs[2],MAXXLAT - 1);
02454 }
02455
02456 val = (char *) ast_variable_retrieve(cfg,this,"controlstates");
02457 rpt_vars[n].p.csstanzaname = val;
02458
02459
02460 val = (char *) ast_variable_retrieve(cfg,this,"scheduler");
02461 rpt_vars[n].p.skedstanzaname = val;
02462
02463
02464 val = (char *) ast_variable_retrieve(cfg,this,"txlimits");
02465 rpt_vars[n].p.txlimitsstanzaname = val;
02466
02467 longestnode = 0;
02468
02469 vp = ast_variable_browse(cfg, rpt_vars[n].p.nodes);
02470
02471 while(vp){
02472 j = strlen(vp->name);
02473 if (j > longestnode)
02474 longestnode = j;
02475 vp = vp->next;
02476 }
02477
02478 rpt_vars[n].longestnode = longestnode;
02479
02480
02481
02482
02483 rpt_vars[n].longestfunc = 0;
02484 vp = ast_variable_browse(cfg, rpt_vars[n].p.functions);
02485 while(vp){
02486 j = strlen(vp->name);
02487 if (j > rpt_vars[n].longestfunc)
02488 rpt_vars[n].longestfunc = j;
02489 vp = vp->next;
02490 }
02491
02492
02493
02494 rpt_vars[n].link_longestfunc = 0;
02495 vp = ast_variable_browse(cfg, rpt_vars[n].p.link_functions);
02496 while(vp){
02497 j = strlen(vp->name);
02498 if (j > rpt_vars[n].link_longestfunc)
02499 rpt_vars[n].link_longestfunc = j;
02500 vp = vp->next;
02501 }
02502 rpt_vars[n].phone_longestfunc = 0;
02503 if (rpt_vars[n].p.phone_functions)
02504 {
02505 vp = ast_variable_browse(cfg, rpt_vars[n].p.phone_functions);
02506 while(vp){
02507 j = strlen(vp->name);
02508 if (j > rpt_vars[n].phone_longestfunc)
02509 rpt_vars[n].phone_longestfunc = j;
02510 vp = vp->next;
02511 }
02512 }
02513 rpt_vars[n].dphone_longestfunc = 0;
02514 if (rpt_vars[n].p.dphone_functions)
02515 {
02516 vp = ast_variable_browse(cfg, rpt_vars[n].p.dphone_functions);
02517 while(vp){
02518 j = strlen(vp->name);
02519 if (j > rpt_vars[n].dphone_longestfunc)
02520 rpt_vars[n].dphone_longestfunc = j;
02521 vp = vp->next;
02522 }
02523 }
02524 rpt_vars[n].alt_longestfunc = 0;
02525 if (rpt_vars[n].p.alt_functions)
02526 {
02527 vp = ast_variable_browse(cfg, rpt_vars[n].p.alt_functions);
02528 while(vp){
02529 j = strlen(vp->name);
02530 if (j > rpt_vars[n].alt_longestfunc)
02531 rpt_vars[n].alt_longestfunc = j;
02532 vp = vp->next;
02533 }
02534 }
02535 rpt_vars[n].macro_longest = 1;
02536 vp = ast_variable_browse(cfg, rpt_vars[n].p.macro);
02537 while(vp){
02538 j = strlen(vp->name);
02539 if (j > rpt_vars[n].macro_longest)
02540 rpt_vars[n].macro_longest = j;
02541 vp = vp->next;
02542 }
02543
02544
02545 if(rpt_vars[n].p.csstanzaname)
02546 vp = ast_variable_browse(cfg, rpt_vars[n].p.csstanzaname);
02547 else
02548 vp = NULL;
02549 for( i = 0 ; vp && (i < MAX_SYSSTATES) ; i++){
02550 int k,nukw,statenum;
02551 statenum=atoi(vp->name);
02552 strncpy(s1, vp->value, 255);
02553 s1[255] = 0;
02554 nukw = finddelim(s1,strs,32);
02555
02556 for (k = 0 ; k < nukw ; k++){
02557 for(j = 0 ; cs_keywords[j] != NULL ; j++){
02558 if(!strcmp(strs[k],cs_keywords[j])){
02559 switch(j){
02560 case 0:
02561 rpt_vars[n].p.s[statenum].txdisable = 0;
02562 break;
02563 case 1:
02564 rpt_vars[n].p.s[statenum].txdisable = 1;
02565 break;
02566
02567 case 2:
02568 rpt_vars[n].p.s[statenum].autopatchdisable = 0;
02569 break;
02570
02571 case 3:
02572 rpt_vars[n].p.s[statenum].autopatchdisable = 1;
02573 break;
02574
02575 case 4:
02576 rpt_vars[n].p.s[statenum].linkfundisable = 0;
02577 break;
02578
02579 case 5:
02580 rpt_vars[n].p.s[statenum].linkfundisable = 1;
02581 break;
02582
02583 case 6:
02584 rpt_vars[n].p.s[statenum].totdisable = 0;
02585 break;
02586
02587 case 7:
02588 rpt_vars[n].p.s[statenum].totdisable = 1;
02589 break;
02590
02591 case 8:
02592 rpt_vars[n].p.s[statenum].schedulerdisable = 0;
02593 break;
02594
02595 case 9:
02596 rpt_vars[n].p.s[statenum].schedulerdisable = 1;
02597 break;
02598
02599 case 10:
02600 rpt_vars[n].p.s[statenum].userfundisable = 0;
02601 break;
02602
02603 case 11:
02604 rpt_vars[n].p.s[statenum].userfundisable = 1;
02605 break;
02606
02607 case 12:
02608 rpt_vars[n].p.s[statenum].alternatetail = 1;
02609 break;
02610
02611 case 13:
02612 rpt_vars[n].p.s[statenum].alternatetail = 0;
02613 break;
02614
02615 default:
02616 ast_log(LOG_WARNING,
02617 "Unhandled control state keyword %s", cs_keywords[i]);
02618 break;
02619 }
02620 }
02621 }
02622 }
02623 vp = vp->next;
02624 }
02625 ast_mutex_unlock(&rpt_vars[n].lock);
02626 }
02627
02628
02629
02630
02631 static int rpt_do_debug(int fd, int argc, const char * const *argv)
02632 {
02633 int newlevel;
02634
02635 if (argc != 4) {
02636 return RESULT_SHOWUSAGE;
02637 }
02638
02639 newlevel = myatoi(argv[3]);
02640
02641 if (newlevel < 0 || newlevel > 7) {
02642 return RESULT_SHOWUSAGE;
02643 }
02644
02645 if (newlevel) {
02646 ast_cli(fd, "app_rpt Debugging enabled, previous level: %d, new level: %d\n", debug, newlevel);
02647 } else {
02648 ast_cli(fd, "app_rpt Debugging disabled\n");
02649 }
02650
02651 debug = newlevel;
02652
02653 return RESULT_SUCCESS;
02654 }
02655
02656
02657
02658
02659
02660 static int rpt_do_dump(int fd, int argc, const char * const *argv)
02661 {
02662 int i;
02663
02664 if (argc != 3)
02665 return RESULT_SHOWUSAGE;
02666
02667 for(i = 0; i < nrpts; i++)
02668 {
02669 if (!strcmp(argv[2],rpt_vars[i].name))
02670 {
02671 rpt_vars[i].disgorgetime = time(NULL) + 10;
02672 ast_cli(fd, "app_rpt struct dump requested for node %s\n",argv[2]);
02673 return RESULT_SUCCESS;
02674 }
02675 }
02676 return RESULT_FAILURE;
02677 }
02678
02679
02680
02681
02682
02683 static int rpt_do_stats(int fd, int argc, const char * const *argv)
02684 {
02685 int i,j,numoflinks;
02686 int dailytxtime, dailykerchunks;
02687 time_t now;
02688 int totalkerchunks, dailykeyups, totalkeyups, timeouts;
02689 int totalexecdcommands, dailyexecdcommands, hours, minutes, seconds;
02690 int uptime;
02691 long long totaltxtime;
02692 struct rpt_link *l;
02693 char *listoflinks[MAX_STAT_LINKS];
02694 char *lastdtmfcommand,*parrot_ena;
02695 char *tot_state, *ider_state, *patch_state;
02696 char *reverse_patch_state, *sys_ena, *tot_ena, *link_ena, *patch_ena;
02697 char *sch_ena, *input_signal, *called_number, *user_funs, *tail_type;
02698 struct rpt *myrpt;
02699
02700 static char *not_applicable = "N/A";
02701
02702 if(argc != 3)
02703 return RESULT_SHOWUSAGE;
02704
02705 tot_state = ider_state =
02706 patch_state = reverse_patch_state =
02707 input_signal = not_applicable;
02708 called_number = lastdtmfcommand = NULL;
02709
02710 time(&now);
02711 for(i = 0; i < nrpts; i++)
02712 {
02713 if (!strcmp(argv[2],rpt_vars[i].name)){
02714
02715 myrpt = &rpt_vars[i];
02716 rpt_mutex_lock(&myrpt->lock);
02717 uptime = (int)(now - starttime);
02718 dailytxtime = myrpt->dailytxtime;
02719 totaltxtime = myrpt->totaltxtime;
02720 dailykeyups = myrpt->dailykeyups;
02721 totalkeyups = myrpt->totalkeyups;
02722 dailykerchunks = myrpt->dailykerchunks;
02723 totalkerchunks = myrpt->totalkerchunks;
02724 dailyexecdcommands = myrpt->dailyexecdcommands;
02725 totalexecdcommands = myrpt->totalexecdcommands;
02726 timeouts = myrpt->timeouts;
02727
02728
02729 reverse_patch_state = "DOWN";
02730 numoflinks = 0;
02731 l = myrpt->links.next;
02732 while(l && (l != &myrpt->links)){
02733 if(numoflinks >= MAX_STAT_LINKS){
02734 ast_log(LOG_NOTICE,
02735 "maximum number of links exceeds %d in rpt_do_stats()!",MAX_STAT_LINKS);
02736 break;
02737 }
02738 if (l->name[0] == '0'){
02739 reverse_patch_state = "UP";
02740 l = l->next;
02741 continue;
02742 }
02743 listoflinks[numoflinks] = ast_strdup(l->name);
02744 if(listoflinks[numoflinks] == NULL){
02745 break;
02746 }
02747 else{
02748 numoflinks++;
02749 }
02750 l = l->next;
02751 }
02752
02753 if(myrpt->keyed)
02754 input_signal = "YES";
02755 else
02756 input_signal = "NO";
02757
02758 if(myrpt->p.parrotmode)
02759 parrot_ena = "ENABLED";
02760 else
02761 parrot_ena = "DISABLED";
02762
02763 if(myrpt->p.s[myrpt->p.sysstate_cur].txdisable)
02764 sys_ena = "DISABLED";
02765 else
02766 sys_ena = "ENABLED";
02767
02768 if(myrpt->p.s[myrpt->p.sysstate_cur].totdisable)
02769 tot_ena = "DISABLED";
02770 else
02771 tot_ena = "ENABLED";
02772
02773 if(myrpt->p.s[myrpt->p.sysstate_cur].linkfundisable)
02774 link_ena = "DISABLED";
02775 else
02776 link_ena = "ENABLED";
02777
02778 if(myrpt->p.s[myrpt->p.sysstate_cur].autopatchdisable)
02779 patch_ena = "DISABLED";
02780 else
02781 patch_ena = "ENABLED";
02782
02783 if(myrpt->p.s[myrpt->p.sysstate_cur].schedulerdisable)
02784 sch_ena = "DISABLED";
02785 else
02786 sch_ena = "ENABLED";
02787
02788 if(myrpt->p.s[myrpt->p.sysstate_cur].userfundisable)
02789 user_funs = "DISABLED";
02790 else
02791 user_funs = "ENABLED";
02792
02793 if(myrpt->p.s[myrpt->p.sysstate_cur].alternatetail)
02794 tail_type = "ALTERNATE";
02795 else
02796 tail_type = "STANDARD";
02797
02798 if(!myrpt->totimer)
02799 tot_state = "TIMED OUT!";
02800 else if(myrpt->totimer != myrpt->p.totime)
02801 tot_state = "ARMED";
02802 else
02803 tot_state = "RESET";
02804
02805 if(myrpt->tailid)
02806 ider_state = "QUEUED IN TAIL";
02807 else if(myrpt->mustid)
02808 ider_state = "QUEUED FOR CLEANUP";
02809 else
02810 ider_state = "CLEAN";
02811
02812 switch(myrpt->callmode){
02813 case 1:
02814 patch_state = "DIALING";
02815 break;
02816 case 2:
02817 patch_state = "CONNECTING";
02818 break;
02819 case 3:
02820 patch_state = "UP";
02821 break;
02822
02823 case 4:
02824 patch_state = "CALL FAILED";
02825 break;
02826
02827 default:
02828 patch_state = "DOWN";
02829 }
02830
02831 if(strlen(myrpt->exten)){
02832 called_number = ast_strdup(myrpt->exten);
02833 }
02834
02835 if(strlen(myrpt->lastdtmfcommand)){
02836 lastdtmfcommand = ast_strdup(myrpt->lastdtmfcommand);
02837 }
02838 rpt_mutex_unlock(&myrpt->lock);
02839
02840 ast_cli(fd, "************************ NODE %s STATISTICS *************************\n\n", myrpt->name);
02841 ast_cli(fd, "Selected system state............................: %d\n", myrpt->p.sysstate_cur);
02842 ast_cli(fd, "Signal on input..................................: %s\n", input_signal);
02843 ast_cli(fd, "System...........................................: %s\n", sys_ena);
02844 ast_cli(fd, "Parrot Mode......................................: %s\n", parrot_ena);
02845 ast_cli(fd, "Scheduler........................................: %s\n", sch_ena);
02846 ast_cli(fd, "Tail Time........................................: %s\n", tail_type);
02847 ast_cli(fd, "Time out timer...................................: %s\n", tot_ena);
02848 ast_cli(fd, "Time out timer state.............................: %s\n", tot_state);
02849 ast_cli(fd, "Time outs since system initialization............: %d\n", timeouts);
02850 ast_cli(fd, "Identifier state.................................: %s\n", ider_state);
02851 ast_cli(fd, "Kerchunks today..................................: %d\n", dailykerchunks);
02852 ast_cli(fd, "Kerchunks since system initialization............: %d\n", totalkerchunks);
02853 ast_cli(fd, "Keyups today.....................................: %d\n", dailykeyups);
02854 ast_cli(fd, "Keyups since system initialization...............: %d\n", totalkeyups);
02855 ast_cli(fd, "DTMF commands today..............................: %d\n", dailyexecdcommands);
02856 ast_cli(fd, "DTMF commands since system initialization........: %d\n", totalexecdcommands);
02857 ast_cli(fd, "Last DTMF command executed.......................: %s\n",
02858 (lastdtmfcommand && strlen(lastdtmfcommand)) ? lastdtmfcommand : not_applicable);
02859 hours = dailytxtime/3600000;
02860 dailytxtime %= 3600000;
02861 minutes = dailytxtime/60000;
02862 dailytxtime %= 60000;
02863 seconds = dailytxtime/1000;
02864 dailytxtime %= 1000;
02865
02866 ast_cli(fd, "TX time today....................................: %02d:%02d:%02d.%d\n",
02867 hours, minutes, seconds, dailytxtime);
02868
02869 hours = (int) totaltxtime/3600000;
02870 totaltxtime %= 3600000;
02871 minutes = (int) totaltxtime/60000;
02872 totaltxtime %= 60000;
02873 seconds = (int) totaltxtime/1000;
02874 totaltxtime %= 1000;
02875
02876 ast_cli(fd, "TX time since system initialization..............: %02d:%02d:%02d.%d\n",
02877 hours, minutes, seconds, (int) totaltxtime);
02878
02879 hours = uptime/3600;
02880 uptime %= 3600;
02881 minutes = uptime/60;
02882 uptime %= 60;
02883
02884 ast_cli(fd, "Uptime...........................................: %02d:%02d:%02d\n",
02885 hours, minutes, uptime);
02886
02887 ast_cli(fd, "Nodes currently connected to us..................: ");
02888 if(!numoflinks){
02889 ast_cli(fd,"<NONE>");
02890 }
02891 else{
02892 for(j = 0 ;j < numoflinks; j++){
02893 ast_cli(fd, "%s", listoflinks[j]);
02894 if(j % 4 == 3){
02895 ast_cli(fd, "\n");
02896 ast_cli(fd, " : ");
02897 }
02898 else{
02899 if((numoflinks - 1) - j > 0)
02900 ast_cli(fd, ", ");
02901 }
02902 }
02903 }
02904 ast_cli(fd,"\n");
02905
02906 ast_cli(fd, "Autopatch........................................: %s\n", patch_ena);
02907 ast_cli(fd, "Autopatch state..................................: %s\n", patch_state);
02908 ast_cli(fd, "Autopatch called number..........................: %s\n",
02909 (called_number && strlen(called_number)) ? called_number : not_applicable);
02910 ast_cli(fd, "Reverse patch/IAXRPT connected...................: %s\n", reverse_patch_state);
02911 ast_cli(fd, "User linking commands............................: %s\n", link_ena);
02912 ast_cli(fd, "User functions...................................: %s\n\n", user_funs);
02913
02914 for(j = 0; j < numoflinks; j++){
02915 ast_free(listoflinks[j]);
02916 }
02917 ast_free(called_number);
02918 ast_free(lastdtmfcommand);
02919 return RESULT_SUCCESS;
02920 }
02921 }
02922 return RESULT_FAILURE;
02923 }
02924
02925
02926
02927
02928
02929 static int rpt_do_lstats(int fd, int argc, const char * const *argv)
02930 {
02931 int i,j;
02932 char *connstate;
02933 struct rpt *myrpt;
02934 struct rpt_link *l;
02935 struct rpt_lstat *s,*t;
02936 struct rpt_lstat s_head;
02937 if(argc != 3)
02938 return RESULT_SHOWUSAGE;
02939
02940 s = NULL;
02941 s_head.next = &s_head;
02942 s_head.prev = &s_head;
02943
02944 for(i = 0; i < nrpts; i++)
02945 {
02946 if (!strcmp(argv[2],rpt_vars[i].name)){
02947
02948 myrpt = &rpt_vars[i];
02949 rpt_mutex_lock(&myrpt->lock);
02950
02951 j = 0;
02952 l = myrpt->links.next;
02953 while(l && (l != &myrpt->links)){
02954 if (l->name[0] == '0'){
02955 l = l->next;
02956 continue;
02957 }
02958 if((s = (struct rpt_lstat *) ast_malloc(sizeof(struct rpt_lstat))) == NULL){
02959 ast_log(LOG_ERROR, "Malloc failed in rpt_do_lstats\n");
02960 rpt_mutex_unlock(&myrpt->lock);
02961 return RESULT_FAILURE;
02962 }
02963 memset(s, 0, sizeof(struct rpt_lstat));
02964 strncpy(s->name, l->name, MAXREMSTR - 1);
02965 if (l->chan) pbx_substitute_variables_helper(l->chan, "${IAXPEER(CURRENTCHANNEL)}", s->peer, MAXPEERSTR - 1);
02966 else strcpy(s->peer,"(none)");
02967 s->mode = l->mode;
02968 s->outbound = l->outbound;
02969 s->reconnects = l->reconnects;
02970 s->connecttime = l->connecttime;
02971 s->thisconnected = l->thisconnected;
02972 memcpy(s->chan_stat,l->chan_stat,NRPTSTAT * sizeof(struct rpt_chan_stat));
02973 insque((struct qelem *) s, (struct qelem *) s_head.next);
02974 memset(l->chan_stat,0,NRPTSTAT * sizeof(struct rpt_chan_stat));
02975 l = l->next;
02976 }
02977 rpt_mutex_unlock(&myrpt->lock);
02978 ast_cli(fd, "NODE PEER RECONNECTS DIRECTION CONNECT TIME CONNECT STATE\n");
02979 ast_cli(fd, "---- ---- ---------- --------- ------------ -------------\n");
02980
02981 for(s = s_head.next; s != &s_head; s = s->next){
02982 int hours, minutes, seconds;
02983 long long connecttime = s->connecttime;
02984 char conntime[21];
02985 hours = (int) connecttime/3600000;
02986 connecttime %= 3600000;
02987 minutes = (int) connecttime/60000;
02988 connecttime %= 60000;
02989 seconds = (int) connecttime/1000;
02990 connecttime %= 1000;
02991 snprintf(conntime, 20, "%02d:%02d:%02d.%d",
02992 hours, minutes, seconds, (int) connecttime);
02993 conntime[20] = 0;
02994 if(s->thisconnected)
02995 connstate = "ESTABLISHED";
02996 else
02997 connstate = "CONNECTING";
02998 ast_cli(fd, "%-10s%-20s%-12d%-11s%-20s%-20s\n",
02999 s->name, s->peer, s->reconnects, (s->outbound)? "OUT":"IN", conntime, connstate);
03000 }
03001
03002 s = s_head.next;
03003 while(s != &s_head){
03004 t = s;
03005 s = s->next;
03006 remque((struct qelem *)t);
03007 ast_free(t);
03008 }
03009 return RESULT_SUCCESS;
03010 }
03011 }
03012 return RESULT_FAILURE;
03013 }
03014
03015
03016
03017
03018
03019 static int rpt_do_nodes(int fd, int argc, const char * const *argv)
03020 {
03021 int i,j;
03022 char ns;
03023 char lbuf[MAXLINKLIST],*strs[MAXLINKLIST];
03024 struct rpt *myrpt;
03025 if(argc != 3)
03026 return RESULT_SHOWUSAGE;
03027
03028 for(i = 0; i < nrpts; i++)
03029 {
03030 if (!strcmp(argv[2],rpt_vars[i].name)){
03031
03032 myrpt = &rpt_vars[i];
03033 rpt_mutex_lock(&myrpt->lock);
03034 __mklinklist(myrpt,NULL,lbuf);
03035 rpt_mutex_unlock(&myrpt->lock);
03036
03037 ns = finddelim(lbuf,strs,MAXLINKLIST);
03038
03039 if (ns) qsort((void *)strs,ns,sizeof(char *),mycompar);
03040 ast_cli(fd,"\n");
03041 ast_cli(fd, "************************* CONNECTED NODES *************************\n\n");
03042 for(j = 0 ;; j++){
03043 if(!strs[j]){
03044 if(!j){
03045 ast_cli(fd,"<NONE>");
03046 }
03047 break;
03048 }
03049 ast_cli(fd, "%s", strs[j]);
03050 if(j % 8 == 7){
03051 ast_cli(fd, "\n");
03052 }
03053 else{
03054 if(strs[j + 1])
03055 ast_cli(fd, ", ");
03056 }
03057 }
03058 ast_cli(fd,"\n\n");
03059 return RESULT_SUCCESS;
03060 }
03061 }
03062 return RESULT_FAILURE;
03063 }
03064
03065
03066
03067
03068
03069 static int rpt_do_local_nodes(int fd, int argc, const char * const *argv)
03070 {
03071
03072 int i;
03073 ast_cli(fd, "\nNode\n----\n");
03074 for (i=0; i< nrpts; i++)
03075 {
03076 ast_cli(fd, "%s\n", rpt_vars[i].name);
03077 }
03078 ast_cli(fd,"\n");
03079 return RESULT_SUCCESS;
03080 }
03081
03082
03083
03084
03085
03086
03087 static int rpt_do_reload(int fd, int argc, const char * const *argv)
03088 {
03089 int n;
03090
03091 if (argc > 2) return RESULT_SHOWUSAGE;
03092
03093 for(n = 0; n < nrpts; n++) rpt_vars[n].reload = 1;
03094
03095 return RESULT_FAILURE;
03096 }
03097
03098
03099
03100
03101
03102 static int rpt_do_restart(int fd, int argc, const char * const *argv)
03103 {
03104 int i;
03105
03106 if (argc > 2) return RESULT_SHOWUSAGE;
03107 for(i = 0; i < nrpts; i++)
03108 {
03109 if (rpt_vars[i].rxchannel) ast_softhangup(rpt_vars[i].rxchannel,AST_SOFTHANGUP_DEV);
03110 }
03111 return RESULT_FAILURE;
03112 }
03113
03114
03115
03116
03117
03118
03119 static int rpt_do_fun(int fd, int argc, const char * const *argv)
03120 {
03121 int i,busy=0;
03122
03123 if (argc != 4) return RESULT_SHOWUSAGE;
03124
03125 for(i = 0; i < nrpts; i++){
03126 if(!strcmp(argv[2], rpt_vars[i].name)){
03127 struct rpt *myrpt = &rpt_vars[i];
03128 rpt_mutex_lock(&myrpt->lock);
03129 if ((MAXMACRO - strlen(myrpt->macrobuf)) < strlen(argv[3])){
03130 rpt_mutex_unlock(&myrpt->lock);
03131 busy=1;
03132 }
03133 if(!busy){
03134 myrpt->macrotimer = MACROTIME;
03135 strncat(myrpt->macrobuf,argv[3],MAXMACRO - 1);
03136 }
03137 rpt_mutex_unlock(&myrpt->lock);
03138 }
03139 }
03140 if(busy){
03141 ast_cli(fd, "Function decoder busy");
03142 }
03143 return RESULT_FAILURE;
03144 }
03145
03146
03147
03148
03149
03150
03151
03152
03153 static int rpt_push_alt_macro(struct rpt *myrpt, char *sptr)
03154 {
03155 int busy=0;
03156
03157 rpt_mutex_lock(&myrpt->lock);
03158 if ((MAXMACRO - strlen(myrpt->macrobuf)) < strlen(sptr)){
03159 rpt_mutex_unlock(&myrpt->lock);
03160 busy=1;
03161 }
03162 if(!busy){
03163 int x;
03164 if (debug)ast_log(LOG_NOTICE, "rpt_push_alt_macro %s\n",sptr);
03165 myrpt->macrotimer = MACROTIME;
03166 for(x = 0; *(sptr + x); x++)
03167 myrpt->macrobuf[x] = *(sptr + x) | 0x80;
03168 *(sptr + x) = 0;
03169 }
03170 rpt_mutex_unlock(&myrpt->lock);
03171
03172 if(busy)ast_log(LOG_WARNING, "Function decoder busy on app_rpt command macro.\n");
03173
03174 return busy;
03175 }
03176
03177
03178
03179 static int rpt_do_fun1(int fd, int argc, const char * const *argv)
03180 {
03181 int i;
03182
03183 if (argc != 4) return RESULT_SHOWUSAGE;
03184
03185 for(i = 0; i < nrpts; i++){
03186 if(!strcmp(argv[2], rpt_vars[i].name)){
03187 struct rpt *myrpt = &rpt_vars[i];
03188 rpt_push_alt_macro(myrpt, (char *) argv[3]);
03189 }
03190 }
03191 return RESULT_FAILURE;
03192 }
03193
03194
03195
03196
03197 static int rpt_do_cmd(int fd, int argc, const char * const *argv)
03198 {
03199 int i, l;
03200 int busy=0;
03201 int maxActions = sizeof(function_table)/sizeof(struct function_table_tag);
03202
03203 int thisRpt = -1;
03204 int thisAction = -1;
03205 struct rpt *myrpt = NULL;
03206 if (argc != 6) return RESULT_SHOWUSAGE;
03207
03208 for(i = 0; i < nrpts; i++)
03209 {
03210 if(!strcmp(argv[2], rpt_vars[i].name))
03211 {
03212 thisRpt = i;
03213 myrpt = &rpt_vars[i];
03214 break;
03215 }
03216 }
03217
03218 if (thisRpt < 0)
03219 {
03220 ast_cli(fd, "Unknown node number %s.\n", argv[2]);
03221 return RESULT_FAILURE;
03222 }
03223
03224
03225 l = strlen(argv[3]);
03226 for(i = 0 ; i < maxActions; i++)
03227 {
03228 if(!strncasecmp(argv[3], function_table[i].action, l))
03229 {
03230 thisAction = i;
03231 break;
03232 }
03233 }
03234
03235 if (thisAction < 0)
03236 {
03237 ast_cli(fd, "Unknown action name %s.\n", argv[3]);
03238 return RESULT_FAILURE;
03239 }
03240
03241
03242
03243 rpt_mutex_lock(&myrpt->lock);
03244
03245 if (rpt_vars[thisRpt].cmdAction.state == CMD_STATE_IDLE)
03246 {
03247 rpt_vars[thisRpt].cmdAction.state = CMD_STATE_BUSY;
03248 rpt_vars[thisRpt].cmdAction.functionNumber = thisAction;
03249 strncpy(rpt_vars[thisRpt].cmdAction.param, argv[4], MAXDTMF);
03250 strncpy(rpt_vars[thisRpt].cmdAction.digits, argv[5], MAXDTMF);
03251 rpt_vars[thisRpt].cmdAction.command_source = SOURCE_RPT;
03252 rpt_vars[thisRpt].cmdAction.state = CMD_STATE_READY;
03253 }
03254 else
03255 {
03256 busy = 1;
03257 }
03258 rpt_mutex_unlock(&myrpt->lock);
03259
03260 return (busy ? RESULT_FAILURE : RESULT_SUCCESS);
03261 }
03262
03263 static int play_tone_pair(struct ast_channel *chan, int f1, int f2, int duration, int amplitude)
03264 {
03265 int res;
03266
03267 if ((res = ast_tonepair_start(chan, f1, f2, duration, amplitude)))
03268 return res;
03269
03270 while(chan->generatordata) {
03271 if (ast_safe_sleep(chan,1)) return -1;
03272 }
03273
03274 return 0;
03275 }
03276
03277 static int play_tone(struct ast_channel *chan, int freq, int duration, int amplitude)
03278 {
03279 return play_tone_pair(chan, freq, 0, duration, amplitude);
03280 }
03281
03282 static int play_silence(struct ast_channel *chan, int duration)
03283 {
03284 return play_tone_pair(chan, 0, 0, duration, 0);
03285 }
03286
03287 #ifdef NEW_ASTERISK
03288
03289 static char *res2cli(int r)
03290
03291 {
03292 switch (r)
03293 {
03294 case RESULT_SUCCESS:
03295 return(CLI_SUCCESS);
03296 case RESULT_SHOWUSAGE:
03297 return(CLI_SHOWUSAGE);
03298 default:
03299 return(CLI_FAILURE);
03300 }
03301 }
03302
03303 static char *handle_cli_debug(struct ast_cli_entry *e,
03304 int cmd, struct ast_cli_args *a)
03305 {
03306 switch (cmd) {
03307 case CLI_INIT:
03308 e->command = "rpt debug level";
03309 e->usage = debug_usage;
03310 return NULL;
03311 case CLI_GENERATE:
03312 return NULL;
03313 }
03314 return res2cli(rpt_do_debug(a->fd, a->argc, a->argv));
03315 }
03316
03317 static char *handle_cli_dump(struct ast_cli_entry *e,
03318 int cmd, struct ast_cli_args *a)
03319 {
03320 switch (cmd) {
03321 case CLI_INIT:
03322 e->command = "rpt dump level";
03323 e->usage = dump_usage;
03324 return NULL;
03325 case CLI_GENERATE:
03326 return NULL;
03327 }
03328 return res2cli(rpt_do_dump(a->fd,a->argc,a->argv));
03329 }
03330
03331
03332 static char *handle_cli_stats(struct ast_cli_entry *e,
03333 int cmd, struct ast_cli_args *a)
03334 {
03335 switch (cmd) {
03336 case CLI_INIT:
03337 e->command = "rpt stats";
03338 e->usage = dump_stats;
03339 return NULL;
03340 case CLI_GENERATE:
03341 return NULL;
03342 }
03343 return res2cli(rpt_do_stats(a->fd,a->argc,a->argv));
03344 }
03345
03346 static char *handle_cli_nodes(struct ast_cli_entry *e,
03347 int cmd, struct ast_cli_args *a)
03348 {
03349 switch (cmd) {
03350 case CLI_INIT:
03351 e->command = "rpt nodes";
03352 e->usage = dump_nodes;
03353 return NULL;
03354 case CLI_GENERATE:
03355 return NULL;
03356 }
03357 return res2cli(rpt_do_nodes(a->fd,a->argc,a->argv));
03358 }
03359
03360 static char *handle_cli_local_nodes(struct ast_cli_entry *e,
03361 int cmd, struct ast_cli_args *a)
03362 {
03363 switch (cmd) {
03364 case CLI_INIT:
03365 e->command = "rpt localnodes";
03366 e->usage = usage_local_nodes;
03367 return NULL;
03368 case CLI_GENERATE:
03369 return NULL;
03370 }
03371 return res2cli(rpt_do_local_nodes(a->fd,a->argc,a->argv));
03372 }
03373
03374 static char *handle_cli_lstats(struct ast_cli_entry *e,
03375 int cmd, struct ast_cli_args *a)
03376 {
03377 switch (cmd) {
03378 case CLI_INIT:
03379 e->command = "rpt lstats";
03380 e->usage = dump_lstats;
03381 return NULL;
03382 case CLI_GENERATE:
03383 return NULL;
03384 }
03385 return res2cli(rpt_do_lstats(a->fd,a->argc,a->argv));
03386 }
03387
03388 static char *handle_cli_reload(struct ast_cli_entry *e,
03389 int cmd, struct ast_cli_args *a)
03390 {
03391 switch (cmd) {
03392 case CLI_INIT:
03393 e->command = "rpt reload";
03394 e->usage = reload_usage;
03395 return NULL;
03396 case CLI_GENERATE:
03397 return NULL;
03398 }
03399 return res2cli(rpt_do_reload(a->fd,a->argc,a->argv));
03400 }
03401
03402 static char *handle_cli_restart(struct ast_cli_entry *e,
03403 int cmd, struct ast_cli_args *a)
03404 {
03405 switch (cmd) {
03406 case CLI_INIT:
03407 e->command = "rpt restart";
03408 e->usage = restart_usage;
03409 return NULL;
03410 case CLI_GENERATE:
03411 return NULL;
03412 }
03413 return res2cli(rpt_do_restart(a->fd,a->argc,a->argv));
03414 }
03415
03416 static char *handle_cli_fun(struct ast_cli_entry *e,
03417 int cmd, struct ast_cli_args *a)
03418 {
03419 switch (cmd) {
03420 case CLI_INIT:
03421 e->command = "rpt fun";
03422 e->usage = fun_usage;
03423 return NULL;
03424 case CLI_GENERATE:
03425 return NULL;
03426 }
03427 return res2cli(rpt_do_fun(a->fd,a->argc,a->argv));
03428 }
03429
03430 static char *handle_cli_fun1(struct ast_cli_entry *e,
03431 int cmd, struct ast_cli_args *a)
03432 {
03433 switch (cmd) {
03434 case CLI_INIT:
03435 e->command = "rpt fun1";
03436 e->usage = fun_usage;
03437 return NULL;
03438 case CLI_GENERATE:
03439 return NULL;
03440 }
03441 return res2cli(rpt_do_fun1(a->fd,a->argc,a->argv));
03442 }
03443
03444 static char *handle_cli_cmd(struct ast_cli_entry *e,
03445 int cmd, struct ast_cli_args *a)
03446 {
03447 switch (cmd) {
03448 case CLI_INIT:
03449 e->command = "rpt cmd";
03450 e->usage = cmd_usage;
03451 return NULL;
03452 case CLI_GENERATE:
03453 return NULL;
03454 }
03455 return res2cli(rpt_do_cmd(a->fd,a->argc,a->argv));
03456 }
03457
03458 static struct ast_cli_entry rpt_cli[] = {
03459 AST_CLI_DEFINE(handle_cli_debug,"Enable app_rpt debugging"),
03460 AST_CLI_DEFINE(handle_cli_dump,"Dump app_rpt structs for debugging"),
03461 AST_CLI_DEFINE(handle_cli_stats,"Dump node statistics"),
03462 AST_CLI_DEFINE(handle_cli_nodes,"Dump node list"),
03463 AST_CLI_DEFINE(handle_cli_local_nodes, "Dump list of local node numbers"),
03464 AST_CLI_DEFINE(handle_cli_lstats,"Dump link statistics"),
03465 AST_CLI_DEFINE(handle_cli_reload,"Reload app_rpt config"),
03466 AST_CLI_DEFINE(handle_cli_restart,"Restart app_rpt"),
03467 AST_CLI_DEFINE(handle_cli_fun,"Execute a DTMF function"),
03468 AST_CLI_DEFINE(handle_cli_fun1,"Execute a DTMF function"),
03469 AST_CLI_DEFINE(handle_cli_cmd,"Execute a DTMF function")
03470 };
03471
03472 #endif
03473
03474 static int send_morse(struct ast_channel *chan, char *string, int speed, int freq, int amplitude)
03475 {
03476
03477 static struct morse_bits mbits[] = {
03478 {0, 0},
03479 {0, 0},
03480 {6, 18},
03481 {0, 0},
03482 {7, 72},
03483 {0, 0},
03484 {0, 0},
03485 {6, 30},
03486 {5, 13},
03487 {6, 29},
03488 {0, 0},
03489 {5, 10},
03490 {6, 51},
03491 {6, 33},
03492 {6, 42},
03493 {5, 9},
03494 {5, 31},
03495 {5, 30},
03496 {5, 28},
03497 {5, 24},
03498 {5, 16},
03499 {5, 0},
03500 {5, 1},
03501 {5, 3},
03502 {5, 7},
03503 {5, 15},
03504 {6, 7},
03505 {6, 21},
03506 {0, 0},
03507 {5, 33},
03508 {0, 0},
03509 {6, 12},
03510 {0, 0},
03511 {2, 2},
03512 {4, 1},
03513 {4, 5},
03514 {3, 1},
03515 {1, 0},
03516 {4, 4},
03517 {3, 3},
03518 {4, 0},
03519 {2, 0},
03520 {4, 14},
03521 {3, 5},
03522 {4, 2},
03523 {2, 3},
03524 {2, 1},
03525 {3, 7},
03526 {4, 6},
03527 {4, 11},
03528 {3, 2},
03529 {3, 0},
03530 {1, 1},
03531 {3, 4},
03532 {4, 8},
03533 {3, 6},
03534 {4, 9},
03535 {4, 13},
03536 {4, 3}
03537 };
03538
03539
03540 int dottime;
03541 int dashtime;
03542 int intralettertime;
03543 int interlettertime;
03544 int interwordtime;
03545 int len, ddcomb;
03546 int res;
03547 int c;
03548 int i;
03549 int flags;
03550
03551 res = 0;
03552
03553
03554
03555 dottime = 900/speed;
03556
03557
03558
03559 dashtime = 3 * dottime;
03560 intralettertime = dottime;
03561 interlettertime = dottime * 4 ;
03562 interwordtime = dottime * 7;
03563
03564 for(;(*string) && (!res); string++){
03565
03566 c = *string;
03567
03568
03569
03570 if((c >= 'a') && (c <= 'z'))
03571 c -= 0x20;
03572
03573
03574
03575 if(c > 'Z')
03576 continue;
03577
03578
03579
03580 if(c == ' '){
03581 if(!res)
03582 res = play_silence(chan, interwordtime);
03583 continue;
03584 }
03585
03586
03587
03588 c -= 0x20;
03589
03590
03591
03592 len = mbits[c].len;
03593 ddcomb = mbits[c].ddcomb;
03594
03595
03596
03597 for(; len ; len--){
03598 if(!res)
03599 res = play_tone(chan, freq, (ddcomb & 1) ? dashtime : dottime, amplitude);
03600 if(!res)
03601 res = play_silence(chan, intralettertime);
03602 ddcomb >>= 1;
03603 }
03604
03605
03606
03607 if(!res)
03608 res = play_silence(chan, interlettertime - intralettertime);
03609 }
03610
03611
03612
03613 if (!res)
03614 res = ast_waitstream(chan, "");
03615 ast_stopstream(chan);
03616
03617
03618
03619
03620
03621 for(i = 0; i < 20 ; i++){
03622 flags = DAHDI_IOMUX_WRITEEMPTY | DAHDI_IOMUX_NOWAIT;
03623 res = ioctl(chan->fds[0], DAHDI_IOMUX, &flags);
03624 if(flags & DAHDI_IOMUX_WRITEEMPTY)
03625 break;
03626 if( ast_safe_sleep(chan, 50)){
03627 res = -1;
03628 break;
03629 }
03630 }
03631
03632
03633 return res;
03634 }
03635
03636 static int send_tone_telemetry(struct ast_channel *chan, char *tonestring)
03637 {
03638 char *p,*stringp;
03639 char *tonesubset;
03640 int f1,f2;
03641 int duration;
03642 int amplitude;
03643 int res;
03644 int i;
03645 int flags;
03646
03647 res = 0;
03648
03649 if(!tonestring)
03650 return res;
03651
03652 p = stringp = ast_strdup(tonestring);
03653
03654 for(;tonestring;){
03655 tonesubset = strsep(&stringp,")");
03656 if(!tonesubset)
03657 break;
03658 if(sscanf(tonesubset,"(%30d,%30d,%30d,%30d", &f1, &f2, &duration, &litude) != 4)
03659 break;
03660 res = play_tone_pair(chan, f1, f2, duration, amplitude);
03661 if(res)
03662 break;
03663 }
03664 ast_free(p);
03665 if(!res)
03666 res = play_tone_pair(chan, 0, 0, 100, 0);
03667
03668 if (!res)
03669 res = ast_waitstream(chan, "");
03670
03671 ast_stopstream(chan);
03672
03673
03674
03675
03676
03677 for(i = 0; i < 20 ; i++){
03678 flags = DAHDI_IOMUX_WRITEEMPTY | DAHDI_IOMUX_NOWAIT;
03679 res = ioctl(chan->fds[0], DAHDI_IOMUX, &flags);
03680 if(flags & DAHDI_IOMUX_WRITEEMPTY)
03681 break;
03682 if( ast_safe_sleep(chan, 50)){
03683 res = -1;
03684 break;
03685 }
03686 }
03687
03688 return res;
03689
03690 }
03691
03692 static int sayfile(struct ast_channel *mychannel,char *fname)
03693 {
03694 int res;
03695
03696 res = ast_streamfile(mychannel, fname, 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 return res;
03703 }
03704
03705 static int saycharstr(struct ast_channel *mychannel,char *str)
03706 {
03707 int res;
03708
03709 res = ast_say_character_str(mychannel,str,NULL,mychannel->language);
03710 if (!res)
03711 res = ast_waitstream(mychannel, "");
03712 else
03713 ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", mychannel->name);
03714 ast_stopstream(mychannel);
03715 return res;
03716 }
03717
03718 static int saynum(struct ast_channel *mychannel, int num)
03719 {
03720 int res;
03721 res = ast_say_number(mychannel, num, NULL, mychannel->language, NULL);
03722 if(!res)
03723 res = ast_waitstream(mychannel, "");
03724 else
03725 ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", mychannel->name);
03726 ast_stopstream(mychannel);
03727 return res;
03728 }
03729
03730
03731
03732
03733 static int saynode(struct rpt *myrpt, struct ast_channel *mychannel, char *name)
03734 {
03735 int res;
03736 char *val,fname[300];
03737
03738 val = (char *) ast_variable_retrieve(myrpt->cfg, myrpt->name, "nodenames");
03739 if (!val) val = NODENAMES;
03740 snprintf(fname,sizeof(fname) - 1,"%s/%s",val,name);
03741 if (ast_fileexists(fname,NULL,mychannel->language) > 0)
03742 return(sayfile(mychannel,fname));
03743 res = sayfile(mychannel,"rpt/node");
03744 if (!res)
03745 res = ast_say_character_str(mychannel,name,NULL,mychannel->language);
03746 return res;
03747 }
03748
03749 static int telem_any(struct rpt *myrpt,struct ast_channel *chan, char *entry)
03750 {
03751 int res;
03752 char c;
03753
03754 static int morsespeed;
03755 static int morsefreq;
03756 static int morseampl;
03757 static int morseidfreq = 0;
03758 static int morseidampl;
03759 static char mcat[] = MORSE;
03760
03761 res = 0;
03762
03763 if(!morseidfreq){
03764 morsespeed = retrieve_astcfgint(myrpt, mcat, "speed", 5, 20, 20);
03765 morsefreq = retrieve_astcfgint(myrpt, mcat, "frequency", 300, 3000, 800);
03766 morseampl = retrieve_astcfgint(myrpt, mcat, "amplitude", 200, 8192, 4096);
03767 morseidampl = retrieve_astcfgint(myrpt, mcat, "idamplitude", 200, 8192, 2048);
03768 morseidfreq = retrieve_astcfgint(myrpt, mcat, "idfrequency", 300, 3000, 330);
03769 }
03770
03771
03772
03773 if(entry[0] == '|'){
03774 c = entry[1];
03775 if((c >= 'a')&&(c <= 'z'))
03776 c -= 0x20;
03777
03778 switch(c){
03779 case 'I':
03780 res = send_morse(chan, entry + 2, morsespeed, morseidfreq, morseidampl);
03781 break;
03782
03783 case 'M':
03784 res = send_morse(chan, entry + 2, morsespeed, morsefreq, morseampl);
03785 break;
03786
03787 case 'T':
03788 res = send_tone_telemetry(chan, entry + 2);
03789 break;
03790 default:
03791 res = -1;
03792 }
03793 }
03794 else
03795 res = sayfile(chan, entry);
03796 return res;
03797 }
03798
03799
03800
03801
03802
03803
03804
03805 static int telem_lookup(struct rpt *myrpt,struct ast_channel *chan, char *node, char *name)
03806 {
03807
03808 int res;
03809 int i;
03810 char *entry;
03811 char *telemetry;
03812 char *telemetry_save;
03813
03814 res = 0;
03815 telemetry_save = NULL;
03816 entry = NULL;
03817
03818
03819 telemetry = (char *) ast_variable_retrieve(myrpt->cfg, node, TELEMETRY);
03820 if(telemetry ){
03821 telemetry_save = ast_strdup(telemetry);
03822 if(!telemetry_save){
03823 ast_log(LOG_WARNING,"ast_strdup() failed in telem_lookup()\n");
03824 return res;
03825 }
03826 entry = (char *) ast_variable_retrieve(myrpt->cfg, telemetry_save, name);
03827 }
03828
03829
03830
03831 if(!entry){
03832
03833 for(i = 0; i < sizeof(tele_defs)/sizeof(struct telem_defaults) ; i++){
03834 if(!strcasecmp(tele_defs[i].name, name))
03835 entry = tele_defs[i].value;
03836 }
03837 }
03838 if(entry){
03839 if(strlen(entry))
03840 if (chan) telem_any(myrpt,chan, entry);
03841 }
03842 else{
03843 res = -1;
03844 }
03845 ast_free(telemetry_save);
03846 return res;
03847 }
03848
03849
03850
03851
03852
03853 static int get_wait_interval(struct rpt *myrpt, int type)
03854 {
03855 int interval;
03856 char *wait_times;
03857 char *wait_times_save;
03858
03859 wait_times_save = NULL;
03860 wait_times = (char *) ast_variable_retrieve(myrpt->cfg, myrpt->name, "wait_times");
03861
03862 if(wait_times){
03863 wait_times_save = ast_strdup(wait_times);
03864 if(!wait_times_save)
03865 return 0;
03866
03867 }
03868
03869 switch(type){
03870 case DLY_TELEM:
03871 if(wait_times)
03872 interval = retrieve_astcfgint(myrpt,wait_times_save, "telemwait", 500, 5000, 1000);
03873 else
03874 interval = 1000;
03875 break;
03876
03877 case DLY_ID:
03878 if(wait_times)
03879 interval = retrieve_astcfgint(myrpt,wait_times_save, "idwait",250,5000,500);
03880 else
03881 interval = 500;
03882 break;
03883
03884 case DLY_UNKEY:
03885 if(wait_times)
03886 interval = retrieve_astcfgint(myrpt,wait_times_save, "unkeywait",50,5000,1000);
03887 else
03888 interval = 1000;
03889 break;
03890
03891 case DLY_LINKUNKEY:
03892 if(wait_times)
03893 interval = retrieve_astcfgint(myrpt,wait_times_save, "linkunkeywait",500,5000,1000);
03894 else
03895 interval = 1000;
03896 break;
03897
03898 case DLY_CALLTERM:
03899 if(wait_times)
03900 interval = retrieve_astcfgint(myrpt,wait_times_save, "calltermwait",500,5000,1500);
03901 else
03902 interval = 1500;
03903 break;
03904
03905 case DLY_COMP:
03906 if(wait_times)
03907 interval = retrieve_astcfgint(myrpt,wait_times_save, "compwait",500,5000,200);
03908 else
03909 interval = 200;
03910 break;
03911
03912 case DLY_PARROT:
03913 if(wait_times)
03914 interval = retrieve_astcfgint(myrpt,wait_times_save, "parrotwait",500,5000,200);
03915 else
03916 interval = 200;
03917 break;
03918
03919 default:
03920 interval = 0;
03921 break;
03922 }
03923 ast_free(wait_times_save);
03924 return interval;
03925 }
03926
03927
03928
03929
03930
03931 static void wait_interval(struct rpt *myrpt, int type, struct ast_channel *chan)
03932 {
03933 int interval;
03934 interval = get_wait_interval(myrpt, type);
03935 if(debug)
03936 ast_log(LOG_NOTICE,"Delay interval = %d\n", interval);
03937 if(interval)
03938 ast_safe_sleep(chan,interval);
03939 if(debug)
03940 ast_log(LOG_NOTICE,"Delay complete\n");
03941 return;
03942 }
03943
03944 static int split_freq(char *mhz, char *decimals, char *freq);
03945
03946 static void *rpt_tele_thread(void *this)
03947 {
03948 struct dahdi_confinfo ci;
03949 int res = 0,haslink,hastx,hasremote,imdone = 0, unkeys_queued, x;
03950 struct rpt_tele *mytele = (struct rpt_tele *)this;
03951 struct rpt_tele *tlist;
03952 struct rpt *myrpt;
03953 struct rpt_link *l,*l1,linkbase;
03954 struct ast_channel *mychannel;
03955 int vmajor, vminor, m;
03956 char *p,*ct,*ct_copy,*ident, *nodename,*cp;
03957 time_t t;
03958 #ifdef NEW_ASTERISK
03959 struct ast_tm localtm;
03960 #else
03961 struct tm localtm;
03962 #endif
03963 char lbuf[MAXLINKLIST],*strs[MAXLINKLIST];
03964 int i,ns,rbimode;
03965 char mhz[MAXREMSTR];
03966 char decimals[MAXREMSTR];
03967 char mystr[200];
03968 struct dahdi_params par;
03969
03970
03971
03972 myrpt = mytele->rpt;
03973
03974
03975 rpt_mutex_lock(&myrpt->lock);
03976 nodename = ast_strdup(myrpt->name);
03977 if(!nodename)
03978 {
03979 fprintf(stderr,"rpt:Sorry unable strdup nodename\n");
03980 rpt_mutex_lock(&myrpt->lock);
03981 remque((struct qelem *)mytele);
03982 ast_log(LOG_NOTICE,"Telemetry thread aborted at line %d, mode: %d\n",__LINE__, mytele->mode);
03983 rpt_mutex_unlock(&myrpt->lock);
03984 ast_free(mytele);
03985 pthread_exit(NULL);
03986 }
03987
03988 if (myrpt->p.ident){
03989 ident = ast_strdup(myrpt->p.ident);
03990 if(!ident)
03991 {
03992 fprintf(stderr,"rpt:Sorry unable strdup ident\n");
03993 rpt_mutex_lock(&myrpt->lock);
03994 remque((struct qelem *)mytele);
03995 ast_log(LOG_NOTICE,"Telemetry thread aborted at line %d, mode: %d\n",
03996 __LINE__, mytele->mode);
03997 rpt_mutex_unlock(&myrpt->lock);
03998 ast_free(nodename);
03999 ast_free(mytele);
04000 pthread_exit(NULL);
04001 }
04002 }
04003 else
04004 {
04005 ident = "";
04006 }
04007 rpt_mutex_unlock(&myrpt->lock);
04008
04009
04010
04011
04012 mychannel = ast_request("DAHDI", AST_FORMAT_SLINEAR, NULL, "pseudo", NULL);
04013 if (!mychannel)
04014 {
04015 fprintf(stderr,"rpt:Sorry unable to obtain pseudo channel\n");
04016 rpt_mutex_lock(&myrpt->lock);
04017 remque((struct qelem *)mytele);
04018 ast_log(LOG_NOTICE,"Telemetry thread aborted at line %d, mode: %d\n",__LINE__, mytele->mode);
04019 rpt_mutex_unlock(&myrpt->lock);
04020 ast_free(nodename);
04021 ast_free(ident);
04022 ast_free(mytele);
04023 pthread_exit(NULL);
04024 }
04025 #ifdef AST_CDR_FLAG_POST_DISABLED
04026 if (mychannel->cdr)
04027 ast_set_flag(mychannel->cdr,AST_CDR_FLAG_POST_DISABLED);
04028 #endif
04029 rpt_mutex_lock(&myrpt->lock);
04030 mytele->chan = mychannel;
04031 rpt_mutex_unlock(&myrpt->lock);
04032
04033 while((mytele->mode != SETREMOTE) && (mytele->mode != UNKEY) &&
04034 (mytele->mode != LINKUNKEY))
04035 {
04036 rpt_mutex_lock(&myrpt->lock);
04037 if (!myrpt->active_telem)
04038 {
04039 myrpt->active_telem = mytele;
04040 rpt_mutex_unlock(&myrpt->lock);
04041 break;
04042 }
04043 rpt_mutex_unlock(&myrpt->lock);
04044 usleep(100000);
04045 }
04046
04047
04048 ci.chan = 0;
04049
04050
04051
04052 ci.confno = (((mytele->mode == ID) || (mytele->mode == IDTALKOVER) || (mytele->mode == UNKEY) ||
04053 (mytele->mode == TAILMSG) || (mytele->mode == LINKUNKEY) || (mytele->mode == TIMEOUT) ||
04054 (mytele->mode == PARROT) || (mytele->mode == STATS_TIME_LOCAL)) ?
04055 myrpt->txconf : myrpt->conf);
04056 ci.confmode = DAHDI_CONF_CONFANN;
04057
04058 if (ioctl(mychannel->fds[0],DAHDI_SETCONF,&ci) == -1)
04059 {
04060 ast_log(LOG_WARNING, "Unable to set conference mode to Announce\n");
04061 rpt_mutex_lock(&myrpt->lock);
04062 myrpt->active_telem = NULL;
04063 remque((struct qelem *)mytele);
04064 rpt_mutex_unlock(&myrpt->lock);
04065 ast_log(LOG_NOTICE,"Telemetry thread aborted at line %d, mode: %d\n",__LINE__, mytele->mode);
04066 ast_free(nodename);
04067 ast_free(ident);
04068 ast_free(mytele);
04069 ast_hangup(mychannel);
04070 pthread_exit(NULL);
04071 }
04072 ast_stopstream(mychannel);
04073 switch(mytele->mode)
04074 {
04075 case ID:
04076 case ID1:
04077
04078 wait_interval(myrpt, (mytele->mode == ID) ? DLY_ID : DLY_TELEM,mychannel);
04079 res = telem_any(myrpt,mychannel, ident);
04080 imdone=1;
04081 break;
04082
04083 case TAILMSG:
04084 res = ast_streamfile(mychannel, myrpt->p.tailmessages[myrpt->tailmessagen], mychannel->language);
04085 break;
04086
04087 case IDTALKOVER:
04088 p = (char *) ast_variable_retrieve(myrpt->cfg, nodename, "idtalkover");
04089 if(p)
04090 res = telem_any(myrpt,mychannel, p);
04091 imdone=1;
04092 break;
04093
04094 case PROC:
04095
04096 wait_interval(myrpt, DLY_TELEM, mychannel);
04097 res = telem_lookup(myrpt, mychannel, myrpt->name, "patchup");
04098 if(res < 0){
04099 res = ast_streamfile(mychannel, "rpt/callproceeding", mychannel->language);
04100 }
04101 break;
04102 case TERM:
04103
04104 wait_interval(myrpt, DLY_CALLTERM, mychannel);
04105 res = telem_lookup(myrpt, mychannel, myrpt->name, "patchdown");
04106 if(res < 0){
04107 res = ast_streamfile(mychannel, "rpt/callterminated", mychannel->language);
04108 }
04109 break;
04110 case COMPLETE:
04111
04112 wait_interval(myrpt, DLY_TELEM, mychannel);
04113 res = telem_lookup(myrpt,mychannel, myrpt->name, "functcomplete");
04114 break;
04115 case MACRO_NOTFOUND:
04116
04117 wait_interval(myrpt, DLY_TELEM, mychannel);
04118 res = ast_streamfile(mychannel, "rpt/macro_notfound", mychannel->language);
04119 break;
04120 case MACRO_BUSY:
04121
04122 wait_interval(myrpt, DLY_TELEM, mychannel);
04123 res = ast_streamfile(mychannel, "rpt/macro_busy", mychannel->language);
04124 break;
04125 case UNKEY:
04126 if(myrpt->patchnoct && myrpt->callmode){
04127 imdone = 1;
04128 break;
04129 }
04130
04131
04132
04133
04134
04135 x = get_wait_interval(myrpt, DLY_UNKEY);
04136 rpt_mutex_lock(&myrpt->lock);
04137 myrpt->unkeytocttimer = x;
04138 rpt_mutex_unlock(&myrpt->lock);
04139
04140
04141
04142
04143
04144 tlist = myrpt->tele.next;
04145 unkeys_queued = 0;
04146 if (tlist != &myrpt->tele)
04147 {
04148 rpt_mutex_lock(&myrpt->lock);
04149 while(tlist != &myrpt->tele){
04150 if (tlist->mode == UNKEY) unkeys_queued++;
04151 tlist = tlist->next;
04152 }
04153 rpt_mutex_unlock(&myrpt->lock);
04154 }
04155 if( unkeys_queued > 1){
04156 imdone = 1;
04157 break;
04158 }
04159
04160
04161
04162 while(myrpt->unkeytocttimer)
04163 {
04164 int ctint;
04165 if(myrpt->unkeytocttimer > 100)
04166 ctint = 100;
04167 else
04168 ctint = myrpt->unkeytocttimer;
04169 ast_safe_sleep(mychannel, ctint);
04170 rpt_mutex_lock(&myrpt->lock);
04171 if(myrpt->unkeytocttimer < ctint)
04172 myrpt->unkeytocttimer = 0;
04173 else
04174 myrpt->unkeytocttimer -= ctint;
04175 rpt_mutex_unlock(&myrpt->lock);
04176 }
04177
04178
04179
04180
04181
04182 if(myrpt->keyed){
04183 imdone = 1;
04184 break;
04185 }
04186
04187 rpt_mutex_lock(&myrpt->lock);
04188 myrpt->dailykerchunks++;
04189 myrpt->totalkerchunks++;
04190 rpt_mutex_unlock(&myrpt->lock);
04191
04192 haslink = 0;
04193 hastx = 0;
04194 hasremote = 0;
04195 l = myrpt->links.next;
04196 if (l != &myrpt->links)
04197 {
04198 rpt_mutex_lock(&myrpt->lock);
04199 while(l != &myrpt->links)
04200 {
04201 if (l->name[0] == '0')
04202 {
04203 l = l->next;
04204 continue;
04205 }
04206 haslink = 1;
04207 if (l->mode) {
04208 hastx++;
04209 if (l->isremote) hasremote++;
04210 }
04211 l = l->next;
04212 }
04213 rpt_mutex_unlock(&myrpt->lock);
04214 }
04215 if (haslink)
04216 {
04217
04218 res = telem_lookup(myrpt,mychannel, myrpt->name, (!hastx) ? "remotemon" : "remotetx");
04219 if(res)
04220 ast_log(LOG_WARNING, "telem_lookup:remotexx failed on %s\n", mychannel->name);
04221
04222
04223
04224 if (myrpt->cmdnode[0])
04225 {
04226 ast_safe_sleep(mychannel,200);
04227 res = telem_lookup(myrpt,mychannel, myrpt->name, "cmdmode");
04228 if(res)
04229 ast_log(LOG_WARNING, "telem_lookup:cmdmode failed on %s\n", mychannel->name);
04230 ast_stopstream(mychannel);
04231 }
04232 }
04233 else if((ct = (char *) ast_variable_retrieve(myrpt->cfg, nodename, "unlinkedct"))){
04234 ct_copy = ast_strdup(ct);
04235 if(ct_copy)
04236 {
04237 res = telem_lookup(myrpt,mychannel, myrpt->name, ct_copy);
04238 ast_free(ct_copy);
04239 }
04240 else
04241 res = -1;
04242 if(res)
04243 ast_log(LOG_WARNING, "telem_lookup:ctx failed on %s\n", mychannel->name);
04244 }
04245 if (hasremote && (!myrpt->cmdnode[0]))
04246 {
04247
04248 ci.chan = 0;
04249 ci.confno = myrpt->conf;
04250 ci.confmode = DAHDI_CONF_CONFANN;
04251
04252 if (ioctl(mychannel->fds[0],DAHDI_SETCONF,&ci) == -1)
04253 {
04254 ast_log(LOG_WARNING, "Unable to set conference mode to Announce\n");
04255 rpt_mutex_lock(&myrpt->lock);
04256 myrpt->active_telem = NULL;
04257 remque((struct qelem *)mytele);
04258 rpt_mutex_unlock(&myrpt->lock);
04259 ast_log(LOG_NOTICE,"Telemetry thread aborted at line %d, mode: %d\n",__LINE__, mytele->mode);
04260 ast_free(nodename);
04261 ast_free(ident);
04262 ast_free(mytele);
04263 ast_hangup(mychannel);
04264 pthread_exit(NULL);
04265 }
04266 if((ct = (char *) ast_variable_retrieve(myrpt->cfg, nodename, "remotect"))){
04267 ast_safe_sleep(mychannel,200);
04268 ct_copy = ast_strdup(ct);
04269 if(ct_copy)
04270 {
04271 res = telem_lookup(myrpt,mychannel, myrpt->name, ct_copy);
04272 ast_free(ct_copy);
04273 }
04274 else
04275 res = -1;
04276
04277 if(res)
04278 ast_log(LOG_WARNING, "telem_lookup:ctx failed on %s\n", mychannel->name);
04279 }
04280 }
04281 #if defined(_MDC_DECODE_H_) && defined(MDC_SAY_WHEN_DOING_CT)
04282 if (myrpt->lastunit)
04283 {
04284 char mystr[10];
04285
04286 ast_safe_sleep(mychannel,200);
04287
04288 ci.chan = 0;
04289 ci.confno = myrpt->txconf;
04290 ci.confmode = DAHDI_CONF_CONFANN;
04291
04292 if (ioctl(mychannel->fds[0],DAHDI_SETCONF,&ci) == -1)
04293 {
04294 ast_log(LOG_WARNING, "Unable to set conference mode to Announce\n");
04295 rpt_mutex_lock(&myrpt->lock);
04296 myrpt->active_telem = NULL;
04297 remque((struct qelem *)mytele);
04298 rpt_mutex_unlock(&myrpt->lock);
04299 ast_log(LOG_NOTICE,"Telemetry thread aborted at line %d, mode: %d\n",__LINE__, mytele->mode);
04300 ast_free(nodename);
04301 ast_free(ident);
04302 ast_free(mytele);
04303 ast_hangup(mychannel);
04304 pthread_exit(NULL);
04305 }
04306 sprintf(mystr,"%04x",myrpt->lastunit);
04307 myrpt->lastunit = 0;
04308 ast_say_character_str(mychannel,mystr,NULL,mychannel->language);
04309 break;
04310 }
04311 #endif
04312 imdone = 1;
04313 break;
04314 case LINKUNKEY:
04315 if(myrpt->patchnoct && myrpt->callmode){
04316 imdone = 1;
04317 break;
04318 }
04319
04320
04321
04322
04323
04324 x = get_wait_interval(myrpt, DLY_LINKUNKEY);
04325 mytele->mylink.linkunkeytocttimer = x;
04326
04327
04328
04329
04330
04331 tlist = myrpt->tele.next;
04332 unkeys_queued = 0;
04333 if (tlist != &myrpt->tele)
04334 {
04335 rpt_mutex_lock(&myrpt->lock);
04336 while(tlist != &myrpt->tele){
04337 if (tlist->mode == LINKUNKEY) unkeys_queued++;
04338 tlist = tlist->next;
04339 }
04340 rpt_mutex_unlock(&myrpt->lock);
04341 }
04342 if( unkeys_queued > 1){
04343 imdone = 1;
04344 break;
04345 }
04346
04347
04348
04349 while(mytele->mylink.linkunkeytocttimer)
04350 {
04351 int ctint;
04352 if(mytele->mylink.linkunkeytocttimer > 100)
04353 ctint = 100;
04354 else
04355 ctint = mytele->mylink.linkunkeytocttimer;
04356 ast_safe_sleep(mychannel, ctint);
04357 rpt_mutex_lock(&myrpt->lock);
04358 if(mytele->mylink.linkunkeytocttimer < ctint)
04359 mytele->mylink.linkunkeytocttimer = 0;
04360 else
04361 mytele->mylink.linkunkeytocttimer -= ctint;
04362 rpt_mutex_unlock(&myrpt->lock);
04363 }
04364
04365 if((ct = (char *) ast_variable_retrieve(myrpt->cfg, nodename, "linkunkeyct"))){
04366 ct_copy = ast_strdup(ct);
04367 if(ct_copy){
04368 res = telem_lookup(myrpt,mychannel, myrpt->name, ct_copy);
04369 ast_free(ct_copy);
04370 }
04371 else
04372 res = -1;
04373 if(res)
04374 ast_log(LOG_WARNING, "telem_lookup:ctx failed on %s\n", mychannel->name);
04375 }
04376 imdone = 1;
04377 break;
04378 case REMDISC:
04379
04380 wait_interval(myrpt, DLY_TELEM, mychannel);
04381 l = myrpt->links.next;
04382 haslink = 0;
04383
04384 if (l != &myrpt->links)
04385 {
04386 rpt_mutex_lock(&myrpt->lock);
04387 while(l != &myrpt->links)
04388 {
04389 if (l->name[0] == '0')
04390 {
04391 l = l->next;
04392 continue;
04393 }
04394 if (!strcmp(l->name,mytele->mylink.name))
04395 {
04396 haslink = 1;
04397 break;
04398 }
04399 l = l->next;
04400 }
04401 rpt_mutex_unlock(&myrpt->lock);
04402 }
04403 if (haslink)
04404 {
04405 imdone = 1;
04406 break;
04407 }
04408 res = saynode(myrpt,mychannel,mytele->mylink.name);
04409 if (!res)
04410 res = ast_streamfile(mychannel, ((mytele->mylink.hasconnected) ?
04411 "rpt/remote_disc" : "rpt/remote_busy"), mychannel->language);
04412 break;
04413 case REMALREADY:
04414
04415 wait_interval(myrpt, DLY_TELEM, mychannel);
04416 res = ast_streamfile(mychannel, "rpt/remote_already", mychannel->language);
04417 break;
04418 case REMNOTFOUND:
04419
04420 wait_interval(myrpt, DLY_TELEM, mychannel);
04421 res = ast_streamfile(mychannel, "rpt/remote_notfound", mychannel->language);
04422 break;
04423 case REMGO:
04424
04425 wait_interval(myrpt, DLY_TELEM, mychannel);
04426 res = ast_streamfile(mychannel, "rpt/remote_go", mychannel->language);
04427 break;
04428 case CONNECTED:
04429
04430 wait_interval(myrpt, DLY_TELEM, mychannel);
04431 res = saynode(myrpt,mychannel,mytele->mylink.name);
04432 if (!res)
04433 res = ast_streamfile(mychannel, "rpt/connected", mychannel->language);
04434 if (!res)
04435 res = ast_waitstream(mychannel, "");
04436 else
04437 ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", mychannel->name);
04438 ast_stopstream(mychannel);
04439 res = ast_streamfile(mychannel, "digits/2", mychannel->language);
04440 if (!res)
04441 res = ast_waitstream(mychannel, "");
04442 else
04443 ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", mychannel->name);
04444 ast_stopstream(mychannel);
04445 res = saynode(myrpt,mychannel,myrpt->name);
04446 imdone = 1;
04447 break;
04448 case CONNFAIL:
04449 res = saynode(myrpt,mychannel,mytele->mylink.name);
04450 if (!res)
04451 res = ast_streamfile(mychannel, "rpt/connection_failed", mychannel->language);
04452 break;
04453 case MEMNOTFOUND:
04454
04455 wait_interval(myrpt, DLY_TELEM, mychannel);
04456 res = ast_streamfile(mychannel, "rpt/memory_notfound", mychannel->language);
04457 break;
04458 case PLAYBACK:
04459
04460 wait_interval(myrpt, DLY_TELEM, mychannel);
04461 res = ast_streamfile(mychannel, mytele->param, mychannel->language);
04462 break;
04463 case TOPKEY:
04464
04465 wait_interval(myrpt, DLY_TELEM, mychannel);
04466 for(i = 0; i < TOPKEYN; i++)
04467 {
04468 if (!myrpt->topkey[i].node[0]) continue;
04469 if ((!myrpt->topkeylong) && (myrpt->topkey[i].keyed)) continue;
04470 res = saynode(myrpt, mychannel, myrpt->topkey[i].node);
04471 if (!res) res = sayfile(mychannel,(myrpt->topkey[i].keyed) ?
04472 "rpt/keyedfor" : "rpt/unkeyedfor");
04473 if (!res) res = saynum(mychannel,
04474 myrpt->topkey[i].timesince);
04475 if (!res) res = sayfile(mychannel,"rpt/seconds");
04476 if (!myrpt->topkeylong) break;
04477 }
04478 imdone = 1;
04479 break;
04480 case SETREMOTE:
04481 ast_mutex_lock(&myrpt->remlock);
04482 res = 0;
04483 if(!strcmp(myrpt->remoterig, remote_rig_ft897))
04484 {
04485 res = set_ft897(myrpt);
04486 }
04487 else if(!strcmp(myrpt->remoterig, remote_rig_tm271))
04488 {
04489 res = set_tm271(myrpt);
04490 }
04491 else if(!strcmp(myrpt->remoterig, remote_rig_ic706))
04492 {
04493 res = set_ic706(myrpt);
04494 }
04495 #ifdef HAVE_IOPERM
04496 else if(!strcmp(myrpt->remoterig, remote_rig_rbi)||!strcmp(myrpt->remoterig, remote_rig_ppp16))
04497 {
04498 if (ioperm(myrpt->p.iobase,1,1) == -1)
04499 {
04500 rpt_mutex_unlock(&myrpt->lock);
04501 ast_log(LOG_WARNING, "Cant get io permission on IO port %x hex\n",myrpt->p.iobase);
04502 res = -1;
04503 }
04504 else res = setrbi(myrpt);
04505 }
04506 #endif
04507 else if(!strcmp(myrpt->remoterig, remote_rig_kenwood))
04508 {
04509 if (myrpt->iofd >= 0) setdtr(myrpt->iofd,1);
04510 res = setkenwood(myrpt);
04511 if (myrpt->iofd >= 0) setdtr(myrpt->iofd,0);
04512 if (ast_safe_sleep(mychannel,200) == -1)
04513 {
04514 ast_mutex_unlock(&myrpt->remlock);
04515 res = -1;
04516 break;
04517 }
04518 if (myrpt->iofd < 0)
04519 {
04520 i = DAHDI_FLUSH_EVENT;
04521 if (ioctl(myrpt->dahditxchannel->fds[0],DAHDI_FLUSH,&i) == -1)
04522 {
04523 ast_mutex_unlock(&myrpt->remlock);
04524 ast_log(LOG_ERROR,"Cant flush events");
04525 res = -1;
04526 break;
04527 }
04528 if (ioctl(myrpt->dahdirxchannel->fds[0],DAHDI_GET_PARAMS,&par) == -1)
04529 {
04530 ast_mutex_unlock(&myrpt->remlock);
04531 ast_log(LOG_ERROR,"Cant get params");
04532 res = -1;
04533 break;
04534 }
04535 myrpt->remoterx =
04536 (par.rxisoffhook || (myrpt->tele.next != &myrpt->tele));
04537 }
04538 }
04539
04540 ast_mutex_unlock(&myrpt->remlock);
04541 if (!res)
04542 {
04543 imdone = 1;
04544 break;
04545 }
04546
04547 case INVFREQ:
04548
04549 wait_interval(myrpt, DLY_TELEM, mychannel);
04550 res = ast_streamfile(mychannel, "rpt/invalid-freq", mychannel->language);
04551 break;
04552 case REMMODE:
04553 cp = 0;
04554 wait_interval(myrpt, DLY_TELEM, mychannel);
04555 switch(myrpt->remmode)
04556 {
04557 case REM_MODE_FM:
04558 saycharstr(mychannel,"FM");
04559 break;
04560 case REM_MODE_USB:
04561 saycharstr(mychannel,"USB");
04562 break;
04563 case REM_MODE_LSB:
04564 saycharstr(mychannel,"LSB");
04565 break;
04566 case REM_MODE_AM:
04567 saycharstr(mychannel,"AM");
04568 break;
04569 }
04570 wait_interval(myrpt, DLY_COMP, mychannel);
04571 if (!res) res = telem_lookup(myrpt,mychannel, myrpt->name, "functcomplete");
04572 break;
04573 case LOGINREQ:
04574 wait_interval(myrpt, DLY_TELEM, mychannel);
04575 sayfile(mychannel,"rpt/login");
04576 saycharstr(mychannel,myrpt->name);
04577 break;
04578 case REMLOGIN:
04579 wait_interval(myrpt, DLY_TELEM, mychannel);
04580 saycharstr(mychannel,myrpt->loginuser);
04581 saynode(myrpt,mychannel,myrpt->name);
04582 wait_interval(myrpt, DLY_COMP, mychannel);
04583 if (!res) res = telem_lookup(myrpt,mychannel, myrpt->name, "functcomplete");
04584 break;
04585 case REMXXX:
04586 wait_interval(myrpt, DLY_TELEM, mychannel);
04587 res = 0;
04588 switch(mytele->submode)
04589 {
04590 case 100:
04591 sayfile(mychannel, "rpt/rxpl");
04592 sayfile(mychannel, "rpt/off");
04593 break;
04594 case 101:
04595 sayfile(mychannel, "rpt/rxpl");
04596 sayfile(mychannel, "rpt/on");
04597 break;
04598 case 102:
04599 sayfile(mychannel, "rpt/txpl");
04600 sayfile(mychannel, "rpt/off");
04601 break;
04602 case 103:
04603 sayfile(mychannel, "rpt/txpl");
04604 sayfile(mychannel, "rpt/on");
04605 break;
04606 case 104:
04607 sayfile(mychannel, "rpt/lopwr");
04608 break;
04609 case 105:
04610 sayfile(mychannel, "rpt/medpwr");
04611 break;
04612 case 106:
04613 sayfile(mychannel, "rpt/hipwr");
04614 break;
04615 case 113:
04616 sayfile(mychannel,"rpt/down");
04617 sayfile(mychannel, "rpt/slow");
04618 break;
04619 case 114:
04620 sayfile(mychannel,"rpt/down");
04621 sayfile(mychannel, "rpt/quick");
04622 break;
04623 case 115:
04624 sayfile(mychannel,"rpt/down");
04625 sayfile(mychannel, "rpt/fast");
04626 break;
04627 case 116:
04628 sayfile(mychannel,"rpt/up");
04629 sayfile(mychannel, "rpt/slow");
04630 break;
04631 case 117:
04632 sayfile(mychannel,"rpt/up");
04633 sayfile(mychannel, "rpt/quick");
04634 break;
04635 case 118:
04636 sayfile(mychannel,"rpt/up");
04637 sayfile(mychannel, "rpt/fast");
04638 break;
04639 default:
04640 res = -1;
04641 }
04642 wait_interval(myrpt, DLY_COMP, mychannel);
04643 if (!res) res = telem_lookup(myrpt,mychannel, myrpt->name, "functcomplete");
04644 break;
04645 case SCAN:
04646 ast_mutex_lock(&myrpt->remlock);
04647 if (myrpt->hfscanstop)
04648 {
04649 myrpt->hfscanstatus = 0;
04650 myrpt->hfscanmode = 0;
04651 myrpt->hfscanstop = 0;
04652 mytele->mode = SCANSTAT;
04653 ast_mutex_unlock(&myrpt->remlock);
04654 if (ast_safe_sleep(mychannel,1000) == -1) break;
04655 sayfile(mychannel, "rpt/stop");
04656 imdone = 1;
04657 break;
04658 }
04659 if (myrpt->hfscanstatus > -2) service_scan(myrpt);
04660 i = myrpt->hfscanstatus;
04661 myrpt->hfscanstatus = 0;
04662 if (i) mytele->mode = SCANSTAT;
04663 ast_mutex_unlock(&myrpt->remlock);
04664 if (i < 0) sayfile(mychannel, "rpt/stop");
04665 else if (i > 0) saynum(mychannel,i);
04666 imdone = 1;
04667 break;
04668 case TUNE:
04669 ast_mutex_lock(&myrpt->remlock);
04670 if (!strcmp(myrpt->remoterig,remote_rig_ic706))
04671 {
04672 set_mode_ic706(myrpt, REM_MODE_AM);
04673 if(play_tone(mychannel, 800, 6000, 8192) == -1) break;
04674 ast_safe_sleep(mychannel,500);
04675 set_mode_ic706(myrpt, myrpt->remmode);
04676 myrpt->tunerequest = 0;
04677 ast_mutex_unlock(&myrpt->remlock);
04678 imdone = 1;
04679 break;
04680 }
04681 set_mode_ft897(myrpt, REM_MODE_AM);
04682 simple_command_ft897(myrpt, 8);
04683 if(play_tone(mychannel, 800, 6000, 8192) == -1) break;
04684 simple_command_ft897(myrpt, 0x88);
04685 ast_safe_sleep(mychannel,500);
04686 set_mode_ft897(myrpt, myrpt->remmode);
04687 myrpt->tunerequest = 0;
04688 ast_mutex_unlock(&myrpt->remlock);
04689 imdone = 1;
04690 break;
04691 case REMSHORTSTATUS:
04692 case REMLONGSTATUS:
04693 wait_interval(myrpt, DLY_TELEM, mychannel);
04694 res = saynode(myrpt,mychannel,myrpt->name);
04695 if(!res)
04696 res = sayfile(mychannel,"rpt/frequency");
04697 if(!res)
04698 res = split_freq(mhz, decimals, myrpt->freq);
04699 if (!multimode_capable(myrpt)) decimals[3] = 0;
04700 if(!res){
04701 m = atoi(mhz);
04702 if(m < 100)
04703 res = saynum(mychannel, m);
04704 else
04705 res = saycharstr(mychannel, mhz);
04706 }
04707 if(!res)
04708 res = sayfile(mychannel, "letters/dot");
04709 if(!res)
04710 res = saycharstr(mychannel, decimals);
04711
04712 if(res) break;
04713 if(myrpt->remmode == REM_MODE_FM){
04714 switch(myrpt->offset){
04715
04716 case REM_MINUS:
04717 res = sayfile(mychannel,"rpt/minus");
04718 break;
04719
04720 case REM_SIMPLEX:
04721 res = sayfile(mychannel,"rpt/simplex");
04722 break;
04723
04724 case REM_PLUS:
04725 res = sayfile(mychannel,"rpt/plus");
04726 break;
04727
04728 default:
04729 break;
04730 }
04731 }
04732 else{
04733 switch(myrpt->remmode){
04734
04735 case REM_MODE_USB:
04736 res = saycharstr(mychannel, "USB");
04737 break;
04738
04739 case REM_MODE_LSB:
04740 res = saycharstr(mychannel, "LSB");
04741 break;
04742
04743 case REM_MODE_AM:
04744 res = saycharstr(mychannel, "AM");
04745 break;
04746
04747
04748 default:
04749 break;
04750 }
04751 }
04752
04753 if (res == -1) break;
04754
04755 if(mytele->mode == REMSHORTSTATUS){
04756 wait_interval(myrpt, DLY_COMP, mychannel);
04757 if (!res) res = telem_lookup(myrpt,mychannel, myrpt->name, "functcomplete");
04758 break;
04759 }
04760
04761 if (strcmp(myrpt->remoterig,remote_rig_ic706))
04762 {
04763 switch(myrpt->powerlevel){
04764
04765 case REM_LOWPWR:
04766 res = sayfile(mychannel,"rpt/lopwr") ;
04767 break;
04768 case REM_MEDPWR:
04769 res = sayfile(mychannel,"rpt/medpwr");
04770 break;
04771 case REM_HIPWR:
04772 res = sayfile(mychannel,"rpt/hipwr");
04773 break;
04774 }
04775 }
04776
04777 rbimode = ((!strncmp(myrpt->remoterig,remote_rig_rbi,3))
04778 || (!strncmp(myrpt->remoterig,remote_rig_ic706,3)));
04779 if (res || (sayfile(mychannel,"rpt/rxpl") == -1)) break;
04780 if (rbimode && (sayfile(mychannel,"rpt/txpl") == -1)) break;
04781 if ((sayfile(mychannel,"rpt/frequency") == -1) ||
04782 (saycharstr(mychannel,myrpt->rxpl) == -1)) break;
04783 if ((!rbimode) && ((sayfile(mychannel,"rpt/txpl") == -1) ||
04784 (sayfile(mychannel,"rpt/frequency") == -1) ||
04785 (saycharstr(mychannel,myrpt->txpl) == -1))) break;
04786 if(myrpt->remmode == REM_MODE_FM){
04787 if ((sayfile(mychannel,"rpt/rxpl") == -1) ||
04788 (sayfile(mychannel,((myrpt->rxplon) ? "rpt/on" : "rpt/off")) == -1) ||
04789 (sayfile(mychannel,"rpt/txpl") == -1) ||
04790 (sayfile(mychannel,((myrpt->txplon) ? "rpt/on" : "rpt/off")) == -1))
04791 {
04792 break;
04793 }
04794 }
04795 wait_interval(myrpt, DLY_COMP, mychannel);
04796 if (!res) res = telem_lookup(myrpt,mychannel, myrpt->name, "functcomplete");
04797 break;
04798 case STATUS:
04799
04800 wait_interval(myrpt, DLY_TELEM, mychannel);
04801 hastx = 0;
04802 linkbase.next = &linkbase;
04803 linkbase.prev = &linkbase;
04804 rpt_mutex_lock(&myrpt->lock);
04805
04806 l = myrpt->links.next;
04807 while(l != &myrpt->links)
04808 {
04809 if (l->name[0] == '0')
04810 {
04811 l = l->next;
04812 continue;
04813 }
04814 l1 = ast_malloc(sizeof(struct rpt_link));
04815 if (!l1)
04816 {
04817 ast_log(LOG_WARNING, "Cannot alloc memory on %s\n", mychannel->name);
04818 remque((struct qelem *)mytele);
04819 myrpt->active_telem = NULL;
04820 rpt_mutex_unlock(&myrpt->lock);
04821 ast_log(LOG_NOTICE,"Telemetry thread aborted at line %d, mode: %d\n",__LINE__, mytele->mode);
04822 ast_free(nodename);
04823 ast_free(ident);
04824 ast_free(mytele);
04825 ast_hangup(mychannel);
04826 pthread_exit(NULL);
04827 }
04828 memcpy(l1,l,sizeof(struct rpt_link));
04829 l1->next = l1->prev = NULL;
04830 insque((struct qelem *)l1,(struct qelem *)linkbase.next);
04831 l = l->next;
04832 }
04833 rpt_mutex_unlock(&myrpt->lock);
04834 res = saynode(myrpt,mychannel,myrpt->name);
04835 if (myrpt->callmode)
04836 {
04837 hastx = 1;
04838 res = ast_streamfile(mychannel, "rpt/autopatch_on", mychannel->language);
04839 if (!res)
04840 res = ast_waitstream(mychannel, "");
04841 else
04842 ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", mychannel->name);
04843 ast_stopstream(mychannel);
04844 }
04845 l = linkbase.next;
04846 while(l != &linkbase)
04847 {
04848 char *s;
04849
04850 hastx = 1;
04851 res = saynode(myrpt,mychannel,l->name);
04852 s = "rpt/tranceive";
04853 if (!l->mode) s = "rpt/monitor";
04854 if (!l->thisconnected) s = "rpt/connecting";
04855 res = ast_streamfile(mychannel, s, mychannel->language);
04856 if (!res)
04857 res = ast_waitstream(mychannel, "");
04858 else
04859 ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", mychannel->name);
04860 ast_stopstream(mychannel);
04861 l = l->next;
04862 }
04863 if (!hastx)
04864 {
04865 res = ast_streamfile(mychannel, "rpt/repeat_only", mychannel->language);
04866 if (!res)
04867 res = ast_waitstream(mychannel, "");
04868 else
04869 ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", mychannel->name);
04870 ast_stopstream(mychannel);
04871 }
04872
04873 l = linkbase.next;
04874 while(l != &linkbase)
04875 {
04876 l1 = l;
04877 l = l->next;
04878 remque((struct qelem *)l1);
04879 ast_free(l1);
04880 }
04881 imdone = 1;
04882 break;
04883 case FULLSTATUS:
04884 rpt_mutex_lock(&myrpt->lock);
04885
04886 __mklinklist(myrpt,NULL,lbuf);
04887 rpt_mutex_unlock(&myrpt->lock);
04888
04889 ns = finddelim(lbuf,strs,MAXLINKLIST);
04890
04891 if (ns) qsort((void *)strs,ns,sizeof(char *),mycompar);
04892
04893 wait_interval(myrpt, DLY_TELEM, mychannel);
04894 hastx = 0;
04895 res = saynode(myrpt,mychannel,myrpt->name);
04896 if (myrpt->callmode)
04897 {
04898 hastx = 1;
04899 res = ast_streamfile(mychannel, "rpt/autopatch_on", mychannel->language);
04900 if (!res)
04901 res = ast_waitstream(mychannel, "");
04902 else
04903 ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", mychannel->name);
04904 ast_stopstream(mychannel);
04905 }
04906
04907 for(i = 0; i < ns; i++)
04908 {
04909 char *s,mode = 'T';
04910
04911
04912 if ((*strs[i] < '0') || (*strs[i] > '9'))
04913 {
04914 mode = *strs[i];
04915 strs[i]++;
04916 }
04917
04918 hastx = 1;
04919 res = saynode(myrpt,mychannel,strs[i]);
04920 s = "rpt/tranceive";
04921 if (mode == 'R') s = "rpt/monitor";
04922 if (mode == 'C') s = "rpt/connecting";
04923 res = ast_streamfile(mychannel, s, mychannel->language);
04924 if (!res)
04925 res = ast_waitstream(mychannel, "");
04926 else
04927 ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", mychannel->name);
04928 ast_stopstream(mychannel);
04929 }
04930 if (!hastx)
04931 {
04932 res = ast_streamfile(mychannel, "rpt/repeat_only", mychannel->language);
04933 if (!res)
04934 res = ast_waitstream(mychannel, "");
04935 else
04936 ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", mychannel->name);
04937 ast_stopstream(mychannel);
04938 }
04939 imdone = 1;
04940 break;
04941
04942 case LASTNODEKEY:
04943 rpt_mutex_lock(&myrpt->lock);
04944 if(myrpt->lastnodewhichkeyedusup){
04945 p = ast_strdup(myrpt->lastnodewhichkeyedusup);
04946 if(!p){
04947 ast_log(LOG_WARNING, "ast_strdup failed in telemetery LASTNODEKEY");
04948 imdone = 1;
04949 break;
04950 }
04951 }
04952 else
04953 p = NULL;
04954 rpt_mutex_unlock(&myrpt->lock);
04955 if(!p){
04956 imdone = 1;
04957 break;
04958 }
04959 wait_interval(myrpt, DLY_TELEM, mychannel);
04960 res = saynode(myrpt,mychannel,p);
04961 ast_free(p);
04962 imdone = 1;
04963 break;
04964
04965 case UNAUTHTX:
04966 wait_interval(myrpt, DLY_TELEM, mychannel);
04967 res = ast_streamfile(mychannel, "rpt/unauthtx", mychannel->language);
04968 if (!res)
04969 res = ast_waitstream(mychannel, "");
04970 else
04971 ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", mychannel->name);
04972 ast_stopstream(mychannel);
04973 imdone = 1;
04974 break;
04975
04976 case PARROT:
04977
04978 sprintf(mystr,PARROTFILE,myrpt->name,(unsigned int)mytele->parrot);
04979 if (ast_fileexists(mystr,NULL,mychannel->language) <= 0)
04980 {
04981 imdone = 1;
04982 myrpt->parrotstate = 0;
04983 break;
04984 }
04985 wait_interval(myrpt, DLY_PARROT, mychannel);
04986 sprintf(mystr,PARROTFILE,myrpt->name,(unsigned int)mytele->parrot);
04987 res = ast_streamfile(mychannel, mystr, mychannel->language);
04988 if (!res)
04989 res = ast_waitstream(mychannel, "");
04990 else
04991 ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", mychannel->name);
04992 ast_stopstream(mychannel);
04993 sprintf(mystr,PARROTFILE,myrpt->name,(unsigned int)mytele->parrot);
04994 strcat(mystr,".wav");
04995 unlink(mystr);
04996 imdone = 1;
04997 myrpt->parrotstate = 0;
04998 break;
04999
05000 case TIMEOUT:
05001 res = saynode(myrpt,mychannel,myrpt->name);
05002 if (!res)
05003 res = ast_streamfile(mychannel, "rpt/timeout", mychannel->language);
05004 break;
05005
05006 case TIMEOUT_WARNING:
05007 time(&t);
05008 res = saynode(myrpt,mychannel,myrpt->name);
05009 if (!res)
05010 res = ast_streamfile(mychannel, "rpt/timeout-warning", mychannel->language);
05011 if (!res)
05012 res = ast_waitstream(mychannel, "");
05013 else
05014 ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", mychannel->name);
05015 ast_stopstream(mychannel);
05016 if(!res)
05017 ast_say_number(mychannel, myrpt->p.remotetimeout -
05018 (t - myrpt->last_activity_time),
05019 "", mychannel->language, (char *) NULL);
05020 if (!res)
05021 res = ast_waitstream(mychannel, "");
05022 ast_stopstream(mychannel);
05023 res = ast_streamfile(mychannel, "queue-seconds", mychannel->language);
05024 break;
05025
05026 case ACT_TIMEOUT_WARNING:
05027 time(&t);
05028 res = saynode(myrpt,mychannel,myrpt->name);
05029 if (!res)
05030 res = ast_streamfile(mychannel, "rpt/act-timeout-warning", mychannel->language);
05031 if (!res)
05032 res = ast_waitstream(mychannel, "");
05033 else
05034 ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", mychannel->name);
05035 ast_stopstream(mychannel);
05036 if(!res)
05037 ast_say_number(mychannel, myrpt->p.remoteinacttimeout -
05038 (t - myrpt->last_activity_time),
05039 "", mychannel->language, (char *) NULL);
05040 if (!res)
05041 res = ast_waitstream(mychannel, "");
05042 ast_stopstream(mychannel);
05043 res = ast_streamfile(mychannel, "queue-seconds", mychannel->language);
05044 break;
05045
05046 case STATS_TIME:
05047 case STATS_TIME_LOCAL:
05048 wait_interval(myrpt, DLY_TELEM, mychannel);
05049 t = time(NULL);
05050 rpt_localtime(&t, &localtm);
05051
05052 if((localtm.tm_hour >= 0) && (localtm.tm_hour < 12))
05053 p = "rpt/goodmorning";
05054 else if((localtm.tm_hour >= 12) && (localtm.tm_hour < 18))
05055 p = "rpt/goodafternoon";
05056 else
05057 p = "rpt/goodevening";
05058 if (sayfile(mychannel,p) == -1)
05059 {
05060 imdone = 1;
05061 break;
05062 }
05063
05064 if (sayfile(mychannel,"rpt/thetimeis") == -1)
05065 {
05066 imdone = 1;
05067 break;
05068 }
05069
05070 res = ast_say_time(mychannel, t, "", mychannel->language);
05071 if (!res)
05072 res = ast_waitstream(mychannel, "");
05073 ast_stopstream(mychannel);
05074 imdone = 1;
05075 break;
05076 case STATS_VERSION:
05077 p = strstr(tdesc, "version");
05078 if(!p)
05079 break;
05080 if(sscanf(p, "version %30d.%30d", &vmajor, &vminor) != 2)
05081 break;
05082 wait_interval(myrpt, DLY_TELEM, mychannel);
05083
05084 if (sayfile(mychannel,"rpt/version") == -1)
05085 {
05086 imdone = 1;
05087 break;
05088 }
05089 if(!res)
05090 ast_say_number(mychannel, vmajor, "", mychannel->language, (char *) NULL);
05091 if (!res)
05092 res = ast_waitstream(mychannel, "");
05093 ast_stopstream(mychannel);
05094 if (saycharstr(mychannel,".") == -1)
05095 {
05096 imdone = 1;
05097 break;
05098 }
05099 if(!res)
05100 ast_say_number(mychannel, vminor, "", mychannel->language, (char *) NULL);
05101 if (!res){
05102 res = ast_waitstream(mychannel, "");
05103 ast_stopstream(mychannel);
05104 }
05105 else
05106 ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", mychannel->name);
05107 imdone = 1;
05108 break;
05109 case ARB_ALPHA:
05110 wait_interval(myrpt, DLY_TELEM, mychannel);
05111 if(mytele->param)
05112 saycharstr(mychannel, mytele->param);
05113 imdone = 1;
05114 break;
05115 case REV_PATCH:
05116 wait_interval(myrpt, DLY_TELEM, mychannel);
05117 if(mytele->param) {
05118
05119
05120 char *tpl_working, *tpl_current;
05121 char *tmp[100], *myparm;
05122 int looptemp=0,idx=0, dres = 0;
05123
05124
05125 tpl_working = ast_strdup(mytele->param);
05126 myparm = strsep(&tpl_working,",");
05127 tpl_current=strsep(&tpl_working, ":");
05128
05129 while(tpl_current && looptemp < sizeof(tmp)) {
05130 tmp[looptemp]=tpl_current;
05131 looptemp++;
05132 tpl_current=strsep(&tpl_working,":");
05133 }
05134
05135 for(idx=0; idx<looptemp; idx++) {
05136 if(!strcmp(tmp[idx], "PARKED")) {
05137 ast_say_digits(mychannel, atoi(myparm), "", mychannel->language);
05138 } else if(!strcmp(tmp[idx], "NODE")) {
05139 ast_say_digits(mychannel, atoi(myrpt->name), "", mychannel->language);
05140 } else {
05141 dres = ast_streamfile(mychannel, tmp[idx], mychannel->language);
05142 if(!dres) {
05143 dres = ast_waitstream(mychannel, "");
05144 } else {
05145 ast_log(LOG_WARNING, "ast_streamfile of %s failed on %s\n", tmp[idx], mychannel->name);
05146 dres = 0;
05147 }
05148 }
05149 }
05150 ast_free(tpl_working);
05151 }
05152 imdone = 1;
05153 break;
05154 case TEST_TONE:
05155 imdone = 1;
05156 if (myrpt->stopgen) break;
05157 myrpt->stopgen = -1;
05158 if ((res = ast_tonepair_start(mychannel, 1004.0, 0, 99999999, 7200.0)))
05159 {
05160 myrpt->stopgen = 0;
05161 break;
05162 }
05163 while(mychannel->generatordata && (myrpt->stopgen <= 0)) {
05164 if (ast_safe_sleep(mychannel,1)) break;
05165 imdone = 1;
05166 }
05167 myrpt->stopgen = 0;
05168 break;
05169 default:
05170 break;
05171 }
05172 if (!imdone)
05173 {
05174 if (!res)
05175 res = ast_waitstream(mychannel, "");
05176 else {
05177 ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", mychannel->name);
05178 res = 0;
05179 }
05180 }
05181 ast_stopstream(mychannel);
05182 rpt_mutex_lock(&myrpt->lock);
05183 if (mytele->mode == TAILMSG)
05184 {
05185 if (!res)
05186 {
05187 myrpt->tailmessagen++;
05188 if(myrpt->tailmessagen >= myrpt->p.tailmessagemax) myrpt->tailmessagen = 0;
05189 }
05190 else
05191 {
05192 myrpt->tmsgtimer = myrpt->p.tailsquashedtime;
05193 }
05194 }
05195 remque((struct qelem *)mytele);
05196 myrpt->active_telem = NULL;
05197 rpt_mutex_unlock(&myrpt->lock);
05198 ast_free(nodename);
05199 ast_free(ident);
05200 ast_free(mytele);
05201 ast_hangup(mychannel);
05202 #ifdef APP_RPT_LOCK_DEBUG
05203 {
05204 struct lockthread *t;
05205
05206 sleep(5);
05207 ast_mutex_lock(&locklock);
05208 t = get_lockthread(pthread_self());
05209 if (t) memset(t,0,sizeof(struct lockthread));
05210 ast_mutex_unlock(&locklock);
05211 }
05212 #endif
05213 pthread_exit(NULL);
05214 }
05215
05216 static void rpt_telemetry(struct rpt *myrpt,int mode, void *data)
05217 {
05218 struct rpt_tele *tele;
05219 struct rpt_link *mylink = NULL;
05220 int res;
05221 pthread_attr_t attr;
05222 char *v1, *v2;
05223
05224 if(debug > 6)
05225 ast_log(LOG_NOTICE,"mode=%i data=%s\n",mode, (char *)data);
05226
05227 switch(mode)
05228 {
05229 case UNKEY:
05230
05231
05232 v1 = (char *) ast_variable_retrieve(myrpt->cfg, myrpt->name,
05233 "unlinkedct");
05234 v2 = (char *) ast_variable_retrieve(myrpt->cfg, myrpt->name,
05235 "remotect");
05236 if (telem_lookup(myrpt,NULL, myrpt->name, "remotemon") &&
05237 telem_lookup(myrpt,NULL, myrpt->name, "remotetx") &&
05238 telem_lookup(myrpt,NULL, myrpt->name, "cmdmode") &&
05239 (!(v1 && telem_lookup(myrpt,NULL, myrpt->name, v1))) &&
05240 (!(v2 && telem_lookup(myrpt,NULL, myrpt->name, v2)))) return;
05241 break;
05242 case LINKUNKEY:
05243 if (!ast_variable_retrieve(myrpt->cfg, myrpt->name, "linkunkeyct"))
05244 return;
05245 break;
05246 default:
05247 break;
05248 }
05249 tele = ast_malloc(sizeof(struct rpt_tele));
05250 if (!tele)
05251 {
05252 ast_log(LOG_WARNING, "Unable to allocate memory\n");
05253 pthread_exit(NULL);
05254 return;
05255 }
05256
05257 memset((char *)tele,0,sizeof(struct rpt_tele));
05258 tele->rpt = myrpt;
05259 tele->mode = mode;
05260 if (mode == PARROT) tele->parrot = (uintptr_t) data;
05261 else mylink = (struct rpt_link *) data;
05262 rpt_mutex_lock(&myrpt->lock);
05263 if((mode == CONNFAIL) || (mode == REMDISC) || (mode == CONNECTED) ||
05264 (mode == LINKUNKEY)){
05265 memset(&tele->mylink,0,sizeof(struct rpt_link));
05266 if (mylink){
05267 memcpy(&tele->mylink,mylink,sizeof(struct rpt_link));
05268 }
05269 }
05270 else if ((mode == ARB_ALPHA) || (mode == REV_PATCH) || (mode == PLAYBACK)) {
05271 strncpy(tele->param, (char *) data, TELEPARAMSIZE - 1);
05272 tele->param[TELEPARAMSIZE - 1] = 0;
05273 }
05274 if (mode == REMXXX) tele->submode = (intptr_t) data;
05275 insque((struct qelem *)tele, (struct qelem *)myrpt->tele.next);
05276 rpt_mutex_unlock(&myrpt->lock);
05277 pthread_attr_init(&attr);
05278 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
05279 res = ast_pthread_create(&tele->threadid,&attr,rpt_tele_thread,(void *) tele);
05280 if(res < 0){
05281 rpt_mutex_lock(&myrpt->lock);
05282 remque((struct qlem *) tele);
05283 rpt_mutex_unlock(&myrpt->lock);
05284 ast_log(LOG_WARNING, "Could not create telemetry thread: %s",strerror(res));
05285 }
05286 return;
05287 }
05288
05289 static void *rpt_call(void *this)
05290 {
05291 struct dahdi_confinfo ci;
05292 struct rpt *myrpt = (struct rpt *)this;
05293 int res;
05294 int stopped,congstarted,dialtimer,lastcidx,aborted;
05295 struct ast_channel *mychannel,*genchannel;
05296
05297 myrpt->mydtmf = 0;
05298
05299 mychannel = ast_request("DAHDI", AST_FORMAT_SLINEAR, NULL, "pseudo", NULL);
05300 if (!mychannel)
05301 {
05302 fprintf(stderr,"rpt:Sorry unable to obtain pseudo channel\n");
05303 pthread_exit(NULL);
05304 }
05305 #ifdef AST_CDR_FLAG_POST_DISABLED
05306 if (mychannel->cdr)
05307 ast_set_flag(mychannel->cdr,AST_CDR_FLAG_POST_DISABLED);
05308 #endif
05309 ci.chan = 0;
05310 ci.confno = myrpt->conf;
05311 #if 0
05312 ci.confmode = DAHDI_CONF_REALANDPSEUDO | DAHDI_CONF_TALKER | DAHDI_CONF_LISTENER
05313 | DAHDI_CONF_PSEUDO_TALKER | DAHDI_CONF_PSEUDO_LISTENER;
05314 #endif
05315 ci.confmode = DAHDI_CONF_CONF | DAHDI_CONF_TALKER | DAHDI_CONF_LISTENER;
05316
05317 if (ioctl(mychannel->fds[0],DAHDI_SETCONF,&ci) == -1)
05318 {
05319 ast_log(LOG_WARNING, "Unable to set conference mode to Announce\n");
05320 ast_hangup(mychannel);
05321 myrpt->callmode = 0;
05322 pthread_exit(NULL);
05323 }
05324
05325 genchannel = ast_request("DAHDI", AST_FORMAT_SLINEAR, NULL, "pseudo", NULL);
05326 if (!genchannel)
05327 {
05328 fprintf(stderr,"rpt:Sorry unable to obtain pseudo channel\n");
05329 ast_hangup(mychannel);
05330 pthread_exit(NULL);
05331 }
05332 #ifdef AST_CDR_FLAG_POST_DISABLED
05333 if (genchannel->cdr)
05334 ast_set_flag(genchannel->cdr,AST_CDR_FLAG_POST_DISABLED);
05335 #endif
05336 ci.chan = 0;
05337 ci.confno = myrpt->conf;
05338 ci.confmode = DAHDI_CONF_REALANDPSEUDO | DAHDI_CONF_TALKER | DAHDI_CONF_LISTENER
05339 | DAHDI_CONF_PSEUDO_TALKER | DAHDI_CONF_PSEUDO_LISTENER;
05340
05341 if (ioctl(genchannel->fds[0],DAHDI_SETCONF,&ci) == -1)
05342 {
05343 ast_log(LOG_WARNING, "Unable to set conference mode to Announce\n");
05344 ast_hangup(mychannel);
05345 ast_hangup(genchannel);
05346 myrpt->callmode = 0;
05347 pthread_exit(NULL);
05348 }
05349 if (myrpt->p.tonezone && (tone_zone_set_zone(mychannel->fds[0],myrpt->p.tonezone) == -1))
05350 {
05351 ast_log(LOG_WARNING, "Unable to set tone zone %s\n",myrpt->p.tonezone);
05352 ast_hangup(mychannel);
05353 ast_hangup(genchannel);
05354 myrpt->callmode = 0;
05355 pthread_exit(NULL);
05356 }
05357 if (myrpt->p.tonezone && (tone_zone_set_zone(genchannel->fds[0],myrpt->p.tonezone) == -1))
05358 {
05359 ast_log(LOG_WARNING, "Unable to set tone zone %s\n",myrpt->p.tonezone);
05360 ast_hangup(mychannel);
05361 ast_hangup(genchannel);
05362 myrpt->callmode = 0;
05363 pthread_exit(NULL);
05364 }
05365
05366 if ((!myrpt->patchquiet) && (tone_zone_play_tone(genchannel->fds[0],DAHDI_TONE_DIALTONE) < 0))
05367 {
05368 ast_log(LOG_WARNING, "Cannot start dialtone\n");
05369 ast_hangup(mychannel);
05370 ast_hangup(genchannel);
05371 myrpt->callmode = 0;
05372 pthread_exit(NULL);
05373 }
05374 stopped = 0;
05375 congstarted = 0;
05376 dialtimer = 0;
05377 lastcidx = 0;
05378 myrpt->calldigittimer = 0;
05379 aborted = 0;
05380
05381 while ((myrpt->callmode == 1) || (myrpt->callmode == 4))
05382 {
05383 if((myrpt->patchdialtime)&&(myrpt->callmode == 1)&&(myrpt->cidx != lastcidx)){
05384 dialtimer = 0;
05385 lastcidx = myrpt->cidx;
05386 }
05387
05388 if((myrpt->patchdialtime)&&(dialtimer >= myrpt->patchdialtime)){
05389 if(debug)
05390 ast_log(LOG_NOTICE, "dialtimer %i > patchdialtime %i\n", dialtimer,myrpt->patchdialtime);
05391 rpt_mutex_lock(&myrpt->lock);
05392 aborted = 1;
05393 myrpt->callmode = 0;
05394 rpt_mutex_unlock(&myrpt->lock);
05395 break;
05396 }
05397
05398 if ((!myrpt->patchquiet) && (!stopped) && (myrpt->callmode == 1) && (myrpt->cidx > 0))
05399 {
05400 stopped = 1;
05401
05402 tone_zone_play_tone(genchannel->fds[0],-1);
05403 }
05404 if (myrpt->callmode == 1)
05405 {
05406 if(myrpt->calldigittimer > PATCH_DIALPLAN_TIMEOUT)
05407 {
05408 myrpt->callmode = 2;
05409 break;
05410 }
05411
05412 if (myrpt->calldigittimer)
05413 myrpt->calldigittimer += MSWAIT;
05414 }
05415 if (myrpt->callmode == 4)
05416 {
05417 if(!congstarted){
05418 congstarted = 1;
05419
05420 tone_zone_play_tone(genchannel->fds[0],DAHDI_TONE_CONGESTION);
05421 }
05422 }
05423 res = ast_safe_sleep(mychannel, MSWAIT);
05424 if (res < 0)
05425 {
05426 if(debug)
05427 ast_log(LOG_NOTICE, "ast_safe_sleep=%i\n", res);
05428 ast_hangup(mychannel);
05429 ast_hangup(genchannel);
05430 rpt_mutex_lock(&myrpt->lock);
05431 myrpt->callmode = 0;
05432 rpt_mutex_unlock(&myrpt->lock);
05433 pthread_exit(NULL);
05434 }
05435 dialtimer += MSWAIT;
05436 }
05437
05438 tone_zone_play_tone(genchannel->fds[0],-1);
05439
05440 if (!myrpt->callmode)
05441 {
05442 if(debug)
05443 ast_log(LOG_NOTICE, "callmode==0\n");
05444 ast_hangup(mychannel);
05445 ast_hangup(genchannel);
05446 rpt_mutex_lock(&myrpt->lock);
05447 myrpt->callmode = 0;
05448 myrpt->macropatch=0;
05449 channel_revert(myrpt);
05450 rpt_mutex_unlock(&myrpt->lock);
05451 if((!myrpt->patchquiet) && aborted)
05452 rpt_telemetry(myrpt, TERM, NULL);
05453 pthread_exit(NULL);
05454 }
05455
05456 if (myrpt->p.ourcallerid && *myrpt->p.ourcallerid){
05457 char *name, *loc, *instr;
05458 instr = ast_strdup(myrpt->p.ourcallerid);
05459 if(instr){
05460 ast_callerid_parse(instr, &name, &loc);
05461 if(loc){
05462 mychannel->caller.id.number.valid = 1;
05463 ast_free(mychannel->caller.id.number.str);
05464 mychannel->caller.id.number.str = ast_strdup(loc);
05465 }
05466 if(name){
05467 mychannel->caller.id.name.valid = 1;
05468 ast_free(mychannel->caller.id.name.str);
05469 mychannel->caller.id.name.str = ast_strdup(name);
05470 }
05471 ast_free(instr);
05472 }
05473 }
05474
05475 ast_copy_string(mychannel->exten, myrpt->exten, sizeof(mychannel->exten) - 1);
05476 ast_copy_string(mychannel->context, myrpt->patchcontext, sizeof(mychannel->context) - 1);
05477
05478 if (myrpt->p.acctcode)
05479 ast_cdr_setaccount(mychannel,myrpt->p.acctcode);
05480 mychannel->priority = 1;
05481 ast_channel_undefer_dtmf(mychannel);
05482 if (ast_pbx_start(mychannel) < 0)
05483 {
05484 ast_log(LOG_WARNING, "Unable to start PBX!!\n");
05485 ast_hangup(mychannel);
05486 ast_hangup(genchannel);
05487 rpt_mutex_lock(&myrpt->lock);
05488 myrpt->callmode = 0;
05489 rpt_mutex_unlock(&myrpt->lock);
05490 pthread_exit(NULL);
05491 }
05492 usleep(10000);
05493 rpt_mutex_lock(&myrpt->lock);
05494 myrpt->callmode = 3;
05495
05496 ci.chan = 0;
05497 ci.confno = myrpt->conf;
05498 ci.confmode = (myrpt->p.duplex == 2) ? DAHDI_CONF_CONFANNMON :
05499 (DAHDI_CONF_CONF | DAHDI_CONF_LISTENER | DAHDI_CONF_TALKER);
05500
05501 if (ioctl(myrpt->pchannel->fds[0],DAHDI_SETCONF,&ci) == -1)
05502 {
05503 ast_log(LOG_WARNING, "Unable to set conference mode to Announce\n");
05504 ast_hangup(mychannel);
05505 ast_hangup(genchannel);
05506 myrpt->callmode = 0;
05507 pthread_exit(NULL);
05508 }
05509
05510 if (ioctl(mychannel->fds[0],DAHDI_CHANNO,&res) == -1)
05511 {
05512 ast_log(LOG_WARNING, "Unable to get autopatch channel number\n");
05513 ast_hangup(mychannel);
05514 myrpt->callmode = 0;
05515 pthread_exit(NULL);
05516 }
05517 ci.chan = 0;
05518 ci.confno = res;
05519 ci.confmode = DAHDI_CONF_MONITOR;
05520
05521 if (ioctl(myrpt->voxchannel->fds[0],DAHDI_SETCONF,&ci) == -1)
05522 {
05523 ast_log(LOG_WARNING, "Unable to set conference mode to Announce\n");
05524 ast_hangup(mychannel);
05525 myrpt->callmode = 0;
05526 pthread_exit(NULL);
05527 }
05528 while(myrpt->callmode)
05529 {
05530 if ((!mychannel->pbx) && (myrpt->callmode != 4))
05531 {
05532
05533 if(myrpt->patchfarenddisconnect || (myrpt->p.duplex < 2)){
05534 if(debug)ast_log(LOG_NOTICE,"callmode=%i, patchfarenddisconnect=%i, duplex=%i\n",\
05535 myrpt->callmode,myrpt->patchfarenddisconnect,myrpt->p.duplex);
05536 myrpt->callmode = 0;
05537 myrpt->macropatch=0;
05538 if(!myrpt->patchquiet){
05539 rpt_mutex_unlock(&myrpt->lock);
05540 rpt_telemetry(myrpt, TERM, NULL);
05541 rpt_mutex_lock(&myrpt->lock);
05542 }
05543 }
05544 else{
05545 myrpt->callmode = 4;
05546 rpt_mutex_unlock(&myrpt->lock);
05547
05548 tone_zone_play_tone(genchannel->fds[0],DAHDI_TONE_CONGESTION);
05549 rpt_mutex_lock(&myrpt->lock);
05550 }
05551 }
05552 if (myrpt->mydtmf)
05553 {
05554 struct ast_frame wf = {AST_FRAME_DTMF, } ;
05555 wf.subclass.integer = myrpt->mydtmf;
05556 rpt_mutex_unlock(&myrpt->lock);
05557 ast_queue_frame(mychannel,&wf);
05558 #ifdef NEW_ASTERISK
05559 ast_senddigit(genchannel,myrpt->mydtmf,0);
05560 #else
05561 ast_senddigit(genchannel,myrpt->mydtmf);
05562 #endif
05563 rpt_mutex_lock(&myrpt->lock);
05564 myrpt->mydtmf = 0;
05565 }
05566 rpt_mutex_unlock(&myrpt->lock);
05567 usleep(MSWAIT * 1000);
05568 rpt_mutex_lock(&myrpt->lock);
05569 }
05570 if(debug)
05571 ast_log(LOG_NOTICE, "exit channel loop\n");
05572 rpt_mutex_unlock(&myrpt->lock);
05573 tone_zone_play_tone(genchannel->fds[0],-1);
05574 if (mychannel->pbx) ast_softhangup(mychannel,AST_SOFTHANGUP_DEV);
05575 ast_hangup(genchannel);
05576 rpt_mutex_lock(&myrpt->lock);
05577 myrpt->callmode = 0;
05578 myrpt->macropatch=0;
05579 channel_revert(myrpt);
05580 rpt_mutex_unlock(&myrpt->lock);
05581
05582 ci.chan = 0;
05583 ci.confno = myrpt->conf;
05584 ci.confmode = ((myrpt->p.duplex == 2) || (myrpt->p.duplex == 4)) ? DAHDI_CONF_CONFANNMON :
05585 (DAHDI_CONF_CONF | DAHDI_CONF_LISTENER | DAHDI_CONF_TALKER);
05586
05587 if (ioctl(myrpt->pchannel->fds[0],DAHDI_SETCONF,&ci) == -1)
05588 {
05589 ast_log(LOG_WARNING, "Unable to set conference mode to Announce\n");
05590 }
05591 pthread_exit(NULL);
05592 }
05593
05594 static void send_link_dtmf(struct rpt *myrpt,char c)
05595 {
05596 char str[300];
05597 struct ast_frame wf;
05598 struct rpt_link *l;
05599
05600 snprintf(str, sizeof(str), "D %s %s %d %c", myrpt->cmdnode, myrpt->name, ++(myrpt->dtmfidx), c);
05601 wf.frametype = AST_FRAME_TEXT;
05602 wf.subclass.integer = 0;
05603 wf.offset = 0;
05604 wf.mallocd = 0;
05605 wf.datalen = strlen(str) + 1;
05606 wf.samples = 0;
05607 l = myrpt->links.next;
05608
05609 while(l != &myrpt->links)
05610 {
05611 if (l->name[0] == '0')
05612 {
05613 l = l->next;
05614 continue;
05615 }
05616
05617 if (!strcmp(l->name,myrpt->cmdnode))
05618 {
05619 wf.data.ptr = str;
05620 if (l->chan) ast_write(l->chan,&wf);
05621 return;
05622 }
05623 l = l->next;
05624 }
05625 l = myrpt->links.next;
05626
05627 while(l != &myrpt->links)
05628 {
05629 wf.data.ptr = str;
05630 if (l->chan) ast_write(l->chan,&wf);
05631 l = l->next;
05632 }
05633 return;
05634 }
05635
05636 static void send_link_keyquery(struct rpt *myrpt)
05637 {
05638 char str[300];
05639 struct ast_frame wf;
05640 struct rpt_link *l;
05641
05642 rpt_mutex_lock(&myrpt->lock);
05643 memset(myrpt->topkey,0,sizeof(myrpt->topkey));
05644 myrpt->topkeystate = 1;
05645 time(&myrpt->topkeytime);
05646 rpt_mutex_unlock(&myrpt->lock);
05647 snprintf(str, sizeof(str), "K? * %s 0 0", myrpt->name);
05648 wf.frametype = AST_FRAME_TEXT;
05649 wf.subclass.integer = 0;
05650 wf.offset = 0;
05651 wf.mallocd = 0;
05652 wf.datalen = strlen(str) + 1;
05653 wf.samples = 0;
05654 l = myrpt->links.next;
05655
05656 while(l != &myrpt->links)
05657 {
05658 wf.data.ptr = str;
05659 if (l->chan) ast_write(l->chan,&wf);
05660 l = l->next;
05661 }
05662 return;
05663 }
05664
05665
05666
05667 static void send_newkey(struct ast_channel *chan)
05668 {
05669
05670
05671 ast_sendtext(chan,newkeystr);
05672 return;
05673 }
05674
05675
05676
05677
05678
05679
05680
05681
05682
05683
05684
05685
05686
05687 static int connect_link(struct rpt *myrpt, char* node, int mode, int perma)
05688 {
05689 char *val, *s, *s1, *s2, *tele;
05690 char lstr[MAXLINKLIST],*strs[MAXLINKLIST];
05691 char tmp[300], deststr[300] = "",modechange = 0;
05692 char sx[320],*sy;
05693 struct rpt_link *l;
05694 int reconnects = 0;
05695 int i,n;
05696 struct dahdi_confinfo ci;
05697
05698 val = node_lookup(myrpt,node);
05699 if (!val){
05700 if(strlen(node) >= myrpt->longestnode)
05701 return -1;
05702 return 1;
05703 }
05704
05705 if(!strcmp(myrpt->name,node))
05706 return -2;
05707
05708 if(debug > 3){
05709 ast_log(LOG_NOTICE,"Connect attempt to node %s\n", node);
05710 ast_log(LOG_NOTICE,"Mode: %s\n",(mode)?"Transceive":"Monitor");
05711 ast_log(LOG_NOTICE,"Connection type: %s\n",(perma)?"Permalink":"Normal");
05712 }
05713
05714 strncpy(tmp,val,sizeof(tmp) - 1);
05715 s = tmp;
05716 s1 = strsep(&s,",");
05717 if (!strchr(s1,':') && strchr(s1,'/') && strncasecmp(s1, "local/", 6))
05718 {
05719 sy = strchr(s1,'/');
05720 *sy = 0;
05721 sprintf(sx,"%s:4569/%s",s1,sy + 1);
05722 s1 = sx;
05723 }
05724 s2 = strsep(&s,",");
05725 rpt_mutex_lock(&myrpt->lock);
05726 l = myrpt->links.next;
05727
05728 while(l != &myrpt->links){
05729 if (l->name[0] == '0')
05730 {
05731 l = l->next;
05732 continue;
05733 }
05734
05735 if (!strcmp(l->name, node))
05736 break;
05737 l = l->next;
05738 }
05739
05740 if (l != &myrpt->links){
05741
05742 if ((l->mode) || (!l->chan)) {
05743 rpt_mutex_unlock(&myrpt->lock);
05744 return 2;
05745 }
05746 reconnects = l->reconnects;
05747 rpt_mutex_unlock(&myrpt->lock);
05748 if (l->chan) ast_softhangup(l->chan, AST_SOFTHANGUP_DEV);
05749 l->retries = l->max_retries + 1;
05750 l->disced = 2;
05751 modechange = 1;
05752 } else
05753 {
05754 __mklinklist(myrpt,NULL,lstr);
05755 rpt_mutex_unlock(&myrpt->lock);
05756 n = finddelim(lstr,strs,MAXLINKLIST);
05757 for(i = 0; i < n; i++)
05758 {
05759 if ((*strs[i] < '0') ||
05760 (*strs[i] > '9')) strs[i]++;
05761 if (!strcmp(strs[i],node))
05762 {
05763 return 2;
05764 }
05765 }
05766 }
05767 strncpy(myrpt->lastlinknode,node,MAXNODESTR - 1);
05768
05769 l = ast_malloc(sizeof(struct rpt_link));
05770 if (!l)
05771 {
05772 ast_log(LOG_WARNING, "Unable to malloc\n");
05773 return -1;
05774 }
05775
05776 memset((char *)l,0,sizeof(struct rpt_link));
05777 l->mode = mode;
05778 l->outbound = 1;
05779 l->thisconnected = 0;
05780 voxinit_link(l,1);
05781 strncpy(l->name, node, MAXNODESTR - 1);
05782 l->isremote = (s && ast_true(s));
05783 if (modechange) l->connected = 1;
05784 l->hasconnected = l->perma = perma;
05785 #ifdef ALLOW_LOCAL_CHANNELS
05786 if ((strncasecmp(s1,"iax2/", 5) == 0) || (strncasecmp(s1, "local/", 6) == 0))
05787 strncpy(deststr, s1, sizeof(deststr));
05788 else
05789 snprintf(deststr, sizeof(deststr), "IAX2/%s", s1);
05790 #else
05791 snprintf(deststr, sizeof(deststr), "IAX2/%s", s1);
05792 #endif
05793 tele = strchr(deststr, '/');
05794 if (!tele){
05795 ast_log(LOG_WARNING,"link3:Dial number (%s) must be in format tech/number\n",deststr);
05796 ast_free(l);
05797 return -1;
05798 }
05799 *tele++ = 0;
05800 l->chan = ast_request(deststr, AST_FORMAT_SLINEAR, NULL, tele, NULL);
05801 if (l->chan){
05802 ast_set_read_format(l->chan, AST_FORMAT_SLINEAR);
05803 ast_set_write_format(l->chan, AST_FORMAT_SLINEAR);
05804 #ifdef AST_CDR_FLAG_POST_DISABLED
05805 if (l->chan->cdr)
05806 ast_set_flag(l->chan->cdr,AST_CDR_FLAG_POST_DISABLED);
05807 #endif
05808 #ifndef NEW_ASTERISK
05809 l->chan->whentohangup = 0;
05810 #endif
05811 l->chan->appl = "Apprpt";
05812 l->chan->data = "(Remote Rx)";
05813 if (debug > 3)
05814 ast_log(LOG_NOTICE, "rpt (remote) initiating call to %s/%s on %s\n",
05815 deststr, tele, l->chan->name);
05816 l->chan->caller.id.number.valid = 1;
05817 ast_free(l->chan->caller.id.number.str);
05818 l->chan->caller.id.number.str = ast_strdup(myrpt->name);
05819 ast_call(l->chan,tele,999);
05820 }
05821 else {
05822 if(debug > 3)
05823 ast_log(LOG_NOTICE, "Unable to place call to %s/%s on %s\n",
05824 deststr,tele,l->chan->name);
05825 if (myrpt->p.archivedir)
05826 {
05827 char str[100];
05828 sprintf(str,"LINKFAIL,%s",l->name);
05829 donodelog(myrpt,str);
05830 }
05831 ast_free(l);
05832 return -1;
05833 }
05834
05835 l->pchan = ast_request("DAHDI", AST_FORMAT_SLINEAR, NULL, "pseudo", NULL);
05836 if (!l->pchan){
05837 ast_log(LOG_WARNING,"rpt connect: Sorry unable to obtain pseudo channel\n");
05838 ast_hangup(l->chan);
05839 ast_free(l);
05840 return -1;
05841 }
05842 ast_set_read_format(l->pchan, AST_FORMAT_SLINEAR);
05843 ast_set_write_format(l->pchan, AST_FORMAT_SLINEAR);
05844 #ifdef AST_CDR_FLAG_POST_DISABLED
05845 if (l->pchan->cdr)
05846 ast_set_flag(l->pchan->cdr,AST_CDR_FLAG_POST_DISABLED);
05847 #endif
05848
05849 ci.chan = 0;
05850 ci.confno = myrpt->conf;
05851 ci.confmode = DAHDI_CONF_CONF | DAHDI_CONF_LISTENER | DAHDI_CONF_TALKER;
05852
05853 if (ioctl(l->pchan->fds[0], DAHDI_SETCONF, &ci) == -1)
05854 {
05855 ast_log(LOG_WARNING, "Unable to set conference mode to Announce\n");
05856 ast_hangup(l->chan);
05857 ast_hangup(l->pchan);
05858 ast_free(l);
05859 return -1;
05860 }
05861 rpt_mutex_lock(&myrpt->lock);
05862 l->reconnects = reconnects;
05863
05864 l->max_retries = MAX_RETRIES;
05865 if (perma)
05866 l->max_retries = MAX_RETRIES_PERM;
05867 if (l->isremote) l->retries = l->max_retries + 1;
05868 insque((struct qelem *)l,(struct qelem *)myrpt->links.next);
05869 __kickshort(myrpt);
05870 rpt_mutex_unlock(&myrpt->lock);
05871 if (!l->phonemode) send_newkey(l->chan);
05872 return 0;
05873 }
05874
05875
05876
05877
05878
05879
05880
05881 static int function_ilink(struct rpt *myrpt, char *param, char *digits, int command_source, struct rpt_link *mylink)
05882 {
05883
05884 char *val, *s, *s1, *s2;
05885 char tmp[300];
05886 char digitbuf[MAXNODESTR],*strs[MAXLINKLIST];
05887 char mode,perma;
05888 char sx[320],*sy;
05889 struct rpt_link *l;
05890 int i,r;
05891
05892 if(!param)
05893 return DC_ERROR;
05894
05895
05896 if (myrpt->p.s[myrpt->p.sysstate_cur].txdisable || myrpt->p.s[myrpt->p.sysstate_cur].linkfundisable )
05897 return DC_ERROR;
05898
05899 strncpy(digitbuf,digits,MAXNODESTR - 1);
05900
05901 if(debug > 6)
05902 printf("@@@@ ilink param = %s, digitbuf = %s\n", (param)? param : "(null)", digitbuf);
05903
05904 switch(myatoi(param)){
05905 case 11:
05906 case 1:
05907 if ((digitbuf[0] == '0') && (myrpt->lastlinknode[0]))
05908 strcpy(digitbuf,myrpt->lastlinknode);
05909 val = node_lookup(myrpt,digitbuf);
05910 if (!val){
05911 if(strlen(digitbuf) >= myrpt->longestnode)
05912 return DC_ERROR;
05913 break;
05914 }
05915 strncpy(tmp,val,sizeof(tmp) - 1);
05916 s = tmp;
05917 s1 = strsep(&s,",");
05918 if (!strchr(s1,':') && strchr(s1,'/') && strncasecmp(s1, "local/", 6))
05919 {
05920 sy = strchr(s1,'/');
05921 *sy = 0;
05922 sprintf(sx,"%s:4569/%s",s1,sy + 1);
05923 s1 = sx;
05924 }
05925 s2 = strsep(&s,",");
05926 rpt_mutex_lock(&myrpt->lock);
05927 l = myrpt->links.next;
05928
05929 while(l != &myrpt->links){
05930 if (l->name[0] == '0')
05931 {
05932 l = l->next;
05933 continue;
05934 }
05935
05936 if (!strcmp(l->name, digitbuf))
05937 break;
05938 l = l->next;
05939 }
05940 if (l != &myrpt->links){
05941 struct ast_frame wf;
05942
05943
05944 if ((myatoi(param) < 10) &&
05945 (l->max_retries > MAX_RETRIES))
05946 {
05947 rpt_mutex_unlock(&myrpt->lock);
05948 return DC_COMPLETE;
05949 }
05950 strncpy(myrpt->lastlinknode,digitbuf,MAXNODESTR - 1);
05951 l->retries = l->max_retries + 1;
05952 l->disced = 1;
05953 rpt_mutex_unlock(&myrpt->lock);
05954 wf.frametype = AST_FRAME_TEXT;
05955 wf.subclass.integer = 0;
05956 wf.offset = 0;
05957 wf.mallocd = 0;
05958 wf.datalen = strlen(discstr) + 1;
05959 wf.samples = 0;
05960 wf.data.ptr = discstr;
05961 if (l->chan)
05962 {
05963 ast_write(l->chan,&wf);
05964 if (ast_safe_sleep(l->chan,250) == -1) return DC_ERROR;
05965 ast_softhangup(l->chan,AST_SOFTHANGUP_DEV);
05966 }
05967 rpt_telemetry(myrpt, COMPLETE, NULL);
05968 return DC_COMPLETE;
05969 }
05970 rpt_mutex_unlock(&myrpt->lock);
05971 return DC_COMPLETE;
05972 case 2:
05973 case 3:
05974 case 12:
05975 case 13:
05976 if ((digitbuf[0] == '0') && (myrpt->lastlinknode[0]))
05977 strcpy(digitbuf,myrpt->lastlinknode);
05978
05979 perma = (atoi(param) > 10) ? 1 : 0;
05980 mode = (atoi(param) & 1) ? 1 : 0;
05981 r = connect_link(myrpt, digitbuf, mode, perma);
05982 switch(r){
05983 case -2:
05984 return DC_COMPLETE;
05985
05986 case 0:
05987 rpt_telemetry(myrpt, COMPLETE, NULL);
05988 return DC_COMPLETE;
05989
05990 case 1:
05991 break;
05992
05993 case 2:
05994 rpt_telemetry(myrpt, REMALREADY, NULL);
05995 return DC_COMPLETE;
05996
05997 default:
05998 rpt_telemetry(myrpt, CONNFAIL, NULL);
05999 return DC_COMPLETE;
06000 }
06001 break;
06002
06003 case 4:
06004
06005
06006 if (((command_source != SOURCE_RPT) &&
06007 (command_source != SOURCE_PHONE) &&
06008 (command_source != SOURCE_ALT) &&
06009 (command_source != SOURCE_DPHONE)) ||
06010 (myrpt->links.next == &myrpt->links))
06011 return DC_COMPLETE;
06012
06013
06014 if ((myrpt->cmdnode[0]) || (!strcmp(myrpt->name, digitbuf))){
06015
06016 rpt_telemetry(myrpt, REMALREADY, NULL);
06017 return DC_COMPLETE;
06018 }
06019 if ((digitbuf[0] == '0') && (myrpt->lastlinknode[0]))
06020 strcpy(digitbuf,myrpt->lastlinknode);
06021
06022 val = node_lookup(myrpt,digitbuf);
06023 if (!val){
06024 if(strlen(digitbuf) >= myrpt->longestnode)
06025 return DC_ERROR;
06026 break;
06027
06028 }
06029 rpt_mutex_lock(&myrpt->lock);
06030 strcpy(myrpt->lastlinknode,digitbuf);
06031 strncpy(myrpt->cmdnode, digitbuf, sizeof(myrpt->cmdnode) - 1);
06032 rpt_mutex_unlock(&myrpt->lock);
06033 rpt_telemetry(myrpt, REMGO, NULL);
06034 return DC_COMPLETE;
06035
06036 case 5:
06037 rpt_telemetry(myrpt, STATUS, NULL);
06038 return DC_COMPLETE;
06039
06040 case 15:
06041 rpt_telemetry(myrpt, FULLSTATUS, NULL);
06042 return DC_COMPLETE;
06043
06044
06045 case 6:
06046 rpt_mutex_lock(&myrpt->lock);
06047 myrpt->savednodes[0] = 0;
06048 l = myrpt->links.next;
06049
06050 while(l != &myrpt->links){
06051 struct ast_frame wf;
06052 if (l->name[0] == '0')
06053 {
06054 l = l->next;
06055 continue;
06056 }
06057
06058 sprintf(tmp,"%c%c%s",(l->mode) ? 'X' : 'M',(l->perma) ? 'P':'T',l->name);
06059 if(strlen(tmp) + strlen(myrpt->savednodes) + 1 < MAXNODESTR){
06060 if(myrpt->savednodes[0])
06061 strcat(myrpt->savednodes, ",");
06062 strcat(myrpt->savednodes, tmp);
06063 }
06064 l->retries = l->max_retries + 1;
06065 l->disced = 2;
06066 rpt_mutex_unlock(&myrpt->lock);
06067
06068
06069 wf.frametype = AST_FRAME_TEXT;
06070 wf.subclass.integer = 0;
06071 wf.offset = 0;
06072 wf.mallocd = 0;
06073 wf.datalen = strlen(discstr) + 1;
06074 wf.samples = 0;
06075 wf.data.ptr = discstr;
06076 if (l->chan)
06077 {
06078 ast_write(l->chan,&wf);
06079 ast_safe_sleep(l->chan,250);
06080 ast_softhangup(l->chan,AST_SOFTHANGUP_DEV);
06081 }
06082 rpt_mutex_lock(&myrpt->lock);
06083 l = l->next;
06084 }
06085 rpt_mutex_unlock(&myrpt->lock);
06086 if(debug > 3)
06087 ast_log(LOG_NOTICE,"Nodes disconnected: %s\n",myrpt->savednodes);
06088 rpt_telemetry(myrpt, COMPLETE, NULL);
06089 return DC_COMPLETE;
06090
06091 case 7:
06092 rpt_telemetry(myrpt, LASTNODEKEY, NULL);
06093 break;
06094
06095
06096 #ifdef _MDC_DECODE_H_
06097 case 8:
06098 myrpt->lastunit = 0xd00d;
06099 mdc1200_notify(myrpt,NULL,myrpt->lastunit);
06100 mdc1200_send(myrpt,myrpt->lastunit);
06101 break;
06102 #endif
06103
06104 case 16:
06105 strcpy(tmp, myrpt->savednodes);
06106 finddelim(tmp, strs, MAXLINKLIST);
06107 for(i = 0; tmp[0] && strs[i] != NULL && i < MAXLINKLIST; i++){
06108 s1 = strs[i];
06109 mode = (s1[0] == 'X') ? 1 : 0;
06110 perma = (s1[1] == 'P') ? 1 : 0;
06111 connect_link(myrpt, s1 + 2, mode, perma);
06112 }
06113 rpt_telemetry(myrpt, COMPLETE, NULL);
06114 break;
06115
06116 case 200:
06117 case 201:
06118 case 202:
06119 case 203:
06120 case 204:
06121 case 205:
06122 case 206:
06123 case 207:
06124 case 208:
06125 case 209:
06126 case 210:
06127 case 211:
06128 case 212:
06129 case 213:
06130 case 214:
06131 case 215:
06132 if (((myrpt->p.propagate_dtmf) &&
06133 (command_source == SOURCE_LNK)) ||
06134 ((myrpt->p.propagate_phonedtmf) &&
06135 ((command_source == SOURCE_PHONE) ||
06136 (command_source == SOURCE_ALT) ||
06137 (command_source == SOURCE_DPHONE))))
06138 do_dtmf_local(myrpt,
06139 remdtmfstr[myatoi(param) - 200]);
06140 default:
06141 return DC_ERROR;
06142
06143 }
06144
06145 return DC_INDETERMINATE;
06146 }
06147
06148
06149
06150
06151
06152 static int function_autopatchup(struct rpt *myrpt, char *param, char *digitbuf, int command_source, struct rpt_link *mylink)
06153 {
06154 pthread_attr_t attr;
06155 int i, idx, paramlength;
06156 char *lparam;
06157 char *value = NULL;
06158 char *paramlist[20];
06159
06160 static char *keywords[] = {
06161 "context",
06162 "dialtime",
06163 "farenddisconnect",
06164 "noct",
06165 "quiet",
06166 NULL
06167 };
06168
06169 if (myrpt->p.s[myrpt->p.sysstate_cur].txdisable || myrpt->p.s[myrpt->p.sysstate_cur].autopatchdisable)
06170 return DC_ERROR;
06171
06172 if(debug)
06173 printf("@@@@ Autopatch up\n");
06174
06175 if(!myrpt->callmode){
06176
06177 myrpt->patchnoct = 0;
06178 myrpt->patchdialtime = 0;
06179 myrpt->patchfarenddisconnect = 0;
06180 myrpt->patchquiet = 0;
06181 strncpy(myrpt->patchcontext, myrpt->p.ourcontext, MAXPATCHCONTEXT);
06182
06183 if(param){
06184
06185 lparam = ast_strdup(param);
06186 if(!lparam){
06187 ast_log(LOG_ERROR,"App_rpt out of memory on line %d\n",__LINE__);
06188 return DC_ERROR;
06189 }
06190 paramlength = finddelim(lparam, paramlist, 20);
06191 for(i = 0; i < paramlength; i++){
06192 idx = matchkeyword(paramlist[i], &value, keywords);
06193 if(value)
06194 value = skipchars(value, "= ");
06195 switch(idx){
06196
06197 case 1:
06198 strncpy(myrpt->patchcontext, value, MAXPATCHCONTEXT - 1) ;
06199 break;
06200
06201 case 2:
06202 myrpt->patchdialtime = atoi(value);
06203 break;
06204
06205 case 3:
06206 myrpt->patchfarenddisconnect = atoi(value);
06207 break;
06208
06209 case 4:
06210 myrpt->patchnoct = atoi(value);
06211 break;
06212
06213 case 5:
06214 myrpt->patchquiet = atoi(value);
06215 break;
06216
06217 default:
06218 break;
06219 }
06220 }
06221 ast_free(lparam);
06222 }
06223 }
06224
06225 rpt_mutex_lock(&myrpt->lock);
06226
06227
06228
06229 if ((myrpt->callmode == 2) || (myrpt->callmode == 3)){
06230 myrpt->mydtmf = myrpt->p.endchar;
06231 }
06232 if (myrpt->callmode){
06233 rpt_mutex_unlock(&myrpt->lock);
06234 return DC_COMPLETE;
06235 }
06236 myrpt->callmode = 1;
06237 myrpt->cidx = 0;
06238 myrpt->exten[myrpt->cidx] = 0;
06239 rpt_mutex_unlock(&myrpt->lock);
06240 pthread_attr_init(&attr);
06241 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
06242 ast_pthread_create(&myrpt->rpt_call_thread,&attr,rpt_call,(void *) myrpt);
06243 return DC_COMPLETE;
06244 }
06245
06246
06247
06248
06249
06250 static int function_autopatchdn(struct rpt *myrpt, char *param, char *digitbuf, int command_source, struct rpt_link *mylink)
06251 {
06252 if (myrpt->p.s[myrpt->p.sysstate_cur].txdisable || myrpt->p.s[myrpt->p.sysstate_cur].autopatchdisable)
06253 return DC_ERROR;
06254
06255 if(debug)
06256 printf("@@@@ Autopatch down\n");
06257
06258 rpt_mutex_lock(&myrpt->lock);
06259
06260 myrpt->macropatch=0;
06261
06262 if (!myrpt->callmode){
06263 rpt_mutex_unlock(&myrpt->lock);
06264 return DC_COMPLETE;
06265 }
06266
06267 myrpt->callmode = 0;
06268 channel_revert(myrpt);
06269 rpt_mutex_unlock(&myrpt->lock);
06270 rpt_telemetry(myrpt, TERM, NULL);
06271 return DC_COMPLETE;
06272 }
06273
06274
06275
06276
06277
06278 static int function_status(struct rpt *myrpt, char *param, char *digitbuf, int command_source, struct rpt_link *mylink)
06279 {
06280
06281 if (!param)
06282 return DC_ERROR;
06283
06284 if ((myrpt->p.s[myrpt->p.sysstate_cur].txdisable) || (myrpt->p.s[myrpt->p.sysstate_cur].userfundisable))
06285 return DC_ERROR;
06286
06287 if(debug)
06288 printf("@@@@ status param = %s, digitbuf = %s\n", (param)? param : "(null)", digitbuf);
06289
06290 switch(myatoi(param)){
06291 case 1:
06292 rpt_telemetry(myrpt, ID1, NULL);
06293 return DC_COMPLETE;
06294 case 2:
06295 rpt_telemetry(myrpt, STATS_TIME, NULL);
06296 return DC_COMPLETE;
06297 case 3:
06298 rpt_telemetry(myrpt, STATS_VERSION, NULL);
06299 return DC_COMPLETE;
06300 case 11:
06301 rpt_telemetry(myrpt, ID , NULL);
06302 return DC_COMPLETE;
06303 case 12:
06304 rpt_telemetry(myrpt, STATS_TIME_LOCAL, NULL);
06305 return DC_COMPLETE;
06306 default:
06307 return DC_ERROR;
06308 }
06309 return DC_INDETERMINATE;
06310 }
06311
06312
06313
06314 static int function_macro(struct rpt *myrpt, char *param, char *digitbuf, int command_source, struct rpt_link *mylink)
06315 {
06316 char *val;
06317 int i;
06318 if (myrpt->remote)
06319 return DC_ERROR;
06320
06321 if(debug)
06322 printf("@@@@ macro-oni param = %s, digitbuf = %s\n", (param)? param : "(null)", digitbuf);
06323
06324 if(strlen(digitbuf) < 1)
06325 return DC_INDETERMINATE;
06326
06327 for(i = 0 ; i < digitbuf[i] ; i++) {
06328 if((digitbuf[i] < '0') || (digitbuf[i] > '9'))
06329 return DC_ERROR;
06330 }
06331
06332 if (*digitbuf == '0') val = myrpt->p.startupmacro;
06333 else val = (char *) ast_variable_retrieve(myrpt->cfg, myrpt->p.macro, digitbuf);
06334
06335 if (!val){
06336 if (strlen(digitbuf) < myrpt->macro_longest)
06337 return DC_INDETERMINATE;
06338 rpt_telemetry(myrpt, MACRO_NOTFOUND, NULL);
06339 return DC_COMPLETE;
06340 }
06341 rpt_mutex_lock(&myrpt->lock);
06342 if ((MAXMACRO - strlen(myrpt->macrobuf)) < strlen(val))
06343 {
06344 rpt_mutex_unlock(&myrpt->lock);
06345 rpt_telemetry(myrpt, MACRO_BUSY, NULL);
06346 return DC_ERROR;
06347 }
06348 myrpt->macrotimer = MACROTIME;
06349 strncat(myrpt->macrobuf,val,MAXMACRO - 1);
06350 rpt_mutex_unlock(&myrpt->lock);
06351 return DC_COMPLETE;
06352 }
06353
06354
06355
06356
06357
06358 static int function_playback(struct rpt *myrpt, char *param, char *digitbuf, int command_source, struct rpt_link *mylink)
06359 {
06360
06361 if (myrpt->remote)
06362 return DC_ERROR;
06363
06364 if(debug)
06365 printf("@@@@ playback param = %s, digitbuf = %s\n", (param)? param : "(null)", digitbuf);
06366
06367 if (ast_fileexists(param,NULL,myrpt->rxchannel->language) <= 0)
06368 return DC_ERROR;
06369
06370 rpt_telemetry(myrpt,PLAYBACK,param);
06371 return DC_COMPLETE;
06372 }
06373
06374
06375
06376
06377
06378 static int function_cop(struct rpt *myrpt, char *param, char *digitbuf, int command_source, struct rpt_link *mylink)
06379 {
06380 char string[16];
06381 int res;
06382
06383 int i, r;
06384
06385 if(!param)
06386 return DC_ERROR;
06387
06388 switch(myatoi(param)){
06389 case 1:
06390 res = system("killall -9 asterisk");
06391 return DC_COMPLETE;
06392
06393 case 2:
06394 myrpt->p.s[myrpt->p.sysstate_cur].txdisable = 0;
06395 rpt_telemetry(myrpt, ARB_ALPHA, (void *) "RPTENA");
06396 return DC_COMPLETE;
06397
06398 case 3:
06399 myrpt->p.s[myrpt->p.sysstate_cur].txdisable = 1;
06400 return DC_COMPLETE;
06401
06402 case 4:
06403 if (myrpt->stopgen < 0)
06404 {
06405 myrpt->stopgen = 1;
06406 }
06407 else
06408 {
06409 myrpt->stopgen = 0;
06410 rpt_telemetry(myrpt, TEST_TONE, NULL);
06411 }
06412 return DC_COMPLETE;
06413
06414 case 5:
06415 myrpt->disgorgetime = time(NULL) + 10;
06416 return DC_COMPLETE;
06417
06418 case 6:
06419 if (command_source != SOURCE_PHONE) return DC_INDETERMINATE;
06420 return DC_DOKEY;
06421
06422
06423 case 7:
06424 myrpt->p.s[myrpt->p.sysstate_cur].totdisable = 0;
06425 rpt_telemetry(myrpt, ARB_ALPHA, (void *) "TOTENA");
06426 return DC_COMPLETE;
06427
06428 case 8:
06429 myrpt->p.s[myrpt->p.sysstate_cur].totdisable = 1;
06430 rpt_telemetry(myrpt, ARB_ALPHA, (void *) "TOTDIS");
06431 return DC_COMPLETE;
06432
06433 case 9:
06434 myrpt->p.s[myrpt->p.sysstate_cur].autopatchdisable = 0;
06435 rpt_telemetry(myrpt, ARB_ALPHA, (void *) "APENA");
06436 return DC_COMPLETE;
06437
06438 case 10:
06439 myrpt->p.s[myrpt->p.sysstate_cur].autopatchdisable = 1;
06440 rpt_telemetry(myrpt, ARB_ALPHA, (void *) "APDIS");
06441 return DC_COMPLETE;
06442
06443 case 11:
06444 myrpt->p.s[myrpt->p.sysstate_cur].linkfundisable = 0;
06445 rpt_telemetry(myrpt, ARB_ALPHA, (void *) "LNKENA");
06446 return DC_COMPLETE;
06447
06448 case 12:
06449 myrpt->p.s[myrpt->p.sysstate_cur].linkfundisable = 1;
06450 rpt_telemetry(myrpt, ARB_ALPHA, (void *) "LNKDIS");
06451 return DC_COMPLETE;
06452
06453 case 13:
06454 string[0] = string[1] = 'S';
06455 string[2] = myrpt->p.sysstate_cur + '0';
06456 string[3] = '\0';
06457 rpt_telemetry(myrpt, ARB_ALPHA, (void *) string);
06458 return DC_COMPLETE;
06459
06460 case 14:
06461 if(strlen(digitbuf) == 0)
06462 break;
06463 if((digitbuf[0] < '0') || (digitbuf[0] > '9'))
06464 return DC_ERROR;
06465 myrpt->p.sysstate_cur = digitbuf[0] - '0';
06466 string[0] = string[1] = 'S';
06467 string[2] = myrpt->p.sysstate_cur + '0';
06468 string[3] = '\0';
06469 rpt_telemetry(myrpt, ARB_ALPHA, (void *) string);
06470 return DC_COMPLETE;
06471
06472 case 15:
06473 myrpt->p.s[myrpt->p.sysstate_cur].schedulerdisable = 0;
06474 rpt_telemetry(myrpt, ARB_ALPHA, (void *) "SKENA");
06475 return DC_COMPLETE;
06476
06477 case 16:
06478 myrpt->p.s[myrpt->p.sysstate_cur].schedulerdisable = 1;
06479 rpt_telemetry(myrpt, ARB_ALPHA, (void *) "SKDIS");
06480 return DC_COMPLETE;
06481
06482 case 17:
06483 myrpt->p.s[myrpt->p.sysstate_cur].userfundisable = 0;
06484 rpt_telemetry(myrpt, ARB_ALPHA, (void *) "UFENA");
06485 return DC_COMPLETE;
06486
06487 case 18:
06488 myrpt->p.s[myrpt->p.sysstate_cur].userfundisable = 1;
06489 rpt_telemetry(myrpt, ARB_ALPHA, (void *) "UFDIS");
06490 return DC_COMPLETE;
06491
06492 case 19:
06493 myrpt->p.s[myrpt->p.sysstate_cur].alternatetail = 1;
06494 rpt_telemetry(myrpt, ARB_ALPHA, (void *) "ATENA");
06495 return DC_COMPLETE;
06496
06497 case 20:
06498 myrpt->p.s[myrpt->p.sysstate_cur].alternatetail = 0;
06499 rpt_telemetry(myrpt, ARB_ALPHA, (void *) "ATDIS");
06500 return DC_COMPLETE;
06501
06502 case 21:
06503 birdbath(myrpt);
06504 if (myrpt->p.parrotmode < 2)
06505 {
06506 myrpt->p.parrotmode = 0;
06507 rpt_telemetry(myrpt,COMPLETE,NULL);
06508 return DC_COMPLETE;
06509 }
06510 break;
06511
06512 case 22:
06513 birdbath(myrpt);
06514 if (myrpt->p.parrotmode < 2)
06515 {
06516 myrpt->p.parrotmode = 1;
06517 rpt_telemetry(myrpt,COMPLETE,NULL);
06518 return DC_COMPLETE;
06519 }
06520 break;
06521 case 23:
06522 birdbath(myrpt);
06523 rpt_telemetry(myrpt,COMPLETE,NULL);
06524 return DC_COMPLETE;
06525 case 24:
06526 flush_telem(myrpt);
06527 rpt_telemetry(myrpt,COMPLETE,NULL);
06528 return DC_COMPLETE;
06529 case 25:
06530 send_link_keyquery(myrpt);
06531 myrpt->topkeylong = 0;
06532 rpt_telemetry(myrpt,COMPLETE,NULL);
06533 return DC_COMPLETE;
06534 case 26:
06535 send_link_keyquery(myrpt);
06536 myrpt->topkeylong = 1;
06537 rpt_telemetry(myrpt,COMPLETE,NULL);
06538 return DC_COMPLETE;
06539
06540 case 30:
06541
06542 if(strlen(digitbuf) < 2)
06543 break;
06544
06545 for(i = 0 ; i < 2 ; i++){
06546 if((digitbuf[i] < '0') || (digitbuf[i] > '9'))
06547 return DC_ERROR;
06548 }
06549
06550 r = retreive_memory(myrpt, digitbuf);
06551 if (r < 0){
06552 rpt_telemetry(myrpt,MEMNOTFOUND,NULL);
06553 return DC_COMPLETE;
06554 }
06555 if (r > 0){
06556 return DC_ERROR;
06557 }
06558 if (setrem(myrpt) == -1) return DC_ERROR;
06559 return DC_COMPLETE;
06560
06561 case 31:
06562
06563
06564 if(strlen(digitbuf) < 2)
06565 break;
06566
06567 for(i = 0 ; i < 2 ; i++){
06568 if((digitbuf[i] < '0') || (digitbuf[i] > '9'))
06569 return DC_ERROR;
06570 }
06571 channel_steer(myrpt,digitbuf);
06572 return DC_COMPLETE;
06573
06574 case 32:
06575 i = strlen(digitbuf);
06576 if(!i){
06577 if(debug > 3)
06578 ast_log(LOG_NOTICE,"Padtest entered");
06579 myrpt->inpadtest = 1;
06580 }
06581 else{
06582 if(debug > 3)
06583 ast_log(LOG_NOTICE,"Padtest len= %d digits=%s",i,digitbuf);
06584 if(digitbuf[i-1] != myrpt->p.endchar)
06585 break;
06586 rpt_telemetry(myrpt, ARB_ALPHA, digitbuf);
06587 myrpt->inpadtest = 0;
06588 if(debug > 3)
06589 ast_log(LOG_NOTICE,"Padtest exited");
06590 return DC_COMPLETE;
06591 }
06592 }
06593 return DC_INDETERMINATE;
06594 }
06595
06596
06597
06598 static int collect_function_digits(struct rpt *myrpt, char *digits,
06599 int command_source, struct rpt_link *mylink)
06600 {
06601 int i,rv;
06602 char *stringp,*action,*param,*functiondigits;
06603 char function_table_name[30] = "";
06604 char workstring[200];
06605
06606 struct ast_variable *vp;
06607
06608 if (debug > 6) ast_log(LOG_NOTICE,"digits=%s source=%d\n",digits, command_source);
06609
06610
06611
06612
06613 if (command_source == SOURCE_DPHONE) {
06614 if (!myrpt->p.dphone_functions) return DC_INDETERMINATE;
06615 strncpy(function_table_name, myrpt->p.dphone_functions, sizeof(function_table_name) - 1);
06616 }
06617 else if (command_source == SOURCE_ALT) {
06618 if (!myrpt->p.alt_functions) return DC_INDETERMINATE;
06619 strncpy(function_table_name, myrpt->p.alt_functions, sizeof(function_table_name) - 1);
06620 }
06621 else if (command_source == SOURCE_PHONE) {
06622 if (!myrpt->p.phone_functions) return DC_INDETERMINATE;
06623 strncpy(function_table_name, myrpt->p.phone_functions, sizeof(function_table_name) - 1);
06624 }
06625 else if (command_source == SOURCE_LNK)
06626 strncpy(function_table_name, myrpt->p.link_functions, sizeof(function_table_name) - 1);
06627 else
06628 strncpy(function_table_name, myrpt->p.functions, sizeof(function_table_name) - 1);
06629
06630 vp = ast_variable_browse(myrpt->cfg, function_table_name);
06631 while(vp) {
06632 if(!strncasecmp(vp->name, digits, strlen(vp->name)))
06633 break;
06634 vp = vp->next;
06635 }
06636
06637 if(!vp) {
06638 int n;
06639
06640 n = myrpt->longestfunc;
06641 if (command_source == SOURCE_LNK) n = myrpt->link_longestfunc;
06642 else
06643 if (command_source == SOURCE_PHONE) n = myrpt->phone_longestfunc;
06644 else
06645 if (command_source == SOURCE_ALT) n = myrpt->alt_longestfunc;
06646 else
06647 if (command_source == SOURCE_DPHONE) n = myrpt->dphone_longestfunc;
06648
06649 if(strlen(digits) >= n)
06650 return DC_ERROR;
06651 else
06652 return DC_INDETERMINATE;
06653 }
06654
06655 strncpy(workstring, vp->value, sizeof(workstring) - 1 );
06656 stringp = workstring;
06657 action = strsep(&stringp, ",");
06658 param = stringp;
06659 if(debug)
06660 printf("@@@@ action: %s, param = %s\n",action, (param) ? param : "(null)");
06661
06662 for(i = 0 ; i < (sizeof(function_table)/sizeof(struct function_table_tag)); i++){
06663 if(!strncasecmp(action, function_table[i].action, strlen(action)))
06664 break;
06665 }
06666 if(debug)
06667 printf("@@@@ table index i = %d\n",i);
06668 if(i == (sizeof(function_table)/sizeof(struct function_table_tag))){
06669
06670 return DC_ERROR;
06671 }
06672 if(function_table[i].function == NULL){
06673
06674 if(debug)
06675 printf("@@@@ NULL for action: %s\n",action);
06676 return DC_ERROR;
06677 }
06678 functiondigits = digits + strlen(vp->name);
06679 rv=(*function_table[i].function)(myrpt, param, functiondigits, command_source, mylink);
06680 if (debug > 6) ast_log(LOG_NOTICE,"rv=%i\n",rv);
06681 return(rv);
06682 }
06683
06684
06685 static void handle_link_data(struct rpt *myrpt, struct rpt_link *mylink,
06686 char *str)
06687 {
06688
06689
06690 char tmp[512],tmp1[512],cmd[300] = "",dest[300],src[300],c;
06691 int i,seq, res, ts;
06692 struct rpt_link *l;
06693 struct ast_frame wf;
06694
06695 wf.frametype = AST_FRAME_TEXT;
06696 wf.subclass.integer = 0;
06697 wf.offset = 0;
06698 wf.mallocd = 0;
06699 wf.datalen = strlen(str) + 1;
06700 wf.samples = 0;
06701
06702 strncpy(tmp,str,sizeof(tmp) - 1);
06703
06704 if (!strcmp(tmp,discstr))
06705 {
06706 mylink->disced = 1;
06707 mylink->retries = mylink->max_retries + 1;
06708 ast_softhangup(mylink->chan,AST_SOFTHANGUP_DEV);
06709 return;
06710 }
06711 if (!strcmp(tmp,newkeystr))
06712 {
06713 mylink->newkey = 1;
06714 return;
06715 }
06716 if (tmp[0] == 'L')
06717 {
06718 rpt_mutex_lock(&myrpt->lock);
06719 strcpy(mylink->linklist,tmp + 2);
06720 time(&mylink->linklistreceived);
06721 rpt_mutex_unlock(&myrpt->lock);
06722 if (debug > 6) ast_log(LOG_NOTICE,"@@@@ node %s received node list %s from node %s\n",
06723 myrpt->name,tmp,mylink->name);
06724 return;
06725 }
06726 if (tmp[0] == 'K')
06727 {
06728 if (sscanf(tmp, "%299s %299s %299s %30d %30d", cmd, dest, src, &seq, &ts) != 5)
06729 {
06730 ast_log(LOG_WARNING, "Unable to parse keying string %s\n",str);
06731 return;
06732 }
06733 if (dest[0] == '0')
06734 {
06735 strcpy(dest,myrpt->name);
06736 }
06737
06738 if (strcmp(dest,myrpt->name))
06739 {
06740 l = myrpt->links.next;
06741
06742 while(l != &myrpt->links)
06743 {
06744 if (l->name[0] == '0')
06745 {
06746 l = l->next;
06747 continue;
06748 }
06749
06750 if ((l == mylink) || (!strcmp(l->name,mylink->name)))
06751 {
06752 l = l->next;
06753 continue;
06754 }
06755
06756 if (!strcmp(l->name,dest))
06757 {
06758
06759 if (strcmp(l->name,src)) {
06760 wf.data.ptr = str;
06761 if (l->chan) ast_write(l->chan,&wf);
06762 }
06763 return;
06764 }
06765 l = l->next;
06766 }
06767 }
06768
06769 if ((strcmp(dest,myrpt->name)) || (dest[0] == '*'))
06770 {
06771 l = myrpt->links.next;
06772
06773 while(l != &myrpt->links)
06774 {
06775 if (l->name[0] == '0')
06776 {
06777 l = l->next;
06778 continue;
06779 }
06780
06781 if ((l == mylink) || (!strcmp(l->name,mylink->name)))
06782 {
06783 l = l->next;
06784 continue;
06785 }
06786
06787 if (strcmp(l->name,src)) {
06788 wf.data.ptr = str;
06789 if (l->chan) ast_write(l->chan,&wf);
06790 }
06791 l = l->next;
06792 }
06793 }
06794
06795 if (strcmp(dest,myrpt->name) && (dest[0] != '*')) return;
06796 if (cmd[1] == '?')
06797 {
06798 time_t now;
06799 int n = 0;
06800
06801 time(&now);
06802 if (myrpt->lastkeyedtime)
06803 {
06804 n = (int)(now - myrpt->lastkeyedtime);
06805 }
06806 sprintf(tmp1,"K %s %s %d %d",src,myrpt->name,myrpt->keyed,n);
06807 wf.data.ptr = tmp1;
06808 wf.datalen = strlen(tmp1) + 1;
06809 if (mylink->chan) ast_write(mylink->chan,&wf);
06810 return;
06811 }
06812 if (myrpt->topkeystate != 1) return;
06813 rpt_mutex_lock(&myrpt->lock);
06814 for(i = 0; i < TOPKEYN; i++)
06815 {
06816 if (!strcmp(myrpt->topkey[i].node,src)) break;
06817 }
06818 if (i >= TOPKEYN)
06819 {
06820 for(i = 0; i < TOPKEYN; i++)
06821 {
06822 if (!myrpt->topkey[i].node[0]) break;
06823 }
06824 }
06825 if (i < TOPKEYN)
06826 {
06827 strncpy(myrpt->topkey[i].node,src,TOPKEYMAXSTR - 1);
06828 myrpt->topkey[i].timesince = ts;
06829 myrpt->topkey[i].keyed = seq;
06830 }
06831 rpt_mutex_unlock(&myrpt->lock);
06832 return;
06833 }
06834 if (tmp[0] == 'I')
06835 {
06836
06837
06838 if (sscanf(tmp,"%299s %299s %30x",cmd,src,&seq) != 3)
06839 {
06840 ast_log(LOG_WARNING, "Unable to parse ident string %s\n",str);
06841 return;
06842 }
06843 mdc1200_notify(myrpt,src,seq);
06844 strcpy(dest,"*");
06845 }
06846 else
06847 {
06848
06849
06850 if (sscanf(tmp,"%299s %299s %299s %30d %1c",cmd,dest,src,&seq,&c) != 5)
06851 {
06852 ast_log(LOG_WARNING, "Unable to parse link string %s\n",str);
06853 return;
06854 }
06855 if (strcmp(cmd,"D"))
06856 {
06857 ast_log(LOG_WARNING, "Unable to parse link string %s\n",str);
06858 return;
06859 }
06860 }
06861 if (dest[0] == '0')
06862 {
06863 strcpy(dest,myrpt->name);
06864 }
06865
06866
06867 if (strcmp(dest,myrpt->name))
06868 {
06869 l = myrpt->links.next;
06870
06871 while(l != &myrpt->links)
06872 {
06873 if (l->name[0] == '0')
06874 {
06875 l = l->next;
06876 continue;
06877 }
06878
06879 if ((l == mylink) || (!strcmp(l->name,mylink->name)))
06880 {
06881 l = l->next;
06882 continue;
06883 }
06884
06885 if (!strcmp(l->name,dest))
06886 {
06887
06888 if (strcmp(l->name,src)) {
06889 wf.data.ptr = str;
06890 if (l->chan) ast_write(l->chan,&wf);
06891 }
06892 return;
06893 }
06894 l = l->next;
06895 }
06896 l = myrpt->links.next;
06897
06898 while(l != &myrpt->links)
06899 {
06900 if (l->name[0] == '0')
06901 {
06902 l = l->next;
06903 continue;
06904 }
06905
06906 if ((l == mylink) || (!strcmp(l->name,mylink->name)))
06907 {
06908 l = l->next;
06909 continue;
06910 }
06911
06912 if (strcmp(l->name,src)) {
06913 wf.data.ptr = str;
06914 if (l->chan) ast_write(l->chan,&wf);
06915 }
06916 l = l->next;
06917 }
06918 return;
06919 }
06920 if (myrpt->p.archivedir)
06921 {
06922 char dtmfstr[100];
06923
06924 sprintf(dtmfstr,"DTMF,%s,%c",mylink->name,c);
06925 donodelog(myrpt,dtmfstr);
06926 }
06927 c = func_xlat(myrpt,c,&myrpt->p.outxlat);
06928 if (!c) return;
06929 rpt_mutex_lock(&myrpt->lock);
06930 if (c == myrpt->p.endchar) myrpt->stopgen = 1;
06931 if (myrpt->callmode == 1)
06932 {
06933 myrpt->exten[myrpt->cidx++] = c;
06934 myrpt->exten[myrpt->cidx] = 0;
06935
06936 if (ast_exists_extension(myrpt->pchannel,myrpt->patchcontext,myrpt->exten,1,NULL))
06937 {
06938
06939 if (!ast_matchmore_extension(myrpt->pchannel,myrpt->patchcontext,
06940 myrpt->exten,1,NULL))
06941 {
06942 myrpt->callmode = 2;
06943 if(!myrpt->patchquiet)
06944 {
06945 rpt_mutex_unlock(&myrpt->lock);
06946 rpt_telemetry(myrpt,PROC,NULL);
06947 rpt_mutex_lock(&myrpt->lock);
06948 }
06949 }
06950 else
06951 {
06952 myrpt->calldigittimer = 1;
06953 }
06954 }
06955
06956 if (!ast_canmatch_extension(myrpt->pchannel,myrpt->patchcontext,myrpt->exten,1,NULL))
06957 {
06958
06959 myrpt->callmode = 4;
06960 }
06961 }
06962 if ((!myrpt->inpadtest) &&(c == myrpt->p.funcchar))
06963 {
06964 myrpt->rem_dtmfidx = 0;
06965 myrpt->rem_dtmfbuf[myrpt->rem_dtmfidx] = 0;
06966 time(&myrpt->rem_dtmf_time);
06967 rpt_mutex_unlock(&myrpt->lock);
06968 return;
06969 }
06970 else if (myrpt->rem_dtmfidx < 0)
06971 {
06972 if ((myrpt->callmode == 2) || (myrpt->callmode == 3))
06973 {
06974 myrpt->mydtmf = c;
06975 }
06976 if (myrpt->p.propagate_dtmf) do_dtmf_local(myrpt,c);
06977 if (myrpt->p.propagate_phonedtmf) do_dtmf_phone(myrpt,mylink,c);
06978 rpt_mutex_unlock(&myrpt->lock);
06979 return;
06980 }
06981 else if (((myrpt->inpadtest) || (c != myrpt->p.endchar)) && (myrpt->rem_dtmfidx >= 0))
06982 {
06983 time(&myrpt->rem_dtmf_time);
06984 if (myrpt->rem_dtmfidx < MAXDTMF)
06985 {
06986 myrpt->rem_dtmfbuf[myrpt->rem_dtmfidx++] = c;
06987 myrpt->rem_dtmfbuf[myrpt->rem_dtmfidx] = 0;
06988
06989 rpt_mutex_unlock(&myrpt->lock);
06990 strncpy(cmd, myrpt->rem_dtmfbuf, sizeof(cmd) - 1);
06991 res = collect_function_digits(myrpt, cmd, SOURCE_LNK, mylink);
06992 rpt_mutex_lock(&myrpt->lock);
06993
06994 switch(res){
06995
06996 case DC_INDETERMINATE:
06997 break;
06998
06999 case DC_REQ_FLUSH:
07000 myrpt->rem_dtmfidx = 0;
07001 myrpt->rem_dtmfbuf[0] = 0;
07002 break;
07003
07004
07005 case DC_COMPLETE:
07006 case DC_COMPLETEQUIET:
07007 myrpt->totalexecdcommands++;
07008 myrpt->dailyexecdcommands++;
07009 strncpy(myrpt->lastdtmfcommand, cmd, MAXDTMF-1);
07010 myrpt->lastdtmfcommand[MAXDTMF-1] = '\0';
07011 myrpt->rem_dtmfbuf[0] = 0;
07012 myrpt->rem_dtmfidx = -1;
07013 myrpt->rem_dtmf_time = 0;
07014 break;
07015
07016 case DC_ERROR:
07017 default:
07018 myrpt->rem_dtmfbuf[0] = 0;
07019 myrpt->rem_dtmfidx = -1;
07020 myrpt->rem_dtmf_time = 0;
07021 break;
07022 }
07023 }
07024
07025 }
07026 rpt_mutex_unlock(&myrpt->lock);
07027 return;
07028 }
07029
07030 static void handle_link_phone_dtmf(struct rpt *myrpt, struct rpt_link *mylink,
07031 char c)
07032 {
07033
07034 char cmd[300];
07035 int res;
07036
07037 if (myrpt->p.archivedir)
07038 {
07039 char str[100];
07040
07041 sprintf(str,"DTMF(P),%s,%c",mylink->name,c);
07042 donodelog(myrpt,str);
07043 }
07044 rpt_mutex_lock(&myrpt->lock);
07045
07046 if (mylink->phonemode == 3)
07047 {
07048 if(c == myrpt->p.endchar)
07049 {
07050 mylink->lastrealrx = 0;
07051 rpt_mutex_unlock(&myrpt->lock);
07052 return;
07053 }
07054
07055 if(c == myrpt->p.funcchar)
07056 {
07057 mylink->lastrealrx = !mylink->lastrealrx;
07058 rpt_mutex_unlock(&myrpt->lock);
07059 return;
07060 }
07061 }
07062 else
07063 {
07064 if (c == myrpt->p.endchar)
07065 {
07066 if (mylink->lastrx)
07067 {
07068 mylink->lastrealrx = 0;
07069 rpt_mutex_unlock(&myrpt->lock);
07070 return;
07071 }
07072 myrpt->stopgen = 1;
07073 if (myrpt->cmdnode[0])
07074 {
07075 myrpt->cmdnode[0] = 0;
07076 myrpt->dtmfidx = -1;
07077 myrpt->dtmfbuf[0] = 0;
07078 rpt_mutex_unlock(&myrpt->lock);
07079 rpt_telemetry(myrpt,COMPLETE,NULL);
07080 return;
07081 }
07082 }
07083 }
07084 if (myrpt->cmdnode[0])
07085 {
07086 rpt_mutex_unlock(&myrpt->lock);
07087 send_link_dtmf(myrpt,c);
07088 return;
07089 }
07090 if (myrpt->callmode == 1)
07091 {
07092 myrpt->exten[myrpt->cidx++] = c;
07093 myrpt->exten[myrpt->cidx] = 0;
07094
07095 if (ast_exists_extension(myrpt->pchannel,myrpt->patchcontext,myrpt->exten,1,NULL))
07096 {
07097
07098 if (!ast_matchmore_extension(myrpt->pchannel,myrpt->patchcontext,
07099 myrpt->exten,1,NULL))
07100 {
07101 myrpt->callmode = 2;
07102 if(!myrpt->patchquiet)
07103 {
07104 rpt_mutex_unlock(&myrpt->lock);
07105 rpt_telemetry(myrpt,PROC,NULL);
07106 rpt_mutex_lock(&myrpt->lock);
07107 }
07108 }
07109 else
07110 {
07111 myrpt->calldigittimer = 1;
07112 }
07113 }
07114
07115 if (!ast_canmatch_extension(myrpt->pchannel,myrpt->patchcontext,myrpt->exten,1,NULL))
07116 {
07117
07118 myrpt->callmode = 4;
07119 }
07120 }
07121 if ((myrpt->callmode == 2) || (myrpt->callmode == 3))
07122 {
07123 myrpt->mydtmf = c;
07124 }
07125 if ((!myrpt->inpadtest) && (c == myrpt->p.funcchar))
07126 {
07127 myrpt->rem_dtmfidx = 0;
07128 myrpt->rem_dtmfbuf[myrpt->rem_dtmfidx] = 0;
07129 time(&myrpt->rem_dtmf_time);
07130 rpt_mutex_unlock(&myrpt->lock);
07131 return;
07132 }
07133 else if (((myrpt->inpadtest) || (c != myrpt->p.endchar)) && (myrpt->rem_dtmfidx >= 0))
07134 {
07135 time(&myrpt->rem_dtmf_time);
07136 if (myrpt->rem_dtmfidx < MAXDTMF)
07137 {
07138 myrpt->rem_dtmfbuf[myrpt->rem_dtmfidx++] = c;
07139 myrpt->rem_dtmfbuf[myrpt->rem_dtmfidx] = 0;
07140
07141 rpt_mutex_unlock(&myrpt->lock);
07142 strncpy(cmd, myrpt->rem_dtmfbuf, sizeof(cmd) - 1);
07143 switch(mylink->phonemode)
07144 {
07145 case 1:
07146 res = collect_function_digits(myrpt, cmd,
07147 SOURCE_PHONE, mylink);
07148 break;
07149 case 2:
07150 res = collect_function_digits(myrpt, cmd,
07151 SOURCE_DPHONE,mylink);
07152 break;
07153 case 4:
07154 res = collect_function_digits(myrpt, cmd,
07155 SOURCE_ALT,mylink);
07156 break;
07157 default:
07158 res = collect_function_digits(myrpt, cmd,
07159 SOURCE_LNK, mylink);
07160 break;
07161 }
07162
07163 rpt_mutex_lock(&myrpt->lock);
07164
07165 switch(res){
07166
07167 case DC_INDETERMINATE:
07168 break;
07169
07170 case DC_DOKEY:
07171 mylink->lastrealrx = 1;
07172 break;
07173
07174 case DC_REQ_FLUSH:
07175 myrpt->rem_dtmfidx = 0;
07176 myrpt->rem_dtmfbuf[0] = 0;
07177 break;
07178
07179
07180 case DC_COMPLETE:
07181 case DC_COMPLETEQUIET:
07182 myrpt->totalexecdcommands++;
07183 myrpt->dailyexecdcommands++;
07184 strncpy(myrpt->lastdtmfcommand, cmd, MAXDTMF-1);
07185 myrpt->lastdtmfcommand[MAXDTMF-1] = '\0';
07186 myrpt->rem_dtmfbuf[0] = 0;
07187 myrpt->rem_dtmfidx = -1;
07188 myrpt->rem_dtmf_time = 0;
07189 break;
07190
07191 case DC_ERROR:
07192 default:
07193 myrpt->rem_dtmfbuf[0] = 0;
07194 myrpt->rem_dtmfidx = -1;
07195 myrpt->rem_dtmf_time = 0;
07196 break;
07197 }
07198 }
07199
07200 }
07201 rpt_mutex_unlock(&myrpt->lock);
07202 return;
07203 }
07204
07205
07206
07207
07208
07209
07210
07211
07212
07213
07214
07215
07216
07217
07218
07219
07220
07221
07222
07223
07224
07225
07226
07227
07228
07229
07230
07231
07232
07233
07234
07235
07236 static int rbi_mhztoband(char *str)
07237 {
07238 int i;
07239
07240 i = atoi(str) / 10;
07241 switch(i)
07242 {
07243 case 2:
07244 return 10;
07245 case 5:
07246 return 11;
07247 case 14:
07248 return 2;
07249 case 22:
07250 return 3;
07251 case 44:
07252 return 4;
07253 case 124:
07254 return 0;
07255 case 125:
07256 return 1;
07257 case 126:
07258 return 8;
07259 case 127:
07260 return 5;
07261 case 128:
07262 return 6;
07263 case 129:
07264 return 7;
07265 default:
07266 break;
07267 }
07268 return -1;
07269 }
07270
07271
07272 static int rbi_pltocode(char *str)
07273 {
07274 int i;
07275 char *s;
07276
07277 s = strchr(str,'.');
07278 i = 0;
07279 if (s) i = atoi(s + 1);
07280 i += atoi(str) * 10;
07281 switch(i)
07282 {
07283 case 670:
07284 return 0;
07285 case 719:
07286 return 1;
07287 case 744:
07288 return 2;
07289 case 770:
07290 return 3;
07291 case 797:
07292 return 4;
07293 case 825:
07294 return 5;
07295 case 854:
07296 return 6;
07297 case 885:
07298 return 7;
07299 case 915:
07300 return 8;
07301 case 948:
07302 return 9;
07303 case 974:
07304 return 10;
07305 case 1000:
07306 return 11;
07307 case 1035:
07308 return 12;
07309 case 1072:
07310 return 13;
07311 case 1109:
07312 return 14;
07313 case 1148:
07314 return 15;
07315 case 1188:
07316 return 16;
07317 case 1230:
07318 return 17;
07319 case 1273:
07320 return 18;
07321 case 1318:
07322 return 19;
07323 case 1365:
07324 return 20;
07325 case 1413:
07326 return 21;
07327 case 1462:
07328 return 22;
07329 case 1514:
07330 return 23;
07331 case 1567:
07332 return 24;
07333 case 1622:
07334 return 25;
07335 case 1679:
07336 return 26;
07337 case 1738:
07338 return 27;
07339 case 1799:
07340 return 28;
07341 case 1862:
07342 return 29;
07343 case 1928:
07344 return 30;
07345 case 2035:
07346 return 31;
07347 case 2107:
07348 return 32;
07349 case 2181:
07350 return 33;
07351 case 2257:
07352 return 34;
07353 case 2336:
07354 return 35;
07355 case 2418:
07356 return 36;
07357 case 2503:
07358 return 37;
07359 }
07360 return -1;
07361 }
07362
07363
07364
07365
07366
07367 static void rbi_out_parallel(struct rpt *myrpt,unsigned char *data)
07368 {
07369 #ifdef __i386__
07370 int i,j;
07371 unsigned char od,d;
07372 static volatile long long delayvar;
07373
07374 for(i = 0 ; i < 5 ; i++){
07375 od = *data++;
07376 for(j = 0 ; j < 8 ; j++){
07377 d = od & 1;
07378 outb(d,myrpt->p.iobase);
07379
07380 for(delayvar = 1; delayvar < 15000; delayvar++);
07381 od >>= 1;
07382 outb(d | 2,myrpt->p.iobase);
07383
07384 for(delayvar = 1; delayvar < 30000; delayvar++);
07385 outb(d,myrpt->p.iobase);
07386
07387 for(delayvar = 1; delayvar < 10000; delayvar++);
07388 }
07389 }
07390
07391 for(delayvar = 1; delayvar < 50000; delayvar++);
07392 #endif
07393 }
07394
07395 static void rbi_out(struct rpt *myrpt,unsigned char *data)
07396 {
07397 struct dahdi_radio_param r;
07398
07399 memset(&r,0,sizeof(struct dahdi_radio_param));
07400 r.radpar = DAHDI_RADPAR_REMMODE;
07401 r.data = DAHDI_RADPAR_REM_RBI1;
07402
07403 if (ioctl(myrpt->dahdirxchannel->fds[0],DAHDI_RADIO_SETPARAM,&r) == -1)
07404 {
07405 rbi_out_parallel(myrpt,data);
07406 return;
07407 }
07408 r.radpar = DAHDI_RADPAR_REMCOMMAND;
07409 memcpy(&r.data,data,5);
07410 if (ioctl(myrpt->dahdirxchannel->fds[0],DAHDI_RADIO_SETPARAM,&r) == -1)
07411 {
07412 ast_log(LOG_WARNING,"Cannot send RBI command for channel %s\n",myrpt->dahdirxchannel->name);
07413 return;
07414 }
07415 }
07416
07417 static int serial_remote_io(struct rpt *myrpt, unsigned char *txbuf, int txbytes,
07418 unsigned char *rxbuf, int rxmaxbytes, int asciiflag)
07419 {
07420 int i,j,idx,oldmode,olddata;
07421 struct dahdi_radio_param prm;
07422 char c;
07423
07424 if(debug) {
07425 ast_log(LOG_NOTICE, "ioport=%s iofd=0x%x\n",myrpt->p.ioport,myrpt->iofd);
07426 printf("String output was:\n");
07427 for(i = 0; i < txbytes; i++)
07428 printf("%02X ", (unsigned char ) txbuf[i]);
07429 printf("\n");
07430 }
07431
07432 if (myrpt->iofd >= 0)
07433 {
07434 if (write(myrpt->iofd,txbuf,txbytes) != txbytes)
07435 {
07436 return -1;
07437 }
07438 if ((!rxmaxbytes) || (rxbuf == NULL))
07439 {
07440 return(0);
07441 }
07442 memset(rxbuf,0,rxmaxbytes);
07443 for(i = 0; i < rxmaxbytes; i++)
07444 {
07445 j = read(myrpt->iofd,&c,1);
07446 if (j < 1)
07447 {
07448 return(i);
07449 }
07450 rxbuf[i] = c;
07451 if (asciiflag & 1)
07452 {
07453 rxbuf[i + 1] = 0;
07454 if (c == '\r') break;
07455 }
07456 }
07457 if(debug) {
07458 printf("String returned was:\n");
07459 for(j = 0; j < i; j++)
07460 printf("%02X ", (unsigned char ) rxbuf[j]);
07461 printf("\n");
07462 }
07463 return(i);
07464 }
07465
07466
07467 if (myrpt->rxchannel != myrpt->dahdirxchannel) return -1;
07468
07469 prm.radpar = DAHDI_RADPAR_UIOMODE;
07470 if (ioctl(myrpt->dahdirxchannel->fds[0],DAHDI_RADIO_GETPARAM,&prm) == -1) return -1;
07471 oldmode = prm.data;
07472 prm.radpar = DAHDI_RADPAR_UIODATA;
07473 if (ioctl(myrpt->dahdirxchannel->fds[0],DAHDI_RADIO_GETPARAM,&prm) == -1) return -1;
07474 olddata = prm.data;
07475 prm.radpar = DAHDI_RADPAR_REMMODE;
07476 if (asciiflag & 1) prm.data = DAHDI_RADPAR_REM_SERIAL_ASCII;
07477 else prm.data = DAHDI_RADPAR_REM_SERIAL;
07478 if (ioctl(myrpt->dahdirxchannel->fds[0],DAHDI_RADIO_SETPARAM,&prm) == -1) return -1;
07479 if (asciiflag & 2)
07480 {
07481 i = DAHDI_ONHOOK;
07482 if (ioctl(myrpt->dahdirxchannel->fds[0],DAHDI_HOOK,&i) == -1) return -1;
07483 usleep(100000);
07484 }
07485 prm.radpar = DAHDI_RADPAR_REMCOMMAND;
07486 prm.data = rxmaxbytes;
07487 memcpy(prm.buf,txbuf,txbytes);
07488 prm.index = txbytes;
07489 if (ioctl(myrpt->dahdirxchannel->fds[0],DAHDI_RADIO_SETPARAM,&prm) == -1) return -1;
07490 if (rxbuf)
07491 {
07492 *rxbuf = 0;
07493 memcpy(rxbuf,prm.buf,prm.index);
07494 }
07495 idx = prm.index;
07496 prm.radpar = DAHDI_RADPAR_REMMODE;
07497 prm.data = DAHDI_RADPAR_REM_NONE;
07498 if (ioctl(myrpt->dahdirxchannel->fds[0],DAHDI_RADIO_SETPARAM,&prm) == -1) return -1;
07499 if (asciiflag & 2)
07500 {
07501 i = DAHDI_OFFHOOK;
07502 if (ioctl(myrpt->dahdirxchannel->fds[0],DAHDI_HOOK,&i) == -1) return -1;
07503 }
07504 prm.radpar = DAHDI_RADPAR_UIOMODE;
07505 prm.data = oldmode;
07506 if (ioctl(myrpt->dahdirxchannel->fds[0],DAHDI_RADIO_SETPARAM,&prm) == -1) return -1;
07507 prm.radpar = DAHDI_RADPAR_UIODATA;
07508 prm.data = olddata;
07509 if (ioctl(myrpt->dahdirxchannel->fds[0],DAHDI_RADIO_SETPARAM,&prm) == -1) return -1;
07510 return(idx);
07511 }
07512
07513 static int civ_cmd(struct rpt *myrpt,unsigned char *cmd, int cmdlen)
07514 {
07515 unsigned char rxbuf[100];
07516 int i,rv ;
07517
07518 rv = serial_remote_io(myrpt,cmd,cmdlen,rxbuf,cmdlen + 6,0);
07519 if (rv == -1) return(-1);
07520 if (rv != (cmdlen + 6)) return(1);
07521 for(i = 0; i < 6; i++)
07522 if (rxbuf[i] != cmd[i]) return(1);
07523 if (rxbuf[cmdlen] != 0xfe) return(1);
07524 if (rxbuf[cmdlen + 1] != 0xfe) return(1);
07525 if (rxbuf[cmdlen + 4] != 0xfb) return(1);
07526 if (rxbuf[cmdlen + 5] != 0xfd) return(1);
07527 return(0);
07528 }
07529
07530 static int sendkenwood(struct rpt *myrpt,char *txstr, char *rxstr)
07531 {
07532 int i;
07533
07534 ast_log(LOG_NOTICE,"Sent to kenwood: %s\n",txstr);
07535 if (debug) printf("Send to kenwood: %s\n",txstr);
07536 i = serial_remote_io(myrpt, (unsigned char *)txstr, strlen(txstr),
07537 (unsigned char *)rxstr,RAD_SERIAL_BUFLEN - 1,3);
07538 if (i < 0) return -1;
07539 if ((i > 0) && (rxstr[i - 1] == '\r'))
07540 rxstr[i-- - 1] = 0;
07541 if (debug) printf("Got from kenwood: %s\n",rxstr);
07542 ast_log(LOG_NOTICE,"Got from kenwood: %s\n",rxstr);
07543 return(i);
07544 }
07545
07546
07547 static int kenwood_pltocode(char *str)
07548 {
07549 int i;
07550 char *s;
07551
07552 s = strchr(str,'.');
07553 i = 0;
07554 if (s) i = atoi(s + 1);
07555 i += atoi(str) * 10;
07556 switch(i)
07557 {
07558 case 670:
07559 return 1;
07560 case 719:
07561 return 3;
07562 case 744:
07563 return 4;
07564 case 770:
07565 return 5;
07566 case 797:
07567 return 6;
07568 case 825:
07569 return 7;
07570 case 854:
07571 return 8;
07572 case 885:
07573 return 9;
07574 case 915:
07575 return 10;
07576 case 948:
07577 return 11;
07578 case 974:
07579 return 12;
07580 case 1000:
07581 return 13;
07582 case 1035:
07583 return 14;
07584 case 1072:
07585 return 15;
07586 case 1109:
07587 return 16;
07588 case 1148:
07589 return 17;
07590 case 1188:
07591 return 18;
07592 case 1230:
07593 return 19;
07594 case 1273:
07595 return 20;
07596 case 1318:
07597 return 21;
07598 case 1365:
07599 return 22;
07600 case 1413:
07601 return 23;
07602 case 1462:
07603 return 24;
07604 case 1514:
07605 return 25;
07606 case 1567:
07607 return 26;
07608 case 1622:
07609 return 27;
07610 case 1679:
07611 return 28;
07612 case 1738:
07613 return 29;
07614 case 1799:
07615 return 30;
07616 case 1862:
07617 return 31;
07618 case 1928:
07619 return 32;
07620 case 2035:
07621 return 33;
07622 case 2107:
07623 return 34;
07624 case 2181:
07625 return 35;
07626 case 2257:
07627 return 36;
07628 case 2336:
07629 return 37;
07630 case 2418:
07631 return 38;
07632 case 2503:
07633 return 39;
07634 }
07635 return -1;
07636 }
07637
07638 static int sendrxkenwood(struct rpt *myrpt, char *txstr, char *rxstr,
07639 char *cmpstr)
07640 {
07641 int i,j;
07642
07643 for(i = 0;i < KENWOOD_RETRIES;i++)
07644 {
07645 j = sendkenwood(myrpt,txstr,rxstr);
07646 if (j < 0) return(j);
07647 if (j == 0) continue;
07648 if (!strncmp(rxstr,cmpstr,strlen(cmpstr))) return(0);
07649 }
07650 return(-1);
07651 }
07652
07653 static int setkenwood(struct rpt *myrpt)
07654 {
07655 char rxstr[RAD_SERIAL_BUFLEN],txstr[RAD_SERIAL_BUFLEN],freq[20];
07656 char mhz[MAXREMSTR],offset[20],band,decimals[MAXREMSTR],band1,band2;
07657 int myrxpl;
07658
07659 int offsets[] = {0,2,1};
07660 int powers[] = {2,1,0};
07661
07662 if (sendrxkenwood(myrpt,"VMC 0,0\r",rxstr,"VMC") < 0) return -1;
07663 split_freq(mhz, decimals, myrpt->freq);
07664 if (atoi(mhz) > 400)
07665 {
07666 band = '6';
07667 band1 = '1';
07668 band2 = '5';
07669 strcpy(offset,"005000000");
07670 }
07671 else
07672 {
07673 band = '2';
07674 band1 = '0';
07675 band2 = '2';
07676 strcpy(offset,"000600000");
07677 }
07678 strcpy(freq,"000000");
07679 strncpy(freq,decimals,strlen(decimals));
07680 myrxpl = myrpt->rxplon;
07681 if (IS_XPMR(myrpt)) myrxpl = 0;
07682 sprintf(txstr,"VW %c,%05d%s,0,%d,0,%d,%d,,%02d,,%02d,%s\r",
07683 band,atoi(mhz),freq,offsets[(int)myrpt->offset],
07684 (myrpt->txplon != 0),myrxpl,
07685 kenwood_pltocode(myrpt->txpl),kenwood_pltocode(myrpt->rxpl),
07686 offset);
07687 if (sendrxkenwood(myrpt,txstr,rxstr,"VW") < 0) return -1;
07688 sprintf(txstr,"RBN %c\r",band2);
07689 if (sendrxkenwood(myrpt,txstr,rxstr,"RBN") < 0) return -1;
07690 sprintf(txstr,"PC %c,%d\r",band1,powers[(int)myrpt->powerlevel]);
07691 if (sendrxkenwood(myrpt,txstr,rxstr,"PC") < 0) return -1;
07692 return 0;
07693 }
07694
07695 static int set_tm271(struct rpt *myrpt)
07696 {
07697 char rxstr[RAD_SERIAL_BUFLEN],txstr[RAD_SERIAL_BUFLEN],freq[20];
07698 char mhz[MAXREMSTR],decimals[MAXREMSTR];
07699
07700 int offsets[] = {0,2,1};
07701 int powers[] = {2,1,0};
07702
07703 split_freq(mhz, decimals, myrpt->freq);
07704 strcpy(freq,"000000");
07705 strncpy(freq,decimals,strlen(decimals));
07706
07707 sprintf(txstr,"VF %04d%s,4,%d,0,%d,0,0,%d,%d,000,00600000,0,0\r",
07708 atoi(mhz),freq,offsets[(int)myrpt->offset],
07709 (myrpt->txplon != 0),kenwood_pltocode(myrpt->txpl),
07710 kenwood_pltocode(myrpt->rxpl));
07711
07712 if (sendrxkenwood(myrpt,txstr,rxstr,"VF") < 0) return -1;
07713 if (sendrxkenwood(myrpt,"VM 0\r",rxstr,"VM") < 0) return -1;
07714 sprintf(txstr,"PC %d\r",powers[(int)myrpt->powerlevel]);
07715 if (sendrxkenwood(myrpt,txstr,rxstr,"PC") < 0) return -1;
07716 return 0;
07717 }
07718
07719 static int setrbi(struct rpt *myrpt)
07720 {
07721 char tmp[MAXREMSTR] = "",*s;
07722 unsigned char rbicmd[5];
07723 int band,txoffset = 0,txpower = 0,rxpl;
07724
07725
07726 if (!myrpt->remoterig) return(0);
07727 if (!myrpt->remoterig[0]) return(0);
07728
07729 if (strncmp(myrpt->remoterig,remote_rig_rbi,3)) return(0);
07730 if (setrbi_check(myrpt) == -1) return(-1);
07731 strncpy(tmp, myrpt->freq, sizeof(tmp) - 1);
07732 s = strchr(tmp,'.');
07733
07734
07735 if (s == NULL){
07736 if(debug)
07737 printf("@@@@ Frequency needs a decimal\n");
07738 return -1;
07739 }
07740
07741 *s++ = 0;
07742 if (strlen(tmp) < 2){
07743 if(debug)
07744 printf("@@@@ Bad MHz digits: %s\n", tmp);
07745 return -1;
07746 }
07747
07748 if (strlen(s) < 3){
07749 if(debug)
07750 printf("@@@@ Bad KHz digits: %s\n", s);
07751 return -1;
07752 }
07753
07754 if ((s[2] != '0') && (s[2] != '5')){
07755 if(debug)
07756 printf("@@@@ KHz must end in 0 or 5: %c\n", s[2]);
07757 return -1;
07758 }
07759
07760 band = rbi_mhztoband(tmp);
07761 if (band == -1){
07762 if(debug)
07763 printf("@@@@ Bad Band: %s\n", tmp);
07764 return -1;
07765 }
07766
07767 rxpl = rbi_pltocode(myrpt->rxpl);
07768
07769 if (rxpl == -1){
07770 if(debug)
07771 printf("@@@@ Bad TX PL: %s\n", myrpt->rxpl);
07772 return -1;
07773 }
07774
07775
07776 switch(myrpt->offset)
07777 {
07778 case REM_MINUS:
07779 txoffset = 0;
07780 break;
07781 case REM_PLUS:
07782 txoffset = 0x10;
07783 break;
07784 case REM_SIMPLEX:
07785 txoffset = 0x20;
07786 break;
07787 }
07788 switch(myrpt->powerlevel)
07789 {
07790 case REM_LOWPWR:
07791 txpower = 0;
07792 break;
07793 case REM_MEDPWR:
07794 txpower = 0x20;
07795 break;
07796 case REM_HIPWR:
07797 txpower = 0x10;
07798 break;
07799 }
07800 rbicmd[0] = 0;
07801 rbicmd[1] = band | txpower | 0xc0;
07802 rbicmd[2] = (*(s - 2) - '0') | txoffset | 0x80;
07803 if (s[2] == '5') rbicmd[2] |= 0x40;
07804 rbicmd[3] = ((*s - '0') << 4) + (s[1] - '0');
07805 rbicmd[4] = rxpl;
07806 if (myrpt->txplon) rbicmd[4] |= 0x40;
07807 if (myrpt->rxplon) rbicmd[4] |= 0x80;
07808 rbi_out(myrpt,rbicmd);
07809 return 0;
07810 }
07811
07812 static int setrtx(struct rpt *myrpt)
07813 {
07814 char tmp[MAXREMSTR] = "",*s,rigstr[200],pwr,res = 0;
07815 int band,txoffset = 0,txpower = 0,rxpl,txpl;
07816 float ofac;
07817 double txfreq;
07818
07819
07820 if (!myrpt->remoterig) return(0);
07821 if (!myrpt->remoterig[0]) return(0);
07822
07823 if (!ISRIG_RTX(myrpt->remoterig)) return(0);
07824
07825 if (!IS_XPMR(myrpt)) return(0);
07826 strncpy(tmp, myrpt->freq, sizeof(tmp) - 1);
07827 s = strchr(tmp,'.');
07828
07829
07830 if(debug)printf("setrtx() %s %s\n",myrpt->name,myrpt->remoterig);
07831
07832 if (s == NULL){
07833 if(debug)
07834 printf("@@@@ Frequency needs a decimal\n");
07835 return -1;
07836 }
07837 *s++ = 0;
07838 if (strlen(tmp) < 2){
07839 if(debug)
07840 printf("@@@@ Bad MHz digits: %s\n", tmp);
07841 return -1;
07842 }
07843
07844 if (strlen(s) < 3){
07845 if(debug)
07846 printf("@@@@ Bad KHz digits: %s\n", s);
07847 return -1;
07848 }
07849
07850 if ((s[2] != '0') && (s[2] != '5')){
07851 if(debug)
07852 printf("@@@@ KHz must end in 0 or 5: %c\n", s[2]);
07853 return -1;
07854 }
07855
07856 band = rbi_mhztoband(tmp);
07857 if (band == -1){
07858 if(debug)
07859 printf("@@@@ Bad Band: %s\n", tmp);
07860 return -1;
07861 }
07862
07863 rxpl = rbi_pltocode(myrpt->rxpl);
07864
07865 if (rxpl == -1){
07866 if(debug)
07867 printf("@@@@ Bad RX PL: %s\n", myrpt->rxpl);
07868 return -1;
07869 }
07870
07871 txpl = rbi_pltocode(myrpt->txpl);
07872
07873 if (txpl == -1){
07874 if(debug)
07875 printf("@@@@ Bad TX PL: %s\n", myrpt->txpl);
07876 return -1;
07877 }
07878
07879 switch(myrpt->offset)
07880 {
07881 case REM_MINUS:
07882 txoffset = 0;
07883 break;
07884 case REM_PLUS:
07885 txoffset = 0x10;
07886 break;
07887 case REM_SIMPLEX:
07888 txoffset = 0x20;
07889 break;
07890 }
07891 switch(myrpt->powerlevel)
07892 {
07893 case REM_LOWPWR:
07894 txpower = 0;
07895 break;
07896 case REM_MEDPWR:
07897 txpower = 0x20;
07898 break;
07899 case REM_HIPWR:
07900 txpower = 0x10;
07901 break;
07902 }
07903
07904 res = setrtx_check(myrpt);
07905 if (res < 0) return res;
07906 ofac = 0.0;
07907 if (myrpt->offset == REM_MINUS) ofac = -1.0;
07908 if (myrpt->offset == REM_PLUS) ofac = 1.0;
07909
07910 if (!strcmp(myrpt->remoterig,remote_rig_rtx450))
07911 txfreq = atof(myrpt->freq) + (ofac * 5.0);
07912 else
07913 txfreq = atof(myrpt->freq) + (ofac * 0.6);
07914
07915 pwr = 'L';
07916 if (myrpt->powerlevel == REM_HIPWR) pwr = 'H';
07917 if (!res)
07918 {
07919 sprintf(rigstr,"SETFREQ %s %f %s %s %c",myrpt->freq,txfreq,
07920 (myrpt->rxplon) ? myrpt->rxpl : "0.0",
07921 (myrpt->txplon) ? myrpt->txpl : "0.0",pwr);
07922 send_usb_txt(myrpt,rigstr);
07923 rpt_telemetry(myrpt,COMPLETE,NULL);
07924 res = 0;
07925 }
07926 return 0;
07927 }
07928 #if 0
07929
07930
07931
07932
07933 static int setxpmr(struct rpt *myrpt)
07934 {
07935 char rigstr[200];
07936 int rxpl,txpl;
07937
07938
07939 if (!myrpt->remoterig) return(0);
07940 if (!myrpt->remoterig[0]) return(0);
07941
07942 if (ISRIG_RTX(myrpt->remoterig)) return(0);
07943
07944 if (!IS_XPMR(myrpt)) return(0);
07945
07946 if(debug)printf("setxpmr() %s %s\n",myrpt->name,myrpt->remoterig );
07947
07948 rxpl = rbi_pltocode(myrpt->rxpl);
07949
07950 if (rxpl == -1){
07951 if(debug)
07952 printf("@@@@ Bad RX PL: %s\n", myrpt->rxpl);
07953 return -1;
07954 }
07955
07956 txpl = rbi_pltocode(myrpt->txpl);
07957 if (txpl == -1){
07958 if(debug)
07959 printf("@@@@ Bad TX PL: %s\n", myrpt->txpl);
07960 return -1;
07961 }
07962 sprintf(rigstr,"SETFREQ 0.0 0.0 %s %s L",
07963 (myrpt->rxplon) ? myrpt->rxpl : "0.0",
07964 (myrpt->txplon) ? myrpt->txpl : "0.0");
07965 send_usb_txt(myrpt,rigstr);
07966 return 0;
07967 }
07968 #endif
07969
07970 static int setrbi_check(struct rpt *myrpt)
07971 {
07972 char tmp[MAXREMSTR] = "",*s;
07973 int band,txpl;
07974
07975
07976 if (!myrpt->remote) return(0);
07977
07978 if (strncmp(myrpt->remoterig,remote_rig_rbi,3)) return(0);
07979 strncpy(tmp, myrpt->freq, sizeof(tmp) - 1);
07980 s = strchr(tmp,'.');
07981
07982
07983 if (s == NULL){
07984 if(debug)
07985 printf("@@@@ Frequency needs a decimal\n");
07986 return -1;
07987 }
07988
07989 *s++ = 0;
07990 if (strlen(tmp) < 2){
07991 if(debug)
07992 printf("@@@@ Bad MHz digits: %s\n", tmp);
07993 return -1;
07994 }
07995
07996 if (strlen(s) < 3){
07997 if(debug)
07998 printf("@@@@ Bad KHz digits: %s\n", s);
07999 return -1;
08000 }
08001
08002 if ((s[2] != '0') && (s[2] != '5')){
08003 if(debug)
08004 printf("@@@@ KHz must end in 0 or 5: %c\n", s[2]);
08005 return -1;
08006 }
08007
08008 band = rbi_mhztoband(tmp);
08009 if (band == -1){
08010 if(debug)
08011 printf("@@@@ Bad Band: %s\n", tmp);
08012 return -1;
08013 }
08014
08015 txpl = rbi_pltocode(myrpt->txpl);
08016
08017 if (txpl == -1){
08018 if(debug)
08019 printf("@@@@ Bad TX PL: %s\n", myrpt->txpl);
08020 return -1;
08021 }
08022 return 0;
08023 }
08024
08025 static int setrtx_check(struct rpt *myrpt)
08026 {
08027 char tmp[MAXREMSTR] = "",*s;
08028 int band,txpl,rxpl;
08029
08030
08031 if (!myrpt->remote) return(0);
08032
08033 if (strncmp(myrpt->remoterig,remote_rig_rbi,3)) return(0);
08034 strncpy(tmp, myrpt->freq, sizeof(tmp) - 1);
08035 s = strchr(tmp,'.');
08036
08037
08038 if (s == NULL){
08039 if(debug)
08040 printf("@@@@ Frequency needs a decimal\n");
08041 return -1;
08042 }
08043
08044 *s++ = 0;
08045 if (strlen(tmp) < 2){
08046 if(debug)
08047 printf("@@@@ Bad MHz digits: %s\n", tmp);
08048 return -1;
08049 }
08050
08051 if (strlen(s) < 3){
08052 if(debug)
08053 printf("@@@@ Bad KHz digits: %s\n", s);
08054 return -1;
08055 }
08056
08057 if ((s[2] != '0') && (s[2] != '5')){
08058 if(debug)
08059 printf("@@@@ KHz must end in 0 or 5: %c\n", s[2]);
08060 return -1;
08061 }
08062
08063 band = rbi_mhztoband(tmp);
08064 if (band == -1){
08065 if(debug)
08066 printf("@@@@ Bad Band: %s\n", tmp);
08067 return -1;
08068 }
08069
08070 txpl = rbi_pltocode(myrpt->txpl);
08071
08072 if (txpl == -1){
08073 if(debug)
08074 printf("@@@@ Bad TX PL: %s\n", myrpt->txpl);
08075 return -1;
08076 }
08077
08078 rxpl = rbi_pltocode(myrpt->rxpl);
08079
08080 if (rxpl == -1){
08081 if(debug)
08082 printf("@@@@ Bad RX PL: %s\n", myrpt->rxpl);
08083 return -1;
08084 }
08085 return 0;
08086 }
08087
08088 static int check_freq_kenwood(int m, int d, int *defmode)
08089 {
08090 int dflmd = REM_MODE_FM;
08091
08092 if (m == 144){
08093 if(d < 10100)
08094 return -1;
08095 }
08096 else if((m >= 145) && (m < 148)){
08097 ;
08098 }
08099 else if((m >= 430) && (m < 450)){
08100 ;
08101 }
08102 else
08103 return -1;
08104
08105 if(defmode)
08106 *defmode = dflmd;
08107
08108
08109 return 0;
08110 }
08111
08112
08113 static int check_freq_tm271(int m, int d, int *defmode)
08114 {
08115 int dflmd = REM_MODE_FM;
08116
08117 if (m == 144){
08118 if(d < 10100)
08119 return -1;
08120 }
08121 else if((m >= 145) && (m < 148)){
08122 ;
08123 }
08124 return -1;
08125
08126 if(defmode)
08127 *defmode = dflmd;
08128
08129
08130 return 0;
08131 }
08132
08133
08134
08135
08136
08137 static int check_freq_rbi(int m, int d, int *defmode)
08138 {
08139 int dflmd = REM_MODE_FM;
08140
08141 if(m == 50){
08142 if(d < 10100)
08143 return -1;
08144 }
08145 else if((m >= 51) && ( m < 54)){
08146 ;
08147 }
08148 else if(m == 144){
08149 if(d < 10100)
08150 return -1;
08151 }
08152 else if((m >= 145) && (m < 148)){
08153 ;
08154 }
08155 else if((m >= 222) && (m < 225)){
08156 ;
08157 }
08158 else if((m >= 430) && (m < 450)){
08159 ;
08160 }
08161 else if((m >= 1240) && (m < 1300)){
08162 ;
08163 }
08164 else
08165 return -1;
08166
08167 if(defmode)
08168 *defmode = dflmd;
08169
08170
08171 return 0;
08172 }
08173
08174
08175
08176
08177 static int check_freq_rtx(int m, int d, int *defmode, struct rpt *myrpt)
08178 {
08179 int dflmd = REM_MODE_FM;
08180
08181 if (!strcmp(myrpt->remoterig,remote_rig_rtx150))
08182 {
08183
08184 if(m == 144){
08185 if(d < 10100)
08186 return -1;
08187 }
08188 else if((m >= 145) && (m < 148)){
08189 ;
08190 }
08191 else
08192 return -1;
08193 }
08194 else
08195 {
08196 if((m >= 430) && (m < 450)){
08197 ;
08198 }
08199 else
08200 return -1;
08201 }
08202 if(defmode)
08203 *defmode = dflmd;
08204
08205
08206 return 0;
08207 }
08208
08209
08210
08211
08212
08213 static int decimals2int(char *fraction)
08214 {
08215 int i;
08216 char len = strlen(fraction);
08217 int multiplier = 100000;
08218 int res = 0;
08219
08220 if(!len)
08221 return 0;
08222 for( i = 0 ; i < len ; i++, multiplier /= 10)
08223 res += (fraction[i] - '0') * multiplier;
08224 return res;
08225 }
08226
08227
08228
08229
08230
08231
08232 static int split_freq(char *mhz, char *decimals, char *freq)
08233 {
08234 char freq_copy[MAXREMSTR];
08235 char *decp;
08236
08237 decp = strchr(strncpy(freq_copy, freq, MAXREMSTR),'.');
08238 if(decp){
08239 *decp++ = 0;
08240 strncpy(mhz, freq_copy, MAXREMSTR);
08241 strcpy(decimals, "00000");
08242 strncpy(decimals, decp, strlen(decp));
08243 decimals[5] = 0;
08244 return 0;
08245 }
08246 else
08247 return -1;
08248
08249 }
08250
08251
08252
08253
08254
08255 static int split_ctcss_freq(char *hertz, char *decimal, char *freq)
08256 {
08257 char freq_copy[MAXREMSTR];
08258 char *decp;
08259
08260 decp = strchr(strncpy(freq_copy, freq, MAXREMSTR),'.');
08261 if(decp){
08262 *decp++ = 0;
08263 strncpy(hertz, freq_copy, MAXREMSTR);
08264 strncpy(decimal, decp, strlen(decp));
08265 decimal[strlen(decp)] = '\0';
08266 return 0;
08267 }
08268 else
08269 return -1;
08270 }
08271
08272
08273
08274
08275
08276
08277
08278
08279
08280
08281
08282 static int check_freq_ft897(int m, int d, int *defmode)
08283 {
08284 int dflmd = REM_MODE_FM;
08285
08286 if(m == 1){
08287 dflmd = REM_MODE_LSB;
08288 if(d < 80000)
08289 return -1;
08290 }
08291 else if(m == 3){
08292 dflmd = REM_MODE_LSB;
08293 if(d < 50000)
08294 return -1;
08295 }
08296 else if(m == 7){
08297 dflmd = REM_MODE_LSB;
08298 if(d > 30000)
08299 return -1;
08300 }
08301 else if(m == 14){
08302 dflmd = REM_MODE_USB;
08303 if(d > 35000)
08304 return -1;
08305 }
08306 else if(m == 18){
08307 dflmd = REM_MODE_USB;
08308 if((d < 6800) || (d > 16800))
08309 return -1;
08310 }
08311 else if(m == 21){
08312 dflmd = REM_MODE_USB;
08313 if((d < 20000) || (d > 45000))
08314 return -1;
08315 }
08316 else if(m == 24){
08317 dflmd = REM_MODE_USB;
08318 if((d < 89000) || (d > 99000))
08319 return -1;
08320 }
08321 else if(m == 28){
08322 dflmd = REM_MODE_USB;
08323 }
08324 else if(m == 29){
08325 if(d >= 51000)
08326 dflmd = REM_MODE_FM;
08327 else
08328 dflmd = REM_MODE_USB;
08329 if(d > 70000)
08330 return -1;
08331 }
08332 else if(m == 50){
08333 if(d >= 30000)
08334 dflmd = REM_MODE_FM;
08335 else
08336 dflmd = REM_MODE_USB;
08337
08338 }
08339 else if((m >= 51) && ( m < 54)){
08340 dflmd = REM_MODE_FM;
08341 }
08342 else if(m == 144){
08343 if(d >= 30000)
08344 dflmd = REM_MODE_FM;
08345 else
08346 dflmd = REM_MODE_USB;
08347 }
08348 else if((m >= 145) && (m < 148)){
08349 dflmd = REM_MODE_FM;
08350 }
08351 else if((m >= 430) && (m < 450)){
08352 if(m < 438)
08353 dflmd = REM_MODE_USB;
08354 else
08355 dflmd = REM_MODE_FM;
08356 ;
08357 }
08358 else
08359 return -1;
08360
08361 if(defmode)
08362 *defmode = dflmd;
08363
08364 return 0;
08365 }
08366
08367
08368
08369
08370
08371 static int set_freq_ft897(struct rpt *myrpt, char *newfreq)
08372 {
08373 unsigned char cmdstr[5];
08374 int fd,m,d;
08375 char mhz[MAXREMSTR];
08376 char decimals[MAXREMSTR];
08377
08378 fd = 0;
08379 if(debug)
08380 printf("New frequency: %s\n",newfreq);
08381
08382 if(split_freq(mhz, decimals, newfreq))
08383 return -1;
08384
08385 m = atoi(mhz);
08386 d = atoi(decimals);
08387
08388
08389
08390 cmdstr[0] = ((m / 100) << 4) + ((m % 100)/10);
08391 cmdstr[1] = ((m % 10) << 4) + (d / 10000);
08392 cmdstr[2] = (((d % 10000)/1000) << 4) + ((d % 1000)/ 100);
08393 cmdstr[3] = (((d % 100)/10) << 4) + (d % 10);
08394 cmdstr[4] = 0x01;
08395
08396 return serial_remote_io(myrpt, cmdstr, 5, NULL, 0, 0);
08397
08398 }
08399
08400
08401
08402 static int simple_command_ft897(struct rpt *myrpt, char command)
08403 {
08404 unsigned char cmdstr[5];
08405
08406 memset(cmdstr, 0, 5);
08407
08408 cmdstr[4] = command;
08409
08410 return serial_remote_io(myrpt, cmdstr, 5, NULL, 0, 0);
08411
08412 }
08413
08414
08415
08416 static int set_offset_ft897(struct rpt *myrpt, char offset)
08417 {
08418 unsigned char cmdstr[5];
08419
08420 memset(cmdstr, 0, 5);
08421
08422 switch(offset){
08423 case REM_SIMPLEX:
08424 cmdstr[0] = 0x89;
08425 break;
08426
08427 case REM_MINUS:
08428 cmdstr[0] = 0x09;
08429 break;
08430
08431 case REM_PLUS:
08432 cmdstr[0] = 0x49;
08433 break;
08434
08435 default:
08436 return -1;
08437 }
08438
08439 cmdstr[4] = 0x09;
08440
08441 return serial_remote_io(myrpt, cmdstr, 5, NULL, 0, 0);
08442 }
08443
08444
08445
08446 static int set_mode_ft897(struct rpt *myrpt, char newmode)
08447 {
08448 unsigned char cmdstr[5];
08449
08450 memset(cmdstr, 0, 5);
08451
08452 switch(newmode){
08453 case REM_MODE_FM:
08454 cmdstr[0] = 0x08;
08455 break;
08456
08457 case REM_MODE_USB:
08458 cmdstr[0] = 0x01;
08459 break;
08460
08461 case REM_MODE_LSB:
08462 cmdstr[0] = 0x00;
08463 break;
08464
08465 case REM_MODE_AM:
08466 cmdstr[0] = 0x04;
08467 break;
08468
08469 default:
08470 return -1;
08471 }
08472 cmdstr[4] = 0x07;
08473
08474 return serial_remote_io(myrpt, cmdstr, 5, NULL, 0, 0);
08475 }
08476
08477
08478
08479 static int set_ctcss_mode_ft897(struct rpt *myrpt, char txplon, char rxplon)
08480 {
08481 unsigned char cmdstr[5];
08482
08483 memset(cmdstr, 0, 5);
08484
08485 if(rxplon && txplon)
08486 cmdstr[0] = 0x2A;
08487 else if (!rxplon && txplon)
08488 cmdstr[0] = 0x4A;
08489 else if (rxplon && !txplon)
08490 cmdstr[0] = 0x3A;
08491 else
08492 cmdstr[0] = 0x8A;
08493
08494 cmdstr[4] = 0x0A;
08495
08496 return serial_remote_io(myrpt, cmdstr, 5, NULL, 0, 0);
08497 }
08498
08499
08500
08501
08502 static int set_ctcss_freq_ft897(struct rpt *myrpt, char *txtone, char *rxtone)
08503 {
08504 unsigned char cmdstr[5];
08505 char hertz[MAXREMSTR],decimal[MAXREMSTR];
08506 int h,d;
08507
08508 memset(cmdstr, 0, 5);
08509
08510 if(split_ctcss_freq(hertz, decimal, txtone))
08511 return -1;
08512
08513 h = atoi(hertz);
08514 d = atoi(decimal);
08515
08516 cmdstr[0] = ((h / 100) << 4) + (h % 100)/ 10;
08517 cmdstr[1] = ((h % 10) << 4) + (d % 10);
08518
08519 if(rxtone){
08520
08521 if(split_ctcss_freq(hertz, decimal, rxtone))
08522 return -1;
08523
08524 h = atoi(hertz);
08525 d = atoi(decimal);
08526
08527 cmdstr[2] = ((h / 100) << 4) + (h % 100)/ 10;
08528 cmdstr[3] = ((h % 10) << 4) + (d % 10);
08529 }
08530 cmdstr[4] = 0x0B;
08531
08532 return serial_remote_io(myrpt, cmdstr, 5, NULL, 0, 0);
08533 }
08534
08535
08536
08537 static int set_ft897(struct rpt *myrpt)
08538 {
08539 int res;
08540
08541 if(debug)
08542 printf("@@@@ lock on\n");
08543
08544 res = simple_command_ft897(myrpt, 0x00);
08545
08546 if(debug)
08547 printf("@@@@ ptt off\n");
08548
08549 if(!res)
08550 res = simple_command_ft897(myrpt, 0x88);
08551
08552 if(debug)
08553 printf("Modulation mode\n");
08554
08555 if(!res)
08556 res = set_mode_ft897(myrpt, myrpt->remmode);
08557
08558 if(debug)
08559 printf("Split off\n");
08560
08561 if(!res)
08562 simple_command_ft897(myrpt, 0x82);
08563
08564 if(debug)
08565 printf("Frequency\n");
08566
08567 if(!res)
08568 res = set_freq_ft897(myrpt, myrpt->freq);
08569 if((myrpt->remmode == REM_MODE_FM)){
08570 if(debug)
08571 printf("Offset\n");
08572 if(!res)
08573 res = set_offset_ft897(myrpt, myrpt->offset);
08574 if((!res)&&(myrpt->rxplon || myrpt->txplon)){
08575 if(debug)
08576 printf("CTCSS tone freqs.\n");
08577 res = set_ctcss_freq_ft897(myrpt, myrpt->txpl, myrpt->rxpl);
08578 }
08579 if(!res){
08580 if(debug)
08581 printf("CTCSS mode\n");
08582 res = set_ctcss_mode_ft897(myrpt, myrpt->txplon, myrpt->rxplon);
08583 }
08584 }
08585 if((myrpt->remmode == REM_MODE_USB)||(myrpt->remmode == REM_MODE_LSB)){
08586 if(debug)
08587 printf("Clarifier off\n");
08588 simple_command_ft897(myrpt, 0x85);
08589 }
08590 return res;
08591 }
08592
08593 static int closerem_ft897(struct rpt *myrpt)
08594 {
08595 simple_command_ft897(myrpt, 0x88);
08596 return 0;
08597 }
08598
08599
08600
08601
08602
08603
08604
08605 static int multimode_bump_freq_ft897(struct rpt *myrpt, int interval)
08606 {
08607 int m,d;
08608 char mhz[MAXREMSTR], decimals[MAXREMSTR];
08609
08610 if(debug)
08611 printf("Before bump: %s\n", myrpt->freq);
08612
08613 if(split_freq(mhz, decimals, myrpt->freq))
08614 return -1;
08615
08616 m = atoi(mhz);
08617 d = atoi(decimals);
08618
08619 d += (interval / 10);
08620 if(d < 0){
08621 m--;
08622 d += 100000;
08623 }
08624 else if(d >= 100000){
08625 m++;
08626 d -= 100000;
08627 }
08628
08629 if(check_freq_ft897(m, d, NULL)){
08630 if(debug)
08631 printf("Bump freq invalid\n");
08632 return -1;
08633 }
08634
08635 snprintf(myrpt->freq, MAXREMSTR, "%d.%05d", m, d);
08636
08637 if(debug)
08638 printf("After bump: %s\n", myrpt->freq);
08639
08640 return set_freq_ft897(myrpt, myrpt->freq);
08641 }
08642
08643
08644
08645
08646
08647
08648
08649
08650
08651
08652 static int check_freq_ic706(int m, int d, int *defmode, char mars)
08653 {
08654 int dflmd = REM_MODE_FM;
08655 int rv=0;
08656
08657 if(debug > 6)
08658 ast_log(LOG_NOTICE,"(%i,%i,%i,%i)\n",m,d,*defmode,mars);
08659
08660
08661
08662 if(m == 1){
08663 dflmd = REM_MODE_LSB;
08664 if(d < 80000)rv=-1;
08665 }
08666 else if(m == 3){
08667 dflmd = REM_MODE_LSB;
08668 if(d < 50000)rv=-1;
08669 }
08670 else if(m == 7){
08671 dflmd = REM_MODE_LSB;
08672 if(d > 30000)rv=-1;
08673 }
08674 else if(m == 14){
08675 dflmd = REM_MODE_USB;
08676 if(d > 35000)rv=-1;
08677 }
08678 else if(m == 18){
08679 dflmd = REM_MODE_USB;
08680 if((d < 6800) || (d > 16800))rv=-1;
08681 }
08682 else if(m == 21){
08683 dflmd = REM_MODE_USB;
08684 if((d < 20000) || (d > 45000))rv=-1;
08685 }
08686 else if(m == 24){
08687 dflmd = REM_MODE_USB;
08688 if((d < 89000) || (d > 99000))rv=-1;
08689 }
08690 else if(m == 28){
08691 dflmd = REM_MODE_USB;
08692 }
08693 else if(m == 29){
08694 if(d >= 51000)
08695 dflmd = REM_MODE_FM;
08696 else
08697 dflmd = REM_MODE_USB;
08698 if(d > 70000)rv=-1;
08699 }
08700 else if(m == 50){
08701 if(d >= 30000)
08702 dflmd = REM_MODE_FM;
08703 else
08704 dflmd = REM_MODE_USB;
08705 }
08706 else if((m >= 51) && ( m < 54)){
08707 dflmd = REM_MODE_FM;
08708 }
08709 else if(m == 144){
08710 if(d >= 30000)
08711 dflmd = REM_MODE_FM;
08712 else
08713 dflmd = REM_MODE_USB;
08714 }
08715 else if((m >= 145) && (m < 148)){
08716 dflmd = REM_MODE_FM;
08717 }
08718 else if((m >= 430) && (m < 450)){
08719 if(m < 438)
08720 dflmd = REM_MODE_USB;
08721 else
08722 dflmd = REM_MODE_FM;
08723 }
08724
08725
08726 if(mars && rv<0){
08727 if((m >= 450) && (m < 470)){
08728 dflmd = REM_MODE_FM;
08729 rv=0;
08730 }
08731 else if((m >= 148) && (m < 174)){
08732 dflmd = REM_MODE_FM;
08733 rv=0;
08734 }
08735 else if((m >= 138) && (m < 144)){
08736 dflmd = REM_MODE_AM;
08737 rv=0;
08738 }
08739 else if((m >= 108) && (m < 138)){
08740 dflmd = REM_MODE_AM;
08741 rv=0;
08742 }
08743 else if( (m==0 && d>=55000) || (m==1 && d<=75000) ){
08744 dflmd = REM_MODE_AM;
08745 rv=0;
08746 }
08747 else if( (m == 1 && d>75000) || (m>1 && m<30) ){
08748 dflmd = REM_MODE_AM;
08749 rv=0;
08750 }
08751 }
08752
08753 if(defmode)
08754 *defmode = dflmd;
08755
08756 if(debug > 1)
08757 ast_log(LOG_NOTICE,"(%i,%i,%i,%i) returning %i\n",m,d,*defmode,mars,rv);
08758
08759 return rv;
08760 }
08761
08762
08763 static int ic706_pltocode(char *str)
08764 {
08765 int i;
08766 char *s;
08767 int rv=-1;
08768
08769 s = strchr(str,'.');
08770 i = 0;
08771 if (s) i = atoi(s + 1);
08772 i += atoi(str) * 10;
08773 switch(i)
08774 {
08775 case 670:
08776 rv=0;
08777 case 693:
08778 rv=1;
08779 case 719:
08780 rv=2;
08781 case 744:
08782 rv=3;
08783 case 770:
08784 rv=4;
08785 case 797:
08786 rv=5;
08787 case 825:
08788 rv=6;
08789 case 854:
08790 rv=7;
08791 case 885:
08792 rv=8;
08793 case 915:
08794 rv=9;
08795 case 948:
08796 rv=10;
08797 case 974:
08798 rv=11;
08799 case 1000:
08800 rv=12;
08801 case 1035:
08802 rv=13;
08803 case 1072:
08804 rv=14;
08805 case 1109:
08806 rv=15;
08807 case 1148:
08808 rv=16;
08809 case 1188:
08810 rv=17;
08811 case 1230:
08812 rv=18;
08813 case 1273:
08814 rv=19;
08815 case 1318:
08816 rv=20;
08817 case 1365:
08818 rv=21;
08819 case 1413:
08820 rv=22;
08821 case 1462:
08822 rv=23;
08823 case 1514:
08824 rv=24;
08825 case 1567:
08826 rv=25;
08827 case 1598:
08828 rv=26;
08829 case 1622:
08830 rv=27;
08831 case 1655:
08832 rv=28;
08833 case 1679:
08834 rv=29;
08835 case 1713:
08836 rv=30;
08837 case 1738:
08838 rv=31;
08839 case 1773:
08840 rv=32;
08841 case 1799:
08842 rv=33;
08843 case 1835:
08844 rv=34;
08845 case 1862:
08846 rv=35;
08847 case 1899:
08848 rv=36;
08849 case 1928:
08850 rv=37;
08851 case 1966:
08852 rv=38;
08853 case 1995:
08854 rv=39;
08855 case 2035:
08856 rv=40;
08857 case 2065:
08858 rv=41;
08859 case 2107:
08860 rv=42;
08861 case 2181:
08862 rv=43;
08863 case 2257:
08864 rv=44;
08865 case 2291:
08866 rv=45;
08867 case 2336:
08868 rv=46;
08869 case 2418:
08870 rv=47;
08871 case 2503:
08872 rv=48;
08873 case 2541:
08874 rv=49;
08875 }
08876 if(debug > 1)
08877 ast_log(LOG_NOTICE,"%i rv=%i\n",i, rv);
08878
08879 return rv;
08880 }
08881
08882
08883
08884 static int simple_command_ic706(struct rpt *myrpt, char command, char subcommand)
08885 {
08886 unsigned char cmdstr[10];
08887
08888 cmdstr[0] = cmdstr[1] = 0xfe;
08889 cmdstr[2] = myrpt->p.civaddr;
08890 cmdstr[3] = 0xe0;
08891 cmdstr[4] = command;
08892 cmdstr[5] = subcommand;
08893 cmdstr[6] = 0xfd;
08894
08895 return(civ_cmd(myrpt,cmdstr,7));
08896 }
08897
08898
08899
08900
08901
08902 static int set_freq_ic706(struct rpt *myrpt, char *newfreq)
08903 {
08904 unsigned char cmdstr[20];
08905 char mhz[MAXREMSTR], decimals[MAXREMSTR];
08906 int fd,m,d;
08907
08908 fd = 0;
08909 if(debug)
08910 ast_log(LOG_NOTICE,"newfreq:%s\n",newfreq);
08911
08912 if(split_freq(mhz, decimals, newfreq))
08913 return -1;
08914
08915 m = atoi(mhz);
08916 d = atoi(decimals);
08917
08918
08919
08920 cmdstr[0] = cmdstr[1] = 0xfe;
08921 cmdstr[2] = myrpt->p.civaddr;
08922 cmdstr[3] = 0xe0;
08923 cmdstr[4] = 5;
08924 cmdstr[5] = ((d % 10) << 4);
08925 cmdstr[6] = (((d % 1000)/ 100) << 4) + ((d % 100)/10);
08926 cmdstr[7] = ((d / 10000) << 4) + ((d % 10000)/1000);
08927 cmdstr[8] = (((m % 100)/10) << 4) + (m % 10);
08928 cmdstr[9] = (m / 100);
08929 cmdstr[10] = 0xfd;
08930
08931 return(civ_cmd(myrpt,cmdstr,11));
08932 }
08933
08934
08935
08936 static int set_offset_ic706(struct rpt *myrpt, char offset)
08937 {
08938 unsigned char c;
08939
08940 if(debug > 6)
08941 ast_log(LOG_NOTICE,"offset=%i\n",offset);
08942
08943 switch(offset){
08944 case REM_SIMPLEX:
08945 c = 0x10;
08946 break;
08947
08948 case REM_MINUS:
08949 c = 0x11;
08950 break;
08951
08952 case REM_PLUS:
08953 c = 0x12;
08954 break;
08955
08956 default:
08957 return -1;
08958 }
08959
08960 return simple_command_ic706(myrpt,0x0f,c);
08961
08962 }
08963
08964
08965
08966 static int set_mode_ic706(struct rpt *myrpt, char newmode)
08967 {
08968 unsigned char c;
08969
08970 if(debug > 6)
08971 ast_log(LOG_NOTICE,"newmode=%i\n",newmode);
08972
08973 switch(newmode){
08974 case REM_MODE_FM:
08975 c = 5;
08976 break;
08977
08978 case REM_MODE_USB:
08979 c = 1;
08980 break;
08981
08982 case REM_MODE_LSB:
08983 c = 0;
08984 break;
08985
08986 case REM_MODE_AM:
08987 c = 2;
08988 break;
08989
08990 default:
08991 return -1;
08992 }
08993 return simple_command_ic706(myrpt,6,c);
08994 }
08995
08996
08997
08998 static int set_ctcss_mode_ic706(struct rpt *myrpt, char txplon, char rxplon)
08999 {
09000 unsigned char cmdstr[10];
09001 int rv;
09002
09003 if(debug > 6)
09004 ast_log(LOG_NOTICE,"txplon=%i rxplon=%i \n",txplon,rxplon);
09005
09006 cmdstr[0] = cmdstr[1] = 0xfe;
09007 cmdstr[2] = myrpt->p.civaddr;
09008 cmdstr[3] = 0xe0;
09009 cmdstr[4] = 0x16;
09010 cmdstr[5] = 0x42;
09011 cmdstr[6] = (txplon != 0);
09012 cmdstr[7] = 0xfd;
09013
09014 rv = civ_cmd(myrpt,cmdstr,8);
09015 if (rv) return(-1);
09016
09017 cmdstr[0] = cmdstr[1] = 0xfe;
09018 cmdstr[2] = myrpt->p.civaddr;
09019 cmdstr[3] = 0xe0;
09020 cmdstr[4] = 0x16;
09021 cmdstr[5] = 0x43;
09022 cmdstr[6] = (rxplon != 0);
09023 cmdstr[7] = 0xfd;
09024
09025 return(civ_cmd(myrpt,cmdstr,8));
09026 }
09027
09028 #if 0
09029
09030
09031 static int set_ctcss_freq_ic706(struct rpt *myrpt, char *txtone, char *rxtone)
09032 {
09033 unsigned char cmdstr[10];
09034 char hertz[MAXREMSTR],decimal[MAXREMSTR];
09035 int h,d,rv;
09036
09037 memset(cmdstr, 0, 5);
09038
09039 if(debug > 6)
09040 ast_log(LOG_NOTICE,"txtone=%s rxtone=%s \n",txtone,rxtone);
09041
09042 if(split_ctcss_freq(hertz, decimal, txtone))
09043 return -1;
09044
09045 h = atoi(hertz);
09046 d = atoi(decimal);
09047
09048 cmdstr[0] = cmdstr[1] = 0xfe;
09049 cmdstr[2] = myrpt->p.civaddr;
09050 cmdstr[3] = 0xe0;
09051 cmdstr[4] = 0x1b;
09052 cmdstr[5] = 0;
09053 cmdstr[6] = ((h / 100) << 4) + (h % 100)/ 10;
09054 cmdstr[7] = ((h % 10) << 4) + (d % 10);
09055 cmdstr[8] = 0xfd;
09056
09057 rv = civ_cmd(myrpt,cmdstr,9);
09058 if (rv) return(-1);
09059
09060 if (!rxtone) return(0);
09061
09062 if(split_ctcss_freq(hertz, decimal, rxtone))
09063 return -1;
09064
09065 h = atoi(hertz);
09066 d = atoi(decimal);
09067
09068 cmdstr[0] = cmdstr[1] = 0xfe;
09069 cmdstr[2] = myrpt->p.civaddr;
09070 cmdstr[3] = 0xe0;
09071 cmdstr[4] = 0x1b;
09072 cmdstr[5] = 1;
09073 cmdstr[6] = ((h / 100) << 4) + (h % 100)/ 10;
09074 cmdstr[7] = ((h % 10) << 4) + (d % 10);
09075 cmdstr[8] = 0xfd;
09076 return(civ_cmd(myrpt,cmdstr,9));
09077 }
09078 #endif
09079
09080 static int vfo_ic706(struct rpt *myrpt)
09081 {
09082 unsigned char cmdstr[10];
09083
09084 cmdstr[0] = cmdstr[1] = 0xfe;
09085 cmdstr[2] = myrpt->p.civaddr;
09086 cmdstr[3] = 0xe0;
09087 cmdstr[4] = 7;
09088 cmdstr[5] = 0xfd;
09089
09090 return(civ_cmd(myrpt,cmdstr,6));
09091 }
09092
09093 static int mem2vfo_ic706(struct rpt *myrpt)
09094 {
09095 unsigned char cmdstr[10];
09096
09097 cmdstr[0] = cmdstr[1] = 0xfe;
09098 cmdstr[2] = myrpt->p.civaddr;
09099 cmdstr[3] = 0xe0;
09100 cmdstr[4] = 0x0a;
09101 cmdstr[5] = 0xfd;
09102
09103 return(civ_cmd(myrpt,cmdstr,6));
09104 }
09105
09106 static int select_mem_ic706(struct rpt *myrpt, int slot)
09107 {
09108 unsigned char cmdstr[10];
09109
09110 cmdstr[0] = cmdstr[1] = 0xfe;
09111 cmdstr[2] = myrpt->p.civaddr;
09112 cmdstr[3] = 0xe0;
09113 cmdstr[4] = 8;
09114 cmdstr[5] = 0;
09115 cmdstr[6] = ((slot / 10) << 4) + (slot % 10);
09116 cmdstr[7] = 0xfd;
09117
09118 return(civ_cmd(myrpt,cmdstr,8));
09119 }
09120
09121 static int set_ic706(struct rpt *myrpt)
09122 {
09123 int res = 0,i;
09124
09125 if(debug)ast_log(LOG_NOTICE, "Set to VFO A iobase=%i\n",myrpt->p.iobase);
09126
09127 if (!res)
09128 res = simple_command_ic706(myrpt,7,0);
09129
09130 if((myrpt->remmode == REM_MODE_FM))
09131 {
09132 i = ic706_pltocode(myrpt->rxpl);
09133 if (i == -1) return -1;
09134 if(debug)
09135 printf("Select memory number\n");
09136 if (!res)
09137 res = select_mem_ic706(myrpt,i + IC706_PL_MEMORY_OFFSET);
09138 if(debug)
09139 printf("Transfer memory to VFO\n");
09140 if (!res)
09141 res = mem2vfo_ic706(myrpt);
09142 }
09143
09144 if(debug)
09145 printf("Set to VFO\n");
09146
09147 if (!res)
09148 res = vfo_ic706(myrpt);
09149
09150 if(debug)
09151 printf("Modulation mode\n");
09152
09153 if (!res)
09154 res = set_mode_ic706(myrpt, myrpt->remmode);
09155
09156 if(debug)
09157 printf("Split off\n");
09158
09159 if(!res)
09160 simple_command_ic706(myrpt, 0x82,0);
09161
09162 if(debug)
09163 printf("Frequency\n");
09164
09165 if(!res)
09166 res = set_freq_ic706(myrpt, myrpt->freq);
09167 if((myrpt->remmode == REM_MODE_FM)){
09168 if(debug)
09169 printf("Offset\n");
09170 if(!res)
09171 res = set_offset_ic706(myrpt, myrpt->offset);
09172 if(!res){
09173 if(debug)
09174 printf("CTCSS mode\n");
09175 res = set_ctcss_mode_ic706(myrpt, myrpt->txplon, myrpt->rxplon);
09176 }
09177 }
09178 return res;
09179 }
09180
09181
09182
09183
09184
09185
09186
09187 static int multimode_bump_freq_ic706(struct rpt *myrpt, int interval)
09188 {
09189 int m,d;
09190 char mhz[MAXREMSTR], decimals[MAXREMSTR];
09191 unsigned char cmdstr[20];
09192
09193 if(debug)
09194 printf("Before bump: %s\n", myrpt->freq);
09195
09196 if(split_freq(mhz, decimals, myrpt->freq))
09197 return -1;
09198
09199 m = atoi(mhz);
09200 d = atoi(decimals);
09201
09202 d += (interval / 10);
09203 if(d < 0){
09204 m--;
09205 d += 100000;
09206 }
09207 else if(d >= 100000){
09208 m++;
09209 d -= 100000;
09210 }
09211
09212 if(check_freq_ic706(m, d, NULL,myrpt->p.remote_mars)){
09213 if(debug)
09214 printf("Bump freq invalid\n");
09215 return -1;
09216 }
09217
09218 snprintf(myrpt->freq, MAXREMSTR, "%d.%05d", m, d);
09219
09220 if(debug)
09221 printf("After bump: %s\n", myrpt->freq);
09222
09223
09224
09225 cmdstr[0] = cmdstr[1] = 0xfe;
09226 cmdstr[2] = myrpt->p.civaddr;
09227 cmdstr[3] = 0xe0;
09228 cmdstr[4] = 0;
09229 cmdstr[5] = ((d % 10) << 4);
09230 cmdstr[6] = (((d % 1000)/ 100) << 4) + ((d % 100)/10);
09231 cmdstr[7] = ((d / 10000) << 4) + ((d % 10000)/1000);
09232 cmdstr[8] = (((m % 100)/10) << 4) + (m % 10);
09233 cmdstr[9] = (m / 100);
09234 cmdstr[10] = 0xfd;
09235
09236 return(serial_remote_io(myrpt,cmdstr,11,NULL,0,0));
09237 }
09238
09239
09240
09241
09242
09243
09244 static int setrem(struct rpt *myrpt)
09245 {
09246 char str[300];
09247 char *offsets[] = {"SIMPLEX","MINUS","PLUS"};
09248 char *powerlevels[] = {"LOW","MEDIUM","HIGH"};
09249 char *modes[] = {"FM","USB","LSB","AM"};
09250 int res = -1;
09251
09252 #if 0
09253 printf("FREQ,%s,%s,%s,%s,%s,%s,%d,%d\n",myrpt->freq,
09254 modes[(int)myrpt->remmode],
09255 myrpt->txpl,myrpt->rxpl,offsets[(int)myrpt->offset],
09256 powerlevels[(int)myrpt->powerlevel],myrpt->txplon,
09257 myrpt->rxplon);
09258 #endif
09259 if (myrpt->p.archivedir)
09260 {
09261 sprintf(str,"FREQ,%s,%s,%s,%s,%s,%s,%d,%d",myrpt->freq,
09262 modes[(int)myrpt->remmode],
09263 myrpt->txpl,myrpt->rxpl,offsets[(int)myrpt->offset],
09264 powerlevels[(int)myrpt->powerlevel],myrpt->txplon,
09265 myrpt->rxplon);
09266 donodelog(myrpt,str);
09267 }
09268 if(!strcmp(myrpt->remoterig, remote_rig_ft897))
09269 {
09270 rpt_telemetry(myrpt,SETREMOTE,NULL);
09271 res = 0;
09272 }
09273 if(!strcmp(myrpt->remoterig, remote_rig_ic706))
09274 {
09275 rpt_telemetry(myrpt,SETREMOTE,NULL);
09276 res = 0;
09277 }
09278 if(!strcmp(myrpt->remoterig, remote_rig_tm271))
09279 {
09280 rpt_telemetry(myrpt,SETREMOTE,NULL);
09281 res = 0;
09282 }
09283 else if(!strcmp(myrpt->remoterig, remote_rig_rbi))
09284 {
09285 res = setrbi_check(myrpt);
09286 if (!res)
09287 {
09288 rpt_telemetry(myrpt,SETREMOTE,NULL);
09289 res = 0;
09290 }
09291 }
09292 else if(ISRIG_RTX(myrpt->remoterig))
09293 {
09294 setrtx(myrpt);
09295 res = 0;
09296 }
09297 else if(!strcmp(myrpt->remoterig, remote_rig_kenwood)) {
09298 rpt_telemetry(myrpt,SETREMOTE,NULL);
09299 res = 0;
09300 }
09301 else
09302 res = 0;
09303
09304 if (res < 0) ast_log(LOG_ERROR,"Unable to send remote command on node %s\n",myrpt->name);
09305
09306 return res;
09307 }
09308
09309 static int closerem(struct rpt *myrpt)
09310 {
09311 if(!strcmp(myrpt->remoterig, remote_rig_ft897))
09312 return closerem_ft897(myrpt);
09313 else
09314 return 0;
09315 }
09316
09317
09318
09319
09320
09321 static int check_freq(struct rpt *myrpt, int m, int d, int *defmode)
09322 {
09323 if(!strcmp(myrpt->remoterig, remote_rig_ft897))
09324 return check_freq_ft897(m, d, defmode);
09325 else if(!strcmp(myrpt->remoterig, remote_rig_ic706))
09326 return check_freq_ic706(m, d, defmode,myrpt->p.remote_mars);
09327 else if(!strcmp(myrpt->remoterig, remote_rig_rbi))
09328 return check_freq_rbi(m, d, defmode);
09329 else if(!strcmp(myrpt->remoterig, remote_rig_kenwood))
09330 return check_freq_kenwood(m, d, defmode);
09331 else if(!strcmp(myrpt->remoterig, remote_rig_tm271))
09332 return check_freq_tm271(m, d, defmode);
09333 else if(ISRIG_RTX(myrpt->remoterig))
09334 return check_freq_rtx(m, d, defmode, myrpt);
09335 else
09336 return -1;
09337 }
09338
09339
09340
09341
09342
09343
09344 static char check_tx_freq(struct rpt *myrpt)
09345 {
09346 int i,rv=0;
09347 int radio_mhz, radio_decimals, ulimit_mhz, ulimit_decimals, llimit_mhz, llimit_decimals;
09348 char radio_mhz_char[MAXREMSTR];
09349 char radio_decimals_char[MAXREMSTR];
09350 char limit_mhz_char[MAXREMSTR];
09351 char limit_decimals_char[MAXREMSTR];
09352 char limits[256];
09353 char *limit_ranges[40];
09354 struct ast_variable *limitlist;
09355
09356 if(debug > 3){
09357 ast_log(LOG_NOTICE, "myrpt->freq = %s\n", myrpt->freq);
09358 }
09359
09360
09361
09362 if(!myrpt->p.txlimitsstanzaname || !myrpt->loginuser[0] || !myrpt->loginlevel[0]){
09363 if(debug > 3){
09364 ast_log(LOG_NOTICE, "No tx band table defined, or no user logged in. rv=1\n");
09365 }
09366 rv=1;
09367 return 1;
09368 }
09369
09370
09371 limitlist = ast_variable_browse(myrpt->cfg, myrpt->p.txlimitsstanzaname);
09372
09373 if(!limitlist){
09374 ast_log(LOG_WARNING, "No entries in %s band table stanza. rv=0\n", myrpt->p.txlimitsstanzaname);
09375 rv=0;
09376 return 0;
09377 }
09378
09379 split_freq(radio_mhz_char, radio_decimals_char, myrpt->freq);
09380 radio_mhz = atoi(radio_mhz_char);
09381 radio_decimals = decimals2int(radio_decimals_char);
09382
09383 if(debug > 3){
09384 ast_log(LOG_NOTICE, "Login User = %s, login level = %s\n", myrpt->loginuser, myrpt->loginlevel);
09385 }
09386
09387
09388
09389 for(;limitlist; limitlist=limitlist->next){
09390 if(!strcmp(limitlist->name, myrpt->loginlevel))
09391 break;
09392 }
09393
09394 if(!limitlist){
09395 ast_log(LOG_WARNING, "Can't find %s entry in band table stanza %s. rv=0\n", myrpt->loginlevel, myrpt->p.txlimitsstanzaname);
09396 rv=0;
09397 return 0;
09398 }
09399
09400 if(debug > 3){
09401 ast_log(LOG_NOTICE, "Auth: %s = %s\n", limitlist->name, limitlist->value);
09402 }
09403
09404
09405
09406 strncpy(limits, limitlist->value, 256);
09407 limits[255] = 0;
09408 finddelim(limits, limit_ranges, 40);
09409 for(i = 0; i < 40 && limit_ranges[i] ; i++){
09410 char range[40];
09411 char *r,*s;
09412 strncpy(range, limit_ranges[i], 40);
09413 range[39] = 0;
09414 if(debug > 3)
09415 ast_log(LOG_NOTICE, "Check %s within %s\n", myrpt->freq, range);
09416
09417 r = strchr(range, '-');
09418 if(!r){
09419 ast_log(LOG_WARNING, "Malformed range in %s tx band table entry. rv=0\n", limitlist->name);
09420 rv=0;
09421 break;
09422 }
09423 *r++ = 0;
09424 s = eatwhite(range);
09425 r = eatwhite(r);
09426 split_freq(limit_mhz_char, limit_decimals_char, s);
09427 llimit_mhz = atoi(limit_mhz_char);
09428 llimit_decimals = decimals2int(limit_decimals_char);
09429 split_freq(limit_mhz_char, limit_decimals_char, r);
09430 ulimit_mhz = atoi(limit_mhz_char);
09431 ulimit_decimals = decimals2int(limit_decimals_char);
09432
09433 if((radio_mhz >= llimit_mhz) && (radio_mhz <= ulimit_mhz)){
09434 if(radio_mhz == llimit_mhz){
09435 if(radio_decimals >= llimit_decimals){
09436 if(llimit_mhz == ulimit_mhz){
09437 if(radio_decimals <= ulimit_decimals){
09438 rv=1;
09439 break;
09440 }
09441 else{
09442 if(debug > 3)
09443 ast_log(LOG_NOTICE, "Invalid TX frequency, debug msg 1\n");
09444 rv=0;
09445 break;
09446 }
09447 }
09448 else{
09449 rv=1;
09450 break;
09451 }
09452 }
09453 else{
09454 if(debug > 3)
09455 ast_log(LOG_NOTICE, "Invalid TX frequency, debug msg 2\n");
09456 rv=0;
09457 break;
09458 }
09459 }
09460 else if(radio_mhz == ulimit_mhz){
09461 if(radio_decimals <= ulimit_decimals){
09462 if(debug > 3)
09463 ast_log(LOG_NOTICE, "radio_decimals <= ulimit_decimals\n");
09464 rv=1;
09465 break;
09466 }
09467 else{
09468 if(debug > 3)
09469 ast_log(LOG_NOTICE, "Invalid TX frequency, debug msg 3\n");
09470 rv=0;
09471 break;
09472 }
09473 }
09474 else
09475 if(debug > 3)
09476 ast_log(LOG_NOTICE, "Valid TX freq within a multi-Mhz band and ok.\n");
09477 rv=1;
09478 break;
09479 }
09480 }
09481 if(debug > 3)
09482 ast_log(LOG_NOTICE, "rv=%i\n",rv);
09483
09484 return rv;
09485 }
09486
09487
09488
09489
09490
09491
09492 static int multimode_bump_freq(struct rpt *myrpt, int interval)
09493 {
09494 if(!strcmp(myrpt->remoterig, remote_rig_ft897))
09495 return multimode_bump_freq_ft897(myrpt, interval);
09496 else if(!strcmp(myrpt->remoterig, remote_rig_ic706))
09497 return multimode_bump_freq_ic706(myrpt, interval);
09498 else
09499 return -1;
09500 }
09501
09502
09503
09504
09505
09506
09507 static void stop_scan(struct rpt *myrpt)
09508 {
09509 myrpt->hfscanstop = 1;
09510 rpt_telemetry(myrpt,SCAN,0);
09511 }
09512
09513
09514
09515
09516
09517
09518 static int service_scan(struct rpt *myrpt)
09519 {
09520 int res, interval;
09521 char mhz[MAXREMSTR], decimals[MAXREMSTR], k10=0i, k100=0;
09522
09523 switch(myrpt->hfscanmode){
09524
09525 case HF_SCAN_DOWN_SLOW:
09526 interval = -10;
09527 break;
09528
09529 case HF_SCAN_DOWN_QUICK:
09530 interval = -50;
09531 break;
09532
09533 case HF_SCAN_DOWN_FAST:
09534 interval = -200;
09535 break;
09536
09537 case HF_SCAN_UP_SLOW:
09538 interval = 10;
09539 break;
09540
09541 case HF_SCAN_UP_QUICK:
09542 interval = 50;
09543 break;
09544
09545 case HF_SCAN_UP_FAST:
09546 interval = 200;
09547 break;
09548
09549 default:
09550 myrpt->hfscanmode = 0;
09551 return -1;
09552 }
09553
09554 res = split_freq(mhz, decimals, myrpt->freq);
09555
09556 if(!res){
09557 k100 =decimals[0];
09558 k10 = decimals[1];
09559 res = multimode_bump_freq(myrpt, interval);
09560 }
09561
09562 if(!res)
09563 res = split_freq(mhz, decimals, myrpt->freq);
09564
09565
09566 if(res){
09567 myrpt->hfscanmode = 0;
09568 myrpt->hfscanstatus = -2;
09569 return -1;
09570 }
09571
09572
09573 if(k10 != decimals[1]){
09574 int myhund = (interval < 0) ? k100 : decimals[0];
09575 int myten = (interval < 0) ? k10 : decimals[1];
09576 myrpt->hfscanstatus = (myten == '0') ? (myhund - '0') * 100 : (myten - '0') * 10;
09577 } else myrpt->hfscanstatus = 0;
09578 return res;
09579
09580 }
09581
09582
09583
09584 static int get_mem_set(struct rpt *myrpt, char *digitbuf)
09585 {
09586 int res=0;
09587 if(debug)ast_log(LOG_NOTICE," digitbuf=%s\n", digitbuf);
09588 res = retreive_memory(myrpt, digitbuf);
09589 if(!res)res=setrem(myrpt);
09590 if(debug)ast_log(LOG_NOTICE," freq=%s res=%i\n", myrpt->freq, res);
09591 return res;
09592 }
09593
09594
09595
09596
09597 static int channel_steer(struct rpt *myrpt, char *data)
09598 {
09599 int res=0;
09600
09601 if(debug)ast_log(LOG_NOTICE,"remoterig=%s, data=%s\n",myrpt->remoterig,data);
09602 if (!myrpt->remoterig) return(0);
09603 if(data<=0)
09604 {
09605 res=-1;
09606 }
09607 else
09608 {
09609 myrpt->nowchan=strtod(data,NULL);
09610 if(!strcmp(myrpt->remoterig, remote_rig_ppp16))
09611 {
09612 char string[16];
09613 sprintf(string,"SETCHAN %d ",myrpt->nowchan);
09614 send_usb_txt(myrpt,string);
09615 }
09616 else
09617 {
09618 if(get_mem_set(myrpt, data))res=-1;
09619 }
09620 }
09621 if(debug)ast_log(LOG_NOTICE,"nowchan=%i res=%i\n",myrpt->nowchan, res);
09622 return res;
09623 }
09624
09625
09626 static int channel_revert(struct rpt *myrpt)
09627 {
09628 int res=0;
09629 if(debug)ast_log(LOG_NOTICE,"remoterig=%s, nowchan=%02d, waschan=%02d\n",myrpt->remoterig,myrpt->nowchan,myrpt->waschan);
09630 if (!myrpt->remoterig) return(0);
09631 if(myrpt->nowchan!=myrpt->waschan)
09632 {
09633 char data[8];
09634 if(debug)ast_log(LOG_NOTICE,"reverting.\n");
09635 sprintf(data,"%02d",myrpt->waschan);
09636 myrpt->nowchan=myrpt->waschan;
09637 channel_steer(myrpt,data);
09638 res=1;
09639 }
09640 return(res);
09641 }
09642
09643
09644
09645
09646 static int function_remote(struct rpt *myrpt, char *param, char *digitbuf, int command_source, struct rpt_link *mylink)
09647 {
09648 char *s,*s1,*s2;
09649 int i,j,r,ht,k,l,ls2,m,d,offset,offsave, modesave, defmode=0;
09650 intptr_t p;
09651 char multimode = 0;
09652 char oc,*cp,*cp1,*cp2;
09653 char tmp[20], freq[20] = "", savestr[20] = "";
09654 char mhz[MAXREMSTR], decimals[MAXREMSTR];
09655
09656 if(debug > 6) {
09657 ast_log(LOG_NOTICE,"%s param=%s digitbuf=%s source=%i\n",myrpt->name,param,digitbuf,command_source);
09658 }
09659
09660 if((!param) || (command_source == SOURCE_RPT) || (command_source == SOURCE_LNK))
09661 return DC_ERROR;
09662
09663 p = myatoi(param);
09664
09665 if ((p != 99) && (p != 5) && (p != 140) && myrpt->p.authlevel &&
09666 (!myrpt->loginlevel[0])) return DC_ERROR;
09667 multimode = multimode_capable(myrpt);
09668
09669 switch(p){
09670
09671 case 1:
09672 if(strlen(digitbuf) < 2)
09673 break;
09674
09675 for(i = 0 ; i < 2 ; i++){
09676 if((digitbuf[i] < '0') || (digitbuf[i] > '9'))
09677 return DC_ERROR;
09678 }
09679 r=get_mem_set(myrpt, digitbuf);
09680 if (r < 0){
09681 rpt_telemetry(myrpt,MEMNOTFOUND,NULL);
09682 return DC_COMPLETE;
09683 }
09684 else if (r > 0){
09685 return DC_ERROR;
09686 }
09687 return DC_COMPLETE;
09688
09689 case 2:
09690
09691
09692 for(i = 0, j = 0, k = 0, l = 0 ; digitbuf[i] ; i++){
09693 if(digitbuf[i] == '*'){
09694 j++;
09695 continue;
09696 }
09697 if((digitbuf[i] < '0') || (digitbuf[i] > '9'))
09698 goto invalid_freq;
09699 else{
09700 if(j == 0)
09701 l++;
09702 if(j == 1)
09703 k++;
09704 }
09705 }
09706
09707 i = strlen(digitbuf) - 1;
09708 if(multimode){
09709 if((j > 2) || (l > 3) || (k > 6))
09710 goto invalid_freq;
09711 }
09712 else{
09713 if((j > 2) || (l > 4) || (k > 3))
09714 goto invalid_freq;
09715 }
09716
09717
09718
09719 if(j < 2)
09720 break;
09721
09722
09723
09724 strncpy(tmp, digitbuf ,sizeof(tmp) - 1);
09725
09726 s = tmp;
09727 s1 = strsep(&s, "*");
09728 s2 = strsep(&s,"*");
09729 ls2 = strlen(s2);
09730
09731 switch(ls2){
09732 case 1:
09733 ht = 0;
09734 k = 100 * atoi(s2);
09735 break;
09736
09737 case 2:
09738 ht = 0;
09739 k = 10 * atoi(s2);
09740 break;
09741
09742 case 3:
09743 if(!multimode){
09744 if((s2[2] != '0')&&(s2[2] != '5'))
09745 goto invalid_freq;
09746 }
09747 ht = 0;
09748 k = atoi(s2);
09749 break;
09750 case 4:
09751 k = atoi(s2)/10;
09752 ht = 10 * (atoi(s2+(ls2-1)));
09753 break;
09754
09755 case 5:
09756 k = atoi(s2)/100;
09757 ht = (atoi(s2+(ls2-2)));
09758 break;
09759
09760 default:
09761 goto invalid_freq;
09762 }
09763
09764
09765
09766 snprintf(freq, sizeof(freq), "%s.%03d%02d",s1, k, ht);
09767
09768 if(debug)
09769 ast_log(LOG_NOTICE, "New frequency: %s\n", freq);
09770
09771 split_freq(mhz, decimals, freq);
09772 m = atoi(mhz);
09773 d = atoi(decimals);
09774
09775 if(check_freq(myrpt, m, d, &defmode))
09776 goto invalid_freq;
09777
09778
09779 if((defmode == REM_MODE_FM) && (digitbuf[i] == '*'))
09780 break;
09781
09782
09783 offset = REM_SIMPLEX;
09784
09785 if(defmode == REM_MODE_FM){
09786 oc = *s;
09787
09788 if (oc){
09789 switch(oc){
09790 case '1':
09791 offset = REM_MINUS;
09792 break;
09793
09794 case '2':
09795 offset = REM_SIMPLEX;
09796 break;
09797
09798 case '3':
09799 offset = REM_PLUS;
09800 break;
09801
09802 default:
09803 goto invalid_freq;
09804 }
09805 }
09806 }
09807 offsave = myrpt->offset;
09808 modesave = myrpt->remmode;
09809 strncpy(savestr, myrpt->freq, sizeof(savestr) - 1);
09810 strncpy(myrpt->freq, freq, sizeof(myrpt->freq) - 1);
09811 myrpt->offset = offset;
09812 myrpt->remmode = defmode;
09813
09814 if (setrem(myrpt) == -1){
09815 myrpt->offset = offsave;
09816 myrpt->remmode = modesave;
09817 strncpy(myrpt->freq, savestr, sizeof(myrpt->freq) - 1);
09818 goto invalid_freq;
09819 }
09820
09821 return DC_COMPLETE;
09822
09823 invalid_freq:
09824 rpt_telemetry(myrpt,INVFREQ,NULL);
09825 return DC_ERROR;
09826
09827 case 3:
09828 for(i = 0, j = 0, k = 0, l = 0 ; digitbuf[i] ; i++){
09829 if(digitbuf[i] == '*'){
09830 j++;
09831 continue;
09832 }
09833 if((digitbuf[i] < '0') || (digitbuf[i] > '9'))
09834 return DC_ERROR;
09835 else{
09836 if(j)
09837 l++;
09838 else
09839 k++;
09840 }
09841 }
09842 if((j > 1) || (k > 3) || (l > 1))
09843 return DC_ERROR;
09844 i = strlen(digitbuf) - 1;
09845 if((j != 1) || (k < 2)|| (l != 1))
09846 break;
09847 if(debug)
09848 printf("PL digits entered %s\n", digitbuf);
09849
09850 strncpy(tmp, digitbuf, sizeof(tmp) - 1);
09851
09852 s = strchr(tmp,'*');
09853 if(s)
09854 *s = '.';
09855 strncpy(savestr, myrpt->rxpl, sizeof(savestr) - 1);
09856 strncpy(myrpt->rxpl, tmp, sizeof(myrpt->rxpl) - 1);
09857 if(!strcmp(myrpt->remoterig, remote_rig_rbi))
09858 {
09859 strncpy(myrpt->txpl, tmp, sizeof(myrpt->txpl) - 1);
09860 }
09861 if (setrem(myrpt) == -1){
09862 strncpy(myrpt->rxpl, savestr, sizeof(myrpt->rxpl) - 1);
09863 return DC_ERROR;
09864 }
09865 return DC_COMPLETE;
09866
09867 case 4:
09868
09869 if(!strcmp(myrpt->remoterig, remote_rig_rbi))
09870 return DC_ERROR;
09871
09872
09873
09874
09875
09876 if(!strcmp(myrpt->remoterig, remote_rig_ic706))
09877 {
09878 if(debug)
09879 ast_log(LOG_WARNING,"Setting IC706 Tx CTCSS Code Not Supported. Set Rx Code for both.\n");
09880 return DC_ERROR;
09881 }
09882 for(i = 0, j = 0, k = 0, l = 0 ; digitbuf[i] ; i++){
09883 if(digitbuf[i] == '*'){
09884 j++;
09885 continue;
09886 }
09887 if((digitbuf[i] < '0') || (digitbuf[i] > '9'))
09888 return DC_ERROR;
09889 else{
09890 if(j)
09891 l++;
09892 else
09893 k++;
09894 }
09895 }
09896 if((j > 1) || (k > 3) || (l > 1))
09897 return DC_ERROR;
09898 i = strlen(digitbuf) - 1;
09899 if((j != 1) || (k < 2)|| (l != 1))
09900 break;
09901 if(debug)
09902 printf("PL digits entered %s\n", digitbuf);
09903
09904 strncpy(tmp, digitbuf, sizeof(tmp) - 1);
09905
09906 s = strchr(tmp,'*');
09907 if(s)
09908 *s = '.';
09909 strncpy(savestr, myrpt->txpl, sizeof(savestr) - 1);
09910 strncpy(myrpt->txpl, tmp, sizeof(myrpt->txpl) - 1);
09911
09912 if (setrem(myrpt) == -1){
09913 strncpy(myrpt->txpl, savestr, sizeof(myrpt->txpl) - 1);
09914 return DC_ERROR;
09915 }
09916 return DC_COMPLETE;
09917
09918
09919 case 6:
09920 if(strlen(digitbuf) < 1)
09921 break;
09922
09923 if(!multimode)
09924 return DC_ERROR;
09925
09926 switch(*digitbuf){
09927 case '1':
09928 split_freq(mhz, decimals, myrpt->freq);
09929 m=atoi(mhz);
09930 if(m < 29)
09931 return DC_ERROR;
09932 myrpt->remmode = REM_MODE_FM;
09933
09934 rpt_telemetry(myrpt,REMMODE,NULL);
09935 break;
09936
09937 case '2':
09938 myrpt->remmode = REM_MODE_USB;
09939 rpt_telemetry(myrpt,REMMODE,NULL);
09940 break;
09941
09942 case '3':
09943 myrpt->remmode = REM_MODE_LSB;
09944 rpt_telemetry(myrpt,REMMODE,NULL);
09945 break;
09946
09947 case '4':
09948 myrpt->remmode = REM_MODE_AM;
09949 rpt_telemetry(myrpt,REMMODE,NULL);
09950 break;
09951
09952 default:
09953 return DC_ERROR;
09954 }
09955
09956 if(setrem(myrpt))
09957 return DC_ERROR;
09958 return DC_COMPLETEQUIET;
09959 case 99:
09960
09961 if (myrpt->loginlevel[0])
09962 return DC_ERROR;
09963 *myrpt->loginuser = 0;
09964 myrpt->loginlevel[0] = 0;
09965 cp = ast_strdup(param);
09966 cp1 = strchr(cp,',');
09967 ast_mutex_lock(&myrpt->lock);
09968 if (cp1)
09969 {
09970 *cp1 = 0;
09971 cp2 = strchr(cp1 + 1,',');
09972 if (cp2)
09973 {
09974 *cp2 = 0;
09975 strncpy(myrpt->loginlevel,cp2 + 1,
09976 sizeof(myrpt->loginlevel) - 1);
09977 }
09978 strncpy(myrpt->loginuser,cp1 + 1,sizeof(myrpt->loginuser));
09979 ast_mutex_unlock(&myrpt->lock);
09980 if (myrpt->p.archivedir)
09981 {
09982 char str[100];
09983
09984 sprintf(str,"LOGIN,%s,%s",
09985 myrpt->loginuser,myrpt->loginlevel);
09986 donodelog(myrpt,str);
09987 }
09988 if (debug)
09989 printf("loginuser %s level %s\n",myrpt->loginuser,myrpt->loginlevel);
09990 rpt_telemetry(myrpt,REMLOGIN,NULL);
09991 }
09992 ast_free(cp);
09993 return DC_COMPLETEQUIET;
09994 case 100:
09995 myrpt->rxplon = 0;
09996 setrem(myrpt);
09997 rpt_telemetry(myrpt,REMXXX,(void *)p);
09998 return DC_COMPLETEQUIET;
09999 case 101:
10000 myrpt->rxplon = 1;
10001 setrem(myrpt);
10002 rpt_telemetry(myrpt,REMXXX,(void *)p);
10003 return DC_COMPLETEQUIET;
10004 case 102:
10005 myrpt->txplon = 0;
10006 setrem(myrpt);
10007 rpt_telemetry(myrpt,REMXXX,(void *)p);
10008 return DC_COMPLETEQUIET;
10009 case 103:
10010 myrpt->txplon = 1;
10011 setrem(myrpt);
10012 rpt_telemetry(myrpt,REMXXX,(void *)p);
10013 return DC_COMPLETEQUIET;
10014 case 104:
10015 if(!strcmp(myrpt->remoterig, remote_rig_ic706))
10016 return DC_ERROR;
10017 myrpt->powerlevel = REM_LOWPWR;
10018 setrem(myrpt);
10019 rpt_telemetry(myrpt,REMXXX,(void *)p);
10020 return DC_COMPLETEQUIET;
10021 case 105:
10022 if(!strcmp(myrpt->remoterig, remote_rig_ic706))
10023 return DC_ERROR;
10024 if (ISRIG_RTX(myrpt->remoterig)) return DC_ERROR;
10025 myrpt->powerlevel = REM_MEDPWR;
10026 setrem(myrpt);
10027 rpt_telemetry(myrpt,REMXXX,(void *)p);
10028 return DC_COMPLETEQUIET;
10029 case 106:
10030 if(!strcmp(myrpt->remoterig, remote_rig_ic706))
10031 return DC_ERROR;
10032 myrpt->powerlevel = REM_HIPWR;
10033 setrem(myrpt);
10034 rpt_telemetry(myrpt,REMXXX,(void *)p);
10035 return DC_COMPLETEQUIET;
10036 case 107:
10037 multimode_bump_freq(myrpt, -20);
10038 return DC_COMPLETE;
10039 case 108:
10040 multimode_bump_freq(myrpt, -100);
10041 return DC_COMPLETE;
10042 case 109:
10043 multimode_bump_freq(myrpt, -500);
10044 return DC_COMPLETE;
10045 case 110:
10046 multimode_bump_freq(myrpt, 20);
10047 return DC_COMPLETE;
10048 case 111:
10049 multimode_bump_freq(myrpt, 100);
10050 return DC_COMPLETE;
10051 case 112:
10052 multimode_bump_freq(myrpt, 500);
10053 return DC_COMPLETE;
10054 case 113:
10055 myrpt->scantimer = REM_SCANTIME;
10056 myrpt->hfscanmode = HF_SCAN_DOWN_SLOW;
10057 rpt_telemetry(myrpt,REMXXX,(void *)p);
10058 return DC_COMPLETEQUIET;
10059 case 114:
10060 myrpt->scantimer = REM_SCANTIME;
10061 myrpt->hfscanmode = HF_SCAN_DOWN_QUICK;
10062 rpt_telemetry(myrpt,REMXXX,(void *)p);
10063 return DC_COMPLETEQUIET;
10064 case 115:
10065 myrpt->scantimer = REM_SCANTIME;
10066 myrpt->hfscanmode = HF_SCAN_DOWN_FAST;
10067 rpt_telemetry(myrpt,REMXXX,(void *)p);
10068 return DC_COMPLETEQUIET;
10069 case 116:
10070 myrpt->scantimer = REM_SCANTIME;
10071 myrpt->hfscanmode = HF_SCAN_UP_SLOW;
10072 rpt_telemetry(myrpt,REMXXX,(void *)p);
10073 return DC_COMPLETEQUIET;
10074 case 117:
10075 myrpt->scantimer = REM_SCANTIME;
10076 myrpt->hfscanmode = HF_SCAN_UP_QUICK;
10077 rpt_telemetry(myrpt,REMXXX,(void *)p);
10078 return DC_COMPLETEQUIET;
10079 case 118:
10080 myrpt->scantimer = REM_SCANTIME;
10081 myrpt->hfscanmode = HF_SCAN_UP_FAST;
10082 rpt_telemetry(myrpt,REMXXX,(void *)p);
10083 return DC_COMPLETEQUIET;
10084 case 119:
10085 if(debug > 3)
10086 ast_log(LOG_NOTICE,"TUNE REQUEST\n");
10087
10088 if((!myrpt->tunerequest) &&
10089 ((!strcmp(myrpt->remoterig, remote_rig_ft897) ||
10090 !strcmp(myrpt->remoterig, remote_rig_ic706)) )) {
10091 myrpt->remotetx = 0;
10092 ast_indicate(myrpt->txchannel,AST_CONTROL_RADIO_UNKEY);
10093 myrpt->tunerequest = 1;
10094 rpt_telemetry(myrpt,TUNE,NULL);
10095 return DC_COMPLETEQUIET;
10096 }
10097 return DC_ERROR;
10098 case 5:
10099 rpt_telemetry(myrpt,REMLONGSTATUS,NULL);
10100 return DC_COMPLETEQUIET;
10101 case 140:
10102 rpt_telemetry(myrpt,REMSHORTSTATUS,NULL);
10103 return DC_COMPLETEQUIET;
10104 case 200:
10105 case 201:
10106 case 202:
10107 case 203:
10108 case 204:
10109 case 205:
10110 case 206:
10111 case 207:
10112 case 208:
10113 case 209:
10114 case 210:
10115 case 211:
10116 case 212:
10117 case 213:
10118 case 214:
10119 case 215:
10120 do_dtmf_local(myrpt,remdtmfstr[p - 200]);
10121 return DC_COMPLETEQUIET;
10122 default:
10123 break;
10124 }
10125 return DC_INDETERMINATE;
10126 }
10127
10128
10129 static int handle_remote_dtmf_digit(struct rpt *myrpt,char c, char *keyed, int phonemode)
10130 {
10131 time_t now;
10132 int ret,res = 0,src;
10133
10134 if(debug > 6)
10135 ast_log(LOG_NOTICE,"c=%c phonemode=%i dtmfidx=%i\n",c,phonemode,myrpt->dtmfidx);
10136
10137 time(&myrpt->last_activity_time);
10138
10139 if(myrpt->hfscanmode){
10140 stop_scan(myrpt);
10141 return 0;
10142 }
10143
10144 time(&now);
10145
10146 if ((myrpt->dtmf_time_rem + DTMF_TIMEOUT) < now)
10147 {
10148 myrpt->dtmfidx = -1;
10149 myrpt->dtmfbuf[0] = 0;
10150 myrpt->dtmf_time_rem = 0;
10151 }
10152
10153 if (myrpt->dtmfidx == -1)
10154 {
10155
10156 if (c != myrpt->p.funcchar)
10157 {
10158 if (!myrpt->p.propagate_dtmf)
10159 {
10160 rpt_mutex_lock(&myrpt->lock);
10161 do_dtmf_local(myrpt,c);
10162 rpt_mutex_unlock(&myrpt->lock);
10163 }
10164 return 0;
10165 }
10166 myrpt->dtmfidx = 0;
10167 myrpt->dtmfbuf[0] = 0;
10168 myrpt->dtmf_time_rem = now;
10169 return 0;
10170 }
10171
10172 if (myrpt->dtmfidx >= MAXDTMF)
10173 {
10174 myrpt->dtmfidx = 0;
10175 myrpt->dtmfbuf[0] = 0;
10176 myrpt->dtmf_time_rem = now;
10177 }
10178 if (c == myrpt->p.funcchar)
10179 {
10180
10181 if ((myrpt->dtmfidx < 1) ||
10182 (myrpt->dtmfbuf[myrpt->dtmfidx - 1] == myrpt->p.funcchar))
10183 {
10184 myrpt->dtmfidx = 0;
10185 myrpt->dtmfbuf[0] = 0;
10186 myrpt->dtmf_time_rem = now;
10187 return 0;
10188 }
10189 }
10190 myrpt->dtmfbuf[myrpt->dtmfidx++] = c;
10191 myrpt->dtmfbuf[myrpt->dtmfidx] = 0;
10192 myrpt->dtmf_time_rem = now;
10193
10194
10195 src = SOURCE_RMT;
10196 if (phonemode == 2) src = SOURCE_DPHONE;
10197 else if (phonemode) src = SOURCE_PHONE;
10198 else if (phonemode == 4) src = SOURCE_ALT;
10199 ret = collect_function_digits(myrpt, myrpt->dtmfbuf, src, NULL);
10200
10201 switch(ret){
10202
10203 case DC_INDETERMINATE:
10204 res = 0;
10205 break;
10206
10207 case DC_DOKEY:
10208 if (keyed) *keyed = 1;
10209 res = 0;
10210 break;
10211
10212 case DC_REQ_FLUSH:
10213 myrpt->dtmfidx = 0;
10214 myrpt->dtmfbuf[0] = 0;
10215 res = 0;
10216 break;
10217
10218
10219 case DC_COMPLETE:
10220 res = 1;
10221 case DC_COMPLETEQUIET:
10222 myrpt->totalexecdcommands++;
10223 myrpt->dailyexecdcommands++;
10224 strncpy(myrpt->lastdtmfcommand, myrpt->dtmfbuf, MAXDTMF-1);
10225 myrpt->lastdtmfcommand[MAXDTMF-1] = '\0';
10226 myrpt->dtmfbuf[0] = 0;
10227 myrpt->dtmfidx = -1;
10228 myrpt->dtmf_time_rem = 0;
10229 break;
10230
10231 case DC_ERROR:
10232 default:
10233 myrpt->dtmfbuf[0] = 0;
10234 myrpt->dtmfidx = -1;
10235 myrpt->dtmf_time_rem = 0;
10236 res = 0;
10237 break;
10238 }
10239
10240 return res;
10241 }
10242
10243 static int handle_remote_data(struct rpt *myrpt, char *str)
10244 {
10245
10246
10247 char tmp[300],cmd[300],dest[300],src[300],c;
10248 int seq,res;
10249
10250
10251 strncpy(tmp,str,sizeof(tmp) - 1);
10252 if (!strcmp(tmp,discstr)) return 0;
10253 if (!strcmp(tmp,newkeystr))
10254 {
10255 myrpt->newkey = 1;
10256 return 0;
10257 }
10258
10259 #ifndef DO_NOT_NOTIFY_MDC1200_ON_REMOTE_BASES
10260 if (tmp[0] == 'I')
10261 {
10262
10263
10264 if (sscanf(tmp,"%299s %299s %30x",cmd,src,&seq) != 3)
10265 {
10266 ast_log(LOG_WARNING, "Unable to parse ident string %s\n",str);
10267 return 0;
10268 }
10269 mdc1200_notify(myrpt,src,seq);
10270 return 0;
10271 }
10272 #endif
10273
10274
10275 if (sscanf(tmp,"%299s %299s %299s %30d %1c",cmd,dest,src,&seq,&c) != 5)
10276 {
10277 ast_log(LOG_WARNING, "Unable to parse link string %s\n",str);
10278 return 0;
10279 }
10280 if (strcmp(cmd,"D"))
10281 {
10282 ast_log(LOG_WARNING, "Unable to parse link string %s\n",str);
10283 return 0;
10284 }
10285
10286 if (strcmp(dest,myrpt->name)) return 0;
10287 if (myrpt->p.archivedir)
10288 {
10289 char dtmfstr[100];
10290
10291 sprintf(dtmfstr,"DTMF,%c",c);
10292 donodelog(myrpt,dtmfstr);
10293 }
10294 c = func_xlat(myrpt,c,&myrpt->p.outxlat);
10295 if (!c) return(0);
10296 res = handle_remote_dtmf_digit(myrpt,c, NULL, 0);
10297 if (res != 1)
10298 return res;
10299 rpt_telemetry(myrpt,COMPLETE,NULL);
10300 return 0;
10301 }
10302
10303 static int handle_remote_phone_dtmf(struct rpt *myrpt, char c, char *keyed, int phonemode)
10304 {
10305 int res;
10306
10307
10308 if(phonemode == 3)
10309 {
10310 if (keyed && *keyed && ((c == myrpt->p.funcchar) || (c == myrpt->p.endchar)))
10311 {
10312 *keyed = 0;
10313 return 0;
10314 }
10315 else if (keyed && !*keyed && (c = myrpt->p.funcchar))
10316 {
10317 *keyed = 1;
10318 return 0;
10319 }
10320 }
10321 else
10322 {
10323
10324 if (keyed && *keyed && (c == myrpt->p.endchar))
10325 {
10326 *keyed = 0;
10327 return DC_INDETERMINATE;
10328 }
10329 }
10330 if (myrpt->p.archivedir)
10331 {
10332 char str[100];
10333
10334 sprintf(str,"DTMF(P),%c",c);
10335 donodelog(myrpt,str);
10336 }
10337 res = handle_remote_dtmf_digit(myrpt,c,keyed, phonemode);
10338 if (res != 1)
10339 return res;
10340 rpt_telemetry(myrpt,COMPLETE,NULL);
10341 return 0;
10342 }
10343
10344 static int attempt_reconnect(struct rpt *myrpt, struct rpt_link *l)
10345 {
10346 char *val, *s, *s1, *s2, *tele;
10347 char tmp[300], deststr[300] = "";
10348 char sx[320],*sy;
10349
10350
10351 val = node_lookup(myrpt,l->name);
10352 if (!val)
10353 {
10354 fprintf(stderr,"attempt_reconnect: cannot find node %s\n",l->name);
10355 return -1;
10356 }
10357
10358 rpt_mutex_lock(&myrpt->lock);
10359
10360 remque((struct qelem *) l);
10361 rpt_mutex_unlock(&myrpt->lock);
10362 strncpy(tmp,val,sizeof(tmp) - 1);
10363 s = tmp;
10364 s1 = strsep(&s,",");
10365 if (!strchr(s1,':') && strchr(s1,'/') && strncasecmp(s1, "local/", 6))
10366 {
10367 sy = strchr(s1,'/');
10368 *sy = 0;
10369 sprintf(sx,"%s:4569/%s",s1,sy + 1);
10370 s1 = sx;
10371 }
10372 s2 = strsep(&s,",");
10373 snprintf(deststr, sizeof(deststr), "IAX2/%s", s1);
10374 tele = strchr(deststr, '/');
10375 if (!tele) {
10376 fprintf(stderr,"attempt_reconnect:Dial number (%s) must be in format tech/number\n",deststr);
10377 return -1;
10378 }
10379 *tele++ = 0;
10380 l->elaptime = 0;
10381 l->connecttime = 0;
10382 l->thisconnected = 0;
10383 l->newkey = 0;
10384 l->chan = ast_request(deststr, AST_FORMAT_SLINEAR, NULL, tele, NULL);
10385 if (l->chan){
10386 ast_set_read_format(l->chan, AST_FORMAT_SLINEAR);
10387 ast_set_write_format(l->chan, AST_FORMAT_SLINEAR);
10388 #ifndef NEW_ASTERISK
10389 l->chan->whentohangup = 0;
10390 #endif
10391 l->chan->appl = "Apprpt";
10392 l->chan->data = "(Remote Rx)";
10393 if (option_verbose > 2)
10394 ast_verbose(VERBOSE_PREFIX_3 "rpt (attempt_reconnect) initiating call to %s/%s on %s\n",
10395 deststr, tele, l->chan->name);
10396 l->chan->caller.id.number.valid = 1;
10397 ast_free(l->chan->caller.id.number.str);
10398 l->chan->caller.id.number.str = ast_strdup(myrpt->name);
10399 ast_call(l->chan,tele,999);
10400
10401 }
10402 else
10403 {
10404 if (option_verbose > 2)
10405 ast_verbose(VERBOSE_PREFIX_3 "Unable to place call to %s/%s on %s\n",
10406 deststr,tele,l->chan->name);
10407 return -1;
10408 }
10409 rpt_mutex_lock(&myrpt->lock);
10410
10411 insque((struct qelem *)l,(struct qelem *)myrpt->links.next);
10412 rpt_mutex_unlock(&myrpt->lock);
10413 ast_log(LOG_WARNING,"Reconnect Attempt to %s in process\n",l->name);
10414 if (!l->phonemode) send_newkey(l->chan);
10415 return 0;
10416 }
10417
10418
10419 static void local_dtmf_helper(struct rpt *myrpt,char c_in)
10420 {
10421 int res;
10422 pthread_attr_t attr;
10423 char cmd[MAXDTMF+1] = "",c;
10424
10425
10426 c = c_in & 0x7f;
10427 if (myrpt->p.archivedir)
10428 {
10429 char str[100];
10430
10431 sprintf(str,"DTMF,MAIN,%c",c);
10432 donodelog(myrpt,str);
10433 }
10434 if (c == myrpt->p.endchar)
10435 {
10436
10437 if (myrpt->p.simple && myrpt->callmode)
10438 {
10439 if(debug)
10440 ast_log(LOG_WARNING, "simple mode autopatch kill\n");
10441 rpt_mutex_lock(&myrpt->lock);
10442 myrpt->callmode = 0;
10443 myrpt->macropatch=0;
10444 channel_revert(myrpt);
10445 rpt_mutex_unlock(&myrpt->lock);
10446 rpt_telemetry(myrpt,TERM,NULL);
10447 return;
10448 }
10449 rpt_mutex_lock(&myrpt->lock);
10450 myrpt->stopgen = 1;
10451 if (myrpt->cmdnode[0])
10452 {
10453 myrpt->cmdnode[0] = 0;
10454 myrpt->dtmfidx = -1;
10455 myrpt->dtmfbuf[0] = 0;
10456 rpt_mutex_unlock(&myrpt->lock);
10457 rpt_telemetry(myrpt,COMPLETE,NULL);
10458 return;
10459 }
10460 else if(!myrpt->inpadtest)
10461 {
10462 rpt_mutex_unlock(&myrpt->lock);
10463 if (myrpt->p.propagate_phonedtmf)
10464 do_dtmf_phone(myrpt,NULL,c);
10465 return;
10466 }
10467 else
10468 rpt_mutex_unlock(&myrpt->lock);
10469 }
10470 rpt_mutex_lock(&myrpt->lock);
10471 if (myrpt->cmdnode[0])
10472 {
10473 rpt_mutex_unlock(&myrpt->lock);
10474 send_link_dtmf(myrpt,c);
10475 return;
10476 }
10477 if (!myrpt->p.simple)
10478 {
10479 if ((!myrpt->inpadtest)&&(c == myrpt->p.funcchar))
10480 {
10481 myrpt->dtmfidx = 0;
10482 myrpt->dtmfbuf[myrpt->dtmfidx] = 0;
10483 rpt_mutex_unlock(&myrpt->lock);
10484 time(&myrpt->dtmf_time);
10485 return;
10486 }
10487 else if (((myrpt->inpadtest)||(c != myrpt->p.endchar)) && (myrpt->dtmfidx >= 0))
10488 {
10489 time(&myrpt->dtmf_time);
10490
10491 if (myrpt->dtmfidx < MAXDTMF)
10492 {
10493 int src;
10494
10495 myrpt->dtmfbuf[myrpt->dtmfidx++] = c;
10496 myrpt->dtmfbuf[myrpt->dtmfidx] = 0;
10497
10498 strncpy(cmd, myrpt->dtmfbuf, sizeof(cmd) - 1);
10499
10500 rpt_mutex_unlock(&myrpt->lock);
10501 src = SOURCE_RPT;
10502 if (c_in & 0x80) src = SOURCE_ALT;
10503 res = collect_function_digits(myrpt, cmd, src, NULL);
10504 rpt_mutex_lock(&myrpt->lock);
10505 switch(res){
10506 case DC_INDETERMINATE:
10507 break;
10508 case DC_REQ_FLUSH:
10509 myrpt->dtmfidx = 0;
10510 myrpt->dtmfbuf[0] = 0;
10511 break;
10512 case DC_COMPLETE:
10513 case DC_COMPLETEQUIET:
10514 myrpt->totalexecdcommands++;
10515 myrpt->dailyexecdcommands++;
10516 strncpy(myrpt->lastdtmfcommand, cmd, MAXDTMF-1);
10517 myrpt->lastdtmfcommand[MAXDTMF-1] = '\0';
10518 myrpt->dtmfbuf[0] = 0;
10519 myrpt->dtmfidx = -1;
10520 myrpt->dtmf_time = 0;
10521 break;
10522
10523 case DC_ERROR:
10524 default:
10525 myrpt->dtmfbuf[0] = 0;
10526 myrpt->dtmfidx = -1;
10527 myrpt->dtmf_time = 0;
10528 break;
10529 }
10530 if(res != DC_INDETERMINATE) {
10531 rpt_mutex_unlock(&myrpt->lock);
10532 return;
10533 }
10534 }
10535 }
10536 }
10537 else
10538 {
10539 if ((!myrpt->callmode) && (c == myrpt->p.funcchar))
10540 {
10541 myrpt->callmode = 1;
10542 myrpt->patchnoct = 0;
10543 myrpt->patchquiet = 0;
10544 myrpt->patchfarenddisconnect = 0;
10545 myrpt->patchdialtime = 0;
10546 strncpy(myrpt->patchcontext, myrpt->p.ourcontext, MAXPATCHCONTEXT);
10547 myrpt->cidx = 0;
10548 myrpt->exten[myrpt->cidx] = 0;
10549 rpt_mutex_unlock(&myrpt->lock);
10550 pthread_attr_init(&attr);
10551 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
10552 ast_pthread_create(&myrpt->rpt_call_thread,&attr,rpt_call,(void *)myrpt);
10553 return;
10554 }
10555 }
10556 if (myrpt->callmode == 1)
10557 {
10558 myrpt->exten[myrpt->cidx++] = c;
10559 myrpt->exten[myrpt->cidx] = 0;
10560
10561 if (ast_exists_extension(myrpt->pchannel,myrpt->patchcontext,myrpt->exten,1,NULL))
10562 {
10563
10564 if (!ast_matchmore_extension(myrpt->pchannel,myrpt->patchcontext,
10565 myrpt->exten,1,NULL))
10566 {
10567 myrpt->callmode = 2;
10568 rpt_mutex_unlock(&myrpt->lock);
10569 if(!myrpt->patchquiet)
10570 rpt_telemetry(myrpt,PROC,NULL);
10571 return;
10572 }
10573 else
10574 {
10575 myrpt->calldigittimer = 1;
10576 }
10577 }
10578
10579 if (!ast_canmatch_extension(myrpt->pchannel,myrpt->patchcontext,myrpt->exten,1,NULL))
10580 {
10581
10582 myrpt->callmode = 4;
10583 }
10584 rpt_mutex_unlock(&myrpt->lock);
10585 return;
10586 }
10587 if ((myrpt->callmode == 2) || (myrpt->callmode == 3))
10588 {
10589 myrpt->mydtmf = c;
10590 }
10591 rpt_mutex_unlock(&myrpt->lock);
10592 if ((myrpt->dtmfidx < 0) && myrpt->p.propagate_phonedtmf)
10593 do_dtmf_phone(myrpt,NULL,c);
10594 return;
10595 }
10596
10597
10598
10599
10600 static void queue_id(struct rpt *myrpt)
10601 {
10602 if(myrpt->p.idtime){
10603 myrpt->mustid = myrpt->tailid = 0;
10604 myrpt->idtimer = myrpt->p.idtime;
10605 rpt_mutex_unlock(&myrpt->lock);
10606 rpt_telemetry(myrpt,ID,NULL);
10607 rpt_mutex_lock(&myrpt->lock);
10608 }
10609 }
10610
10611
10612
10613
10614 static void do_scheduler(struct rpt *myrpt)
10615 {
10616 int i,res;
10617
10618 #ifdef NEW_ASTERISK
10619 struct ast_tm tmnow;
10620 #else
10621 struct tm tmnow;
10622 #endif
10623 struct ast_variable *skedlist;
10624 char *strs[5],*vp,*val,value[100];
10625
10626 memcpy(&myrpt->lasttv, &myrpt->curtv, sizeof(struct timeval));
10627
10628 if( (res = gettimeofday(&myrpt->curtv, NULL)) < 0)
10629 ast_log(LOG_NOTICE, "Scheduler gettime of day returned: %s\n", strerror(res));
10630
10631
10632
10633 if(myrpt->lasttv.tv_sec == myrpt->curtv.tv_sec)
10634 return;
10635
10636 rpt_localtime(&myrpt->curtv.tv_sec, &tmnow);
10637
10638
10639
10640 if((tmnow.tm_hour == 0)&&(tmnow.tm_min == 0)&&(tmnow.tm_sec == 0)){
10641 myrpt->dailykeyups = 0;
10642 myrpt->dailytxtime = 0;
10643 myrpt->dailykerchunks = 0;
10644 myrpt->dailyexecdcommands = 0;
10645 }
10646
10647 if(tmnow.tm_sec != 0)
10648 return;
10649
10650
10651
10652
10653
10654
10655 if (myrpt->remote)
10656 return;
10657
10658
10659
10660 if(myrpt->p.s[myrpt->p.sysstate_cur].schedulerdisable){
10661 if(debug > 6)
10662 ast_log(LOG_NOTICE, "Scheduler disabled\n");
10663 return;
10664 }
10665
10666 if(!myrpt->p.skedstanzaname){
10667 if(debug > 6)
10668 ast_log(LOG_NOTICE,"No stanza for scheduler in rpt.conf\n");
10669 return;
10670 }
10671
10672
10673 skedlist = ast_variable_browse(myrpt->cfg, myrpt->p.skedstanzaname);
10674
10675 if(debug > 6){
10676 ast_log(LOG_NOTICE, "Time now: %02d:%02d %02d %02d %02d\n",
10677 tmnow.tm_hour,tmnow.tm_min,tmnow.tm_mday,tmnow.tm_mon + 1, tmnow.tm_wday);
10678 }
10679
10680 for(; skedlist; skedlist = skedlist->next){
10681 if(debug > 6)
10682 ast_log(LOG_NOTICE, "Scheduler entry %s = %s being considered\n",skedlist->name, skedlist->value);
10683 strncpy(value,skedlist->value,99);
10684 value[99] = 0;
10685
10686 for( i = 0, vp = value ; i < 5; i++){
10687 if(!*vp)
10688 break;
10689 while((*vp == ' ') || (*vp == 0x09))
10690 vp++;
10691 strs[i] = vp;
10692 while((*vp != ' ') && (*vp != 0x09) && (*vp != 0))
10693 vp++;
10694 if(*vp)
10695 *vp++ = 0;
10696 }
10697 if(debug > 6)
10698 ast_log(LOG_NOTICE, "i = %d, min = %s, hour = %s, mday=%s, mon=%s, wday=%s\n",i,
10699 strs[0], strs[1], strs[2], strs[3], strs[4]);
10700 if(i == 5){
10701 if((*strs[0] != '*')&&(atoi(strs[0]) != tmnow.tm_min))
10702 continue;
10703 if((*strs[1] != '*')&&(atoi(strs[1]) != tmnow.tm_hour))
10704 continue;
10705 if((*strs[2] != '*')&&(atoi(strs[2]) != tmnow.tm_mday))
10706 continue;
10707 if((*strs[3] != '*')&&(atoi(strs[3]) != tmnow.tm_mon + 1))
10708 continue;
10709 if(atoi(strs[4]) == 7)
10710 strs[4] = "0";
10711 if((*strs[4] != '*')&&(atoi(strs[4]) != tmnow.tm_wday))
10712 continue;
10713 if(debug)
10714 ast_log(LOG_NOTICE, "Executing scheduler entry %s = %s\n", skedlist->name, skedlist->value);
10715 if(atoi(skedlist->name) == 0)
10716 return;
10717 val = (char *) ast_variable_retrieve(myrpt->cfg, myrpt->p.macro, skedlist->name);
10718 if (!val){
10719 ast_log(LOG_WARNING,"Scheduler could not find macro %s\n",skedlist->name);
10720 return;
10721 }
10722 if ((MAXMACRO - strlen(myrpt->macrobuf)) < strlen(val)){
10723 ast_log(LOG_WARNING, "Scheduler could not execute macro %s: Macro buffer full\n",
10724 skedlist->name);
10725 return;
10726 }
10727 myrpt->macrotimer = MACROTIME;
10728 strncat(myrpt->macrobuf,val,MAXMACRO - 1);
10729 }
10730 else{
10731 ast_log(LOG_WARNING,"Malformed scheduler entry in rpt.conf: %s = %s\n",
10732 skedlist->name, skedlist->value);
10733 }
10734 }
10735
10736 }
10737
10738
10739 static void *rpt(void *this)
10740 {
10741 struct rpt *myrpt = (struct rpt *)this;
10742 char *tele,*idtalkover,c,myfirst,*p;
10743 int ms = MSWAIT,i,lasttx=0,val,remrx=0,identqueued,othertelemqueued;
10744 int tailmessagequeued,ctqueued,dtmfed,lastmyrx,localmsgqueued;
10745 struct ast_channel *who;
10746 struct dahdi_confinfo ci;
10747 time_t t;
10748 struct rpt_link *l,*m;
10749 struct rpt_tele *telem;
10750 char tmpstr[300],lstr[MAXLINKLIST];
10751
10752
10753 if (myrpt->p.archivedir) mkdir(myrpt->p.archivedir,0600);
10754 sprintf(tmpstr,"%s/%s",myrpt->p.archivedir,myrpt->name);
10755 mkdir(tmpstr,0600);
10756 rpt_mutex_lock(&myrpt->lock);
10757
10758 telem = myrpt->tele.next;
10759 while(telem != &myrpt->tele)
10760 {
10761 ast_softhangup(telem->chan,AST_SOFTHANGUP_DEV);
10762 telem = telem->next;
10763 }
10764 rpt_mutex_unlock(&myrpt->lock);
10765
10766 for(i = 0; i < nrpts; i++)
10767 {
10768 if (&rpt_vars[i] == myrpt)
10769 {
10770 load_rpt_vars(i,0);
10771 break;
10772 }
10773 }
10774
10775 rpt_mutex_lock(&myrpt->lock);
10776 while(myrpt->xlink)
10777 {
10778 myrpt->xlink = 3;
10779 rpt_mutex_unlock(&myrpt->lock);
10780 usleep(100000);
10781 rpt_mutex_lock(&myrpt->lock);
10782 }
10783 #ifdef HAVE_IOPERM
10784 if ((!strcmp(myrpt->remoterig, remote_rig_rbi)) &&
10785 (ioperm(myrpt->p.iobase,1,1) == -1))
10786 {
10787 rpt_mutex_unlock(&myrpt->lock);
10788 ast_log(LOG_WARNING, "Cant get io permission on IO port %x hex\n",myrpt->p.iobase);
10789 myrpt->rpt_thread = AST_PTHREADT_STOP;
10790 pthread_exit(NULL);
10791 }
10792 #endif
10793 strncpy(tmpstr,myrpt->rxchanname,sizeof(tmpstr) - 1);
10794 tele = strchr(tmpstr,'/');
10795 if (!tele)
10796 {
10797 fprintf(stderr,"rpt:Rxchannel Dial number (%s) must be in format tech/number\n",myrpt->rxchanname);
10798 rpt_mutex_unlock(&myrpt->lock);
10799 myrpt->rpt_thread = AST_PTHREADT_STOP;
10800 pthread_exit(NULL);
10801 }
10802 *tele++ = 0;
10803 myrpt->rxchannel = ast_request(tmpstr, AST_FORMAT_SLINEAR, NULL, tele, NULL);
10804 myrpt->dahdirxchannel = NULL;
10805 if (!strcasecmp(tmpstr,"DAHDI"))
10806 myrpt->dahdirxchannel = myrpt->rxchannel;
10807 if (myrpt->rxchannel)
10808 {
10809 if (myrpt->rxchannel->_state == AST_STATE_BUSY)
10810 {
10811 fprintf(stderr,"rpt:Sorry unable to obtain Rx channel\n");
10812 rpt_mutex_unlock(&myrpt->lock);
10813 ast_hangup(myrpt->rxchannel);
10814 myrpt->rpt_thread = AST_PTHREADT_STOP;
10815 pthread_exit(NULL);
10816 }
10817 ast_set_read_format(myrpt->rxchannel,AST_FORMAT_SLINEAR);
10818 ast_set_write_format(myrpt->rxchannel,AST_FORMAT_SLINEAR);
10819 #ifdef AST_CDR_FLAG_POST_DISABLED
10820 if (myrpt->rxchannel->cdr)
10821 ast_set_flag(myrpt->rxchannel->cdr,AST_CDR_FLAG_POST_DISABLED);
10822 #endif
10823 #ifndef NEW_ASTERISK
10824 myrpt->rxchannel->whentohangup = 0;
10825 #endif
10826 myrpt->rxchannel->appl = "Apprpt";
10827 myrpt->rxchannel->data = "(Repeater Rx)";
10828 if (option_verbose > 2)
10829 ast_verbose(VERBOSE_PREFIX_3 "rpt (Rx) initiating call to %s/%s on %s\n",
10830 tmpstr,tele,myrpt->rxchannel->name);
10831 ast_call(myrpt->rxchannel,tele,999);
10832 if (myrpt->rxchannel->_state != AST_STATE_UP)
10833 {
10834 rpt_mutex_unlock(&myrpt->lock);
10835 ast_hangup(myrpt->rxchannel);
10836 myrpt->rpt_thread = AST_PTHREADT_STOP;
10837 pthread_exit(NULL);
10838 }
10839 }
10840 else
10841 {
10842 fprintf(stderr,"rpt:Sorry unable to obtain Rx channel\n");
10843 rpt_mutex_unlock(&myrpt->lock);
10844 myrpt->rpt_thread = AST_PTHREADT_STOP;
10845 pthread_exit(NULL);
10846 }
10847 myrpt->dahditxchannel = NULL;
10848 if (myrpt->txchanname)
10849 {
10850 strncpy(tmpstr,myrpt->txchanname,sizeof(tmpstr) - 1);
10851 tele = strchr(tmpstr,'/');
10852 if (!tele)
10853 {
10854 fprintf(stderr,"rpt:Txchannel Dial number (%s) must be in format tech/number\n",myrpt->txchanname);
10855 rpt_mutex_unlock(&myrpt->lock);
10856 ast_hangup(myrpt->rxchannel);
10857 myrpt->rpt_thread = AST_PTHREADT_STOP;
10858 pthread_exit(NULL);
10859 }
10860 *tele++ = 0;
10861 myrpt->txchannel = ast_request(tmpstr, AST_FORMAT_SLINEAR, NULL, tele, NULL);
10862 if (!strcasecmp(tmpstr,"DAHDI"))
10863 myrpt->dahditxchannel = myrpt->txchannel;
10864 if (myrpt->txchannel)
10865 {
10866 if (myrpt->txchannel->_state == AST_STATE_BUSY)
10867 {
10868 fprintf(stderr,"rpt:Sorry unable to obtain Tx channel\n");
10869 rpt_mutex_unlock(&myrpt->lock);
10870 ast_hangup(myrpt->txchannel);
10871 ast_hangup(myrpt->rxchannel);
10872 myrpt->rpt_thread = AST_PTHREADT_STOP;
10873 pthread_exit(NULL);
10874 }
10875 ast_set_read_format(myrpt->txchannel,AST_FORMAT_SLINEAR);
10876 ast_set_write_format(myrpt->txchannel,AST_FORMAT_SLINEAR);
10877 #ifdef AST_CDR_FLAG_POST_DISABLED
10878 if (myrpt->txchannel->cdr)
10879 ast_set_flag(myrpt->txchannel->cdr,AST_CDR_FLAG_POST_DISABLED);
10880 #endif
10881 #ifndef NEW_ASTERISK
10882 myrpt->txchannel->whentohangup = 0;
10883 #endif
10884 myrpt->txchannel->appl = "Apprpt";
10885 myrpt->txchannel->data = "(Repeater Tx)";
10886 if (option_verbose > 2)
10887 ast_verbose(VERBOSE_PREFIX_3 "rpt (Tx) initiating call to %s/%s on %s\n",
10888 tmpstr,tele,myrpt->txchannel->name);
10889 ast_call(myrpt->txchannel,tele,999);
10890 if (myrpt->rxchannel->_state != AST_STATE_UP)
10891 {
10892 rpt_mutex_unlock(&myrpt->lock);
10893 ast_hangup(myrpt->rxchannel);
10894 ast_hangup(myrpt->txchannel);
10895 myrpt->rpt_thread = AST_PTHREADT_STOP;
10896 pthread_exit(NULL);
10897 }
10898 }
10899 else
10900 {
10901 fprintf(stderr,"rpt:Sorry unable to obtain Tx channel\n");
10902 rpt_mutex_unlock(&myrpt->lock);
10903 ast_hangup(myrpt->rxchannel);
10904 myrpt->rpt_thread = AST_PTHREADT_STOP;
10905 pthread_exit(NULL);
10906 }
10907 }
10908 else
10909 {
10910 myrpt->txchannel = myrpt->rxchannel;
10911 if (!strncasecmp(myrpt->rxchanname,"DAHDI",3))
10912 myrpt->dahditxchannel = myrpt->txchannel;
10913 }
10914 ast_indicate(myrpt->txchannel,AST_CONTROL_RADIO_KEY);
10915 ast_indicate(myrpt->txchannel,AST_CONTROL_RADIO_UNKEY);
10916
10917 myrpt->pchannel = ast_request("DAHDI", AST_FORMAT_SLINEAR, NULL, "pseudo", NULL);
10918 if (!myrpt->pchannel)
10919 {
10920 fprintf(stderr,"rpt:Sorry unable to obtain pseudo channel\n");
10921 rpt_mutex_unlock(&myrpt->lock);
10922 if (myrpt->txchannel != myrpt->rxchannel)
10923 ast_hangup(myrpt->txchannel);
10924 ast_hangup(myrpt->rxchannel);
10925 myrpt->rpt_thread = AST_PTHREADT_STOP;
10926 pthread_exit(NULL);
10927 }
10928 #ifdef AST_CDR_FLAG_POST_DISABLED
10929 if (myrpt->pchannel->cdr)
10930 ast_set_flag(myrpt->pchannel->cdr,AST_CDR_FLAG_POST_DISABLED);
10931 #endif
10932 if (!myrpt->dahdirxchannel) myrpt->dahdirxchannel = myrpt->pchannel;
10933 if (!myrpt->dahditxchannel)
10934 {
10935
10936 myrpt->dahditxchannel = ast_request("DAHDI", AST_FORMAT_SLINEAR, NULL, "pseudo", NULL);
10937 if (!myrpt->dahditxchannel)
10938 {
10939 fprintf(stderr,"rpt:Sorry unable to obtain pseudo channel\n");
10940 rpt_mutex_unlock(&myrpt->lock);
10941 if (myrpt->txchannel != myrpt->rxchannel)
10942 ast_hangup(myrpt->txchannel);
10943 ast_hangup(myrpt->rxchannel);
10944 myrpt->rpt_thread = AST_PTHREADT_STOP;
10945 pthread_exit(NULL);
10946 }
10947 ast_set_read_format(myrpt->dahditxchannel,AST_FORMAT_SLINEAR);
10948 ast_set_write_format(myrpt->dahditxchannel,AST_FORMAT_SLINEAR);
10949 #ifdef AST_CDR_FLAG_POST_DISABLED
10950 if (myrpt->dahditxchannel->cdr)
10951 ast_set_flag(myrpt->dahditxchannel->cdr,AST_CDR_FLAG_POST_DISABLED);
10952 #endif
10953 }
10954
10955 myrpt->monchannel = ast_request("DAHDI", AST_FORMAT_SLINEAR, NULL, "pseudo", NULL);
10956 if (!myrpt->monchannel)
10957 {
10958 fprintf(stderr,"rpt:Sorry unable to obtain pseudo channel\n");
10959 rpt_mutex_unlock(&myrpt->lock);
10960 if (myrpt->txchannel != myrpt->rxchannel)
10961 ast_hangup(myrpt->txchannel);
10962 ast_hangup(myrpt->rxchannel);
10963 myrpt->rpt_thread = AST_PTHREADT_STOP;
10964 pthread_exit(NULL);
10965 }
10966 ast_set_read_format(myrpt->monchannel,AST_FORMAT_SLINEAR);
10967 ast_set_write_format(myrpt->monchannel,AST_FORMAT_SLINEAR);
10968 #ifdef AST_CDR_FLAG_POST_DISABLED
10969 if (myrpt->monchannel->cdr)
10970 ast_set_flag(myrpt->monchannel->cdr,AST_CDR_FLAG_POST_DISABLED);
10971 #endif
10972
10973 ci.chan = 0;
10974 ci.confno = -1;
10975 ci.confmode = DAHDI_CONF_CONF | DAHDI_CONF_LISTENER;
10976
10977 if (ioctl(myrpt->dahditxchannel->fds[0],DAHDI_SETCONF,&ci) == -1)
10978 {
10979 ast_log(LOG_WARNING, "Unable to set conference mode to Announce\n");
10980 rpt_mutex_unlock(&myrpt->lock);
10981 ast_hangup(myrpt->pchannel);
10982 ast_hangup(myrpt->monchannel);
10983 if (myrpt->txchannel != myrpt->rxchannel)
10984 ast_hangup(myrpt->txchannel);
10985 ast_hangup(myrpt->rxchannel);
10986 myrpt->rpt_thread = AST_PTHREADT_STOP;
10987 pthread_exit(NULL);
10988 }
10989
10990 myrpt->txconf = ci.confno;
10991
10992 ci.chan = 0;
10993 ci.confno = -1;
10994 ci.confmode = ((myrpt->p.duplex == 2) || (myrpt->p.duplex == 4)) ? DAHDI_CONF_CONFANNMON :
10995 (DAHDI_CONF_CONF | DAHDI_CONF_LISTENER | DAHDI_CONF_TALKER);
10996
10997 if (ioctl(myrpt->pchannel->fds[0],DAHDI_SETCONF,&ci) == -1)
10998 {
10999 ast_log(LOG_WARNING, "Unable to set conference mode to Announce\n");
11000 rpt_mutex_unlock(&myrpt->lock);
11001 ast_hangup(myrpt->pchannel);
11002 ast_hangup(myrpt->monchannel);
11003 if (myrpt->txchannel != myrpt->rxchannel)
11004 ast_hangup(myrpt->txchannel);
11005 ast_hangup(myrpt->rxchannel);
11006 myrpt->rpt_thread = AST_PTHREADT_STOP;
11007 pthread_exit(NULL);
11008 }
11009
11010 myrpt->conf = ci.confno;
11011
11012 ci.chan = 0;
11013 if ((strstr(myrpt->txchannel->name,"pseudo") == NULL) &&
11014 (myrpt->dahditxchannel == myrpt->txchannel))
11015 {
11016
11017 if (ioctl(myrpt->txchannel->fds[0],DAHDI_CHANNO,&ci.confno) == -1)
11018 {
11019 ast_log(LOG_WARNING, "Unable to set tx channel's chan number\n");
11020 rpt_mutex_unlock(&myrpt->lock);
11021 ast_hangup(myrpt->pchannel);
11022 ast_hangup(myrpt->monchannel);
11023 if (myrpt->txchannel != myrpt->rxchannel)
11024 ast_hangup(myrpt->txchannel);
11025 ast_hangup(myrpt->rxchannel);
11026 myrpt->rpt_thread = AST_PTHREADT_STOP;
11027 pthread_exit(NULL);
11028 }
11029 ci.confmode = DAHDI_CONF_MONITORTX;
11030 }
11031 else
11032 {
11033 ci.confno = myrpt->txconf;
11034 ci.confmode = DAHDI_CONF_CONFANNMON;
11035 }
11036
11037 if (ioctl(myrpt->monchannel->fds[0],DAHDI_SETCONF,&ci) == -1)
11038 {
11039 ast_log(LOG_WARNING, "Unable to set conference mode for monitor\n");
11040 rpt_mutex_unlock(&myrpt->lock);
11041 ast_hangup(myrpt->pchannel);
11042 ast_hangup(myrpt->monchannel);
11043 if (myrpt->txchannel != myrpt->rxchannel)
11044 ast_hangup(myrpt->txchannel);
11045 ast_hangup(myrpt->rxchannel);
11046 myrpt->rpt_thread = AST_PTHREADT_STOP;
11047 pthread_exit(NULL);
11048 }
11049
11050 myrpt->parrotchannel = ast_request("DAHDI", AST_FORMAT_SLINEAR, NULL, "pseudo", NULL);
11051 if (!myrpt->parrotchannel)
11052 {
11053 fprintf(stderr,"rpt:Sorry unable to obtain pseudo channel\n");
11054 rpt_mutex_unlock(&myrpt->lock);
11055 if (myrpt->txchannel != myrpt->rxchannel)
11056 ast_hangup(myrpt->txchannel);
11057 ast_hangup(myrpt->rxchannel);
11058 myrpt->rpt_thread = AST_PTHREADT_STOP;
11059 pthread_exit(NULL);
11060 }
11061 ast_set_read_format(myrpt->parrotchannel,AST_FORMAT_SLINEAR);
11062 ast_set_write_format(myrpt->parrotchannel,AST_FORMAT_SLINEAR);
11063 #ifdef AST_CDR_FLAG_POST_DISABLED
11064 if (myrpt->parrotchannel->cdr)
11065 ast_set_flag(myrpt->parrotchannel->cdr,AST_CDR_FLAG_POST_DISABLED);
11066 #endif
11067
11068 myrpt->voxchannel = ast_request("DAHDI", AST_FORMAT_SLINEAR, NULL, "pseudo", NULL);
11069 if (!myrpt->voxchannel)
11070 {
11071 fprintf(stderr,"rpt:Sorry unable to obtain pseudo channel\n");
11072 rpt_mutex_unlock(&myrpt->lock);
11073 if (myrpt->txchannel != myrpt->rxchannel)
11074 ast_hangup(myrpt->txchannel);
11075 ast_hangup(myrpt->rxchannel);
11076 myrpt->rpt_thread = AST_PTHREADT_STOP;
11077 pthread_exit(NULL);
11078 }
11079 ast_set_read_format(myrpt->voxchannel,AST_FORMAT_SLINEAR);
11080 ast_set_write_format(myrpt->voxchannel,AST_FORMAT_SLINEAR);
11081 #ifdef AST_CDR_FLAG_POST_DISABLED
11082 if (myrpt->voxchannel->cdr)
11083 ast_set_flag(myrpt->voxchannel->cdr,AST_CDR_FLAG_POST_DISABLED);
11084 #endif
11085
11086 myrpt->txpchannel = ast_request("DAHDI", AST_FORMAT_SLINEAR, NULL, "pseudo", NULL);
11087 if (!myrpt->txpchannel)
11088 {
11089 fprintf(stderr,"rpt:Sorry unable to obtain pseudo channel\n");
11090 rpt_mutex_unlock(&myrpt->lock);
11091 ast_hangup(myrpt->pchannel);
11092 ast_hangup(myrpt->monchannel);
11093 if (myrpt->txchannel != myrpt->rxchannel)
11094 ast_hangup(myrpt->txchannel);
11095 ast_hangup(myrpt->rxchannel);
11096 myrpt->rpt_thread = AST_PTHREADT_STOP;
11097 pthread_exit(NULL);
11098 }
11099 #ifdef AST_CDR_FLAG_POST_DISABLED
11100 if (myrpt->txpchannel->cdr)
11101 ast_set_flag(myrpt->txpchannel->cdr,AST_CDR_FLAG_POST_DISABLED);
11102 #endif
11103
11104 ci.chan = 0;
11105 ci.confno = myrpt->txconf;
11106 ci.confmode = DAHDI_CONF_CONF | DAHDI_CONF_TALKER ;
11107
11108 if (ioctl(myrpt->txpchannel->fds[0],DAHDI_SETCONF,&ci) == -1)
11109 {
11110 ast_log(LOG_WARNING, "Unable to set conference mode to Announce\n");
11111 rpt_mutex_unlock(&myrpt->lock);
11112 ast_hangup(myrpt->txpchannel);
11113 ast_hangup(myrpt->monchannel);
11114 if (myrpt->txchannel != myrpt->rxchannel)
11115 ast_hangup(myrpt->txchannel);
11116 ast_hangup(myrpt->rxchannel);
11117 myrpt->rpt_thread = AST_PTHREADT_STOP;
11118 pthread_exit(NULL);
11119 }
11120
11121 myrpt->iofd = -1;
11122 if (myrpt->p.ioport && ((myrpt->iofd = openserial(myrpt,myrpt->p.ioport)) == -1))
11123 {
11124 ast_log(LOG_ERROR, "Unable to open %s\n",myrpt->p.ioport);
11125 rpt_mutex_unlock(&myrpt->lock);
11126 ast_hangup(myrpt->pchannel);
11127 if (myrpt->txchannel != myrpt->rxchannel)
11128 ast_hangup(myrpt->txchannel);
11129 ast_hangup(myrpt->rxchannel);
11130 pthread_exit(NULL);
11131 }
11132
11133
11134
11135 myrpt->links.next = &myrpt->links;
11136 myrpt->links.prev = &myrpt->links;
11137 myrpt->tailtimer = 0;
11138 myrpt->totimer = 0;
11139 myrpt->tmsgtimer = myrpt->p.tailmessagetime;
11140 myrpt->idtimer = myrpt->p.politeid;
11141 myrpt->mustid = myrpt->tailid = 0;
11142 myrpt->callmode = 0;
11143 myrpt->tounkeyed = 0;
11144 myrpt->tonotify = 0;
11145 myrpt->retxtimer = 0;
11146 myrpt->rerxtimer = 0;
11147 myrpt->skedtimer = 0;
11148 myrpt->tailevent = 0;
11149 lasttx = 0;
11150 myrpt->keyed = 0;
11151 myrpt->txkeyed = 0;
11152 time(&myrpt->lastkeyedtime);
11153 myrpt->lastkeyedtime -= RPT_LOCKOUT_SECS;
11154 time(&myrpt->lasttxkeyedtime);
11155 myrpt->lasttxkeyedtime -= RPT_LOCKOUT_SECS;
11156 idtalkover = (char *) ast_variable_retrieve(myrpt->cfg, myrpt->name, "idtalkover");
11157 myrpt->dtmfidx = -1;
11158 myrpt->dtmfbuf[0] = 0;
11159 myrpt->rem_dtmfidx = -1;
11160 myrpt->rem_dtmfbuf[0] = 0;
11161 myrpt->dtmf_time = 0;
11162 myrpt->rem_dtmf_time = 0;
11163 myrpt->inpadtest = 0;
11164 myrpt->disgorgetime = 0;
11165 myrpt->lastnodewhichkeyedusup[0] = '\0';
11166 myrpt->dailytxtime = 0;
11167 myrpt->totaltxtime = 0;
11168 myrpt->dailykeyups = 0;
11169 myrpt->totalkeyups = 0;
11170 myrpt->dailykerchunks = 0;
11171 myrpt->totalkerchunks = 0;
11172 myrpt->dailyexecdcommands = 0;
11173 myrpt->totalexecdcommands = 0;
11174 myrpt->timeouts = 0;
11175 myrpt->exten[0] = '\0';
11176 myrpt->lastdtmfcommand[0] = '\0';
11177 voxinit_rpt(myrpt,1);
11178 myrpt->wasvox = 0;
11179 if (myrpt->p.startupmacro)
11180 {
11181 snprintf(myrpt->macrobuf,MAXMACRO - 1,"PPPP%s",myrpt->p.startupmacro);
11182 }
11183 rpt_mutex_unlock(&myrpt->lock);
11184 val = 1;
11185 ast_channel_setoption(myrpt->rxchannel,AST_OPTION_RELAXDTMF,&val,sizeof(char),0);
11186 val = 1;
11187 ast_channel_setoption(myrpt->rxchannel,AST_OPTION_TONE_VERIFY,&val,sizeof(char),0);
11188 if (myrpt->p.archivedir) donodelog(myrpt,"STARTUP");
11189 dtmfed = 0;
11190 if (myrpt->remoterig && !ISRIG_RTX(myrpt->remoterig)) setrem(myrpt);
11191 lastmyrx = 0;
11192 myfirst = 0;
11193 while (ms >= 0)
11194 {
11195 struct ast_frame *f,*f1,*f2;
11196 struct ast_channel *cs[300],*cs1[300];
11197 int totx=0,elap=0,n,x,toexit=0;
11198
11199
11200 if((myrpt->disgorgetime) && (time(NULL) >= myrpt->disgorgetime)){
11201 struct rpt_link *dl;
11202 struct rpt_tele *dt;
11203
11204 myrpt->disgorgetime = 0;
11205 ast_log(LOG_NOTICE,"********** Variable Dump Start (app_rpt) **********\n");
11206 ast_log(LOG_NOTICE,"totx = %d\n",totx);
11207 ast_log(LOG_NOTICE,"remrx = %d\n",remrx);
11208 ast_log(LOG_NOTICE,"lasttx = %d\n",lasttx);
11209 ast_log(LOG_NOTICE,"elap = %d\n",elap);
11210 ast_log(LOG_NOTICE,"toexit = %d\n",toexit);
11211
11212 ast_log(LOG_NOTICE,"myrpt->keyed = %d\n",myrpt->keyed);
11213 ast_log(LOG_NOTICE,"myrpt->localtx = %d\n",myrpt->localtx);
11214 ast_log(LOG_NOTICE,"myrpt->callmode = %d\n",myrpt->callmode);
11215 ast_log(LOG_NOTICE,"myrpt->mustid = %d\n",myrpt->mustid);
11216 ast_log(LOG_NOTICE,"myrpt->tounkeyed = %d\n",myrpt->tounkeyed);
11217 ast_log(LOG_NOTICE,"myrpt->tonotify = %d\n",myrpt->tonotify);
11218 ast_log(LOG_NOTICE,"myrpt->retxtimer = %ld\n",myrpt->retxtimer);
11219 ast_log(LOG_NOTICE,"myrpt->totimer = %d\n",myrpt->totimer);
11220 ast_log(LOG_NOTICE,"myrpt->tailtimer = %d\n",myrpt->tailtimer);
11221 ast_log(LOG_NOTICE,"myrpt->tailevent = %d\n",myrpt->tailevent);
11222
11223 dl = myrpt->links.next;
11224 while(dl != &myrpt->links){
11225 ast_log(LOG_NOTICE,"*** Link Name: %s ***\n",dl->name);
11226 ast_log(LOG_NOTICE," link->lasttx %d\n",dl->lasttx);
11227 ast_log(LOG_NOTICE," link->lastrx %d\n",dl->lastrx);
11228 ast_log(LOG_NOTICE," link->connected %d\n",dl->connected);
11229 ast_log(LOG_NOTICE," link->hasconnected %d\n",dl->hasconnected);
11230 ast_log(LOG_NOTICE," link->outbound %d\n",dl->outbound);
11231 ast_log(LOG_NOTICE," link->disced %d\n",dl->disced);
11232 ast_log(LOG_NOTICE," link->killme %d\n",dl->killme);
11233 ast_log(LOG_NOTICE," link->disctime %ld\n",dl->disctime);
11234 ast_log(LOG_NOTICE," link->retrytimer %ld\n",dl->retrytimer);
11235 ast_log(LOG_NOTICE," link->retries = %d\n",dl->retries);
11236 ast_log(LOG_NOTICE," link->reconnects = %d\n",dl->reconnects);
11237 ast_log(LOG_NOTICE," link->newkey = %d\n",dl->newkey);
11238 dl = dl->next;
11239 }
11240
11241 dt = myrpt->tele.next;
11242 if(dt != &myrpt->tele)
11243 ast_log(LOG_NOTICE,"*** Telemetry Queue ***\n");
11244 while(dt != &myrpt->tele){
11245 ast_log(LOG_NOTICE," Telemetry mode: %d\n",dt->mode);
11246 dt = dt->next;
11247 }
11248 ast_log(LOG_NOTICE,"******* Variable Dump End (app_rpt) *******\n");
11249
11250 }
11251
11252
11253 if (myrpt->reload)
11254 {
11255 struct rpt_tele *inner_telem;
11256
11257 rpt_mutex_lock(&myrpt->lock);
11258 inner_telem = myrpt->tele.next;
11259 while(inner_telem != &myrpt->tele)
11260 {
11261 ast_softhangup(inner_telem->chan,AST_SOFTHANGUP_DEV);
11262 inner_telem = inner_telem->next;
11263 }
11264 myrpt->reload = 0;
11265 rpt_mutex_unlock(&myrpt->lock);
11266 usleep(10000);
11267
11268 for(i = 0; i < nrpts; i++)
11269 {
11270 if (&rpt_vars[i] == myrpt)
11271 {
11272 load_rpt_vars(i,0);
11273 break;
11274 }
11275 }
11276 }
11277
11278 rpt_mutex_lock(&myrpt->lock);
11279 if (ast_check_hangup(myrpt->rxchannel)) break;
11280 if (ast_check_hangup(myrpt->txchannel)) break;
11281 if (ast_check_hangup(myrpt->pchannel)) break;
11282 if (ast_check_hangup(myrpt->monchannel)) break;
11283 if (myrpt->parrotchannel &&
11284 ast_check_hangup(myrpt->parrotchannel)) break;
11285 if (myrpt->voxchannel &&
11286 ast_check_hangup(myrpt->voxchannel)) break;
11287 if (ast_check_hangup(myrpt->txpchannel)) break;
11288 if (myrpt->dahditxchannel && ast_check_hangup(myrpt->dahditxchannel)) break;
11289
11290
11291 myrpt->localtx = myrpt->keyed;
11292
11293 l = myrpt->links.next;
11294 remrx = 0;
11295 while(l != &myrpt->links)
11296 {
11297 if (l->lastrx){
11298 remrx = 1;
11299 if(l->name[0] != '0')
11300 strcpy(myrpt->lastnodewhichkeyedusup, l->name);
11301 }
11302 l = l->next;
11303 }
11304
11305 if(myrpt->p.idtime)
11306 myrpt->mustid |= (myrpt->idtimer) && (myrpt->keyed || remrx) ;
11307
11308
11309 if (myrpt->p.duplex > 1)
11310 {
11311 totx = myrpt->callmode;
11312 totx = totx || myrpt->localtx;
11313 }
11314 else
11315 {
11316 int myrx = myrpt->localtx || remrx || (!myrpt->callmode);
11317
11318 if (lastmyrx != myrx)
11319 {
11320 voxinit_rpt(myrpt,!myrx);
11321 lastmyrx = myrx;
11322 }
11323 totx = 0;
11324 if (myrpt->callmode && (myrpt->voxtotimer <= 0))
11325 {
11326 if (myrpt->voxtostate)
11327 {
11328 myrpt->voxtotimer = myrpt->p.voxtimeout_ms;
11329 myrpt->voxtostate = 0;
11330 }
11331 else
11332 {
11333 myrpt->voxtotimer = myrpt->p.voxrecover_ms;
11334 myrpt->voxtostate = 1;
11335 }
11336 }
11337 if (!myrpt->voxtostate)
11338 totx = myrpt->callmode && myrpt->wasvox;
11339 }
11340
11341 identqueued = 0;
11342 localmsgqueued = 0;
11343 othertelemqueued = 0;
11344 tailmessagequeued = 0;
11345 ctqueued = 0;
11346 telem = myrpt->tele.next;
11347 while(telem != &myrpt->tele)
11348 {
11349 if((telem->mode == ID) || (telem->mode == IDTALKOVER)){
11350 identqueued = 1;
11351 }
11352 else if(telem->mode == TAILMSG)
11353 {
11354 tailmessagequeued = 1;
11355 }
11356 else if(telem->mode == STATS_TIME_LOCAL)
11357 {
11358 localmsgqueued = 1;
11359 }
11360 else
11361 {
11362 if ((telem->mode != UNKEY) && (telem->mode != LINKUNKEY))
11363 othertelemqueued = 1;
11364 else
11365 ctqueued = 1;
11366 }
11367 telem = telem->next;
11368 }
11369
11370
11371 if (!myrpt->p.notelemtx) totx = totx || othertelemqueued;
11372
11373
11374 myrpt->exttx = totx;
11375 totx = totx || myrpt->dtmf_local_timer;
11376
11377 if (myrpt->p.duplex < 2) myrpt->exttx = myrpt->exttx || myrpt->localtx;
11378
11379 totx = totx || remrx;
11380
11381 if (myrpt->p.duplex > 0)
11382 totx = totx || identqueued || ctqueued || localmsgqueued;
11383
11384 if (myrpt->p.duplex > 1)
11385 {
11386 totx = totx || (myrpt->dtmfidx > -1) ||
11387 myrpt->cmdnode[0];
11388 }
11389
11390 totx = totx || (myrpt->parrotstate > 1);
11391
11392 if (!totx)
11393 {
11394 myrpt->totimer = myrpt->p.totime;
11395 myrpt->tounkeyed = 0;
11396 myrpt->tonotify = 0;
11397 }
11398 else{
11399 myrpt->tailtimer = myrpt->p.s[myrpt->p.sysstate_cur].alternatetail ?
11400 myrpt->p.althangtime :
11401 myrpt->p.hangtime;
11402 }
11403
11404 totx = totx && myrpt->totimer;
11405
11406 if ((!myrpt->totimer) && (!myrpt->tonotify))
11407 {
11408 myrpt->tonotify = 1;
11409 myrpt->timeouts++;
11410 rpt_mutex_unlock(&myrpt->lock);
11411 rpt_telemetry(myrpt,TIMEOUT,NULL);
11412 rpt_mutex_lock(&myrpt->lock);
11413 }
11414
11415
11416 if ((!totx) && (!myrpt->totimer) && (!myrpt->tounkeyed) && (!myrpt->keyed))
11417 {
11418 myrpt->tounkeyed = 1;
11419 }
11420 if ((!totx) && (!myrpt->totimer) && myrpt->tounkeyed && myrpt->keyed)
11421 {
11422 myrpt->totimer = myrpt->p.totime;
11423 myrpt->tounkeyed = 0;
11424 myrpt->tonotify = 0;
11425 rpt_mutex_unlock(&myrpt->lock);
11426 continue;
11427 }
11428
11429 if ((!totx) && (!myrpt->totimer) && (myrpt->callmode == 4))
11430 {
11431 if(debug)
11432 ast_log(LOG_NOTICE, "timed-out and in circuit busy after call\n");
11433 myrpt->callmode = 0;
11434 myrpt->macropatch=0;
11435 channel_revert(myrpt);
11436 }
11437
11438 if (!myrpt->totimer) myrpt->tailtimer = 0;
11439
11440 if (myrpt->totimer) totx = totx || myrpt->tailtimer;
11441
11442
11443 if ((myrpt->keyed || remrx) && ((identqueued && idtalkover) || (tailmessagequeued))) {
11444 int hasid = 0,hastalkover = 0;
11445
11446 telem = myrpt->tele.next;
11447 while(telem != &myrpt->tele){
11448 if(telem->mode == ID){
11449 if (telem->chan) ast_softhangup(telem->chan, AST_SOFTHANGUP_DEV);
11450 hasid = 1;
11451 }
11452 if(telem->mode == TAILMSG){
11453 if (telem->chan) ast_softhangup(telem->chan, AST_SOFTHANGUP_DEV);
11454 }
11455 if (telem->mode == IDTALKOVER) hastalkover = 1;
11456 telem = telem->next;
11457 }
11458 rpt_mutex_unlock(&myrpt->lock);
11459 if (hasid && (!hastalkover)) rpt_telemetry(myrpt, IDTALKOVER, NULL);
11460 rpt_mutex_lock(&myrpt->lock);
11461 }
11462
11463
11464
11465
11466
11467 if(myrpt->mustid && (!myrpt->idtimer))
11468 queue_id(myrpt);
11469
11470 if ((myrpt->p.idtime && totx && (!myrpt->exttx) &&
11471 (myrpt->idtimer <= myrpt->p.politeid) && myrpt->tailtimer))
11472 {
11473 myrpt->tailid = 1;
11474 }
11475
11476
11477
11478 if(myrpt->tailevent){
11479 myrpt->tailevent = 0;
11480 if(myrpt->tailid){
11481 totx = 1;
11482 queue_id(myrpt);
11483 }
11484 else if ((myrpt->p.tailmessages[0]) &&
11485 (myrpt->p.tailmessagetime) && (myrpt->tmsgtimer == 0)){
11486 totx = 1;
11487 myrpt->tmsgtimer = myrpt->p.tailmessagetime;
11488 rpt_mutex_unlock(&myrpt->lock);
11489 rpt_telemetry(myrpt, TAILMSG, NULL);
11490 rpt_mutex_lock(&myrpt->lock);
11491 }
11492 }
11493
11494
11495
11496
11497 if (myrpt->p.duplex > 0) totx = totx || (myrpt->tele.next != &myrpt->tele);
11498 totx = totx && !myrpt->p.s[myrpt->p.sysstate_cur].txdisable;
11499 myrpt->txrealkeyed = totx;
11500 totx = totx || (!AST_LIST_EMPTY(&myrpt->txq));
11501 if (totx && (!lasttx))
11502 {
11503 char mydate[100],myfname[100];
11504 time_t myt;
11505
11506 if (myrpt->monstream) ast_closestream(myrpt->monstream);
11507 if (myrpt->p.archivedir)
11508 {
11509 long blocksleft;
11510
11511 time(&myt);
11512 strftime(mydate,sizeof(mydate) - 1,"%Y%m%d%H%M%S",
11513 localtime(&myt));
11514 sprintf(myfname,"%s/%s/%s",myrpt->p.archivedir,
11515 myrpt->name,mydate);
11516 myrpt->monstream = ast_writefile(myfname,"wav49",
11517 "app_rpt Air Archive",O_CREAT | O_APPEND,0,0600);
11518 if (myrpt->p.monminblocks)
11519 {
11520 blocksleft = diskavail(myrpt);
11521 if (blocksleft >= myrpt->p.monminblocks)
11522 donodelog(myrpt,"TXKEY,MAIN");
11523 } else donodelog(myrpt,"TXKEY,MAIN");
11524 }
11525 lasttx = 1;
11526 myrpt->txkeyed = 1;
11527 time(&myrpt->lasttxkeyedtime);
11528 myrpt->dailykeyups++;
11529 myrpt->totalkeyups++;
11530 rpt_mutex_unlock(&myrpt->lock);
11531 ast_indicate(myrpt->txchannel,AST_CONTROL_RADIO_KEY);
11532 rpt_mutex_lock(&myrpt->lock);
11533 }
11534 if ((!totx) && lasttx)
11535 {
11536 if (myrpt->monstream) ast_closestream(myrpt->monstream);
11537 myrpt->monstream = NULL;
11538
11539 lasttx = 0;
11540 myrpt->txkeyed = 0;
11541 time(&myrpt->lasttxkeyedtime);
11542 rpt_mutex_unlock(&myrpt->lock);
11543 ast_indicate(myrpt->txchannel,AST_CONTROL_RADIO_UNKEY);
11544 rpt_mutex_lock(&myrpt->lock);
11545 donodelog(myrpt,"TXUNKEY,MAIN");
11546 }
11547 time(&t);
11548
11549 if ((!myrpt->cmdnode[0]) && (myrpt->dtmfidx >= 0) && ((myrpt->dtmf_time + DTMF_TIMEOUT) < t))
11550 {
11551 myrpt->inpadtest = 0;
11552 myrpt->dtmfidx = -1;
11553 myrpt->dtmfbuf[0] = 0;
11554 }
11555
11556 if ((myrpt->rem_dtmfidx >= 0) && ((myrpt->rem_dtmf_time + DTMF_TIMEOUT) < t))
11557 {
11558 myrpt->inpadtest = 0;
11559 myrpt->rem_dtmfidx = -1;
11560 myrpt->rem_dtmfbuf[0] = 0;
11561 }
11562
11563 if (myrpt->exttx && myrpt->parrotchannel &&
11564 myrpt->p.parrotmode && (!myrpt->parrotstate))
11565 {
11566 char myfname[300];
11567
11568 ci.confno = myrpt->conf;
11569 ci.confmode = DAHDI_CONF_CONFANNMON;
11570 ci.chan = 0;
11571
11572
11573 if (ioctl(myrpt->parrotchannel->fds[0],DAHDI_SETCONF,&ci) == -1)
11574 {
11575 ast_log(LOG_WARNING, "Unable to set conference mode for parrot\n");
11576 break;
11577 }
11578
11579 sprintf(myfname,PARROTFILE,myrpt->name,myrpt->parrotcnt);
11580 strcat(myfname,".wav");
11581 unlink(myfname);
11582 sprintf(myfname,PARROTFILE,myrpt->name,myrpt->parrotcnt);
11583 myrpt->parrotstate = 1;
11584 myrpt->parrottimer = myrpt->p.parrottime;
11585 if (myrpt->parrotstream)
11586 ast_closestream(myrpt->parrotstream);
11587 myrpt->parrotstream = NULL;
11588 myrpt->parrotstream = ast_writefile(myfname,"wav",
11589 "app_rpt Parrot",O_CREAT | O_TRUNC,0,0600);
11590 }
11591
11592
11593
11594 l = myrpt->links.next;
11595 while(l != &myrpt->links)
11596 {
11597 if (l->killme)
11598 {
11599
11600 remque((struct qelem *) l);
11601 if (!strcmp(myrpt->cmdnode,l->name))
11602 myrpt->cmdnode[0] = 0;
11603 rpt_mutex_unlock(&myrpt->lock);
11604
11605 if (l->chan) ast_hangup(l->chan);
11606 ast_hangup(l->pchan);
11607 ast_free(l);
11608 rpt_mutex_lock(&myrpt->lock);
11609
11610 l = myrpt->links.next;
11611 continue;
11612 }
11613 l = l->next;
11614 }
11615 n = 0;
11616 cs[n++] = myrpt->rxchannel;
11617 cs[n++] = myrpt->pchannel;
11618 cs[n++] = myrpt->monchannel;
11619 if (myrpt->parrotchannel) cs[n++] = myrpt->parrotchannel;
11620 if (myrpt->voxchannel) cs[n++] = myrpt->voxchannel;
11621 cs[n++] = myrpt->txpchannel;
11622 if (myrpt->txchannel != myrpt->rxchannel) cs[n++] = myrpt->txchannel;
11623 if (myrpt->dahditxchannel != myrpt->txchannel)
11624 cs[n++] = myrpt->dahditxchannel;
11625 l = myrpt->links.next;
11626 while(l != &myrpt->links)
11627 {
11628 if ((!l->killme) && (!l->disctime) && l->chan)
11629 {
11630 cs[n++] = l->chan;
11631 cs[n++] = l->pchan;
11632 }
11633 l = l->next;
11634 }
11635 if ((myrpt->topkeystate == 1) &&
11636 ((t - myrpt->topkeytime) > TOPKEYWAIT))
11637 {
11638 myrpt->topkeystate = 2;
11639 qsort(myrpt->topkey,TOPKEYN,sizeof(struct rpt_topkey),
11640 topcompar);
11641 }
11642 rpt_mutex_unlock(&myrpt->lock);
11643
11644 if (myrpt->topkeystate == 2)
11645 {
11646 rpt_telemetry(myrpt,TOPKEY,NULL);
11647 myrpt->topkeystate = 3;
11648 }
11649 ms = MSWAIT;
11650 for(x = 0; x < n; x++)
11651 {
11652 int s = -(-x - myrpt->scram - 1) % n;
11653 cs1[x] = cs[s];
11654 }
11655 myrpt->scram++;
11656 who = ast_waitfor_n(cs1,n,&ms);
11657 if (who == NULL) ms = 0;
11658 elap = MSWAIT - ms;
11659 rpt_mutex_lock(&myrpt->lock);
11660 l = myrpt->links.next;
11661 while(l != &myrpt->links)
11662 {
11663 int myrx;
11664
11665 if (l->voxtotimer) l->voxtotimer -= elap;
11666 if (l->voxtotimer < 0) l->voxtotimer = 0;
11667
11668 if (l->lasttx != l->lasttx1)
11669 {
11670 voxinit_link(l,!l->lasttx);
11671 l->lasttx1 = l->lasttx;
11672 }
11673 myrx = l->lastrealrx;
11674 if ((l->phonemode) && (l->phonevox))
11675 {
11676 myrx = myrx || (!AST_LIST_EMPTY(&l->rxq));
11677 if (l->voxtotimer <= 0)
11678 {
11679 if (l->voxtostate)
11680 {
11681 l->voxtotimer = myrpt->p.voxtimeout_ms;
11682 l->voxtostate = 0;
11683 }
11684 else
11685 {
11686 l->voxtotimer = myrpt->p.voxrecover_ms;
11687 l->voxtostate = 1;
11688 }
11689 }
11690 if (!l->voxtostate)
11691 myrx = myrx || l->wasvox ;
11692 }
11693 l->lastrx = myrx;
11694 if (l->linklisttimer)
11695 {
11696 l->linklisttimer -= elap;
11697 if (l->linklisttimer < 0) l->linklisttimer = 0;
11698 }
11699 if ((!l->linklisttimer) && (l->name[0] != '0') && (!l->isremote))
11700 {
11701 struct ast_frame lf;
11702
11703 memset(&lf,0,sizeof(lf));
11704 lf.frametype = AST_FRAME_TEXT;
11705 lf.subclass.integer = 0;
11706 lf.offset = 0;
11707 lf.mallocd = 0;
11708 lf.samples = 0;
11709 l->linklisttimer = LINKLISTTIME;
11710 strcpy(lstr,"L ");
11711 __mklinklist(myrpt,l,lstr + 2);
11712 if (l->chan)
11713 {
11714 lf.datalen = strlen(lstr) + 1;
11715 lf.data.ptr = lstr;
11716 ast_write(l->chan,&lf);
11717 if (debug > 6) ast_log(LOG_NOTICE,
11718 "@@@@ node %s sent node string %s to node %s\n",
11719 myrpt->name,lstr,l->name);
11720 }
11721 }
11722 if (l->newkey)
11723 {
11724 if ((l->retxtimer += elap) >= REDUNDANT_TX_TIME)
11725 {
11726 l->retxtimer = 0;
11727 if (l->chan && l->phonemode == 0)
11728 {
11729 if (l->lasttx)
11730 ast_indicate(l->chan,AST_CONTROL_RADIO_KEY);
11731 else
11732 ast_indicate(l->chan,AST_CONTROL_RADIO_UNKEY);
11733 }
11734 }
11735 if ((l->rerxtimer += elap) >= (REDUNDANT_TX_TIME * 5))
11736 {
11737 if (debug == 7) printf("@@@@ rx un-key\n");
11738 l->lastrealrx = 0;
11739 l->rerxtimer = 0;
11740 if (l->lastrx1)
11741 {
11742 if (myrpt->p.archivedir)
11743 {
11744 char str[100];
11745
11746 sprintf(str,"RXUNKEY(T),%s",l->name);
11747 donodelog(myrpt,str);
11748 }
11749 if(myrpt->p.duplex)
11750 rpt_telemetry(myrpt,LINKUNKEY,l);
11751 l->lastrx1 = 0;
11752 }
11753 }
11754 }
11755 if (l->disctime)
11756 {
11757 l->disctime -= elap;
11758 if (l->disctime <= 0)
11759 l->disctime = 0;
11760 }
11761
11762 if (l->retrytimer)
11763 {
11764 l->retrytimer -= elap;
11765 if (l->retrytimer < 0) l->retrytimer = 0;
11766 }
11767
11768
11769 l->connecttime += elap;
11770
11771
11772 if (l->elaptime < 0)
11773 {
11774 l = l->next;
11775 continue;
11776 }
11777 l->elaptime += elap;
11778
11779 if ((l->elaptime > MAXCONNECTTIME) &&
11780 ((!l->chan) || (l->chan->_state != AST_STATE_UP)))
11781 {
11782 l->elaptime = 0;
11783 rpt_mutex_unlock(&myrpt->lock);
11784 if (l->chan) ast_softhangup(l->chan,AST_SOFTHANGUP_DEV);
11785 rpt_mutex_lock(&myrpt->lock);
11786 break;
11787 }
11788 if ((!l->chan) && (!l->retrytimer) && l->outbound &&
11789 (l->retries++ < l->max_retries) && (l->hasconnected))
11790 {
11791 if (l->chan) ast_hangup(l->chan);
11792 l->chan = 0;
11793 rpt_mutex_unlock(&myrpt->lock);
11794 if ((l->name[0] != '0') && (!l->isremote))
11795 {
11796 if (attempt_reconnect(myrpt,l) == -1)
11797 {
11798 l->retrytimer = RETRY_TIMER_MS;
11799 }
11800 }
11801 else
11802 {
11803 l->retrytimer = l->max_retries + 1;
11804 }
11805
11806 rpt_mutex_lock(&myrpt->lock);
11807 break;
11808 }
11809 if ((!l->chan) && (!l->retrytimer) && l->outbound &&
11810 (l->retries >= l->max_retries))
11811 {
11812
11813 remque((struct qelem *) l);
11814 if (!strcmp(myrpt->cmdnode,l->name))
11815 myrpt->cmdnode[0] = 0;
11816 rpt_mutex_unlock(&myrpt->lock);
11817 if (l->name[0] != '0')
11818 {
11819 if (!l->hasconnected)
11820 rpt_telemetry(myrpt,CONNFAIL,l);
11821 else rpt_telemetry(myrpt,REMDISC,l);
11822 }
11823 if (myrpt->p.archivedir)
11824 {
11825 char str[100];
11826
11827 if (!l->hasconnected)
11828 sprintf(str,"LINKFAIL,%s",l->name);
11829 else
11830 sprintf(str,"LINKDISC,%s",l->name);
11831 donodelog(myrpt,str);
11832 }
11833
11834 ast_hangup(l->pchan);
11835 ast_free(l);
11836 rpt_mutex_lock(&myrpt->lock);
11837 break;
11838 }
11839 if ((!l->chan) && (!l->disctime) && (!l->outbound))
11840 {
11841 if(debug)ast_log(LOG_NOTICE, "LINKDISC AA\n");
11842
11843 remque((struct qelem *) l);
11844 if(myrpt->links.next==&myrpt->links)channel_revert(myrpt);
11845 if (!strcmp(myrpt->cmdnode,l->name))myrpt->cmdnode[0] = 0;
11846 rpt_mutex_unlock(&myrpt->lock);
11847 if (l->name[0] != '0')
11848 {
11849 rpt_telemetry(myrpt,REMDISC,l);
11850 }
11851 if (myrpt->p.archivedir)
11852 {
11853 char str[100];
11854 sprintf(str,"LINKDISC,%s",l->name);
11855 donodelog(myrpt,str);
11856 }
11857
11858 ast_hangup(l->pchan);
11859 ast_free(l);
11860 rpt_mutex_lock(&myrpt->lock);
11861 break;
11862 }
11863 l = l->next;
11864 }
11865 if (myrpt->linkposttimer)
11866 {
11867 myrpt->linkposttimer -= elap;
11868 if (myrpt->linkposttimer < 0) myrpt->linkposttimer = 0;
11869 }
11870 if (myrpt->linkposttimer <= 0)
11871 {
11872 int nstr;
11873 char lst,*str;
11874 time_t now;
11875
11876 myrpt->linkposttimer = LINKPOSTTIME;
11877 nstr = 0;
11878 for(l = myrpt->links.next; l != &myrpt->links; l = l->next)
11879 {
11880
11881 if (l->name[0] == '0') continue;
11882 nstr += strlen(l->name) + 1;
11883 }
11884 str = ast_malloc(nstr + 256);
11885 if (!str)
11886 {
11887 ast_log(LOG_NOTICE,"Cannot ast_malloc()\n");
11888 break;
11889 }
11890 nstr = 0;
11891 strcpy(str,"nodes=");
11892 for(l = myrpt->links.next; l != &myrpt->links; l = l->next)
11893 {
11894
11895 if (l->name[0] == '0') continue;
11896 lst = 'T';
11897 if (!l->mode) lst = 'R';
11898 if (!l->thisconnected) lst = 'C';
11899 if (nstr) strcat(str,",");
11900 sprintf(str + strlen(str),"%c%s",lst,l->name);
11901 nstr = 1;
11902 }
11903 p = strstr(tdesc, "version");
11904 if(p){
11905 int vmajor,vminor;
11906 if(sscanf(p, "version %30d.%30d", &vmajor, &vminor) == 2)
11907 sprintf(str + strlen(str),"&apprptvers=%d.%d",vmajor,vminor);
11908 }
11909 time(&now);
11910 sprintf(str + strlen(str),"&apprptuptime=%d",(int)(now-starttime));
11911 sprintf(str + strlen(str),
11912 "&totalkerchunks=%d&totalkeyups=%d&totaltxtime=%d&timeouts=%d&totalexecdcommands=%d",
11913 myrpt->totalkerchunks,myrpt->totalkeyups,(int) myrpt->totaltxtime/1000,
11914 myrpt->timeouts,myrpt->totalexecdcommands);
11915 rpt_mutex_unlock(&myrpt->lock);
11916 statpost(myrpt,str);
11917 rpt_mutex_lock(&myrpt->lock);
11918 ast_free(str);
11919 }
11920 if (myrpt->keyposttimer)
11921 {
11922 myrpt->keyposttimer -= elap;
11923 if (myrpt->keyposttimer < 0) myrpt->keyposttimer = 0;
11924 }
11925 if (myrpt->keyposttimer <= 0)
11926 {
11927 char str[100];
11928 int diff = 0;
11929 time_t now;
11930
11931 myrpt->keyposttimer = KEYPOSTTIME;
11932 time(&now);
11933 if (myrpt->lastkeyedtime)
11934 {
11935 diff = (int)(now - myrpt->lastkeyedtime);
11936 }
11937 sprintf(str,"keyed=%d&keytime=%d",myrpt->keyed,diff);
11938 rpt_mutex_unlock(&myrpt->lock);
11939 statpost(myrpt,str);
11940 rpt_mutex_lock(&myrpt->lock);
11941 }
11942 if(totx){
11943 myrpt->dailytxtime += elap;
11944 myrpt->totaltxtime += elap;
11945 }
11946 i = myrpt->tailtimer;
11947 if (myrpt->tailtimer) myrpt->tailtimer -= elap;
11948 if (myrpt->tailtimer < 0) myrpt->tailtimer = 0;
11949 if((i) && (myrpt->tailtimer == 0))
11950 myrpt->tailevent = 1;
11951 if ((!myrpt->p.s[myrpt->p.sysstate_cur].totdisable) && myrpt->totimer) myrpt->totimer -= elap;
11952 if (myrpt->totimer < 0) myrpt->totimer = 0;
11953 if (myrpt->idtimer) myrpt->idtimer -= elap;
11954 if (myrpt->idtimer < 0) myrpt->idtimer = 0;
11955 if (myrpt->tmsgtimer) myrpt->tmsgtimer -= elap;
11956 if (myrpt->tmsgtimer < 0) myrpt->tmsgtimer = 0;
11957 if (myrpt->voxtotimer) myrpt->voxtotimer -= elap;
11958 if (myrpt->voxtotimer < 0) myrpt->voxtotimer = 0;
11959 if (myrpt->exttx)
11960 {
11961 myrpt->parrottimer = myrpt->p.parrottime;
11962 }
11963 else
11964 {
11965 if (myrpt->parrottimer) myrpt->parrottimer -= elap;
11966 if (myrpt->parrottimer < 0) myrpt->parrottimer = 0;
11967 }
11968
11969 if (myrpt->macrotimer) myrpt->macrotimer -= elap;
11970 if (myrpt->macrotimer < 0) myrpt->macrotimer = 0;
11971
11972 if (myrpt->dtmf_local_timer)
11973 {
11974 if (myrpt->dtmf_local_timer > 1) myrpt->dtmf_local_timer -= elap;
11975 if (myrpt->dtmf_local_timer < 1) myrpt->dtmf_local_timer = 1;
11976 }
11977 do_dtmf_local(myrpt,0);
11978
11979 if (myrpt->skedtimer <= 0){
11980 myrpt->skedtimer = 200;
11981 do_scheduler(myrpt);
11982 }
11983 else
11984 myrpt->skedtimer -=elap;
11985 if (!ms)
11986 {
11987 rpt_mutex_unlock(&myrpt->lock);
11988 continue;
11989 }
11990 if (myrpt->p.parrotmode && (myrpt->parrotstate == 1) &&
11991 (myrpt->parrottimer <= 0))
11992 {
11993
11994 ci.confno = 0;
11995 ci.confmode = 0;
11996 ci.chan = 0;
11997
11998
11999 if (ioctl(myrpt->parrotchannel->fds[0],DAHDI_SETCONF,&ci) == -1)
12000 {
12001 ast_log(LOG_WARNING, "Unable to set conference mode for parrot\n");
12002 break;
12003 }
12004 if (myrpt->parrotstream)
12005 ast_closestream(myrpt->parrotstream);
12006 myrpt->parrotstream = NULL;
12007 myrpt->parrotstate = 2;
12008 rpt_telemetry(myrpt,PARROT,(void *) ((intptr_t)myrpt->parrotcnt++));
12009 }
12010 if (myrpt->cmdAction.state == CMD_STATE_READY)
12011 {
12012 int status;
12013 myrpt->cmdAction.state = CMD_STATE_EXECUTING;
12014
12015 rpt_mutex_unlock(&myrpt->lock);
12016
12017 status = (*function_table[myrpt->cmdAction.functionNumber].function)(myrpt,myrpt->cmdAction.param, myrpt->cmdAction.digits, myrpt->cmdAction.command_source, NULL);
12018
12019 rpt_mutex_lock(&myrpt->lock);
12020 myrpt->cmdAction.state = CMD_STATE_IDLE;
12021 }
12022
12023 c = myrpt->macrobuf[0];
12024 time(&t);
12025 if (c && (!myrpt->macrotimer) &&
12026 starttime && (t > (starttime + START_DELAY)))
12027 {
12028 char cin = c & 0x7f;
12029 myrpt->macrotimer = MACROTIME;
12030 memmove(myrpt->macrobuf,myrpt->macrobuf + 1,MAXMACRO - 1);
12031 if ((cin == 'p') || (cin == 'P'))
12032 myrpt->macrotimer = MACROPTIME;
12033 rpt_mutex_unlock(&myrpt->lock);
12034 if (myrpt->p.archivedir)
12035 {
12036 char str[100];
12037
12038 sprintf(str,"DTMF(M),MAIN,%c",cin);
12039 donodelog(myrpt,str);
12040 }
12041 local_dtmf_helper(myrpt,c);
12042 } else rpt_mutex_unlock(&myrpt->lock);
12043 if (who == myrpt->rxchannel)
12044 {
12045 int ismuted;
12046
12047 f = ast_read(myrpt->rxchannel);
12048 if (!f)
12049 {
12050 if (debug) printf("@@@@ rpt:Hung Up\n");
12051 break;
12052 }
12053 if (f->frametype == AST_FRAME_VOICE)
12054 {
12055 #ifdef _MDC_DECODE_H_
12056 unsigned char ubuf[2560];
12057 short *sp;
12058 int n;
12059 #endif
12060
12061 if ((!myrpt->localtx) && (!myrpt->p.linktolink)) {
12062 memset(f->data.ptr,0,f->datalen);
12063 }
12064
12065 #ifdef _MDC_DECODE_H_
12066 sp = (short *) f->data;
12067
12068 for(n = 0; n < f->datalen / 2; n++)
12069 {
12070 ubuf[n] = (*sp++ >> 8) + 128;
12071 }
12072 n = mdc_decoder_process_samples(myrpt->mdc,ubuf,f->datalen / 2);
12073 if (n == 1)
12074 {
12075 unsigned char op,arg;
12076 unsigned short unitID;
12077
12078 mdc_decoder_get_packet(myrpt->mdc,&op,&arg,&unitID);
12079 if (debug > 2)
12080 {
12081 ast_log(LOG_NOTICE,"Got (single-length) packet:\n");
12082 ast_log(LOG_NOTICE,"op: %02x, arg: %02x, UnitID: %04x\n",
12083 op & 255,arg & 255,unitID);
12084 }
12085 if ((op == 1) && (arg == 0))
12086 {
12087 myrpt->lastunit = unitID;
12088 mdc1200_notify(myrpt,NULL,myrpt->lastunit);
12089 mdc1200_send(myrpt,myrpt->lastunit);
12090 }
12091 }
12092 if ((debug > 2) && (i == 2))
12093 {
12094 unsigned char op,arg,ex1,ex2,ex3,ex4;
12095 unsigned short unitID;
12096
12097 mdc_decoder_get_double_packet(myrpt->mdc,&op,&arg,&unitID,
12098 &ex1,&ex2,&ex3,&ex4);
12099 ast_log(LOG_NOTICE,"Got (double-length) packet:\n");
12100 ast_log(LOG_NOTICE,"op: %02x, arg: %02x, UnitID: %04x\n",
12101 op & 255,arg & 255,unitID);
12102 ast_log(LOG_NOTICE,"ex1: %02x, ex2: %02x, ex3: %02x, ex4: %02x\n",
12103 ex1 & 255, ex2 & 255, ex3 & 255, ex4 & 255);
12104 }
12105 #endif
12106 #ifdef __RPT_NOTCH
12107
12108 rpt_filter(myrpt,f->data,f->datalen / 2);
12109 #endif
12110 if (ioctl(myrpt->dahdirxchannel->fds[0], DAHDI_GETCONFMUTE, &ismuted) == -1)
12111 {
12112 ismuted = 0;
12113 }
12114 if (dtmfed) ismuted = 1;
12115 dtmfed = 0;
12116 if (ismuted)
12117 {
12118 memset(f->data.ptr,0,f->datalen);
12119 if (myrpt->lastf1)
12120 memset(myrpt->lastf1->data.ptr,0,myrpt->lastf1->datalen);
12121 if (myrpt->lastf2)
12122 memset(myrpt->lastf2->data.ptr,0,myrpt->lastf2->datalen);
12123 }
12124 if (f) f2 = ast_frdup(f);
12125 else f2 = NULL;
12126 f1 = myrpt->lastf2;
12127 myrpt->lastf2 = myrpt->lastf1;
12128 myrpt->lastf1 = f2;
12129 if (ismuted)
12130 {
12131 if (myrpt->lastf1)
12132 memset(myrpt->lastf1->data.ptr,0,myrpt->lastf1->datalen);
12133 if (myrpt->lastf2)
12134 memset(myrpt->lastf2->data.ptr,0,myrpt->lastf2->datalen);
12135 }
12136 if (f1)
12137 {
12138 ast_write(myrpt->pchannel,f1);
12139 ast_frfree(f1);
12140 }
12141 }
12142 #ifndef OLD_ASTERISK
12143 else if (f->frametype == AST_FRAME_DTMF_BEGIN)
12144 {
12145 if (myrpt->lastf1)
12146 memset(myrpt->lastf1->data.ptr,0,myrpt->lastf1->datalen);
12147 if (myrpt->lastf2)
12148 memset(myrpt->lastf2->data.ptr,0,myrpt->lastf2->datalen);
12149 dtmfed = 1;
12150 }
12151 #endif
12152 else if (f->frametype == AST_FRAME_DTMF)
12153 {
12154 c = (char) f->subclass.integer;
12155 ast_frfree(f);
12156 if (myrpt->lastf1)
12157 memset(myrpt->lastf1->data.ptr,0,myrpt->lastf1->datalen);
12158 if (myrpt->lastf2)
12159 memset(myrpt->lastf2->data.ptr,0,myrpt->lastf2->datalen);
12160 dtmfed = 1;
12161 if (!myrpt->keyed) continue;
12162 c = func_xlat(myrpt,c,&myrpt->p.inxlat);
12163 if (c) local_dtmf_helper(myrpt,c);
12164 continue;
12165 }
12166 else if (f->frametype == AST_FRAME_CONTROL)
12167 {
12168 if (f->subclass.integer == AST_CONTROL_HANGUP)
12169 {
12170 if (debug) printf("@@@@ rpt:Hung Up\n");
12171 ast_frfree(f);
12172 break;
12173 }
12174
12175 if (f->subclass.integer == AST_CONTROL_RADIO_KEY)
12176 {
12177 if ((!lasttx) || (myrpt->p.duplex > 1) || (myrpt->p.linktolink))
12178 {
12179 if (debug == 7) printf("@@@@ rx key\n");
12180 myrpt->keyed = 1;
12181 time(&myrpt->lastkeyedtime);
12182 myrpt->keyposttimer = KEYPOSTSHORTTIME;
12183 }
12184 if (myrpt->p.archivedir)
12185 {
12186 donodelog(myrpt,"RXKEY,MAIN");
12187 }
12188 if (f->datalen && f->data.ptr)
12189 {
12190 char busy = 0;
12191
12192 if (debug) ast_log(LOG_NOTICE,"Got PL %s on node %s\n",(char *)f->data.ptr,myrpt->name);
12193
12194 if (strstr((char *)f->data.ptr,"/M/")&& !myrpt->macropatch)
12195 {
12196 char value[16] = "";
12197 strcat(value,"*6");
12198 myrpt->macropatch=1;
12199 rpt_mutex_lock(&myrpt->lock);
12200 if ((MAXMACRO - strlen(myrpt->macrobuf)) < strlen(value)){
12201 rpt_mutex_unlock(&myrpt->lock);
12202 busy=1;
12203 }
12204 if(!busy){
12205 myrpt->macrotimer = MACROTIME;
12206 strncat(myrpt->macrobuf,value,MAXMACRO - 1);
12207 if (!busy) strcpy(myrpt->lasttone,(char*)f->data.ptr);
12208 }
12209 rpt_mutex_unlock(&myrpt->lock);
12210 }
12211 else if (strcmp((char *)f->data.ptr,myrpt->lasttone))
12212 {
12213 char *value = (char *) ast_variable_retrieve(myrpt->cfg, myrpt->p.tonemacro, (char *)f->data.ptr);
12214 if (value)
12215 {
12216 if (debug) ast_log(LOG_NOTICE,"Tone %s doing %s on node %s\n",(char *) f->data.ptr,value,myrpt->name);
12217 rpt_mutex_lock(&myrpt->lock);
12218 if ((MAXMACRO - strlen(myrpt->macrobuf)) < strlen(value)){
12219 rpt_mutex_unlock(&myrpt->lock);
12220 busy=1;
12221 }
12222 if(!busy){
12223 myrpt->macrotimer = MACROTIME;
12224 strncat(myrpt->macrobuf,value,MAXMACRO - 1);
12225 }
12226 rpt_mutex_unlock(&myrpt->lock);
12227 }
12228 if (!busy) strcpy(myrpt->lasttone,(char*)f->data.ptr);
12229 }
12230 } else myrpt->lasttone[0] = 0;
12231 }
12232
12233 if (f->subclass.integer == AST_CONTROL_RADIO_UNKEY)
12234 {
12235 if ((!lasttx) || (myrpt->p.duplex > 1) || (myrpt->p.linktolink))
12236 {
12237 if (debug == 7) printf("@@@@ rx un-key\n");
12238 if(myrpt->p.duplex && myrpt->keyed) {
12239 rpt_telemetry(myrpt,UNKEY,NULL);
12240 }
12241 }
12242 myrpt->keyed = 0;
12243 time(&myrpt->lastkeyedtime);
12244 myrpt->keyposttimer = KEYPOSTSHORTTIME;
12245 if (myrpt->p.archivedir)
12246 {
12247 donodelog(myrpt,"RXUNKEY,MAIN");
12248 }
12249 }
12250 }
12251 ast_frfree(f);
12252 continue;
12253 }
12254 if (who == myrpt->pchannel)
12255 {
12256 f = ast_read(myrpt->pchannel);
12257 if (!f)
12258 {
12259 if (debug) printf("@@@@ rpt:Hung Up\n");
12260 break;
12261 }
12262 if (f->frametype == AST_FRAME_VOICE)
12263 {
12264 ast_write(myrpt->txpchannel,f);
12265 }
12266 if (f->frametype == AST_FRAME_CONTROL)
12267 {
12268 if (f->subclass.integer == AST_CONTROL_HANGUP)
12269 {
12270 if (debug) printf("@@@@ rpt:Hung Up\n");
12271 ast_frfree(f);
12272 break;
12273 }
12274 }
12275 ast_frfree(f);
12276 continue;
12277 }
12278 if (who == myrpt->txchannel)
12279 {
12280 f = ast_read(myrpt->txchannel);
12281 if (!f)
12282 {
12283 if (debug) printf("@@@@ rpt:Hung Up\n");
12284 break;
12285 }
12286 if (f->frametype == AST_FRAME_CONTROL)
12287 {
12288 if (f->subclass.integer == AST_CONTROL_HANGUP)
12289 {
12290 if (debug) printf("@@@@ rpt:Hung Up\n");
12291 ast_frfree(f);
12292 break;
12293 }
12294 }
12295 ast_frfree(f);
12296 continue;
12297 }
12298 if (who == myrpt->dahditxchannel)
12299 {
12300 f = ast_read(myrpt->dahditxchannel);
12301 if (!f)
12302 {
12303 if (debug) printf("@@@@ rpt:Hung Up\n");
12304 break;
12305 }
12306 if (f->frametype == AST_FRAME_VOICE)
12307 {
12308 struct ast_frame *vframe;
12309
12310 if (myrpt->p.duplex < 2)
12311 {
12312 if (myrpt->txrealkeyed)
12313 {
12314 if ((!myfirst) && myrpt->callmode)
12315 {
12316 x = 0;
12317 AST_LIST_TRAVERSE(&myrpt->txq, vframe,
12318 frame_list) x++;
12319 for(;x < myrpt->p.simplexpatchdelay; x++)
12320 {
12321 vframe = ast_frdup(f);
12322 memset(vframe->data.ptr,0,vframe->datalen);
12323 AST_LIST_INSERT_TAIL(&myrpt->txq,vframe,frame_list);
12324 }
12325 myfirst = 1;
12326 }
12327 vframe = ast_frdup(f);
12328 AST_LIST_INSERT_TAIL(&myrpt->txq,
12329 vframe,frame_list);
12330 } else myfirst = 0;
12331 x = 0;
12332 AST_LIST_TRAVERSE(&myrpt->txq, vframe,
12333 frame_list) x++;
12334 if (!x)
12335 {
12336 memset(f->data.ptr,0,f->datalen);
12337 }
12338 else
12339 {
12340 ast_frfree(f);
12341 f = AST_LIST_REMOVE_HEAD(&myrpt->txq,
12342 frame_list);
12343 }
12344 }
12345 else
12346 {
12347 while((vframe = AST_LIST_REMOVE_HEAD(&myrpt->txq,
12348 frame_list))) ast_frfree(vframe);
12349 }
12350 ast_write(myrpt->txchannel,f);
12351 }
12352 if (f->frametype == AST_FRAME_CONTROL)
12353 {
12354 if (f->subclass.integer == AST_CONTROL_HANGUP)
12355 {
12356 if (debug) printf("@@@@ rpt:Hung Up\n");
12357 ast_frfree(f);
12358 break;
12359 }
12360 }
12361 ast_frfree(f);
12362 continue;
12363 }
12364 toexit = 0;
12365 rpt_mutex_lock(&myrpt->lock);
12366 l = myrpt->links.next;
12367 while(l != &myrpt->links)
12368 {
12369 int remnomute;
12370 struct timeval now;
12371
12372 if (l->disctime)
12373 {
12374 l = l->next;
12375 continue;
12376 }
12377
12378 remrx = 0;
12379
12380 m = myrpt->links.next;
12381 while(m != &myrpt->links)
12382 {
12383
12384 if ((m != l) && (m->lastrx)) remrx = 1;
12385 m = m->next;
12386 }
12387 rpt_mutex_unlock(&myrpt->lock);
12388 now = ast_tvnow();
12389 if ((who == l->chan) || (!l->lastlinktv.tv_sec) ||
12390 (ast_tvdiff_ms(now,l->lastlinktv) >= 19))
12391 {
12392 l->lastlinktv = now;
12393 remnomute = myrpt->localtx &&
12394 (!(myrpt->cmdnode[0] ||
12395 (myrpt->dtmfidx > -1)));
12396 totx = (((l->isremote) ? (remnomute) :
12397 myrpt->exttx) || remrx) && l->mode;
12398 if (l->phonemode == 0 && l->chan && (l->lasttx != totx))
12399 {
12400 if (totx)
12401 {
12402 ast_indicate(l->chan,AST_CONTROL_RADIO_KEY);
12403 }
12404 else
12405 {
12406 ast_indicate(l->chan,AST_CONTROL_RADIO_UNKEY);
12407 }
12408 if (myrpt->p.archivedir)
12409 {
12410 char str[100];
12411
12412 if (totx)
12413 sprintf(str,"TXKEY,%s",l->name);
12414 else
12415 sprintf(str,"TXUNKEY,%s",l->name);
12416 donodelog(myrpt,str);
12417 }
12418 }
12419 l->lasttx = totx;
12420 }
12421 rpt_mutex_lock(&myrpt->lock);
12422 if (who == l->chan)
12423 {
12424 rpt_mutex_unlock(&myrpt->lock);
12425 f = ast_read(l->chan);
12426 if (!f)
12427 {
12428 rpt_mutex_lock(&myrpt->lock);
12429 __kickshort(myrpt);
12430 rpt_mutex_unlock(&myrpt->lock);
12431 if ((!l->disced) && (!l->outbound))
12432 {
12433 if ((l->name[0] == '0') || l->isremote)
12434 l->disctime = 1;
12435 else
12436 l->disctime = DISC_TIME;
12437 rpt_mutex_lock(&myrpt->lock);
12438 ast_hangup(l->chan);
12439 l->chan = 0;
12440 break;
12441 }
12442
12443 if (l->retrytimer)
12444 {
12445 ast_hangup(l->chan);
12446 l->chan = 0;
12447 rpt_mutex_lock(&myrpt->lock);
12448 break;
12449 }
12450 if (l->outbound && (l->retries++ < l->max_retries) && (l->hasconnected))
12451 {
12452 rpt_mutex_lock(&myrpt->lock);
12453 if (l->chan) ast_hangup(l->chan);
12454 l->chan = 0;
12455 l->hasconnected = 1;
12456 l->retrytimer = RETRY_TIMER_MS;
12457 l->elaptime = 0;
12458 l->connecttime = 0;
12459 l->thisconnected = 0;
12460 break;
12461 }
12462 rpt_mutex_lock(&myrpt->lock);
12463
12464 remque((struct qelem *) l);
12465 if (!strcmp(myrpt->cmdnode,l->name))
12466 myrpt->cmdnode[0] = 0;
12467 __kickshort(myrpt);
12468 rpt_mutex_unlock(&myrpt->lock);
12469 if (!l->hasconnected)
12470 rpt_telemetry(myrpt,CONNFAIL,l);
12471 else if (l->disced != 2) rpt_telemetry(myrpt,REMDISC,l);
12472 if (myrpt->p.archivedir)
12473 {
12474 char str[100];
12475
12476 if (!l->hasconnected)
12477 sprintf(str,"LINKFAIL,%s",l->name);
12478 else
12479 sprintf(str,"LINKDISC,%s",l->name);
12480 donodelog(myrpt,str);
12481 }
12482 if (l->lastf1) ast_frfree(l->lastf1);
12483 l->lastf1 = NULL;
12484 if (l->lastf2) ast_frfree(l->lastf2);
12485 l->lastf2 = NULL;
12486
12487 ast_hangup(l->chan);
12488 ast_hangup(l->pchan);
12489 ast_free(l);
12490 rpt_mutex_lock(&myrpt->lock);
12491 break;
12492 }
12493 if (f->frametype == AST_FRAME_VOICE)
12494 {
12495 int ismuted,n1;
12496
12497 if ((l->phonemode) && (l->phonevox))
12498 {
12499 n1 = dovox(&l->vox,
12500 f->data.ptr,f->datalen / 2);
12501 if (n1 != l->wasvox)
12502 {
12503 if (debug)ast_log(LOG_DEBUG,"Link Node %s, vox %d\n",l->name,n1);
12504 l->wasvox = n1;
12505 l->voxtostate = 0;
12506 if (n1) l->voxtotimer = myrpt->p.voxtimeout_ms;
12507 else l->voxtotimer = 0;
12508 }
12509 if (l->lastrealrx || n1)
12510 {
12511 if (!myfirst)
12512 {
12513 x = 0;
12514 AST_LIST_TRAVERSE(&l->rxq, f1,
12515 frame_list) x++;
12516 for(;x < myrpt->p.simplexphonedelay; x++)
12517 {
12518 f1 = ast_frdup(f);
12519 memset(f1->data.ptr,0,f1->datalen);
12520 AST_LIST_INSERT_TAIL(&l->rxq,
12521 f1,frame_list);
12522 }
12523 myfirst = 1;
12524 }
12525 f1 = ast_frdup(f);
12526 AST_LIST_INSERT_TAIL(&l->rxq,f1,frame_list);
12527 } else myfirst = 0;
12528 x = 0;
12529 AST_LIST_TRAVERSE(&l->rxq, f1,frame_list) x++;
12530 if (!x)
12531 {
12532 memset(f->data.ptr,0,f->datalen);
12533 }
12534 else
12535 {
12536 ast_frfree(f);
12537 f = AST_LIST_REMOVE_HEAD(&l->rxq,frame_list);
12538 }
12539 if (ioctl(l->chan->fds[0], DAHDI_GETCONFMUTE, &ismuted) == -1)
12540 {
12541 ismuted = 0;
12542 }
12543
12544 ismuted |= (!l->lastrx);
12545 if (l->dtmfed && l->phonemode) ismuted = 1;
12546 l->dtmfed = 0;
12547 if (ismuted)
12548 {
12549 memset(f->data.ptr,0,f->datalen);
12550 if (l->lastf1)
12551 memset(l->lastf1->data.ptr,0,l->lastf1->datalen);
12552 if (l->lastf2)
12553 memset(l->lastf2->data.ptr,0,l->lastf2->datalen);
12554 }
12555 if (f) f2 = ast_frdup(f);
12556 else f2 = NULL;
12557 f1 = l->lastf2;
12558 l->lastf2 = l->lastf1;
12559 l->lastf1 = f2;
12560 if (ismuted)
12561 {
12562 if (l->lastf1)
12563 memset(l->lastf1->data.ptr,0,l->lastf1->datalen);
12564 if (l->lastf2)
12565 memset(l->lastf2->data.ptr,0,l->lastf2->datalen);
12566 }
12567 if (f1)
12568 {
12569 ast_write(l->pchan,f1);
12570 ast_frfree(f1);
12571 }
12572 }
12573 else
12574 {
12575 if (!l->lastrx)
12576 memset(f->data.ptr,0,f->datalen);
12577 ast_write(l->pchan,f);
12578 }
12579 }
12580 #ifndef OLD_ASTERISK
12581 else if (f->frametype == AST_FRAME_DTMF_BEGIN)
12582 {
12583 if (l->lastf1)
12584 memset(l->lastf1->data.ptr,0,l->lastf1->datalen);
12585 if (l->lastf2)
12586 memset(l->lastf2->data.ptr,0,l->lastf2->datalen);
12587 l->dtmfed = 1;
12588 }
12589 #endif
12590 if (f->frametype == AST_FRAME_TEXT)
12591 {
12592 handle_link_data(myrpt,l,f->data.ptr);
12593 }
12594 if (f->frametype == AST_FRAME_DTMF)
12595 {
12596 if (l->lastf1)
12597 memset(l->lastf1->data.ptr,0,l->lastf1->datalen);
12598 if (l->lastf2)
12599 memset(l->lastf2->data.ptr,0,l->lastf2->datalen);
12600 l->dtmfed = 1;
12601 handle_link_phone_dtmf(myrpt,l,f->subclass.integer);
12602 }
12603 if (f->frametype == AST_FRAME_CONTROL)
12604 {
12605 if (f->subclass.integer == AST_CONTROL_ANSWER)
12606 {
12607 char lconnected = l->connected;
12608
12609 __kickshort(myrpt);
12610 l->connected = 1;
12611 l->hasconnected = 1;
12612 l->thisconnected = 1;
12613 l->elaptime = -1;
12614 if (!l->phonemode) send_newkey(l->chan);
12615 if (!l->isremote) l->retries = 0;
12616 if (!lconnected)
12617 {
12618 rpt_telemetry(myrpt,CONNECTED,l);
12619 if (myrpt->p.archivedir)
12620 {
12621 char str[100];
12622
12623 if (l->mode)
12624 sprintf(str,"LINKTRX,%s",l->name);
12625 else
12626 sprintf(str,"LINKMONITOR,%s",l->name);
12627 donodelog(myrpt,str);
12628 }
12629 }
12630 else
12631 l->reconnects++;
12632 }
12633
12634 if (f->subclass.integer == AST_CONTROL_RADIO_KEY)
12635 {
12636 if (debug == 7 ) printf("@@@@ rx key\n");
12637 l->lastrealrx = 1;
12638 l->rerxtimer = 0;
12639 if (!l->lastrx1)
12640 {
12641 if (myrpt->p.archivedir)
12642 {
12643 char str[100];
12644
12645 sprintf(str,"RXKEY,%s",l->name);
12646 donodelog(myrpt,str);
12647 }
12648 l->lastrx1 = 1;
12649 }
12650 }
12651
12652 if (f->subclass.integer == AST_CONTROL_RADIO_UNKEY)
12653 {
12654 if (debug == 7) printf("@@@@ rx un-key\n");
12655 l->lastrealrx = 0;
12656 l->rerxtimer = 0;
12657 if (l->lastrx1)
12658 {
12659 if (myrpt->p.archivedir)
12660 {
12661 char str[100];
12662
12663 sprintf(str,"RXUNKEY,%s",l->name);
12664 donodelog(myrpt,str);
12665 }
12666 l->lastrx1 = 0;
12667 if(myrpt->p.duplex)
12668 rpt_telemetry(myrpt,LINKUNKEY,l);
12669 }
12670 }
12671 if (f->subclass.integer == AST_CONTROL_HANGUP)
12672 {
12673 ast_frfree(f);
12674 rpt_mutex_lock(&myrpt->lock);
12675 __kickshort(myrpt);
12676 rpt_mutex_unlock(&myrpt->lock);
12677 if ((!l->outbound) && (!l->disced))
12678 {
12679 if ((l->name[0] == '0') || l->isremote)
12680 l->disctime = 1;
12681 else
12682 l->disctime = DISC_TIME;
12683 rpt_mutex_lock(&myrpt->lock);
12684 ast_hangup(l->chan);
12685 l->chan = 0;
12686 break;
12687 }
12688 if (l->retrytimer)
12689 {
12690 if (l->chan) ast_hangup(l->chan);
12691 l->chan = 0;
12692 rpt_mutex_lock(&myrpt->lock);
12693 break;
12694 }
12695 if (l->outbound && (l->retries++ < l->max_retries) && (l->hasconnected))
12696 {
12697 rpt_mutex_lock(&myrpt->lock);
12698 if (l->chan) ast_hangup(l->chan);
12699 l->chan = 0;
12700 l->hasconnected = 1;
12701 l->elaptime = 0;
12702 l->retrytimer = RETRY_TIMER_MS;
12703 l->connecttime = 0;
12704 l->thisconnected = 0;
12705 break;
12706 }
12707 rpt_mutex_lock(&myrpt->lock);
12708
12709 remque((struct qelem *) l);
12710 if (!strcmp(myrpt->cmdnode,l->name))
12711 myrpt->cmdnode[0] = 0;
12712 __kickshort(myrpt);
12713 rpt_mutex_unlock(&myrpt->lock);
12714 if (!l->hasconnected)
12715 rpt_telemetry(myrpt,CONNFAIL,l);
12716 else if (l->disced != 2) rpt_telemetry(myrpt,REMDISC,l);
12717 if (myrpt->p.archivedir)
12718 {
12719 char str[100];
12720
12721 if (!l->hasconnected)
12722 sprintf(str,"LINKFAIL,%s",l->name);
12723 else
12724 sprintf(str,"LINKDISC,%s",l->name);
12725 donodelog(myrpt,str);
12726 }
12727 if (l->lastf1) ast_frfree(l->lastf1);
12728 l->lastf1 = NULL;
12729 if (l->lastf2) ast_frfree(l->lastf2);
12730 l->lastf2 = NULL;
12731
12732 ast_hangup(l->chan);
12733 ast_hangup(l->pchan);
12734 ast_free(l);
12735 rpt_mutex_lock(&myrpt->lock);
12736 break;
12737 }
12738 }
12739 ast_frfree(f);
12740 rpt_mutex_lock(&myrpt->lock);
12741 break;
12742 }
12743 if (who == l->pchan)
12744 {
12745 rpt_mutex_unlock(&myrpt->lock);
12746 f = ast_read(l->pchan);
12747 if (!f)
12748 {
12749 if (debug) printf("@@@@ rpt:Hung Up\n");
12750 toexit = 1;
12751 rpt_mutex_lock(&myrpt->lock);
12752 break;
12753 }
12754 if (f->frametype == AST_FRAME_VOICE)
12755 {
12756 if (l->chan) ast_write(l->chan,f);
12757 }
12758 if (f->frametype == AST_FRAME_CONTROL)
12759 {
12760 if (f->subclass.integer == AST_CONTROL_HANGUP)
12761 {
12762 if (debug) printf("@@@@ rpt:Hung Up\n");
12763 ast_frfree(f);
12764 toexit = 1;
12765 rpt_mutex_lock(&myrpt->lock);
12766 break;
12767 }
12768 }
12769 ast_frfree(f);
12770 rpt_mutex_lock(&myrpt->lock);
12771 break;
12772 }
12773 l = l->next;
12774 }
12775 rpt_mutex_unlock(&myrpt->lock);
12776 if (toexit) break;
12777 if (who == myrpt->monchannel)
12778 {
12779 f = ast_read(myrpt->monchannel);
12780 if (!f)
12781 {
12782 if (debug) printf("@@@@ rpt:Hung Up\n");
12783 break;
12784 }
12785 if (f->frametype == AST_FRAME_VOICE)
12786 {
12787 if (myrpt->monstream)
12788 ast_writestream(myrpt->monstream,f);
12789 }
12790 if (f->frametype == AST_FRAME_CONTROL)
12791 {
12792 if (f->subclass.integer == AST_CONTROL_HANGUP)
12793 {
12794 if (debug) printf("@@@@ rpt:Hung Up\n");
12795 ast_frfree(f);
12796 break;
12797 }
12798 }
12799 ast_frfree(f);
12800 continue;
12801 }
12802 if (myrpt->parrotchannel && (who == myrpt->parrotchannel))
12803 {
12804 f = ast_read(myrpt->parrotchannel);
12805 if (!f)
12806 {
12807 if (debug) printf("@@@@ rpt:Hung Up\n");
12808 break;
12809 }
12810 if (!myrpt->p.parrotmode)
12811 {
12812 char myfname[300];
12813
12814 if (myrpt->parrotstream)
12815 {
12816 ast_closestream(myrpt->parrotstream);
12817 myrpt->parrotstream = 0;
12818 }
12819 sprintf(myfname,PARROTFILE,myrpt->name,myrpt->parrotcnt);
12820 strcat(myfname,".wav");
12821 unlink(myfname);
12822 } else if (f->frametype == AST_FRAME_VOICE)
12823 {
12824 if (myrpt->parrotstream)
12825 ast_writestream(myrpt->parrotstream,f);
12826 }
12827 if (f->frametype == AST_FRAME_CONTROL)
12828 {
12829 if (f->subclass.integer == AST_CONTROL_HANGUP)
12830 {
12831 if (debug) printf("@@@@ rpt:Hung Up\n");
12832 ast_frfree(f);
12833 break;
12834 }
12835 }
12836 ast_frfree(f);
12837 continue;
12838 }
12839 if (myrpt->voxchannel && (who == myrpt->voxchannel))
12840 {
12841 f = ast_read(myrpt->voxchannel);
12842 if (!f)
12843 {
12844 if (debug) printf("@@@@ rpt:Hung Up\n");
12845 break;
12846 }
12847 if (f->frametype == AST_FRAME_VOICE)
12848 {
12849 n = dovox(&myrpt->vox,f->data.ptr,f->datalen / 2);
12850 if (n != myrpt->wasvox)
12851 {
12852 if (debug) ast_log(LOG_DEBUG,"Node %s, vox %d\n",myrpt->name,n);
12853 myrpt->wasvox = n;
12854 myrpt->voxtostate = 0;
12855 if (n) myrpt->voxtotimer = myrpt->p.voxtimeout_ms;
12856 else myrpt->voxtotimer = 0;
12857 }
12858 }
12859 if (f->frametype == AST_FRAME_CONTROL)
12860 {
12861 if (f->subclass.integer == AST_CONTROL_HANGUP)
12862 {
12863 if (debug) printf("@@@@ rpt:Hung Up\n");
12864 ast_frfree(f);
12865 break;
12866 }
12867 }
12868 ast_frfree(f);
12869 continue;
12870 }
12871 if (who == myrpt->txpchannel)
12872 {
12873 f = ast_read(myrpt->txpchannel);
12874 if (!f)
12875 {
12876 if (debug) printf("@@@@ rpt:Hung Up\n");
12877 break;
12878 }
12879 if (f->frametype == AST_FRAME_CONTROL)
12880 {
12881 if (f->subclass.integer == AST_CONTROL_HANGUP)
12882 {
12883 if (debug) printf("@@@@ rpt:Hung Up\n");
12884 ast_frfree(f);
12885 break;
12886 }
12887 }
12888 ast_frfree(f);
12889 continue;
12890 }
12891 }
12892 usleep(100000);
12893 ast_hangup(myrpt->pchannel);
12894 ast_hangup(myrpt->monchannel);
12895 if (myrpt->parrotchannel) ast_hangup(myrpt->parrotchannel);
12896 myrpt->parrotstate = 0;
12897 if (myrpt->voxchannel) ast_hangup(myrpt->voxchannel);
12898 ast_hangup(myrpt->txpchannel);
12899 if (myrpt->txchannel != myrpt->rxchannel) ast_hangup(myrpt->txchannel);
12900 if (myrpt->dahditxchannel != myrpt->txchannel) ast_hangup(myrpt->dahditxchannel);
12901 if (myrpt->lastf1) ast_frfree(myrpt->lastf1);
12902 myrpt->lastf1 = NULL;
12903 if (myrpt->lastf2) ast_frfree(myrpt->lastf2);
12904 myrpt->lastf2 = NULL;
12905 ast_hangup(myrpt->rxchannel);
12906 rpt_mutex_lock(&myrpt->lock);
12907 l = myrpt->links.next;
12908 while(l != &myrpt->links)
12909 {
12910 struct rpt_link *ll = l;
12911
12912 remque((struct qelem *) l);
12913
12914 if (l->chan) ast_hangup(l->chan);
12915 ast_hangup(l->pchan);
12916 l = l->next;
12917 ast_free(ll);
12918 }
12919 if (myrpt->xlink == 1) myrpt->xlink = 2;
12920 rpt_mutex_unlock(&myrpt->lock);
12921 if (debug) printf("@@@@ rpt:Hung up channel\n");
12922 myrpt->rpt_thread = AST_PTHREADT_STOP;
12923 pthread_exit(NULL);
12924 return NULL;
12925 }
12926
12927
12928 static void *rpt_master(void *ignore)
12929 {
12930 int i,n;
12931 pthread_attr_t attr;
12932 struct ast_config *cfg;
12933 char *this,*val;
12934
12935
12936 nodelog.next = nodelog.prev = &nodelog;
12937
12938 this = NULL;
12939 n = 0;
12940 #ifndef OLD_ASTERISK
12941
12942 while(!ast_test_flag(&ast_options,AST_OPT_FLAG_FULLY_BOOTED))
12943 usleep(250000);
12944 #endif
12945 #ifdef NEW_ASTERISK
12946 rpt_vars[n].cfg = ast_config_load("rpt.conf",config_flags);
12947 #else
12948 rpt_vars[n].cfg = ast_config_load("rpt.conf");
12949 #endif
12950 cfg = rpt_vars[n].cfg;
12951 if (!cfg || cfg == CONFIG_STATUS_FILEINVALID) {
12952 ast_log(LOG_NOTICE, "Unable to open radio repeater configuration rpt.conf. Radio Repeater disabled.\n");
12953 pthread_exit(NULL);
12954 }
12955 while((this = ast_category_browse(cfg,this)) != NULL)
12956 {
12957 for(i = 0 ; i < strlen(this) ; i++){
12958 if((this[i] < '0') || (this[i] > '9'))
12959 break;
12960 }
12961 if(i != strlen(this)) continue;
12962 memset(&rpt_vars[n],0,sizeof(rpt_vars[n]));
12963 rpt_vars[n].name = ast_strdup(this);
12964 val = (char *) ast_variable_retrieve(cfg,this,"rxchannel");
12965 if (val) rpt_vars[n].rxchanname = ast_strdup(val);
12966 val = (char *) ast_variable_retrieve(cfg,this,"txchannel");
12967 if (val) rpt_vars[n].txchanname = ast_strdup(val);
12968 rpt_vars[n].remote = 0;
12969 rpt_vars[n].remoterig = "";
12970 val = (char *) ast_variable_retrieve(cfg,this,"remote");
12971 if (val)
12972 {
12973 rpt_vars[n].remoterig = ast_strdup(val);
12974 rpt_vars[n].remote = 1;
12975 }
12976 val = (char *) ast_variable_retrieve(cfg,this,"radiotype");
12977 if (val) rpt_vars[n].remoterig = ast_strdup(val);
12978 ast_mutex_init(&rpt_vars[n].lock);
12979 ast_mutex_init(&rpt_vars[n].remlock);
12980 ast_mutex_init(&rpt_vars[n].statpost_lock);
12981 rpt_vars[n].tele.next = &rpt_vars[n].tele;
12982 rpt_vars[n].tele.prev = &rpt_vars[n].tele;
12983 rpt_vars[n].rpt_thread = AST_PTHREADT_NULL;
12984 rpt_vars[n].tailmessagen = 0;
12985 #ifdef _MDC_DECODE_H_
12986 rpt_vars[n].mdc = mdc_decoder_new(8000);
12987 #endif
12988 n++;
12989 }
12990 nrpts = n;
12991 ast_config_destroy(cfg);
12992
12993
12994 for(i = 0; i < n; i++)
12995 {
12996 load_rpt_vars(i,1);
12997
12998
12999 if (rpt_vars[i].remote)
13000 {
13001 if(retreive_memory(&rpt_vars[i],"init")){
13002 if (!strcmp(rpt_vars[i].remoterig,remote_rig_rtx450))
13003 strncpy(rpt_vars[i].freq, "446.500", sizeof(rpt_vars[i].freq) - 1);
13004 else
13005 strncpy(rpt_vars[i].freq, "146.580", sizeof(rpt_vars[i].freq) - 1);
13006 strncpy(rpt_vars[i].rxpl, "100.0", sizeof(rpt_vars[i].rxpl) - 1);
13007
13008 strncpy(rpt_vars[i].txpl, "100.0", sizeof(rpt_vars[i].txpl) - 1);
13009 rpt_vars[i].remmode = REM_MODE_FM;
13010 rpt_vars[i].offset = REM_SIMPLEX;
13011 rpt_vars[i].powerlevel = REM_LOWPWR;
13012 }
13013 continue;
13014 }
13015 else
13016 {
13017 rpt_vars[i].p.memory = rpt_vars[i].name;
13018 if(retreive_memory(&rpt_vars[i],"radiofreq")){
13019 if (!strcmp(rpt_vars[i].remoterig,remote_rig_rtx450))
13020 strncpy(rpt_vars[i].freq, "446.500", sizeof(rpt_vars[i].freq) - 1);
13021 else if (!strcmp(rpt_vars[i].remoterig,remote_rig_rtx150))
13022 strncpy(rpt_vars[i].freq, "146.580", sizeof(rpt_vars[i].freq) - 1);
13023 strncpy(rpt_vars[i].rxpl, "100.0", sizeof(rpt_vars[i].rxpl) - 1);
13024
13025 strncpy(rpt_vars[i].txpl, "100.0", sizeof(rpt_vars[i].txpl) - 1);
13026 rpt_vars[i].remmode = REM_MODE_FM;
13027 rpt_vars[i].offset = REM_SIMPLEX;
13028 rpt_vars[i].powerlevel = REM_LOWPWR;
13029 }
13030 ast_log(LOG_NOTICE,"Normal Repeater Init %s %s %s\n",rpt_vars[i].name, rpt_vars[i].remoterig, rpt_vars[i].freq);
13031 }
13032 if (!rpt_vars[i].p.ident)
13033 {
13034 ast_log(LOG_WARNING,"Did not specify ident for node %s\n",rpt_vars[i].name);
13035 ast_config_destroy(cfg);
13036 pthread_exit(NULL);
13037 }
13038 pthread_attr_init(&attr);
13039 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
13040 ast_pthread_create(&rpt_vars[i].rpt_thread,&attr,rpt,(void *) &rpt_vars[i]);
13041 }
13042 usleep(500000);
13043 time(&starttime);
13044 for(;;)
13045 {
13046
13047 for(i = 0; i < n; i++)
13048 {
13049 int rv;
13050 if (rpt_vars[i].remote) continue;
13051 if (rpt_vars[i].rpt_thread == AST_PTHREADT_STOP)
13052 rv = -1;
13053 else
13054 rv = pthread_kill(rpt_vars[i].rpt_thread,0);
13055 if (rv)
13056 {
13057 if(time(NULL) - rpt_vars[i].lastthreadrestarttime <= 15)
13058 {
13059 if(rpt_vars[i].threadrestarts >= 5)
13060 {
13061 ast_log(LOG_ERROR,"Continual RPT thread restarts, killing Asterisk\n");
13062 exit(1);
13063 }
13064 else
13065 {
13066 ast_log(LOG_NOTICE,"RPT thread restarted on %s\n",rpt_vars[i].name);
13067 rpt_vars[i].threadrestarts++;
13068 }
13069 }
13070 else
13071 rpt_vars[i].threadrestarts = 0;
13072
13073 rpt_vars[i].lastthreadrestarttime = time(NULL);
13074 pthread_attr_init(&attr);
13075 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
13076 ast_pthread_create(&rpt_vars[i].rpt_thread,&attr,rpt,(void *) &rpt_vars[i]);
13077
13078 ast_log(LOG_WARNING, "rpt_thread restarted on node %s\n", rpt_vars[i].name);
13079 }
13080
13081 }
13082 for(;;)
13083 {
13084 struct nodelog *nodep;
13085 char *space,datestr[100],fname[300];
13086 int fd;
13087
13088 ast_mutex_lock(&nodeloglock);
13089 nodep = nodelog.next;
13090 if(nodep == &nodelog)
13091 {
13092 ast_mutex_unlock(&nodeloglock);
13093 break;
13094 }
13095 remque((struct qelem *)nodep);
13096 ast_mutex_unlock(&nodeloglock);
13097 space = strchr(nodep->str,' ');
13098 if (!space)
13099 {
13100 ast_free(nodep);
13101 continue;
13102 }
13103 *space = 0;
13104 strftime(datestr,sizeof(datestr) - 1,"%Y%m%d",
13105 localtime(&nodep->timestamp));
13106 sprintf(fname,"%s/%s/%s.txt",nodep->archivedir,
13107 nodep->str,datestr);
13108 fd = open(fname,O_WRONLY | O_CREAT | O_APPEND,0600);
13109 if (fd == -1)
13110 {
13111 ast_log(LOG_ERROR,"Cannot open node log file %s for write",space + 1);
13112 ast_free(nodep);
13113 continue;
13114 }
13115 if (write(fd,space + 1,strlen(space + 1)) !=
13116 strlen(space + 1))
13117 {
13118 ast_log(LOG_ERROR,"Cannot write node log file %s for write",space + 1);
13119 ast_free(nodep);
13120 continue;
13121 }
13122 close(fd);
13123 ast_free(nodep);
13124 }
13125 sleep(2);
13126 }
13127 ast_config_destroy(cfg);
13128 pthread_exit(NULL);
13129 }
13130
13131 static int rpt_exec(struct ast_channel *chan, const char *data)
13132 {
13133 int res=-1,i,rem_totx,rem_rx,remkeyed,n,phone_mode = 0;
13134 int iskenwood_pci4,authtold,authreq,setting,notremming,reming;
13135 int ismuted,dtmfed,phone_vox = 0;
13136 #ifdef OLD_ASTERISK
13137 struct localuser *u;
13138 #endif
13139 char tmp[256], keyed = 0,keyed1 = 0;
13140 char *options,*stringp,*tele,c,*altp,*memp;
13141 char sx[320],*sy;
13142 struct rpt *myrpt;
13143 struct ast_frame *f,*f1,*f2;
13144 struct ast_channel *who;
13145 struct ast_channel *cs[20];
13146 struct rpt_link *l;
13147 struct dahdi_confinfo ci;
13148 struct dahdi_params par;
13149 int ms,elap,nullfd;
13150 time_t t,last_timeout_warning;
13151 struct dahdi_radio_param z;
13152 struct rpt_tele *telem;
13153 int numlinks;
13154
13155 nullfd = open("/dev/null",O_RDWR);
13156 if (ast_strlen_zero(data)) {
13157 ast_log(LOG_WARNING, "Rpt requires an argument (system node)\n");
13158 return -1;
13159 }
13160
13161 strncpy(tmp, (char *)data, sizeof(tmp)-1);
13162 time(&t);
13163
13164 if (t < starttime) t = starttime + START_DELAY;
13165 if ((!starttime) || (t < (starttime + START_DELAY)))
13166 {
13167 ast_log(LOG_NOTICE,"Node %s rejecting call: too soon!\n",tmp);
13168 ast_safe_sleep(chan,3000);
13169 return -1;
13170 }
13171
13172 ast_log(LOG_NOTICE,"parsing argument=%s \n",tmp);
13173
13174 altp=strstr(tmp, "|*");
13175 if(altp){
13176 altp[0]=0;
13177 altp++;
13178 }
13179
13180 memp=strstr(tmp, "|M");
13181 if(memp){
13182 memp[0]=0;
13183 memp+=2;
13184 }
13185
13186 stringp=tmp;
13187 strsep(&stringp, "|");
13188 options = stringp;
13189
13190 ast_log(LOG_NOTICE,"options=%s \n",options);
13191 if(memp>0)ast_log(LOG_NOTICE,"memp=%s \n",memp);
13192 if(altp>0)ast_log(LOG_NOTICE,"altp=%s \n",altp);
13193
13194 myrpt = NULL;
13195
13196 for(i = 0; i < nrpts; i++)
13197 {
13198
13199 if (!strcmp(tmp,rpt_vars[i].name))
13200 {
13201 myrpt = &rpt_vars[i];
13202 break;
13203 }
13204 }
13205
13206 pbx_builtin_setvar_helper(chan, "RPT_STAT_ERR", "");
13207
13208 if (myrpt == NULL)
13209 {
13210 pbx_builtin_setvar_helper(chan, "RPT_STAT_ERR", "NODE_NOT_FOUND");
13211 ast_log(LOG_WARNING, "Cannot find specified system node %s\n",tmp);
13212 return (priority_jump(NULL,chan));
13213 }
13214
13215 numlinks=linkcount(myrpt);
13216
13217 if(options && *options == 'q')
13218 {
13219 char buf2[128];
13220
13221 if(myrpt->keyed)
13222 pbx_builtin_setvar_helper(chan, "RPT_STAT_RXKEYED", "1");
13223 else
13224 pbx_builtin_setvar_helper(chan, "RPT_STAT_RXKEYED", "0");
13225
13226 if(myrpt->txkeyed)
13227 pbx_builtin_setvar_helper(chan, "RPT_STAT_TXKEYED", "1");
13228 else
13229 pbx_builtin_setvar_helper(chan, "RPT_STAT_TXKEYED", "0");
13230
13231 snprintf(buf2,sizeof(buf2),"%s=%i", "RPT_STAT_XLINK", myrpt->xlink);
13232 pbx_builtin_setvar(chan, buf2);
13233 snprintf(buf2,sizeof(buf2),"%s=%i", "RPT_STAT_LINKS", numlinks);
13234 pbx_builtin_setvar(chan, buf2);
13235 snprintf(buf2,sizeof(buf2),"%s=%d", "RPT_STAT_WASCHAN", myrpt->waschan);
13236 pbx_builtin_setvar(chan, buf2);
13237 snprintf(buf2,sizeof(buf2),"%s=%d", "RPT_STAT_NOWCHAN", myrpt->nowchan);
13238 pbx_builtin_setvar(chan, buf2);
13239 snprintf(buf2,sizeof(buf2),"%s=%d", "RPT_STAT_DUPLEX", myrpt->p.duplex);
13240 pbx_builtin_setvar(chan, buf2);
13241 snprintf(buf2,sizeof(buf2),"%s=%d", "RPT_STAT_PARROT", myrpt->p.parrotmode);
13242 pbx_builtin_setvar(chan, buf2);
13243
13244
13245
13246
13247 snprintf(buf2,sizeof(buf2),"%s=%d", "RPT_STAT_CALLMODE", myrpt->callmode);
13248 pbx_builtin_setvar(chan, buf2);
13249 snprintf(buf2,sizeof(buf2),"%s=%s", "RPT_STAT_LASTTONE", myrpt->lasttone);
13250 pbx_builtin_setvar(chan, buf2);
13251
13252 return priority_jump(myrpt,chan);
13253 }
13254
13255 if(options && *options == 'o')
13256 {
13257 return(channel_revert(myrpt));
13258 }
13259
13260 #if 0
13261 if((altp)&&(*options == 'Z'))
13262 {
13263 rpt_push_alt_macro(myrpt,altp);
13264 return 0;
13265 }
13266 #endif
13267
13268
13269
13270 if (options && ((*options == 'P') || (*options == 'D') || (*options == 'R') || (*options == 'S')))
13271 {
13272 int val;
13273
13274 pbx_builtin_setvar_helper(chan, "RPT_STAT_BUSY", "0");
13275
13276 myrpt->bargechan=0;
13277 if(options && strstr(options, "f")>0)
13278 {
13279 myrpt->bargechan=1;
13280 }
13281
13282 if(memp>0)
13283 {
13284 char radiochan;
13285 radiochan=strtod(data,NULL);
13286
13287
13288 if(numlinks>0 && radiochan!=myrpt->nowchan && !myrpt->bargechan)
13289 {
13290 pbx_builtin_setvar_helper(chan, "RPT_STAT_BUSY", "1");
13291 ast_log(LOG_NOTICE, "Radio Channel Busy.\n");
13292 return (priority_jump(myrpt,chan));
13293 }
13294 else if(radiochan!=myrpt->nowchan || myrpt->bargechan)
13295 {
13296 channel_steer(myrpt,memp);
13297 }
13298 }
13299 if(altp)rpt_push_alt_macro(myrpt,altp);
13300 phone_mode = 1;
13301 if (*options == 'D') phone_mode = 2;
13302 if (*options == 'S') phone_mode = 3;
13303 ast_set_callerid(chan,"0","app_rpt user","0");
13304 val = 1;
13305 ast_channel_setoption(chan,AST_OPTION_TONE_VERIFY,&val,sizeof(char),0);
13306 if ((*(options + 1) == 'V') || (*(options + 1) == 'v')) phone_vox = 1;
13307 }
13308 else
13309 {
13310 #ifdef ALLOW_LOCAL_CHANNELS
13311
13312 if ( (strncmp(chan->name,"IAX2",4)) && (strncmp(chan->name,"Local",5)) ) {
13313 ast_log(LOG_WARNING, "We only accept links via IAX2 or Local!!\n");
13314 return -1;
13315 }
13316 #else
13317 if (strncmp(chan->name,"IAX2",4))
13318 {
13319 ast_log(LOG_WARNING, "We only accept links via IAX2!!\n");
13320 return -1;
13321 }
13322 #endif
13323 if(myrpt->p.s[myrpt->p.sysstate_cur].txdisable){
13324 ast_log(LOG_NOTICE, "Connect attempt to node %s with tx disabled", myrpt->name);
13325 return -1;
13326 }
13327 }
13328 if (options && (*options == 'R'))
13329 {
13330
13331 char *return_context;
13332 int length, m, lot, timeout = 0;
13333 char buffer[256],*template;
13334 char *working, *context, *exten, *priority;
13335 char *s,*orig_s;
13336
13337 rpt_mutex_lock(&myrpt->lock);
13338 m = myrpt->callmode;
13339 rpt_mutex_unlock(&myrpt->lock);
13340
13341 if ((!myrpt->p.nobusyout) && m)
13342 {
13343 if (chan->_state != AST_STATE_UP)
13344 {
13345 ast_indicate(chan,AST_CONTROL_BUSY);
13346 }
13347 while(ast_safe_sleep(chan,10000) != -1);
13348 return -1;
13349 }
13350
13351 if (chan->_state != AST_STATE_UP)
13352 {
13353 ast_answer(chan);
13354 if (!phone_mode) send_newkey(chan);
13355 }
13356
13357 length=strlen(options)+2;
13358 orig_s=ast_malloc(length);
13359 if(!orig_s) {
13360 ast_log(LOG_WARNING, "Out of memory\n");
13361 return -1;
13362 }
13363 s=orig_s;
13364 strncpy(s,options,length);
13365
13366 template=strsep(&s,"|");
13367 if(!template) {
13368 ast_log(LOG_WARNING, "An announce template must be defined\n");
13369 ast_free(orig_s);
13370 return -1;
13371 }
13372
13373 if(s) {
13374 timeout = atoi(strsep(&s, "|"));
13375 timeout *= 1000;
13376 }
13377
13378 return_context = s;
13379
13380 if(return_context != NULL) {
13381
13382
13383 working = return_context;
13384 context = strsep(&working, "|");
13385 exten = strsep(&working, "|");
13386 if(!exten) {
13387
13388 priority = context;
13389 exten = NULL;
13390 context = NULL;
13391 } else {
13392 priority = strsep(&working, "|");
13393 if(!priority) {
13394
13395 priority = exten;
13396 exten = context;
13397 context = NULL;
13398 }
13399 }
13400 if(atoi(priority) < 0) {
13401 ast_log(LOG_WARNING, "Priority '%s' must be a number > 0\n", priority);
13402 ast_free(orig_s);
13403 return -1;
13404 }
13405
13406 chan->priority = atoi(priority);
13407 #ifdef OLD_ASTERISK
13408 if(exten && strcasecmp(exten, "BYEXTENSION"))
13409 #else
13410 if(exten)
13411 #endif
13412 strncpy(chan->exten, exten, sizeof(chan->exten)-1);
13413 if(context)
13414 strncpy(chan->context, context, sizeof(chan->context)-1);
13415 } else {
13416 chan->priority++;
13417 }
13418
13419 if(option_verbose > 2) {
13420 ast_verbose(VERBOSE_PREFIX_3 "Return Context: (%s,%s,%d) ID: %s\n",
13421 chan->context, chan->exten, chan->priority,
13422 S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, ""));
13423 if(!ast_exists_extension(chan, chan->context, chan->exten, chan->priority,
13424 S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, NULL))) {
13425 ast_verbose( VERBOSE_PREFIX_3 "Warning: Return Context Invalid, call will return to default|s\n");
13426 }
13427 }
13428
13429
13430
13431
13432 ast_masq_park_call(chan, NULL, timeout, &lot);
13433
13434 if (option_verbose > 2) ast_verbose( VERBOSE_PREFIX_3 "Call Parking Called, lot: %d, timeout: %d, context: %s\n", lot, timeout, return_context);
13435
13436 snprintf(buffer, sizeof(buffer) - 1, "%d,%s", lot, template + 1);
13437
13438 rpt_telemetry(myrpt,REV_PATCH,buffer);
13439
13440 ast_free(orig_s);
13441
13442 return 0;
13443
13444 }
13445
13446 if (!options)
13447 {
13448 struct ast_hostent ahp;
13449 struct hostent *hp;
13450 struct in_addr ia;
13451 char hisip[100],nodeip[100],*val, *s, *s1, *s2, *s3, *b,*b1;
13452
13453
13454 b = S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, NULL);
13455 if (!b)
13456 {
13457 ast_log(LOG_WARNING, "Does not have callerid on %s\n",tmp);
13458 return -1;
13459 }
13460
13461 memset(hisip,0,sizeof(hisip));
13462 #ifdef ALLOW_LOCAL_CHANNELS
13463
13464 if (strncmp(chan->name,"Local",5)==0) {
13465 strcpy(hisip,"127.0.0.1");
13466 } else {
13467 pbx_substitute_variables_helper(chan,"${IAXPEER(CURRENTCHANNEL)}",hisip,sizeof(hisip) - 1);
13468 }
13469 #else
13470 pbx_substitute_variables_helper(chan,"${IAXPEER(CURRENTCHANNEL)}",hisip,sizeof(hisip) - 1);
13471 #endif
13472
13473 if (!hisip[0])
13474 {
13475 ast_log(LOG_WARNING, "Link IP address cannot be determined!!\n");
13476 return -1;
13477 }
13478
13479 b1 = ast_strdupa(b);
13480 ast_shrink_phone_number(b1);
13481 if (!strcmp(myrpt->name,b1))
13482 {
13483 ast_log(LOG_WARNING, "Trying to link to self!!\n");
13484 return -1;
13485 }
13486
13487 if (*b1 < '1')
13488 {
13489 ast_log(LOG_WARNING, "Node %s Invalid for connection here!!\n",b1);
13490 return -1;
13491 }
13492
13493
13494
13495 val = node_lookup(myrpt,b1);
13496 if (!val)
13497 {
13498 ast_log(LOG_WARNING, "Reported node %s cannot be found!!\n",b1);
13499 return -1;
13500 }
13501 strncpy(tmp,val,sizeof(tmp) - 1);
13502 s = tmp;
13503 s1 = strsep(&s,",");
13504 if (!strchr(s1,':') && strchr(s1,'/') && strncasecmp(s1, "local/", 6))
13505 {
13506 sy = strchr(s1,'/');
13507 *sy = 0;
13508 sprintf(sx,"%s:4569/%s",s1,sy + 1);
13509 s1 = sx;
13510 }
13511 s2 = strsep(&s,",");
13512 if (!s2)
13513 {
13514 ast_log(LOG_WARNING, "Reported node %s not in correct format!!\n",b1);
13515 return -1;
13516 }
13517 if (strcmp(s2,"NONE")) {
13518 hp = ast_gethostbyname(s2, &ahp);
13519 if (!hp)
13520 {
13521 ast_log(LOG_WARNING, "Reported node %s, name %s cannot be found!!\n",b1,s2);
13522 return -1;
13523 }
13524 memcpy(&ia,hp->h_addr,sizeof(in_addr_t));
13525 #ifdef OLD_ASTERISK
13526 ast_inet_ntoa(nodeip,sizeof(nodeip) - 1,ia);
13527 #else
13528 strncpy(nodeip,ast_inet_ntoa(ia),sizeof(nodeip) - 1);
13529 #endif
13530 s3 = strchr(hisip,':');
13531 if (s3) *s3 = 0;
13532 if (strcmp(hisip,nodeip))
13533 {
13534 s3 = strchr(s1,'@');
13535 if (s3) s1 = s3 + 1;
13536 s3 = strchr(s1,'/');
13537 if (s3) *s3 = 0;
13538 s3 = strchr(s1,':');
13539 if (s3) *s3 = 0;
13540 hp = ast_gethostbyname(s1, &ahp);
13541 if (!hp)
13542 {
13543 ast_log(LOG_WARNING, "Reported node %s, name %s cannot be found!!\n",b1,s1);
13544 return -1;
13545 }
13546 memcpy(&ia,hp->h_addr,sizeof(in_addr_t));
13547 #ifdef OLD_ASTERISK
13548 ast_inet_ntoa(nodeip,sizeof(nodeip) - 1,ia);
13549 #else
13550 strncpy(nodeip,ast_inet_ntoa(ia),sizeof(nodeip) - 1);
13551 #endif
13552 if (strcmp(hisip,nodeip))
13553 {
13554 ast_log(LOG_WARNING, "Node %s IP %s does not match link IP %s!!\n",b1,nodeip,hisip);
13555 return -1;
13556 }
13557 }
13558 }
13559 }
13560
13561
13562 if (!myrpt->remote)
13563 {
13564 char *b,*b1;
13565 int reconnects = 0;
13566
13567 rpt_mutex_lock(&myrpt->lock);
13568 i = myrpt->xlink;
13569 rpt_mutex_unlock(&myrpt->lock);
13570 if (i)
13571 {
13572 ast_log(LOG_WARNING, "Cannot connect to node %s, system busy\n",myrpt->name);
13573 return -1;
13574 }
13575
13576 b = S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, NULL);
13577 if (!b)
13578 {
13579 ast_log(LOG_WARNING, "Doesnt have callerid on %s\n",tmp);
13580 return -1;
13581 }
13582
13583 b1 = ast_strdupa(b);
13584 ast_shrink_phone_number(b1);
13585 if (!strcmp(myrpt->name,b1))
13586 {
13587 ast_log(LOG_WARNING, "Trying to link to self!!\n");
13588 return -1;
13589 }
13590 rpt_mutex_lock(&myrpt->lock);
13591 l = myrpt->links.next;
13592
13593 while(l != &myrpt->links)
13594 {
13595 if (l->name[0] == '0')
13596 {
13597 l = l->next;
13598 continue;
13599 }
13600
13601 if (!strcmp(l->name,b1)) break;
13602 l = l->next;
13603 }
13604
13605 if (l != &myrpt->links)
13606 {
13607 l->killme = 1;
13608 l->retries = l->max_retries + 1;
13609 l->disced = 2;
13610 reconnects = l->reconnects;
13611 reconnects++;
13612 rpt_mutex_unlock(&myrpt->lock);
13613 usleep(500000);
13614 } else
13615 rpt_mutex_unlock(&myrpt->lock);
13616
13617 l = ast_malloc(sizeof(struct rpt_link));
13618 if (!l)
13619 {
13620 ast_log(LOG_WARNING, "Unable to malloc\n");
13621 pthread_exit(NULL);
13622 }
13623
13624 memset((char *)l,0,sizeof(struct rpt_link));
13625 l->mode = 1;
13626 strncpy(l->name,b1,MAXNODESTR - 1);
13627 l->isremote = 0;
13628 l->chan = chan;
13629 l->connected = 1;
13630 l->thisconnected = 1;
13631 l->hasconnected = 1;
13632 l->reconnects = reconnects;
13633 l->phonemode = phone_mode;
13634 l->phonevox = phone_vox;
13635 l->lastf1 = NULL;
13636 l->lastf2 = NULL;
13637 l->dtmfed = 0;
13638 voxinit_link(l,1);
13639 ast_set_read_format(l->chan,AST_FORMAT_SLINEAR);
13640 ast_set_write_format(l->chan,AST_FORMAT_SLINEAR);
13641
13642 l->pchan = ast_request("DAHDI", AST_FORMAT_SLINEAR, NULL, "pseudo", NULL);
13643 if (!l->pchan)
13644 {
13645 fprintf(stderr,"rpt:Sorry unable to obtain pseudo channel\n");
13646 pthread_exit(NULL);
13647 }
13648 ast_set_read_format(l->pchan,AST_FORMAT_SLINEAR);
13649 ast_set_write_format(l->pchan,AST_FORMAT_SLINEAR);
13650 #ifdef AST_CDR_FLAG_POST_DISABLED
13651 if (l->pchan->cdr)
13652 ast_set_flag(l->pchan->cdr,AST_CDR_FLAG_POST_DISABLED);
13653 #endif
13654
13655 ci.chan = 0;
13656 ci.confno = myrpt->conf;
13657 ci.confmode = DAHDI_CONF_CONF | DAHDI_CONF_LISTENER | DAHDI_CONF_TALKER;
13658
13659 if (ioctl(l->pchan->fds[0],DAHDI_SETCONF,&ci) == -1)
13660 {
13661 ast_log(LOG_WARNING, "Unable to set conference mode to Announce\n");
13662 pthread_exit(NULL);
13663 }
13664 rpt_mutex_lock(&myrpt->lock);
13665 if ((phone_mode == 2) && (!phone_vox)) l->lastrealrx = 1;
13666 l->max_retries = MAX_RETRIES;
13667
13668 insque((struct qelem *)l,(struct qelem *)myrpt->links.next);
13669 __kickshort(myrpt);
13670 rpt_mutex_unlock(&myrpt->lock);
13671 if (chan->_state != AST_STATE_UP) {
13672 ast_answer(chan);
13673 if (!phone_mode) send_newkey(chan);
13674 }
13675 if (myrpt->p.archivedir)
13676 {
13677 char str[100];
13678
13679 if (l->phonemode)
13680 sprintf(str,"LINK(P),%s",l->name);
13681 else
13682 sprintf(str,"LINK,%s",l->name);
13683 donodelog(myrpt,str);
13684 }
13685 if (!phone_mode) send_newkey(chan);
13686 return 0;
13687 }
13688
13689 rpt_mutex_lock(&myrpt->lock);
13690
13691 if (myrpt->remoteon)
13692 {
13693 rpt_mutex_unlock(&myrpt->lock);
13694 usleep(500000);
13695 if (myrpt->remoteon)
13696 {
13697 ast_log(LOG_WARNING, "Trying to use busy link on %s\n",tmp);
13698 #ifdef AST_CDR_FLAG_POST_DISABLED
13699 if (chan->cdr)
13700 ast_set_flag(chan->cdr,AST_CDR_FLAG_POST_DISABLED);
13701 #endif
13702 return -1;
13703 }
13704 rpt_mutex_lock(&myrpt->lock);
13705 }
13706 if (myrpt->p.rptnode)
13707 {
13708 char killedit = 0;
13709 time_t now;
13710
13711 time(&now);
13712 for(i = 0; i < nrpts; i++)
13713 {
13714 if (!strcasecmp(rpt_vars[i].name,myrpt->p.rptnode))
13715 {
13716 if ((rpt_vars[i].links.next != &rpt_vars[i].links) ||
13717 rpt_vars[i].keyed ||
13718 ((rpt_vars[i].lastkeyedtime + RPT_LOCKOUT_SECS) > now) ||
13719 rpt_vars[i].txkeyed ||
13720 ((rpt_vars[i].lasttxkeyedtime + RPT_LOCKOUT_SECS) > now))
13721 {
13722 rpt_mutex_unlock(&myrpt->lock);
13723 ast_log(LOG_WARNING, "Trying to use busy link (repeater node %s) on %s\n",rpt_vars[i].name,tmp);
13724 #ifdef AST_CDR_FLAG_POST_DISABLED
13725 if (chan->cdr)
13726 ast_set_flag(chan->cdr,AST_CDR_FLAG_POST_DISABLED);
13727 #endif
13728 return -1;
13729 }
13730 while(rpt_vars[i].xlink != 3)
13731 {
13732 if (!killedit)
13733 {
13734 ast_softhangup(rpt_vars[i].rxchannel,AST_SOFTHANGUP_DEV);
13735 rpt_vars[i].xlink = 1;
13736 killedit = 1;
13737 }
13738 rpt_mutex_unlock(&myrpt->lock);
13739 if (ast_safe_sleep(chan,500) == -1)
13740 {
13741 #ifdef AST_CDR_FLAG_POST_DISABLED
13742 if (chan->cdr)
13743 ast_set_flag(chan->cdr,AST_CDR_FLAG_POST_DISABLED);
13744 #endif
13745 return -1;
13746 }
13747 rpt_mutex_lock(&myrpt->lock);
13748 }
13749 break;
13750 }
13751 }
13752 }
13753
13754 #ifdef HAVE_IOPERM
13755 if ( (!strcmp(myrpt->remoterig, remote_rig_rbi)||!strcmp(myrpt->remoterig, remote_rig_ppp16)) &&
13756 (ioperm(myrpt->p.iobase,1,1) == -1))
13757 {
13758 rpt_mutex_unlock(&myrpt->lock);
13759 ast_log(LOG_WARNING, "Can't get io permission on IO port %x hex\n",myrpt->p.iobase);
13760 return -1;
13761 }
13762 #endif
13763 myrpt->remoteon = 1;
13764 #ifdef OLD_ASTERISK
13765 LOCAL_USER_ADD(u);
13766 #endif
13767 rpt_mutex_unlock(&myrpt->lock);
13768
13769 for(i = 0; i < nrpts; i++)
13770 {
13771 if (&rpt_vars[i] == myrpt)
13772 {
13773 load_rpt_vars(i,0);
13774 break;
13775 }
13776 }
13777 rpt_mutex_lock(&myrpt->lock);
13778 tele = strchr(myrpt->rxchanname,'/');
13779 if (!tele)
13780 {
13781 fprintf(stderr,"rpt:Dial number must be in format tech/number\n");
13782 rpt_mutex_unlock(&myrpt->lock);
13783 pthread_exit(NULL);
13784 }
13785 *tele++ = 0;
13786 myrpt->rxchannel = ast_request(myrpt->rxchanname, AST_FORMAT_SLINEAR, NULL, tele, NULL);
13787 myrpt->dahdirxchannel = NULL;
13788 if (!strcasecmp(myrpt->rxchanname,"DAHDI"))
13789 myrpt->dahdirxchannel = myrpt->rxchannel;
13790 if (myrpt->rxchannel)
13791 {
13792 ast_set_read_format(myrpt->rxchannel,AST_FORMAT_SLINEAR);
13793 ast_set_write_format(myrpt->rxchannel,AST_FORMAT_SLINEAR);
13794 #ifdef AST_CDR_FLAG_POST_DISABLED
13795 if (myrpt->rxchannel->cdr)
13796 ast_set_flag(myrpt->rxchannel->cdr,AST_CDR_FLAG_POST_DISABLED);
13797 #endif
13798 #ifndef NEW_ASTERISK
13799 myrpt->rxchannel->whentohangup = 0;
13800 #endif
13801 myrpt->rxchannel->appl = "Apprpt";
13802 myrpt->rxchannel->data = "(Link Rx)";
13803 if (option_verbose > 2)
13804 ast_verbose(VERBOSE_PREFIX_3 "rpt (Rx) initiating call to %s/%s on %s\n",
13805 myrpt->rxchanname,tele,myrpt->rxchannel->name);
13806 rpt_mutex_unlock(&myrpt->lock);
13807 ast_call(myrpt->rxchannel,tele,999);
13808 rpt_mutex_lock(&myrpt->lock);
13809 }
13810 else
13811 {
13812 fprintf(stderr,"rpt:Sorry unable to obtain Rx channel\n");
13813 rpt_mutex_unlock(&myrpt->lock);
13814 pthread_exit(NULL);
13815 }
13816 *--tele = '/';
13817 myrpt->dahditxchannel = NULL;
13818 if (myrpt->txchanname)
13819 {
13820 tele = strchr(myrpt->txchanname,'/');
13821 if (!tele)
13822 {
13823 fprintf(stderr,"rpt:Dial number must be in format tech/number\n");
13824 rpt_mutex_unlock(&myrpt->lock);
13825 ast_hangup(myrpt->rxchannel);
13826 pthread_exit(NULL);
13827 }
13828 *tele++ = 0;
13829 myrpt->txchannel = ast_request(myrpt->txchanname, AST_FORMAT_SLINEAR, NULL, tele, NULL);
13830 if (!strncasecmp(myrpt->txchanname,"DAHDI",3))
13831 myrpt->dahditxchannel = myrpt->txchannel;
13832 if (myrpt->txchannel)
13833 {
13834 ast_set_read_format(myrpt->txchannel,AST_FORMAT_SLINEAR);
13835 ast_set_write_format(myrpt->txchannel,AST_FORMAT_SLINEAR);
13836 #ifdef AST_CDR_FLAG_POST_DISABLED
13837 if (myrpt->txchannel->cdr)
13838 ast_set_flag(myrpt->txchannel->cdr,AST_CDR_FLAG_POST_DISABLED);
13839 #endif
13840 #ifndef NEW_ASTERISK
13841 myrpt->txchannel->whentohangup = 0;
13842 #endif
13843 myrpt->txchannel->appl = "Apprpt";
13844 myrpt->txchannel->data = "(Link Tx)";
13845 if (option_verbose > 2)
13846 ast_verbose(VERBOSE_PREFIX_3 "rpt (Tx) initiating call to %s/%s on %s\n",
13847 myrpt->txchanname,tele,myrpt->txchannel->name);
13848 rpt_mutex_unlock(&myrpt->lock);
13849 ast_call(myrpt->txchannel,tele,999);
13850 rpt_mutex_lock(&myrpt->lock);
13851 }
13852 else
13853 {
13854 fprintf(stderr,"rpt:Sorry unable to obtain Tx channel\n");
13855 rpt_mutex_unlock(&myrpt->lock);
13856 ast_hangup(myrpt->rxchannel);
13857 pthread_exit(NULL);
13858 }
13859 *--tele = '/';
13860 }
13861 else
13862 {
13863 myrpt->txchannel = myrpt->rxchannel;
13864 if (!strncasecmp(myrpt->rxchanname,"DAHDI",3))
13865 myrpt->dahditxchannel = myrpt->rxchannel;
13866 }
13867
13868 myrpt->pchannel = ast_request("DAHDI", AST_FORMAT_SLINEAR, NULL, "pseudo", NULL);
13869 if (!myrpt->pchannel)
13870 {
13871 fprintf(stderr,"rpt:Sorry unable to obtain pseudo channel\n");
13872 rpt_mutex_unlock(&myrpt->lock);
13873 if (myrpt->txchannel != myrpt->rxchannel)
13874 ast_hangup(myrpt->txchannel);
13875 ast_hangup(myrpt->rxchannel);
13876 pthread_exit(NULL);
13877 }
13878 ast_set_read_format(myrpt->pchannel,AST_FORMAT_SLINEAR);
13879 ast_set_write_format(myrpt->pchannel,AST_FORMAT_SLINEAR);
13880 #ifdef AST_CDR_FLAG_POST_DISABLED
13881 if (myrpt->pchannel->cdr)
13882 ast_set_flag(myrpt->pchannel->cdr,AST_CDR_FLAG_POST_DISABLED);
13883 #endif
13884 if (!myrpt->dahdirxchannel) myrpt->dahdirxchannel = myrpt->pchannel;
13885 if (!myrpt->dahditxchannel) myrpt->dahditxchannel = myrpt->pchannel;
13886
13887 ci.chan = 0;
13888 ci.confno = -1;
13889 ci.confmode = DAHDI_CONF_CONFANNMON ;
13890
13891 if (ioctl(myrpt->pchannel->fds[0],DAHDI_SETCONF,&ci) == -1)
13892 {
13893 ast_log(LOG_WARNING, "Unable to set conference mode to Announce\n");
13894 rpt_mutex_unlock(&myrpt->lock);
13895 ast_hangup(myrpt->pchannel);
13896 if (myrpt->txchannel != myrpt->rxchannel)
13897 ast_hangup(myrpt->txchannel);
13898 ast_hangup(myrpt->rxchannel);
13899 pthread_exit(NULL);
13900 }
13901
13902 myrpt->conf = myrpt->txconf = ci.confno;
13903
13904 myrpt->iofd = -1;
13905 if (myrpt->p.ioport && ((myrpt->iofd = openserial(myrpt,myrpt->p.ioport)) == -1))
13906 {
13907 rpt_mutex_unlock(&myrpt->lock);
13908 ast_hangup(myrpt->pchannel);
13909 if (myrpt->txchannel != myrpt->rxchannel)
13910 ast_hangup(myrpt->txchannel);
13911 ast_hangup(myrpt->rxchannel);
13912 pthread_exit(NULL);
13913 }
13914 iskenwood_pci4 = 0;
13915 memset(&z,0,sizeof(z));
13916 if ((myrpt->iofd < 1) && (myrpt->txchannel == myrpt->dahditxchannel))
13917 {
13918 z.radpar = DAHDI_RADPAR_REMMODE;
13919 z.data = DAHDI_RADPAR_REM_NONE;
13920 res = ioctl(myrpt->dahditxchannel->fds[0],DAHDI_RADIO_SETPARAM,&z);
13921
13922 if ((!res) && (!strcmp(myrpt->remoterig,remote_rig_kenwood)))
13923 {
13924 z.radpar = DAHDI_RADPAR_UIOMODE;
13925 z.data = 1;
13926 if (ioctl(myrpt->dahditxchannel->fds[0],DAHDI_RADIO_SETPARAM,&z) == -1)
13927 {
13928 ast_log(LOG_ERROR,"Cannot set UIOMODE\n");
13929 return -1;
13930 }
13931 z.radpar = DAHDI_RADPAR_UIODATA;
13932 z.data = 3;
13933 if (ioctl(myrpt->dahditxchannel->fds[0],DAHDI_RADIO_SETPARAM,&z) == -1)
13934 {
13935 ast_log(LOG_ERROR,"Cannot set UIODATA\n");
13936 return -1;
13937 }
13938 i = DAHDI_OFFHOOK;
13939 if (ioctl(myrpt->dahditxchannel->fds[0],DAHDI_HOOK,&i) == -1)
13940 {
13941 ast_log(LOG_ERROR,"Cannot set hook\n");
13942 return -1;
13943 }
13944 iskenwood_pci4 = 1;
13945 }
13946 }
13947 if (myrpt->txchannel == myrpt->dahditxchannel)
13948 {
13949 i = DAHDI_ONHOOK;
13950 ioctl(myrpt->dahditxchannel->fds[0],DAHDI_HOOK,&i);
13951
13952 if ((myrpt->iofd < 1) && (!res) &&
13953 ((!strcmp(myrpt->remoterig,remote_rig_ft897)) ||
13954 (!strcmp(myrpt->remoterig,remote_rig_ic706)) ||
13955 (!strcmp(myrpt->remoterig,remote_rig_tm271))))
13956 {
13957 z.radpar = DAHDI_RADPAR_UIOMODE;
13958 z.data = 1;
13959 if (ioctl(myrpt->dahditxchannel->fds[0],DAHDI_RADIO_SETPARAM,&z) == -1)
13960 {
13961 ast_log(LOG_ERROR,"Cannot set UIOMODE\n");
13962 return -1;
13963 }
13964 z.radpar = DAHDI_RADPAR_UIODATA;
13965 z.data = 3;
13966 if (ioctl(myrpt->dahditxchannel->fds[0],DAHDI_RADIO_SETPARAM,&z) == -1)
13967 {
13968 ast_log(LOG_ERROR,"Cannot set UIODATA\n");
13969 return -1;
13970 }
13971 }
13972 }
13973 myrpt->remoterx = 0;
13974 myrpt->remotetx = 0;
13975 myrpt->retxtimer = 0;
13976 myrpt->rerxtimer = 0;
13977 myrpt->remoteon = 1;
13978 myrpt->dtmfidx = -1;
13979 myrpt->dtmfbuf[0] = 0;
13980 myrpt->dtmf_time_rem = 0;
13981 myrpt->hfscanmode = 0;
13982 myrpt->hfscanstatus = 0;
13983 if (myrpt->p.startupmacro)
13984 {
13985 snprintf(myrpt->macrobuf,MAXMACRO - 1,"PPPP%s",myrpt->p.startupmacro);
13986 }
13987 time(&myrpt->start_time);
13988 myrpt->last_activity_time = myrpt->start_time;
13989 last_timeout_warning = 0;
13990 myrpt->reload = 0;
13991 myrpt->tele.next = &myrpt->tele;
13992 myrpt->tele.prev = &myrpt->tele;
13993 myrpt->newkey = 0;
13994 rpt_mutex_unlock(&myrpt->lock);
13995 ast_set_write_format(chan, AST_FORMAT_SLINEAR);
13996 ast_set_read_format(chan, AST_FORMAT_SLINEAR);
13997 rem_rx = 0;
13998 remkeyed = 0;
13999
14000 if (myrpt->remote && (myrpt->rxchannel == myrpt->txchannel))
14001 {
14002 i = 128;
14003 ioctl(myrpt->dahdirxchannel->fds[0],DAHDI_ECHOCANCEL,&i);
14004 }
14005 if (chan->_state != AST_STATE_UP) {
14006 ast_answer(chan);
14007 if (!phone_mode) send_newkey(chan);
14008 }
14009
14010 if (myrpt->rxchannel == myrpt->dahdirxchannel)
14011 {
14012 if (ioctl(myrpt->dahdirxchannel->fds[0],DAHDI_GET_PARAMS,&par) != -1)
14013 {
14014 if (par.rxisoffhook)
14015 {
14016 ast_indicate(chan,AST_CONTROL_RADIO_KEY);
14017 myrpt->remoterx = 1;
14018 remkeyed = 1;
14019 }
14020 }
14021 }
14022 if (myrpt->p.archivedir)
14023 {
14024 char mycmd[100],mydate[100],*b,*b1;
14025 time_t myt;
14026 long blocksleft;
14027
14028
14029 mkdir(myrpt->p.archivedir,0600);
14030 sprintf(mycmd,"%s/%s",myrpt->p.archivedir,myrpt->name);
14031 mkdir(mycmd,0600);
14032 time(&myt);
14033 strftime(mydate,sizeof(mydate) - 1,"%Y%m%d%H%M%S",
14034 localtime(&myt));
14035 sprintf(mycmd,"mixmonitor start %s %s/%s/%s.wav49 a",chan->name,
14036 myrpt->p.archivedir,myrpt->name,mydate);
14037 if (myrpt->p.monminblocks)
14038 {
14039 blocksleft = diskavail(myrpt);
14040 if (myrpt->p.remotetimeout)
14041 {
14042 blocksleft -= (myrpt->p.remotetimeout *
14043 MONITOR_DISK_BLOCKS_PER_MINUTE) / 60;
14044 }
14045 if (blocksleft >= myrpt->p.monminblocks)
14046 ast_cli_command(nullfd,mycmd);
14047 } else ast_cli_command(nullfd,mycmd);
14048
14049 b = S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, NULL);
14050 if (!b)
14051 {
14052 b1 = "0";
14053 } else {
14054 b1 = ast_strdupa(b);
14055 ast_shrink_phone_number(b1);
14056 }
14057 sprintf(mycmd,"CONNECT,%s",b1);
14058 donodelog(myrpt,mycmd);
14059 }
14060 myrpt->loginuser[0] = 0;
14061 myrpt->loginlevel[0] = 0;
14062 myrpt->authtelltimer = 0;
14063 myrpt->authtimer = 0;
14064 authtold = 0;
14065 authreq = 0;
14066 if (myrpt->p.authlevel > 1) authreq = 1;
14067 setrem(myrpt);
14068 n = 0;
14069 dtmfed = 0;
14070 cs[n++] = chan;
14071 cs[n++] = myrpt->rxchannel;
14072 cs[n++] = myrpt->pchannel;
14073 if (myrpt->rxchannel != myrpt->txchannel)
14074 cs[n++] = myrpt->txchannel;
14075 if (!phone_mode) send_newkey(chan);
14076
14077 for(;;)
14078 {
14079 if (ast_check_hangup(chan)) break;
14080 if (ast_check_hangup(myrpt->rxchannel)) break;
14081 notremming = 0;
14082 setting = 0;
14083 reming = 0;
14084 telem = myrpt->tele.next;
14085 while(telem != &myrpt->tele)
14086 {
14087 if (telem->mode == SETREMOTE) setting = 1;
14088 if ((telem->mode == SETREMOTE) ||
14089 (telem->mode == SCAN) ||
14090 (telem->mode == TUNE)) reming = 1;
14091 else notremming = 1;
14092 telem = telem->next;
14093 }
14094 if (myrpt->reload)
14095 {
14096 myrpt->reload = 0;
14097
14098 for(i = 0; i < nrpts; i++)
14099 {
14100 if (&rpt_vars[i] == myrpt)
14101 {
14102 load_rpt_vars(i,0);
14103 break;
14104 }
14105 }
14106 }
14107 time(&t);
14108 if (myrpt->p.remotetimeout)
14109 {
14110 time_t r;
14111
14112 r = (t - myrpt->start_time);
14113 if (r >= myrpt->p.remotetimeout)
14114 {
14115 saynode(myrpt,chan,myrpt->name);
14116 sayfile(chan,"rpt/timeout");
14117 ast_safe_sleep(chan,1000);
14118 break;
14119 }
14120 if ((myrpt->p.remotetimeoutwarning) &&
14121 (r >= (myrpt->p.remotetimeout -
14122 myrpt->p.remotetimeoutwarning)) &&
14123 (r <= (myrpt->p.remotetimeout -
14124 myrpt->p.remotetimeoutwarningfreq)))
14125 {
14126 if (myrpt->p.remotetimeoutwarningfreq)
14127 {
14128 if ((t - last_timeout_warning) >=
14129 myrpt->p.remotetimeoutwarningfreq)
14130 {
14131 time(&last_timeout_warning);
14132 rpt_telemetry(myrpt,TIMEOUT_WARNING,0);
14133 }
14134 }
14135 else
14136 {
14137 if (!last_timeout_warning)
14138 {
14139 time(&last_timeout_warning);
14140 rpt_telemetry(myrpt,TIMEOUT_WARNING,0);
14141 }
14142 }
14143 }
14144 }
14145 if (myrpt->p.remoteinacttimeout && myrpt->last_activity_time)
14146 {
14147 time_t r;
14148
14149 r = (t - myrpt->last_activity_time);
14150 if (r >= myrpt->p.remoteinacttimeout)
14151 {
14152 saynode(myrpt,chan,myrpt->name);
14153 ast_safe_sleep(chan,1000);
14154 break;
14155 }
14156 if ((myrpt->p.remotetimeoutwarning) &&
14157 (r >= (myrpt->p.remoteinacttimeout -
14158 myrpt->p.remotetimeoutwarning)) &&
14159 (r <= (myrpt->p.remoteinacttimeout -
14160 myrpt->p.remotetimeoutwarningfreq)))
14161 {
14162 if (myrpt->p.remotetimeoutwarningfreq)
14163 {
14164 if ((t - last_timeout_warning) >=
14165 myrpt->p.remotetimeoutwarningfreq)
14166 {
14167 time(&last_timeout_warning);
14168 rpt_telemetry(myrpt,ACT_TIMEOUT_WARNING,0);
14169 }
14170 }
14171 else
14172 {
14173 if (!last_timeout_warning)
14174 {
14175 time(&last_timeout_warning);
14176 rpt_telemetry(myrpt,ACT_TIMEOUT_WARNING,0);
14177 }
14178 }
14179 }
14180 }
14181 ms = MSWAIT;
14182 who = ast_waitfor_n(cs,n,&ms);
14183 if (who == NULL) ms = 0;
14184 elap = MSWAIT - ms;
14185 if (myrpt->macrotimer) myrpt->macrotimer -= elap;
14186 if (myrpt->macrotimer < 0) myrpt->macrotimer = 0;
14187 if (!ms) continue;
14188
14189 if (myrpt->dtmf_local_timer)
14190 {
14191 if (myrpt->dtmf_local_timer > 1) myrpt->dtmf_local_timer -= elap;
14192 if (myrpt->dtmf_local_timer < 1) myrpt->dtmf_local_timer = 1;
14193 }
14194 rpt_mutex_lock(&myrpt->lock);
14195 do_dtmf_local(myrpt,0);
14196 rpt_mutex_unlock(&myrpt->lock);
14197
14198 rem_totx = myrpt->dtmf_local_timer && (!phone_mode);
14199 rem_totx |= keyed && (!myrpt->tunerequest);
14200 rem_rx = (remkeyed && (!setting)) || (myrpt->tele.next != &myrpt->tele);
14201 if(!strcmp(myrpt->remoterig, remote_rig_ic706))
14202 rem_totx |= myrpt->tunerequest;
14203
14204 if((debug > 6) && rem_totx) {
14205 ast_log(LOG_NOTICE,"Set rem_totx=%i. dtmf_local_timer=%i phone_mode=%i keyed=%i tunerequest=%i\n",rem_totx,myrpt->dtmf_local_timer,phone_mode,keyed,myrpt->tunerequest);
14206 }
14207 if (keyed && (!keyed1))
14208 {
14209 keyed1 = 1;
14210 }
14211
14212 if (!keyed && (keyed1))
14213 {
14214 time_t myt;
14215
14216 keyed1 = 0;
14217 time(&myt);
14218
14219 if ((myrpt->p.authlevel) &&
14220 (!myrpt->loginlevel[0]) &&
14221 (myt > (t + 3)))
14222 {
14223 authreq = 1;
14224 authtold = 0;
14225 myrpt->authtelltimer = AUTHTELLTIME - AUTHTXTIME;
14226 }
14227 }
14228
14229 if (rem_rx && (!myrpt->remoterx))
14230 {
14231 myrpt->remoterx = 1;
14232 ast_indicate(chan,AST_CONTROL_RADIO_KEY);
14233 }
14234 if ((!rem_rx) && (myrpt->remoterx))
14235 {
14236 myrpt->remoterx = 0;
14237 ast_indicate(chan,AST_CONTROL_RADIO_UNKEY);
14238 }
14239
14240 if (authreq && (!myrpt->loginlevel[0]))
14241 {
14242 if ((!authtold) && ((myrpt->authtelltimer += elap)
14243 >= AUTHTELLTIME))
14244 {
14245 authtold = 1;
14246 rpt_telemetry(myrpt,LOGINREQ,NULL);
14247 }
14248 if ((myrpt->authtimer += elap) >= AUTHLOGOUTTIME)
14249 {
14250 break;
14251 }
14252 }
14253 if (myrpt->newkey)
14254 {
14255 if ((myrpt->retxtimer += elap) >= REDUNDANT_TX_TIME)
14256 {
14257 myrpt->retxtimer = 0;
14258 if ((myrpt->remoterx) && (!myrpt->remotetx))
14259 ast_indicate(chan,AST_CONTROL_RADIO_KEY);
14260 else
14261 ast_indicate(chan,AST_CONTROL_RADIO_UNKEY);
14262 }
14263
14264 if ((myrpt->rerxtimer += elap) >= (REDUNDANT_TX_TIME * 2))
14265 {
14266 keyed = 0;
14267 myrpt->rerxtimer = 0;
14268 }
14269 }
14270 if (rem_totx && (!myrpt->remotetx))
14271 {
14272
14273 if ((!myrpt->p.authlevel) || myrpt->loginlevel[0])
14274 {
14275 if(debug > 6)
14276 ast_log(LOG_NOTICE,"Handle rem_totx=%i. dtmf_local_timer=%i tunerequest=%i\n",rem_totx,myrpt->dtmf_local_timer,myrpt->tunerequest);
14277
14278 myrpt->remotetx = 1;
14279
14280 if((myrpt->remtxfreqok = check_tx_freq(myrpt)))
14281 {
14282 time(&myrpt->last_activity_time);
14283 if ((iskenwood_pci4) && (myrpt->txchannel == myrpt->dahditxchannel))
14284 {
14285 z.radpar = DAHDI_RADPAR_UIODATA;
14286 z.data = 1;
14287 if (ioctl(myrpt->dahditxchannel->fds[0],DAHDI_RADIO_SETPARAM,&z) == -1)
14288 {
14289 ast_log(LOG_ERROR,"Cannot set UIODATA\n");
14290 return -1;
14291 }
14292 }
14293 else
14294 {
14295 ast_indicate(myrpt->txchannel,AST_CONTROL_RADIO_KEY);
14296 }
14297 if (myrpt->p.archivedir) donodelog(myrpt,"TXKEY");
14298 }
14299 }
14300 }
14301 if ((!rem_totx) && myrpt->remotetx)
14302 {
14303 myrpt->remotetx = 0;
14304 if(!myrpt->remtxfreqok){
14305 rpt_telemetry(myrpt,UNAUTHTX,NULL);
14306 }
14307 if ((iskenwood_pci4) && (myrpt->txchannel == myrpt->dahditxchannel))
14308 {
14309 z.radpar = DAHDI_RADPAR_UIODATA;
14310 z.data = 3;
14311 if (ioctl(myrpt->dahditxchannel->fds[0],DAHDI_RADIO_SETPARAM,&z) == -1)
14312 {
14313 ast_log(LOG_ERROR,"Cannot set UIODATA\n");
14314 return -1;
14315 }
14316 }
14317 else
14318 {
14319 ast_indicate(myrpt->txchannel,AST_CONTROL_RADIO_UNKEY);
14320 }
14321 if (myrpt->p.archivedir) donodelog(myrpt,"TXUNKEY");
14322 }
14323 if (myrpt->hfscanmode){
14324 myrpt->scantimer -= elap;
14325 if(myrpt->scantimer <= 0){
14326 if (!reming)
14327 {
14328 myrpt->scantimer = REM_SCANTIME;
14329 rpt_telemetry(myrpt,SCAN,0);
14330 } else myrpt->scantimer = 1;
14331 }
14332 }
14333 rpt_mutex_lock(&myrpt->lock);
14334 c = myrpt->macrobuf[0];
14335 if (c && (!myrpt->macrotimer))
14336 {
14337 myrpt->macrotimer = MACROTIME;
14338 memmove(myrpt->macrobuf,myrpt->macrobuf + 1,MAXMACRO - 1);
14339 if ((c == 'p') || (c == 'P'))
14340 myrpt->macrotimer = MACROPTIME;
14341 rpt_mutex_unlock(&myrpt->lock);
14342 if (myrpt->p.archivedir)
14343 {
14344 char str[100];
14345 sprintf(str,"DTMF(M),%c",c);
14346 donodelog(myrpt,str);
14347 }
14348 if (handle_remote_dtmf_digit(myrpt,c,&keyed,0) == -1) break;
14349 continue;
14350 } else rpt_mutex_unlock(&myrpt->lock);
14351 if (who == chan)
14352 {
14353 f = ast_read(chan);
14354 if (!f)
14355 {
14356 if (debug) printf("@@@@ link:Hung Up\n");
14357 break;
14358 }
14359 if (f->frametype == AST_FRAME_VOICE)
14360 {
14361 if (ioctl(chan->fds[0], DAHDI_GETCONFMUTE, &ismuted) == -1)
14362 {
14363 ismuted = 0;
14364 }
14365
14366 ismuted |= (!myrpt->remotetx);
14367 if (dtmfed && phone_mode) ismuted = 1;
14368 dtmfed = 0;
14369 if (ismuted)
14370 {
14371 memset(f->data.ptr,0,f->datalen);
14372 if (myrpt->lastf1)
14373 memset(myrpt->lastf1->data.ptr,0,myrpt->lastf1->datalen);
14374 if (myrpt->lastf2)
14375 memset(myrpt->lastf2->data.ptr,0,myrpt->lastf2->datalen);
14376 }
14377 if (f) f2 = ast_frdup(f);
14378 else f2 = NULL;
14379 f1 = myrpt->lastf2;
14380 myrpt->lastf2 = myrpt->lastf1;
14381 myrpt->lastf1 = f2;
14382 if (ismuted)
14383 {
14384 if (myrpt->lastf1)
14385 memset(myrpt->lastf1->data.ptr,0,myrpt->lastf1->datalen);
14386 if (myrpt->lastf2)
14387 memset(myrpt->lastf2->data.ptr,0,myrpt->lastf2->datalen);
14388 }
14389 if (f1)
14390 {
14391 if (phone_mode)
14392 ast_write(myrpt->txchannel,f1);
14393 else
14394 ast_write(myrpt->txchannel,f);
14395 ast_frfree(f1);
14396 }
14397 }
14398 #ifndef OLD_ASTERISK
14399 else if (f->frametype == AST_FRAME_DTMF_BEGIN)
14400 {
14401 if (myrpt->lastf1)
14402 memset(myrpt->lastf1->data.ptr,0,myrpt->lastf1->datalen);
14403 if (myrpt->lastf2)
14404 memset(myrpt->lastf2->data.ptr,0,myrpt->lastf2->datalen);
14405 dtmfed = 1;
14406 }
14407 #endif
14408 if (f->frametype == AST_FRAME_DTMF)
14409 {
14410 if (myrpt->lastf1)
14411 memset(myrpt->lastf1->data.ptr,0,myrpt->lastf1->datalen);
14412 if (myrpt->lastf2)
14413 memset(myrpt->lastf2->data.ptr,0,myrpt->lastf2->datalen);
14414 dtmfed = 1;
14415 if (handle_remote_phone_dtmf(myrpt,f->subclass.integer,&keyed,phone_mode) == -1)
14416 {
14417 if (debug) printf("@@@@ rpt:Hung Up\n");
14418 ast_frfree(f);
14419 break;
14420 }
14421 }
14422 if (f->frametype == AST_FRAME_TEXT)
14423 {
14424 if (handle_remote_data(myrpt,f->data.ptr) == -1)
14425 {
14426 if (debug) printf("@@@@ rpt:Hung Up\n");
14427 ast_frfree(f);
14428 break;
14429 }
14430 }
14431 if (f->frametype == AST_FRAME_CONTROL)
14432 {
14433 if (f->subclass.integer == AST_CONTROL_HANGUP)
14434 {
14435 if (debug) printf("@@@@ rpt:Hung Up\n");
14436 ast_frfree(f);
14437 break;
14438 }
14439
14440 if (f->subclass.integer == AST_CONTROL_RADIO_KEY)
14441 {
14442 if (debug == 7) printf("@@@@ rx key\n");
14443 keyed = 1;
14444 myrpt->rerxtimer = 0;
14445 }
14446
14447 if (f->subclass.integer == AST_CONTROL_RADIO_UNKEY)
14448 {
14449 myrpt->rerxtimer = 0;
14450 if (debug == 7) printf("@@@@ rx un-key\n");
14451 keyed = 0;
14452 }
14453 }
14454 ast_frfree(f);
14455 continue;
14456 }
14457 if (who == myrpt->rxchannel)
14458 {
14459 f = ast_read(myrpt->rxchannel);
14460 if (!f)
14461 {
14462 if (debug) printf("@@@@ link:Hung Up\n");
14463 break;
14464 }
14465 if (f->frametype == AST_FRAME_VOICE)
14466 {
14467 int myreming = 0;
14468
14469 if(!strcmp(myrpt->remoterig, remote_rig_kenwood))
14470 myreming = reming;
14471
14472 if (myreming || (!remkeyed) ||
14473 ((myrpt->remote) && (myrpt->remotetx)) ||
14474 ((myrpt->remmode != REM_MODE_FM) &&
14475 notremming))
14476 memset(f->data.ptr,0,f->datalen);
14477 ast_write(myrpt->pchannel,f);
14478 }
14479 else if (f->frametype == AST_FRAME_CONTROL)
14480 {
14481 if (f->subclass.integer == AST_CONTROL_HANGUP)
14482 {
14483 if (debug) printf("@@@@ rpt:Hung Up\n");
14484 ast_frfree(f);
14485 break;
14486 }
14487
14488 if (f->subclass.integer == AST_CONTROL_RADIO_KEY)
14489 {
14490 if (debug == 7) printf("@@@@ remote rx key\n");
14491 if (!myrpt->remotetx)
14492 {
14493 remkeyed = 1;
14494 }
14495 }
14496
14497 if (f->subclass.integer == AST_CONTROL_RADIO_UNKEY)
14498 {
14499 if (debug == 7) printf("@@@@ remote rx un-key\n");
14500 if (!myrpt->remotetx)
14501 {
14502 remkeyed = 0;
14503 }
14504 }
14505 }
14506 ast_frfree(f);
14507 continue;
14508 }
14509 if (who == myrpt->pchannel)
14510 {
14511 f = ast_read(myrpt->pchannel);
14512 if (!f)
14513 {
14514 if (debug) printf("@@@@ link:Hung Up\n");
14515 break;
14516 }
14517 if (f->frametype == AST_FRAME_VOICE)
14518 {
14519 ast_write(chan,f);
14520 }
14521 if (f->frametype == AST_FRAME_CONTROL)
14522 {
14523 if (f->subclass.integer == AST_CONTROL_HANGUP)
14524 {
14525 if (debug) printf("@@@@ rpt:Hung Up\n");
14526 ast_frfree(f);
14527 break;
14528 }
14529 }
14530 ast_frfree(f);
14531 continue;
14532 }
14533 if ((myrpt->rxchannel != myrpt->txchannel) &&
14534 (who == myrpt->txchannel))
14535 {
14536 f = ast_read(myrpt->txchannel);
14537 if (!f)
14538 {
14539 if (debug) printf("@@@@ link:Hung Up\n");
14540 break;
14541 }
14542 if (f->frametype == AST_FRAME_CONTROL)
14543 {
14544 if (f->subclass.integer == AST_CONTROL_HANGUP)
14545 {
14546 if (debug) printf("@@@@ rpt:Hung Up\n");
14547 ast_frfree(f);
14548 break;
14549 }
14550 }
14551 ast_frfree(f);
14552 continue;
14553 }
14554 }
14555 if (myrpt->p.archivedir)
14556 {
14557 char mycmd[100],*b,*b1;
14558
14559
14560 b = S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, NULL);
14561 if (!b)
14562 {
14563 b1 = "0";
14564 } else {
14565 b1 = ast_strdupa(b);
14566 ast_shrink_phone_number(b1);
14567 }
14568 sprintf(mycmd,"DISCONNECT,%s",b1);
14569 donodelog(myrpt,mycmd);
14570 }
14571
14572 while(myrpt->tele.next != &myrpt->tele) usleep(100000);
14573 sprintf(tmp,"mixmonitor stop %s",chan->name);
14574 ast_cli_command(nullfd,tmp);
14575 close(nullfd);
14576 rpt_mutex_lock(&myrpt->lock);
14577 myrpt->hfscanmode = 0;
14578 myrpt->hfscanstatus = 0;
14579 myrpt->remoteon = 0;
14580 rpt_mutex_unlock(&myrpt->lock);
14581 if (myrpt->lastf1) ast_frfree(myrpt->lastf1);
14582 myrpt->lastf1 = NULL;
14583 if (myrpt->lastf2) ast_frfree(myrpt->lastf2);
14584 myrpt->lastf2 = NULL;
14585 if ((iskenwood_pci4) && (myrpt->txchannel == myrpt->dahditxchannel))
14586 {
14587 z.radpar = DAHDI_RADPAR_UIOMODE;
14588 z.data = 3;
14589 if (ioctl(myrpt->dahditxchannel->fds[0],DAHDI_RADIO_SETPARAM,&z) == -1)
14590 {
14591 ast_log(LOG_ERROR,"Cannot set UIOMODE\n");
14592 return -1;
14593 }
14594 z.radpar = DAHDI_RADPAR_UIODATA;
14595 z.data = 3;
14596 if (ioctl(myrpt->dahditxchannel->fds[0],DAHDI_RADIO_SETPARAM,&z) == -1)
14597 {
14598 ast_log(LOG_ERROR,"Cannot set UIODATA\n");
14599 return -1;
14600 }
14601 i = DAHDI_OFFHOOK;
14602 if (ioctl(myrpt->dahditxchannel->fds[0],DAHDI_HOOK,&i) == -1)
14603 {
14604 ast_log(LOG_ERROR,"Cannot set hook\n");
14605 return -1;
14606 }
14607 }
14608 if (myrpt->iofd) close(myrpt->iofd);
14609 myrpt->iofd = -1;
14610 ast_hangup(myrpt->pchannel);
14611 if (myrpt->rxchannel != myrpt->txchannel) ast_hangup(myrpt->txchannel);
14612 ast_hangup(myrpt->rxchannel);
14613 closerem(myrpt);
14614 if (myrpt->p.rptnode)
14615 {
14616 rpt_mutex_lock(&myrpt->lock);
14617 for(i = 0; i < nrpts; i++)
14618 {
14619 if (!strcasecmp(rpt_vars[i].name,myrpt->p.rptnode))
14620 {
14621 rpt_vars[i].xlink = 0;
14622 break;
14623 }
14624 }
14625 rpt_mutex_unlock(&myrpt->lock);
14626 }
14627 #ifdef OLD_ASTERISK
14628 LOCAL_USER_REMOVE(u);
14629 #endif
14630 return res;
14631 }
14632
14633 #ifndef OLD_ASTERISK
14634
14635
14636
14637 static int manager_rpt_local_nodes(struct mansession *s, const struct message *m)
14638 {
14639 int i;
14640 astman_append(s, "<?xml version=\"1.0\"?>\r\n");
14641 astman_append(s, "<nodes>\r\n");
14642 for (i=0; i< nrpts; i++)
14643 {
14644 astman_append(s, " <node>%s</node>\r\n", rpt_vars[i].name);
14645 }
14646 astman_append(s, "</nodes>\r\n");
14647 astman_append(s, "\r\n");
14648 return RESULT_SUCCESS;
14649 }
14650
14651
14652
14653
14654
14655
14656
14657 static void rpt_manager_success(struct mansession *s, const struct message *m)
14658 {
14659 const char *id = astman_get_header(m, "ActionID");
14660 if (!ast_strlen_zero(id))
14661 astman_append(s, "ActionID: %s\r\n", id);
14662 astman_append(s, "Response: Success\r\n");
14663 }
14664
14665
14666
14667
14668
14669 static int rpt_manager_do_stats(struct mansession *s, const struct message *m, char *str)
14670 {
14671 int i,j,numoflinks;
14672 int dailytxtime, dailykerchunks;
14673 time_t now;
14674 int totalkerchunks, dailykeyups, totalkeyups, timeouts;
14675 int totalexecdcommands, dailyexecdcommands, hours, minutes, seconds;
14676 long long totaltxtime;
14677 struct rpt_link *l;
14678 char *listoflinks[MAX_STAT_LINKS];
14679 char *lastdtmfcommand,*parrot_ena;
14680 char *tot_state, *ider_state, *patch_state;
14681 char *reverse_patch_state, *sys_ena, *tot_ena, *link_ena, *patch_ena;
14682 char *sch_ena, *input_signal, *called_number, *user_funs, *tail_type;
14683 char *transmitterkeyed;
14684 const char *node = astman_get_header(m, "Node");
14685 struct rpt *myrpt;
14686
14687 static char *not_applicable = "N/A";
14688
14689 tot_state = ider_state =
14690 patch_state = reverse_patch_state =
14691 input_signal = not_applicable;
14692 called_number = lastdtmfcommand = transmitterkeyed = NULL;
14693
14694 time(&now);
14695 for(i = 0; i < nrpts; i++)
14696 {
14697 if ((node)&&(!strcmp(node,rpt_vars[i].name))){
14698 rpt_manager_success(s,m);
14699
14700 myrpt = &rpt_vars[i];
14701
14702 if(myrpt->remote){
14703 char *loginuser, *loginlevel, *freq, *rxpl, *txpl, *modestr;
14704 char offset = 0, powerlevel = 0, rxplon = 0, txplon = 0, remoteon, remmode = 0, reportfmstuff;
14705 char offsetc,powerlevelc;
14706
14707 loginuser = loginlevel = freq = rxpl = txpl = NULL;
14708
14709 rpt_mutex_lock(&myrpt->lock);
14710 if((remoteon = myrpt->remoteon)){
14711 if(!ast_strlen_zero(myrpt->loginuser))
14712 loginuser = ast_strdup(myrpt->loginuser);
14713 if(!ast_strlen_zero(myrpt->loginlevel))
14714 loginlevel = ast_strdup(myrpt->loginlevel);
14715 if(!ast_strlen_zero(myrpt->freq))
14716 freq = ast_strdup(myrpt->freq);
14717 if(!ast_strlen_zero(myrpt->rxpl))
14718 rxpl = ast_strdup(myrpt->rxpl);
14719 if(!ast_strlen_zero(myrpt->txpl))
14720 txpl = ast_strdup(myrpt->txpl);
14721 remmode = myrpt->remmode;
14722 offset = myrpt->offset;
14723 powerlevel = myrpt->powerlevel;
14724 rxplon = myrpt->rxplon;
14725 txplon = myrpt->txplon;
14726 }
14727 rpt_mutex_unlock(&myrpt->lock);
14728 astman_append(s, "IsRemoteBase: YES\r\n");
14729 astman_append(s, "RemoteOn: %s\r\n",(remoteon) ? "YES": "NO");
14730 if(remoteon){
14731 if(loginuser){
14732 astman_append(s, "LogInUser: %s\r\n", loginuser);
14733 ast_free(loginuser);
14734 }
14735 if(loginlevel){
14736 astman_append(s, "LogInLevel: %s\r\n", loginlevel);
14737 ast_free(loginlevel);
14738 }
14739 if(freq){
14740 astman_append(s, "Freq: %s\r\n", freq);
14741 ast_free(freq);
14742 }
14743 reportfmstuff = 0;
14744 switch(remmode){
14745 case REM_MODE_FM:
14746 modestr = "FM";
14747 reportfmstuff = 1;
14748 break;
14749 case REM_MODE_AM:
14750 modestr = "AM";
14751 break;
14752 case REM_MODE_USB:
14753 modestr = "USB";
14754 break;
14755 default:
14756 modestr = "LSB";
14757 break;
14758 }
14759 astman_append(s, "RemMode: %s\r\n", modestr);
14760 if(reportfmstuff){
14761 switch(offset){
14762 case REM_SIMPLEX:
14763 offsetc = 'S';
14764 break;
14765 case REM_MINUS:
14766 offsetc = '-';
14767 break;
14768 default:
14769 offsetc = '+';
14770 break;
14771 }
14772 astman_append(s, "RemOffset: %c\r\n", offsetc);
14773 if(rxplon && rxpl){
14774 astman_append(s, "RxPl: %s\r\n",rxpl);
14775 ast_free(rxpl);
14776 }
14777 if(txplon && txpl){
14778 astman_append(s, "TxPl: %s\r\n",txpl);
14779 ast_free(txpl);
14780 }
14781 }
14782 switch(powerlevel){
14783 case REM_LOWPWR:
14784 powerlevelc = 'L';
14785 break;
14786 case REM_MEDPWR:
14787 powerlevelc = 'M';
14788 break;
14789 default:
14790 powerlevelc = 'H';
14791 break;
14792 }
14793 astman_append(s,"PowerLevel: %c\r\n", powerlevelc);
14794 }
14795 astman_append(s, "\r\n");
14796 return 0;
14797 }
14798
14799
14800
14801 rpt_mutex_lock(&myrpt->lock);
14802 dailytxtime = myrpt->dailytxtime;
14803 totaltxtime = myrpt->totaltxtime;
14804 dailykeyups = myrpt->dailykeyups;
14805 totalkeyups = myrpt->totalkeyups;
14806 dailykerchunks = myrpt->dailykerchunks;
14807 totalkerchunks = myrpt->totalkerchunks;
14808 dailyexecdcommands = myrpt->dailyexecdcommands;
14809 totalexecdcommands = myrpt->totalexecdcommands;
14810 timeouts = myrpt->timeouts;
14811
14812
14813
14814 reverse_patch_state = "DOWN";
14815 numoflinks = 0;
14816 l = myrpt->links.next;
14817 while(l && (l != &myrpt->links)){
14818 if(numoflinks >= MAX_STAT_LINKS){
14819 ast_log(LOG_NOTICE,
14820 "maximum number of links exceeds %d in rpt_do_stats()!",MAX_STAT_LINKS);
14821 break;
14822 }
14823 if (l->name[0] == '0'){
14824 reverse_patch_state = "UP";
14825 l = l->next;
14826 continue;
14827 }
14828 listoflinks[numoflinks] = ast_strdup(l->name);
14829 if(listoflinks[numoflinks] == NULL){
14830 break;
14831 }
14832 else{
14833 numoflinks++;
14834 }
14835 l = l->next;
14836 }
14837
14838 if(myrpt->keyed)
14839 input_signal = "YES";
14840 else
14841 input_signal = "NO";
14842
14843 if(myrpt->txkeyed)
14844 transmitterkeyed = "YES";
14845 else
14846 transmitterkeyed = "NO";
14847
14848 if(myrpt->p.parrotmode)
14849 parrot_ena = "ENABLED";
14850 else
14851 parrot_ena = "DISABLED";
14852
14853 if(myrpt->p.s[myrpt->p.sysstate_cur].txdisable)
14854 sys_ena = "DISABLED";
14855 else
14856 sys_ena = "ENABLED";
14857
14858 if(myrpt->p.s[myrpt->p.sysstate_cur].totdisable)
14859 tot_ena = "DISABLED";
14860 else
14861 tot_ena = "ENABLED";
14862
14863 if(myrpt->p.s[myrpt->p.sysstate_cur].linkfundisable)
14864 link_ena = "DISABLED";
14865 else
14866 link_ena = "ENABLED";
14867
14868 if(myrpt->p.s[myrpt->p.sysstate_cur].autopatchdisable)
14869 patch_ena = "DISABLED";
14870 else
14871 patch_ena = "ENABLED";
14872
14873 if(myrpt->p.s[myrpt->p.sysstate_cur].schedulerdisable)
14874 sch_ena = "DISABLED";
14875 else
14876 sch_ena = "ENABLED";
14877
14878 if(myrpt->p.s[myrpt->p.sysstate_cur].userfundisable)
14879 user_funs = "DISABLED";
14880 else
14881 user_funs = "ENABLED";
14882
14883 if(myrpt->p.s[myrpt->p.sysstate_cur].alternatetail)
14884 tail_type = "ALTERNATE";
14885 else
14886 tail_type = "STANDARD";
14887
14888 if(!myrpt->totimer)
14889 tot_state = "TIMED OUT!";
14890 else if(myrpt->totimer != myrpt->p.totime)
14891 tot_state = "ARMED";
14892 else
14893 tot_state = "RESET";
14894
14895 if(myrpt->tailid)
14896 ider_state = "QUEUED IN TAIL";
14897 else if(myrpt->mustid)
14898 ider_state = "QUEUED FOR CLEANUP";
14899 else
14900 ider_state = "CLEAN";
14901
14902 switch(myrpt->callmode){
14903 case 1:
14904 patch_state = "DIALING";
14905 break;
14906 case 2:
14907 patch_state = "CONNECTING";
14908 break;
14909 case 3:
14910 patch_state = "UP";
14911 break;
14912
14913 case 4:
14914 patch_state = "CALL FAILED";
14915 break;
14916
14917 default:
14918 patch_state = "DOWN";
14919 }
14920
14921 if(strlen(myrpt->exten)){
14922 called_number = ast_strdup(myrpt->exten);
14923 }
14924
14925 if(strlen(myrpt->lastdtmfcommand)){
14926 lastdtmfcommand = ast_strdup(myrpt->lastdtmfcommand);
14927 }
14928 rpt_mutex_unlock(&myrpt->lock);
14929
14930 astman_append(s, "IsRemoteBase: NO\r\n");
14931 astman_append(s, "NodeState: %d\r\n", myrpt->p.sysstate_cur);
14932 astman_append(s, "SignalOnInput: %s\r\n", input_signal);
14933 astman_append(s, "TransmitterKeyed: %s\r\n", transmitterkeyed);
14934 astman_append(s, "Transmitter: %s\r\n", sys_ena);
14935 astman_append(s, "Parrot: %s\r\n", parrot_ena);
14936 astman_append(s, "Scheduler: %s\r\n", sch_ena);
14937 astman_append(s, "TailLength: %s\r\n", tail_type);
14938 astman_append(s, "TimeOutTimer: %s\r\n", tot_ena);
14939 astman_append(s, "TimeOutTimerState: %s\r\n", tot_state);
14940 astman_append(s, "TimeOutsSinceSystemInitialization: %d\r\n", timeouts);
14941 astman_append(s, "IdentifierState: %s\r\n", ider_state);
14942 astman_append(s, "KerchunksToday: %d\r\n", dailykerchunks);
14943 astman_append(s, "KerchunksSinceSystemInitialization: %d\r\n", totalkerchunks);
14944 astman_append(s, "KeyupsToday: %d\r\n", dailykeyups);
14945 astman_append(s, "KeyupsSinceSystemInitialization: %d\r\n", totalkeyups);
14946 astman_append(s, "DtmfCommandsToday: %d\r\n", dailyexecdcommands);
14947 astman_append(s, "DtmfCommandsSinceSystemInitialization: %d\r\n", totalexecdcommands);
14948 astman_append(s, "LastDtmfCommandExecuted: %s\r\n",
14949 (lastdtmfcommand && strlen(lastdtmfcommand)) ? lastdtmfcommand : not_applicable);
14950 hours = dailytxtime/3600000;
14951 dailytxtime %= 3600000;
14952 minutes = dailytxtime/60000;
14953 dailytxtime %= 60000;
14954 seconds = dailytxtime/1000;
14955 dailytxtime %= 1000;
14956
14957 astman_append(s, "TxTimeToday: %02d:%02d:%02d.%d\r\n",
14958 hours, minutes, seconds, dailytxtime);
14959
14960 hours = (int) totaltxtime/3600000;
14961 totaltxtime %= 3600000;
14962 minutes = (int) totaltxtime/60000;
14963 totaltxtime %= 60000;
14964 seconds = (int) totaltxtime/1000;
14965 totaltxtime %= 1000;
14966
14967 astman_append(s, "TxTimeSinceSystemInitialization: %02d:%02d:%02d.%d\r\n",
14968 hours, minutes, seconds, (int) totaltxtime);
14969
14970 sprintf(str, "NodesCurrentlyConnectedToUs: ");
14971 if(!numoflinks){
14972 strcat(str,"<NONE>");
14973 }
14974 else{
14975 for(j = 0 ;j < numoflinks; j++){
14976 sprintf(str+strlen(str), "%s", listoflinks[j]);
14977 if(j < numoflinks - 1)
14978 strcat(str,",");
14979 }
14980 }
14981 astman_append(s,"%s\r\n", str);
14982
14983 astman_append(s, "Autopatch: %s\r\n", patch_ena);
14984 astman_append(s, "AutopatchState: %s\r\n", patch_state);
14985 astman_append(s, "AutopatchCalledNumber: %s\r\n",
14986 (called_number && strlen(called_number)) ? called_number : not_applicable);
14987 astman_append(s, "ReversePatchIaxrptConnected: %s\r\n", reverse_patch_state);
14988 astman_append(s, "UserLinkingCommands: %s\r\n", link_ena);
14989 astman_append(s, "UserFunctions: %s\r\n", user_funs);
14990
14991 for(j = 0; j < numoflinks; j++){
14992 ast_free(listoflinks[j]);
14993 }
14994 if(called_number){
14995 ast_free(called_number);
14996 }
14997 if(lastdtmfcommand){
14998 ast_free(lastdtmfcommand);
14999 }
15000 astman_append(s, "\r\n");
15001 return 0;
15002 }
15003 }
15004 astman_send_error(s, m, "RptStatus unknown or missing node");
15005 return -1;
15006 }
15007
15008
15009
15010
15011
15012
15013
15014 static int manager_rpt_status(struct mansession *s, const struct message *m)
15015 {
15016 int i,res,len,idx;
15017 int uptime,hours,minutes;
15018 time_t now;
15019 const char *cmd = astman_get_header(m, "Command");
15020 char *str;
15021 enum {MGRCMD_RPTSTAT,MGRCMD_NODESTAT};
15022 struct mgrcmdtbl{
15023 const char *cmd;
15024 int index;
15025 };
15026 static struct mgrcmdtbl mct[] = {
15027 {"RptStat",MGRCMD_RPTSTAT},
15028 {"NodeStat",MGRCMD_NODESTAT},
15029 {NULL,0}
15030 };
15031
15032 time(&now);
15033
15034 len = 1024;
15035 if(!(str = ast_malloc(len)))
15036 return -1;
15037
15038
15039 if(ast_strlen_zero(cmd)){
15040 astman_send_error(s, m, "RptStatus missing command");
15041 ast_free(str);
15042 return 0;
15043 }
15044
15045 for(i = 0 ; mct[i].cmd ; i++){
15046 if(!strcmp(mct[i].cmd, cmd))
15047 break;
15048 }
15049
15050 if(!mct[i].cmd){
15051 astman_send_error(s, m, "RptStatus unknown command");
15052 ast_free(str);
15053 return 0;
15054 }
15055 else
15056 idx = mct[i].index;
15057
15058 switch(idx){
15059
15060 case MGRCMD_RPTSTAT:
15061
15062 if((res = snprintf(str, len, "Nodes: ")) > -1)
15063 len -= res;
15064 else{
15065 ast_free(str);
15066 return 0;
15067 }
15068 for(i = 0; i < nrpts; i++){
15069 if(i < nrpts - 1){
15070 if((res = snprintf(str+strlen(str), len, "%s,",rpt_vars[i].name)) < 0){
15071 ast_free(str);
15072 return 0;
15073 }
15074 }
15075 else{
15076 if((res = snprintf(str+strlen(str), len, "%s",rpt_vars[i].name)) < 0){
15077 ast_free(str);
15078 return 0;
15079 }
15080 }
15081 len -= res;
15082 }
15083
15084 rpt_manager_success(s,m);
15085
15086 if(!nrpts)
15087 astman_append(s, "<NONE>\r\n");
15088 else
15089 astman_append(s, "%s\r\n", str);
15090
15091 uptime = (int)(now - starttime);
15092 hours = uptime/3600;
15093 uptime %= 3600;
15094 minutes = uptime/60;
15095 uptime %= 60;
15096
15097 astman_append(s, "RptUptime: %02d:%02d:%02d\r\n",
15098 hours, minutes, uptime);
15099
15100 astman_append(s, "\r\n");
15101 break;
15102
15103 case MGRCMD_NODESTAT:
15104 res = rpt_manager_do_stats(s,m,str);
15105 ast_free(str);
15106 return res;
15107
15108 default:
15109 astman_send_error(s, m, "RptStatus invalid command");
15110 break;
15111 }
15112 ast_free(str);
15113 return 0;
15114 }
15115
15116 #endif
15117
15118 #ifdef OLD_ASTERISK
15119 int unload_module()
15120 #else
15121 static int unload_module(void)
15122 #endif
15123 {
15124 int i, res;
15125
15126 #ifdef OLD_ASTERISK
15127 STANDARD_HANGUP_LOCALUSERS;
15128 #endif
15129 for(i = 0; i < nrpts; i++) {
15130 if (!strcmp(rpt_vars[i].name,rpt_vars[i].p.nodes)) continue;
15131 ast_mutex_destroy(&rpt_vars[i].lock);
15132 ast_mutex_destroy(&rpt_vars[i].remlock);
15133 }
15134 res = ast_unregister_application(app);
15135
15136 #ifdef NEW_ASTERISK
15137 ast_cli_unregister_multiple(rpt_cli, ARRAY_LEN(rpt_cli));
15138 #else
15139
15140 ast_cli_unregister(&cli_debug);
15141 ast_cli_unregister(&cli_dump);
15142 ast_cli_unregister(&cli_stats);
15143 ast_cli_unregister(&cli_lstats);
15144 ast_cli_unregister(&cli_nodes);
15145 ast_cli_unregister(&cli_local_nodes);
15146 ast_cli_unregister(&cli_reload);
15147 ast_cli_unregister(&cli_restart);
15148 ast_cli_unregister(&cli_fun);
15149 ast_cli_unregister(&cli_fun1);
15150 res |= ast_cli_unregister(&cli_cmd);
15151 #endif
15152 #ifndef OLD_ASTERISK
15153 res |= ast_manager_unregister("RptLocalNodes");
15154 res |= ast_manager_unregister("RptStatus");
15155 #endif
15156 return res;
15157 }
15158
15159 #ifdef OLD_ASTERISK
15160 int load_module()
15161 #else
15162 static int load_module(void)
15163 #endif
15164 {
15165 int res;
15166 ast_pthread_create(&rpt_master_thread,NULL,rpt_master,NULL);
15167
15168 #ifdef NEW_ASTERISK
15169 ast_cli_register_multiple(rpt_cli, ARRAY_LEN(rpt_cli));
15170 res = 0;
15171 #else
15172
15173 ast_cli_register(&cli_debug);
15174 ast_cli_register(&cli_dump);
15175 ast_cli_register(&cli_stats);
15176 ast_cli_register(&cli_lstats);
15177 ast_cli_register(&cli_nodes);
15178 ast_cli_register(&cli_local_nodes);
15179 ast_cli_register(&cli_reload);
15180 ast_cli_register(&cli_restart);
15181 ast_cli_register(&cli_fun);
15182 ast_cli_register(&cli_fun1);
15183 res = ast_cli_register(&cli_cmd);
15184 #endif
15185 #ifndef OLD_ASTERISK
15186 res |= ast_manager_register("RptLocalNodes", 0, manager_rpt_local_nodes, "List local node numbers");
15187 res |= ast_manager_register("RptStatus", 0, manager_rpt_status, "Return Rpt Status for CGI");
15188
15189 #endif
15190 res |= ast_register_application(app, rpt_exec, synopsis, descrip);
15191 return res;
15192 }
15193
15194 #ifdef OLD_ASTERISK
15195 char *description()
15196 {
15197 return tdesc;
15198 }
15199 int usecount(void)
15200 {
15201 int res;
15202 STANDARD_USECOUNT(res);
15203 return res;
15204 }
15205
15206 char *key()
15207 {
15208 return ASTERISK_GPL_KEY;
15209 }
15210 #endif
15211
15212 #ifdef OLD_ASTERISK
15213 int reload()
15214 #else
15215 static int reload(void)
15216 #endif
15217 {
15218 int n;
15219
15220 for(n = 0; n < nrpts; n++) rpt_vars[n].reload = 1;
15221 return(0);
15222 }
15223
15224
15225 #ifndef OLD_ASTERISK
15226
15227 AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_DEFAULT, "Radio Repeater/Remote Base Application",
15228 .load = load_module,
15229 .unload = unload_module,
15230 .reload = reload,
15231 );
15232 #endif
15233