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 #ifdef OLD_ASTERISK
00171 #define ast_free free
00172 #define ast_malloc malloc
00173 #define ast_strdup strdup
00174 #endif
00175
00176
00177 #define MAXDTMF 32
00178 #define MAXMACRO 2048
00179 #define MAXLINKLIST 512
00180 #define LINKLISTTIME 10000
00181 #define LINKLISTSHORTTIME 200
00182 #define LINKPOSTTIME 30000
00183 #define LINKPOSTSHORTTIME 200
00184 #define KEYPOSTTIME 30000
00185 #define KEYPOSTSHORTTIME 200
00186 #define MACROTIME 100
00187 #define MACROPTIME 500
00188 #define DTMF_TIMEOUT 3
00189 #define KENWOOD_RETRIES 5
00190 #define TOPKEYN 32
00191 #define TOPKEYWAIT 3
00192 #define TOPKEYMAXSTR 30
00193
00194 #define AUTHTELLTIME 7000
00195 #define AUTHTXTIME 1000
00196 #define AUTHLOGOUTTIME 25000
00197
00198 #ifdef __RPT_NOTCH
00199 #define MAXFILTERS 10
00200 #endif
00201
00202 #define DISC_TIME 10000
00203 #define MAX_RETRIES 5
00204 #define MAX_RETRIES_PERM 1000000000
00205
00206 #define REDUNDANT_TX_TIME 2000
00207
00208 #define RETRY_TIMER_MS 5000
00209
00210 #define PATCH_DIALPLAN_TIMEOUT 1500
00211
00212 #ifdef OLD_ASTERISK
00213 #define START_DELAY 10
00214 #else
00215 #define START_DELAY 2
00216 #endif
00217
00218 #define RPT_LOCKOUT_SECS 10
00219
00220 #define MAXPEERSTR 31
00221 #define MAXREMSTR 15
00222
00223 #define DELIMCHR ','
00224 #define QUOTECHR 34
00225
00226 #define MONITOR_DISK_BLOCKS_PER_MINUTE 38
00227
00228 #define DEFAULT_MONITOR_MIN_DISK_BLOCKS 10000
00229 #define DEFAULT_REMOTE_INACT_TIMEOUT (15 * 60)
00230 #define DEFAULT_REMOTE_TIMEOUT (60 * 60)
00231 #define DEFAULT_REMOTE_TIMEOUT_WARNING (3 * 60)
00232 #define DEFAULT_REMOTE_TIMEOUT_WARNING_FREQ 30
00233
00234 #define NODES "nodes"
00235 #define EXTNODES "extnodes"
00236 #define MEMORY "memory"
00237 #define MACRO "macro"
00238 #define FUNCTIONS "functions"
00239 #define TELEMETRY "telemetry"
00240 #define MORSE "morse"
00241 #define TONEMACRO "tonemacro"
00242 #define FUNCCHAR '*'
00243 #define ENDCHAR '#'
00244 #define EXTNODEFILE "/var/lib/asterisk/rpt_extnodes"
00245 #define NODENAMES "rpt/nodenames"
00246 #define PARROTFILE "/tmp/parrot_%s_%u"
00247
00248 #define PARROTTIME 1000
00249
00250 #define DEFAULT_IOBASE 0x378
00251
00252 #define DEFAULT_CIV_ADDR 0x58
00253
00254 #define MAXCONNECTTIME 5000
00255
00256 #define MAXNODESTR 300
00257
00258 #define MAXNODELEN 16
00259
00260 #define MAXIDENTLEN 32
00261
00262 #define MAXPATCHCONTEXT 100
00263
00264 #define ACTIONSIZE 32
00265
00266 #define TELEPARAMSIZE 256
00267
00268 #define REM_SCANTIME 100
00269
00270 #define DTMF_LOCAL_TIME 250
00271 #define DTMF_LOCAL_STARTTIME 500
00272
00273 #define IC706_PL_MEMORY_OFFSET 50
00274
00275 #define VOX_ON_DEBOUNCE_COUNT 3
00276 #define VOX_OFF_DEBOUNCE_COUNT 20
00277 #define VOX_MAX_THRESHOLD 10000.0
00278 #define VOX_MIN_THRESHOLD 3000.0
00279 #define VOX_TIMEOUT_MS 5000
00280 #define VOX_RECOVER_MS 500
00281 #define SIMPLEX_PATCH_DELAY 25
00282 #define SIMPLEX_PHONE_DELAY 25
00283
00284 #define STATPOST_PROGRAM "/usr/bin/wget,-q,--output-document=/dev/null,--no-check-certificate"
00285
00286 #define ALLOW_LOCAL_CHANNELS
00287
00288 enum {REM_OFF,REM_MONITOR,REM_TX};
00289
00290 enum{ID,PROC,TERM,COMPLETE,UNKEY,REMDISC,REMALREADY,REMNOTFOUND,REMGO,
00291 CONNECTED,CONNFAIL,STATUS,TIMEOUT,ID1, STATS_TIME, PLAYBACK,
00292 STATS_VERSION, IDTALKOVER, ARB_ALPHA, TEST_TONE, REV_PATCH,
00293 TAILMSG, MACRO_NOTFOUND, MACRO_BUSY, LASTNODEKEY, FULLSTATUS,
00294 MEMNOTFOUND, INVFREQ, REMMODE, REMLOGIN, REMXXX, REMSHORTSTATUS,
00295 REMLONGSTATUS, LOGINREQ, SCAN, SCANSTAT, TUNE, SETREMOTE, TOPKEY,
00296 TIMEOUT_WARNING, ACT_TIMEOUT_WARNING, LINKUNKEY, UNAUTHTX, PARROT,
00297 STATS_TIME_LOCAL};
00298
00299
00300 enum {REM_SIMPLEX,REM_MINUS,REM_PLUS};
00301
00302 enum {REM_LOWPWR,REM_MEDPWR,REM_HIPWR};
00303
00304 enum {DC_INDETERMINATE, DC_REQ_FLUSH, DC_ERROR, DC_COMPLETE, DC_COMPLETEQUIET, DC_DOKEY};
00305
00306 enum {SOURCE_RPT, SOURCE_LNK, SOURCE_RMT, SOURCE_PHONE, SOURCE_DPHONE, SOURCE_ALT};
00307
00308 enum {DLY_TELEM, DLY_ID, DLY_UNKEY, DLY_CALLTERM, DLY_COMP, DLY_LINKUNKEY, DLY_PARROT};
00309
00310 enum {REM_MODE_FM,REM_MODE_USB,REM_MODE_LSB,REM_MODE_AM};
00311
00312 enum {HF_SCAN_OFF,HF_SCAN_DOWN_SLOW,HF_SCAN_DOWN_QUICK,
00313 HF_SCAN_DOWN_FAST,HF_SCAN_UP_SLOW,HF_SCAN_UP_QUICK,HF_SCAN_UP_FAST};
00314
00315 #include "asterisk.h"
00316
00317 ASTERISK_FILE_VERSION(__FILE__, "$Revision: 211580 $")
00318
00319 #include <signal.h>
00320 #include <stdio.h>
00321 #include <stdint.h>
00322 #include <unistd.h>
00323 #include <string.h>
00324 #include <stdlib.h>
00325 #include <search.h>
00326 #include <sys/types.h>
00327 #include <sys/stat.h>
00328 #include <errno.h>
00329 #include <dirent.h>
00330 #include <ctype.h>
00331 #include <sys/stat.h>
00332 #include <sys/time.h>
00333 #include <sys/file.h>
00334 #include <sys/ioctl.h>
00335 #ifdef HAVE_SYS_IO_H
00336 #include <sys/io.h>
00337 #endif
00338 #include <sys/vfs.h>
00339 #include <math.h>
00340 #include <dahdi/user.h>
00341 #include <dahdi/tonezone.h>
00342 #include <netinet/in.h>
00343 #include <arpa/inet.h>
00344
00345 #include "asterisk/utils.h"
00346 #include "asterisk/lock.h"
00347 #include "asterisk/file.h"
00348 #include "asterisk/logger.h"
00349 #include "asterisk/channel.h"
00350 #include "asterisk/callerid.h"
00351 #include "asterisk/pbx.h"
00352 #include "asterisk/module.h"
00353 #include "asterisk/translate.h"
00354 #include "asterisk/features.h"
00355 #include "asterisk/options.h"
00356 #include "asterisk/cli.h"
00357 #include "asterisk/config.h"
00358 #include "asterisk/say.h"
00359 #include "asterisk/localtime.h"
00360 #include "asterisk/cdr.h"
00361 #include "asterisk/options.h"
00362 #include "asterisk/manager.h"
00363 #include "asterisk/app.h"
00364
00365 #include <termios.h>
00366
00367 #ifdef NEW_ASTERISK
00368 struct ast_flags config_flags = { CONFIG_FLAG_WITHCOMMENTS };
00369 #endif
00370
00371
00372
00373 int ast_playtones_start(struct ast_channel *chan, int vol, const char* tonelist, int interruptible);
00374
00375 void ast_playtones_stop(struct ast_channel *chan);
00376
00377 static char *tdesc = "Radio Repeater / Remote Base version 0.115 5/12/2008";
00378
00379 static char *app = "Rpt";
00380
00381 static char *synopsis = "Radio Repeater/Remote Base Control System";
00382
00383 static char *descrip =
00384 " Rpt(nodename[|options][|M][|*]): \n"
00385 " Radio Remote Link or Remote Base Link Endpoint Process.\n"
00386 "\n"
00387 " Not specifying an option puts it in normal endpoint mode (where source\n"
00388 " IP and nodename are verified).\n"
00389 "\n"
00390 " Options are as follows:\n"
00391 "\n"
00392 " X - Normal endpoint mode WITHOUT security check. Only specify\n"
00393 " this if you have checked security already (like with an IAX2\n"
00394 " user/password or something).\n"
00395 "\n"
00396 " Rannounce-string[|timeout[|timeout-destination]] - Amateur Radio\n"
00397 " Reverse Autopatch. Caller is put on hold, and announcement (as\n"
00398 " specified by the 'announce-string') is played on radio system.\n"
00399 " Users of radio system can access autopatch, dial specified\n"
00400 " code, and pick up call. Announce-string is list of names of\n"
00401 " recordings, or \"PARKED\" to substitute code for un-parking,\n"
00402 " or \"NODE\" to substitute node number.\n"
00403 "\n"
00404 " P - Phone Control mode. This allows a regular phone user to have\n"
00405 " full control and audio access to the radio system. For the\n"
00406 " user to have DTMF control, the 'phone_functions' parameter\n"
00407 " must be specified for the node in 'rpt.conf'. An additional\n"
00408 " function (cop,6) must be listed so that PTT control is available.\n"
00409 "\n"
00410 " D - Dumb Phone Control mode. This allows a regular phone user to\n"
00411 " have full control and audio access to the radio system. In this\n"
00412 " mode, the PTT is activated for the entire length of the call.\n"
00413 " For the user to have DTMF control (not generally recomended in\n"
00414 " this mode), the 'dphone_functions' parameter must be specified\n"
00415 " for the node in 'rpt.conf'. Otherwise no DTMF control will be\n"
00416 " available to the phone user.\n"
00417 "\n"
00418 " S - Simplex Dumb Phone Control mode. This allows a regular phone user\n"
00419 " audio-only access to the radio system. In this mode, the\n"
00420 " transmitter is toggled on and off when the phone user presses the\n"
00421 " funcchar (*) key on the telephone set. In addition, the transmitter\n"
00422 " will turn off if the endchar (#) key is pressed. When a user first\n"
00423 " calls in, the transmitter will be off, and the user can listen for\n"
00424 " radio traffic. When the user wants to transmit, they press the *\n"
00425 " key, start talking, then press the * key again or the # key to turn\n"
00426 " the transmitter off. No other functions can be executed by the\n"
00427 " user on the phone when this mode is selected. Note: If your\n"
00428 " radio system is full-duplex, we recommend using either P or D\n"
00429 " modes as they provide more flexibility.\n"
00430 "\n"
00431 " q - Query Status. Sets channel variables and returns + 101 in plan.\n"
00432 "\n"
00433 " M - Memory Channel Steer as MXX where XX is the memory channel number.\n"
00434 "\n"
00435 " * - Alt Macro to execute (e.g. *7 for status)\n"
00436 "\n";
00437 ;
00438
00439 static int debug = 0;
00440 static int nrpts = 0;
00441
00442 static char remdtmfstr[] = "0123456789*#ABCD";
00443
00444 enum {TOP_TOP,TOP_WON,WON_BEFREAD,BEFREAD_AFTERREAD};
00445
00446 int max_chan_stat [] = {22000,1000,22000,100,22000,2000,22000};
00447
00448 #define NRPTSTAT 7
00449
00450 struct rpt_chan_stat
00451 {
00452 struct timeval last;
00453 long long total;
00454 unsigned long count;
00455 unsigned long largest;
00456 struct timeval largest_time;
00457 };
00458
00459 char *discstr = "!!DISCONNECT!!";
00460 char *newkeystr = "!NEWKEY!";
00461 static char *remote_rig_ft897="ft897";
00462 static char *remote_rig_rbi="rbi";
00463 static char *remote_rig_kenwood="kenwood";
00464 static char *remote_rig_tm271="tm271";
00465 static char *remote_rig_ic706="ic706";
00466 static char *remote_rig_rtx150="rtx150";
00467 static char *remote_rig_rtx450="rtx450";
00468 static char *remote_rig_ppp16="ppp16";
00469
00470 #define ISRIG_RTX(x) ((!strcmp(x,remote_rig_rtx150)) || (!strcmp(x,remote_rig_rtx450)))
00471 #define IS_XPMR(x) (!strncasecmp(x->rxchanname,"rad",3))
00472
00473 #ifdef OLD_ASTERISK
00474 STANDARD_LOCAL_USER;
00475 LOCAL_USER_DECL;
00476 #endif
00477
00478 #define MSWAIT 200
00479 #define HANGTIME 5000
00480 #define TOTIME 180000
00481 #define IDTIME 300000
00482 #define MAXRPTS 20
00483 #define MAX_STAT_LINKS 32
00484 #define POLITEID 30000
00485 #define FUNCTDELAY 1500
00486
00487 #define MAXXLAT 20
00488 #define MAXXLATTIME 3
00489
00490 #define MAX_SYSSTATES 10
00491
00492 struct vox {
00493 float speech_energy;
00494 float noise_energy;
00495 int enacount;
00496 char voxena;
00497 char lastvox;
00498 int offdebcnt;
00499 int ondebcnt;
00500 } ;
00501
00502 #define mymax(x,y) ((x > y) ? x : y)
00503 #define mymin(x,y) ((x < y) ? x : y)
00504
00505 struct rpt_topkey
00506 {
00507 char node[TOPKEYMAXSTR];
00508 int timesince;
00509 int keyed;
00510 } ;
00511
00512 struct rpt_xlat
00513 {
00514 char funccharseq[MAXXLAT];
00515 char endcharseq[MAXXLAT];
00516 char passchars[MAXXLAT];
00517 int funcindex;
00518 int endindex;
00519 time_t lastone;
00520 } ;
00521
00522 static time_t starttime = 0;
00523
00524 static pthread_t rpt_master_thread;
00525
00526 struct rpt;
00527
00528 struct rpt_link
00529 {
00530 struct rpt_link *next;
00531 struct rpt_link *prev;
00532 char mode;
00533 char isremote;
00534 char phonemode;
00535 char phonevox;
00536 char name[MAXNODESTR];
00537 char lasttx;
00538 char lasttx1;
00539 char lastrx;
00540 char lastrealrx;
00541 char lastrx1;
00542 char connected;
00543 char hasconnected;
00544 char perma;
00545 char thisconnected;
00546 char outbound;
00547 char disced;
00548 char killme;
00549 long elaptime;
00550 long disctime;
00551 long retrytimer;
00552 long retxtimer;
00553 long rerxtimer;
00554 int retries;
00555 int max_retries;
00556 int reconnects;
00557 long long connecttime;
00558 struct ast_channel *chan;
00559 struct ast_channel *pchan;
00560 char linklist[MAXLINKLIST];
00561 time_t linklistreceived;
00562 long linklisttimer;
00563 int dtmfed;
00564 int linkunkeytocttimer;
00565 struct timeval lastlinktv;
00566 struct ast_frame *lastf1,*lastf2;
00567 struct rpt_chan_stat chan_stat[NRPTSTAT];
00568 struct vox vox;
00569 char wasvox;
00570 int voxtotimer;
00571 char voxtostate;
00572 char newkey;
00573 #ifdef OLD_ASTERISK
00574 AST_LIST_HEAD(, ast_frame) rxq;
00575 #else
00576 AST_LIST_HEAD_NOLOCK(, ast_frame) rxq;
00577 #endif
00578 } ;
00579
00580 struct rpt_lstat
00581 {
00582 struct rpt_lstat *next;
00583 struct rpt_lstat *prev;
00584 char peer[MAXPEERSTR];
00585 char name[MAXNODESTR];
00586 char mode;
00587 char outbound;
00588 char reconnects;
00589 char thisconnected;
00590 long long connecttime;
00591 struct rpt_chan_stat chan_stat[NRPTSTAT];
00592 } ;
00593
00594 struct rpt_tele
00595 {
00596 struct rpt_tele *next;
00597 struct rpt_tele *prev;
00598 struct rpt *rpt;
00599 struct ast_channel *chan;
00600 int mode;
00601 struct rpt_link mylink;
00602 char param[TELEPARAMSIZE];
00603 intptr_t submode;
00604 uintptr_t parrot;
00605 pthread_t threadid;
00606 } ;
00607
00608 struct function_table_tag
00609 {
00610 char action[ACTIONSIZE];
00611 int (*function)(struct rpt *myrpt, char *param, char *digitbuf,
00612 int command_source, struct rpt_link *mylink);
00613 } ;
00614
00615
00616
00617 struct morse_bits
00618 {
00619 int len;
00620 int ddcomb;
00621 } ;
00622
00623 struct telem_defaults
00624 {
00625 char name[20];
00626 char value[80];
00627 } ;
00628
00629
00630 struct sysstate
00631 {
00632 char txdisable;
00633 char totdisable;
00634 char linkfundisable;
00635 char autopatchdisable;
00636 char schedulerdisable;
00637 char userfundisable;
00638 char alternatetail;
00639 };
00640
00641
00642 #define CMD_DEPTH 1
00643 #define CMD_STATE_IDLE 0
00644 #define CMD_STATE_BUSY 1
00645 #define CMD_STATE_READY 2
00646 #define CMD_STATE_EXECUTING 3
00647
00648 struct rpt_cmd_struct
00649 {
00650 int state;
00651 int functionNumber;
00652 char param[MAXDTMF];
00653 char digits[MAXDTMF];
00654 int command_source;
00655 };
00656
00657 static struct rpt
00658 {
00659 ast_mutex_t lock;
00660 ast_mutex_t remlock;
00661 ast_mutex_t statpost_lock;
00662 struct ast_config *cfg;
00663 char reload;
00664 char xlink;
00665 unsigned int statpost_seqno;
00666
00667 char *name;
00668 char *rxchanname;
00669 char *txchanname;
00670 char remote;
00671 char *remoterig;
00672 struct rpt_chan_stat chan_stat[NRPTSTAT];
00673 unsigned int scram;
00674
00675 struct {
00676 char *ourcontext;
00677 char *ourcallerid;
00678 char *acctcode;
00679 char *ident;
00680 char *tonezone;
00681 char simple;
00682 char *functions;
00683 char *link_functions;
00684 char *phone_functions;
00685 char *dphone_functions;
00686 char *alt_functions;
00687 char *nodes;
00688 char *extnodes;
00689 char *extnodefile;
00690 int hangtime;
00691 int althangtime;
00692 int totime;
00693 int idtime;
00694 int tailmessagetime;
00695 int tailsquashedtime;
00696 int duplex;
00697 int politeid;
00698 char *tailmessages[500];
00699 int tailmessagemax;
00700 char *memory;
00701 char *macro;
00702 char *tonemacro;
00703 char *startupmacro;
00704 int iobase;
00705 char *ioport;
00706 char funcchar;
00707 char endchar;
00708 char nobusyout;
00709 char notelemtx;
00710 char propagate_dtmf;
00711 char propagate_phonedtmf;
00712 char linktolink;
00713 unsigned char civaddr;
00714 struct rpt_xlat inxlat;
00715 struct rpt_xlat outxlat;
00716 char *archivedir;
00717 int authlevel;
00718 char *csstanzaname;
00719 char *skedstanzaname;
00720 char *txlimitsstanzaname;
00721 long monminblocks;
00722 int remoteinacttimeout;
00723 int remotetimeout;
00724 int remotetimeoutwarning;
00725 int remotetimeoutwarningfreq;
00726 int sysstate_cur;
00727 struct sysstate s[MAX_SYSSTATES];
00728 char parrotmode;
00729 int parrottime;
00730 char *rptnode;
00731 char remote_mars;
00732 int voxtimeout_ms;
00733 int voxrecover_ms;
00734 int simplexpatchdelay;
00735 int simplexphonedelay;
00736 char *statpost_program;
00737 char *statpost_url;
00738 } p;
00739 struct rpt_link links;
00740 int unkeytocttimer;
00741 time_t lastkeyedtime;
00742 time_t lasttxkeyedtime;
00743 char keyed;
00744 char txkeyed;
00745 char exttx;
00746 char localtx;
00747 char remoterx;
00748 char remotetx;
00749 char remoteon;
00750 char remtxfreqok;
00751 char tounkeyed;
00752 char tonotify;
00753 char dtmfbuf[MAXDTMF];
00754 char macrobuf[MAXMACRO];
00755 char rem_dtmfbuf[MAXDTMF];
00756 char lastdtmfcommand[MAXDTMF];
00757 char cmdnode[50];
00758 char nowchan;
00759 char waschan;
00760 char bargechan;
00761 char macropatch;
00762 char parrotstate;
00763 int parrottimer;
00764 unsigned int parrotcnt;
00765 struct ast_channel *rxchannel,*txchannel, *monchannel, *parrotchannel;
00766 struct ast_channel *pchannel,*txpchannel, *dahdirxchannel, *dahditxchannel;
00767 struct ast_channel *voxchannel;
00768 struct ast_frame *lastf1,*lastf2;
00769 struct rpt_tele tele;
00770 struct timeval lasttv,curtv;
00771 pthread_t rpt_call_thread,rpt_thread;
00772 time_t dtmf_time,rem_dtmf_time,dtmf_time_rem;
00773 int calldigittimer;
00774 int tailtimer,totimer,idtimer,txconf,conf,callmode,cidx,scantimer,tmsgtimer,skedtimer;
00775 int mustid,tailid;
00776 int tailevent;
00777 int telemrefcount;
00778 int dtmfidx,rem_dtmfidx;
00779 int dailytxtime,dailykerchunks,totalkerchunks,dailykeyups,totalkeyups,timeouts;
00780 int totalexecdcommands, dailyexecdcommands;
00781 long retxtimer;
00782 long rerxtimer;
00783 long long totaltxtime;
00784 char mydtmf;
00785 char exten[AST_MAX_EXTENSION];
00786 char freq[MAXREMSTR],rxpl[MAXREMSTR],txpl[MAXREMSTR];
00787 char offset;
00788 char powerlevel;
00789 char txplon;
00790 char rxplon;
00791 char remmode;
00792 char tunerequest;
00793 char hfscanmode;
00794 int hfscanstatus;
00795 char hfscanstop;
00796 char lastlinknode[MAXNODESTR];
00797 char savednodes[MAXNODESTR];
00798 int stopgen;
00799 char patchfarenddisconnect;
00800 char patchnoct;
00801 char patchquiet;
00802 char patchcontext[MAXPATCHCONTEXT];
00803 int patchdialtime;
00804 int macro_longest;
00805 int phone_longestfunc;
00806 int alt_longestfunc;
00807 int dphone_longestfunc;
00808 int link_longestfunc;
00809 int longestfunc;
00810 int longestnode;
00811 int threadrestarts;
00812 int tailmessagen;
00813 time_t disgorgetime;
00814 time_t lastthreadrestarttime;
00815 long macrotimer;
00816 char lastnodewhichkeyedusup[MAXNODESTR];
00817 int dtmf_local_timer;
00818 char dtmf_local_str[100];
00819 struct ast_filestream *monstream,*parrotstream;
00820 char loginuser[50];
00821 char loginlevel[10];
00822 long authtelltimer;
00823 long authtimer;
00824 int iofd;
00825 time_t start_time,last_activity_time;
00826 char lasttone[32];
00827 struct rpt_tele *active_telem;
00828 struct rpt_topkey topkey[TOPKEYN];
00829 int topkeystate;
00830 time_t topkeytime;
00831 int topkeylong;
00832 struct vox vox;
00833 char wasvox;
00834 int voxtotimer;
00835 char voxtostate;
00836 int linkposttimer;
00837 int keyposttimer;
00838 char newkey;
00839 char inpadtest;
00840 #ifdef OLD_ASTERISK
00841 AST_LIST_HEAD(, ast_frame) txq;
00842 #else
00843 AST_LIST_HEAD_NOLOCK(, ast_frame) txq;
00844 #endif
00845 char txrealkeyed;
00846 #ifdef __RPT_NOTCH
00847 struct rptfilter
00848 {
00849 char desc[100];
00850 float x0;
00851 float x1;
00852 float x2;
00853 float y0;
00854 float y1;
00855 float y2;
00856 float gain;
00857 float const0;
00858 float const1;
00859 float const2;
00860 } filters[MAXFILTERS];
00861 #endif
00862 #ifdef _MDC_DECODE_H_
00863 mdc_decoder_t *mdc;
00864 unsigned short lastunit;
00865 #endif
00866 struct rpt_cmd_struct cmdAction;
00867 } rpt_vars[MAXRPTS];
00868
00869 struct nodelog {
00870 struct nodelog *next;
00871 struct nodelog *prev;
00872 time_t timestamp;
00873 char archivedir[MAXNODESTR];
00874 char str[MAXNODESTR * 2];
00875 } nodelog;
00876
00877 static int service_scan(struct rpt *myrpt);
00878 static int set_mode_ft897(struct rpt *myrpt, char newmode);
00879 static int set_mode_ic706(struct rpt *myrpt, char newmode);
00880 static int simple_command_ft897(struct rpt *myrpt, char command);
00881 static int setrem(struct rpt *myrpt);
00882 static int setrtx_check(struct rpt *myrpt);
00883 static int channel_revert(struct rpt *myrpt);
00884 static int channel_steer(struct rpt *myrpt, char *data);
00885
00886 AST_MUTEX_DEFINE_STATIC(nodeloglock);
00887
00888 AST_MUTEX_DEFINE_STATIC(nodelookuplock);
00889
00890 #ifdef APP_RPT_LOCK_DEBUG
00891
00892 #warning COMPILING WITH LOCK-DEBUGGING ENABLED!!
00893
00894 #define MAXLOCKTHREAD 100
00895
00896 #define rpt_mutex_lock(x) _rpt_mutex_lock(x,myrpt,__LINE__)
00897 #define rpt_mutex_unlock(x) _rpt_mutex_unlock(x,myrpt,__LINE__)
00898
00899 struct lockthread
00900 {
00901 pthread_t id;
00902 int lockcount;
00903 int lastlock;
00904 int lastunlock;
00905 } lockthreads[MAXLOCKTHREAD];
00906
00907
00908 struct by_lightning
00909 {
00910 int line;
00911 struct timeval tv;
00912 struct rpt *rpt;
00913 struct lockthread lockthread;
00914 } lock_ring[32];
00915
00916 int lock_ring_index = 0;
00917
00918 AST_MUTEX_DEFINE_STATIC(locklock);
00919
00920 static struct lockthread *get_lockthread(pthread_t id)
00921 {
00922 int i;
00923
00924 for(i = 0; i < MAXLOCKTHREAD; i++)
00925 {
00926 if (lockthreads[i].id == id) return(&lockthreads[i]);
00927 }
00928 return(NULL);
00929 }
00930
00931 static struct lockthread *put_lockthread(pthread_t id)
00932 {
00933 int i;
00934
00935 for(i = 0; i < MAXLOCKTHREAD; i++)
00936 {
00937 if (lockthreads[i].id == id)
00938 return(&lockthreads[i]);
00939 }
00940 for(i = 0; i < MAXLOCKTHREAD; i++)
00941 {
00942 if (!lockthreads[i].id)
00943 {
00944 lockthreads[i].lockcount = 0;
00945 lockthreads[i].lastlock = 0;
00946 lockthreads[i].lastunlock = 0;
00947 lockthreads[i].id = id;
00948 return(&lockthreads[i]);
00949 }
00950 }
00951 return(NULL);
00952 }
00953
00954
00955 static void rpt_mutex_spew(void)
00956 {
00957 struct by_lightning lock_ring_copy[32];
00958 int lock_ring_index_copy;
00959 int i,j;
00960 long long diff;
00961 char a[100];
00962 struct timeval lasttv;
00963
00964 ast_mutex_lock(&locklock);
00965 memcpy(&lock_ring_copy, &lock_ring, sizeof(lock_ring_copy));
00966 lock_ring_index_copy = lock_ring_index;
00967 ast_mutex_unlock(&locklock);
00968
00969 lasttv.tv_sec = lasttv.tv_usec = 0;
00970 for(i = 0 ; i < 32 ; i++)
00971 {
00972 j = (i + lock_ring_index_copy) % 32;
00973 strftime(a,sizeof(a) - 1,"%m/%d/%Y %H:%M:%S",
00974 localtime(&lock_ring_copy[j].tv.tv_sec));
00975 diff = 0;
00976 if(lasttv.tv_sec)
00977 {
00978 diff = (lock_ring_copy[j].tv.tv_sec - lasttv.tv_sec)
00979 * 1000000;
00980 diff += (lock_ring_copy[j].tv.tv_usec - lasttv.tv_usec);
00981 }
00982 lasttv.tv_sec = lock_ring_copy[j].tv.tv_sec;
00983 lasttv.tv_usec = lock_ring_copy[j].tv.tv_usec;
00984 if (!lock_ring_copy[j].tv.tv_sec) continue;
00985 if (lock_ring_copy[j].line < 0)
00986 {
00987 ast_log(LOG_NOTICE,"LOCKDEBUG [#%d] UNLOCK app_rpt.c:%d node %s pid %x diff %lld us at %s.%06d\n",
00988 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);
00989 }
00990 else
00991 {
00992 ast_log(LOG_NOTICE,"LOCKDEBUG [#%d] LOCK app_rpt.c:%d node %s pid %x diff %lld us at %s.%06d\n",
00993 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);
00994 }
00995 }
00996 }
00997
00998
00999 static void _rpt_mutex_lock(ast_mutex_t *lockp, struct rpt *myrpt, int line)
01000 {
01001 struct lockthread *t;
01002 pthread_t id;
01003
01004 id = pthread_self();
01005 ast_mutex_lock(&locklock);
01006 t = put_lockthread(id);
01007 if (!t)
01008 {
01009 ast_mutex_unlock(&locklock);
01010 return;
01011 }
01012 if (t->lockcount)
01013 {
01014 int lastline = t->lastlock;
01015 ast_mutex_unlock(&locklock);
01016 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);
01017 rpt_mutex_spew();
01018 return;
01019 }
01020 t->lastlock = line;
01021 t->lockcount = 1;
01022 gettimeofday(&lock_ring[lock_ring_index].tv, NULL);
01023 lock_ring[lock_ring_index].rpt = myrpt;
01024 memcpy(&lock_ring[lock_ring_index].lockthread,t,sizeof(struct lockthread));
01025 lock_ring[lock_ring_index++].line = line;
01026 if(lock_ring_index == 32)
01027 lock_ring_index = 0;
01028 ast_mutex_unlock(&locklock);
01029 ast_mutex_lock(lockp);
01030 }
01031
01032
01033 static void _rpt_mutex_unlock(ast_mutex_t *lockp, struct rpt *myrpt, int line)
01034 {
01035 struct lockthread *t;
01036 pthread_t id;
01037
01038 id = pthread_self();
01039 ast_mutex_lock(&locklock);
01040 t = put_lockthread(id);
01041 if (!t)
01042 {
01043 ast_mutex_unlock(&locklock);
01044 return;
01045 }
01046 if (!t->lockcount)
01047 {
01048 int lastline = t->lastunlock;
01049 ast_mutex_unlock(&locklock);
01050 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);
01051 rpt_mutex_spew();
01052 return;
01053 }
01054 t->lastunlock = line;
01055 t->lockcount = 0;
01056 gettimeofday(&lock_ring[lock_ring_index].tv, NULL);
01057 lock_ring[lock_ring_index].rpt = myrpt;
01058 memcpy(&lock_ring[lock_ring_index].lockthread,t,sizeof(struct lockthread));
01059 lock_ring[lock_ring_index++].line = -line;
01060 if(lock_ring_index == 32)
01061 lock_ring_index = 0;
01062 ast_mutex_unlock(&locklock);
01063 ast_mutex_unlock(lockp);
01064 }
01065
01066 #else
01067
01068 #define rpt_mutex_lock(x) ast_mutex_lock(x)
01069 #define rpt_mutex_unlock(x) ast_mutex_unlock(x)
01070
01071 #endif
01072
01073
01074
01075
01076
01077 static int multimode_capable(struct rpt *myrpt)
01078 {
01079 if(!strcmp(myrpt->remoterig, remote_rig_ft897))
01080 return 1;
01081 if(!strcmp(myrpt->remoterig, remote_rig_ic706))
01082 return 1;
01083 return 0;
01084 }
01085
01086 static void voxinit_rpt(struct rpt *myrpt,char enable)
01087 {
01088
01089 myrpt->vox.speech_energy = 0.0;
01090 myrpt->vox.noise_energy = 0.0;
01091 myrpt->vox.enacount = 0;
01092 myrpt->vox.voxena = 0;
01093 if (!enable) myrpt->vox.voxena = -1;
01094 myrpt->vox.lastvox = 0;
01095 myrpt->vox.ondebcnt = VOX_ON_DEBOUNCE_COUNT;
01096 myrpt->vox.offdebcnt = VOX_OFF_DEBOUNCE_COUNT;
01097 myrpt->wasvox = 0;
01098 myrpt->voxtotimer = 0;
01099 myrpt->voxtostate = 0;
01100 }
01101
01102 static void voxinit_link(struct rpt_link *mylink,char enable)
01103 {
01104
01105 mylink->vox.speech_energy = 0.0;
01106 mylink->vox.noise_energy = 0.0;
01107 mylink->vox.enacount = 0;
01108 mylink->vox.voxena = 0;
01109 if (!enable) mylink->vox.voxena = -1;
01110 mylink->vox.lastvox = 0;
01111 mylink->vox.ondebcnt = VOX_ON_DEBOUNCE_COUNT;
01112 mylink->vox.offdebcnt = VOX_OFF_DEBOUNCE_COUNT;
01113 mylink->wasvox = 0;
01114 mylink->voxtotimer = 0;
01115 mylink->voxtostate = 0;
01116 }
01117
01118 static int dovox(struct vox *v,short *buf,int bs)
01119 {
01120
01121 int i;
01122 float esquare = 0.0;
01123 float energy = 0.0;
01124 float threshold = 0.0;
01125
01126 if (v->voxena < 0) return(v->lastvox);
01127 for(i = 0; i < bs; i++)
01128 {
01129 esquare += (float) buf[i] * (float) buf[i];
01130 }
01131 energy = sqrt(esquare);
01132
01133 if (energy >= v->speech_energy)
01134 v->speech_energy += (energy - v->speech_energy) / 4;
01135 else
01136 v->speech_energy += (energy - v->speech_energy) / 64;
01137
01138 if (energy >= v->noise_energy)
01139 v->noise_energy += (energy - v->noise_energy) / 64;
01140 else
01141 v->noise_energy += (energy - v->noise_energy) / 4;
01142
01143 if (v->voxena) threshold = v->speech_energy / 8;
01144 else
01145 {
01146 threshold = mymax(v->speech_energy / 16,v->noise_energy * 2);
01147 threshold = mymin(threshold,VOX_MAX_THRESHOLD);
01148 }
01149 threshold = mymax(threshold,VOX_MIN_THRESHOLD);
01150 if (energy > threshold)
01151 {
01152 if (v->voxena) v->noise_energy *= 0.75;
01153 v->voxena = 1;
01154 } else v->voxena = 0;
01155 if (v->lastvox != v->voxena)
01156 {
01157 if (v->enacount++ >= ((v->lastvox) ? v->offdebcnt : v->ondebcnt))
01158 {
01159 v->lastvox = v->voxena;
01160 v->enacount = 0;
01161 }
01162 } else v->enacount = 0;
01163 return(v->lastvox);
01164 }
01165
01166
01167
01168
01169
01170
01171
01172
01173
01174 static int rpt_do_debug(int fd, int argc, char *argv[]);
01175 static int rpt_do_dump(int fd, int argc, char *argv[]);
01176 static int rpt_do_stats(int fd, int argc, char *argv[]);
01177 static int rpt_do_lstats(int fd, int argc, char *argv[]);
01178 static int rpt_do_nodes(int fd, int argc, char *argv[]);
01179 static int rpt_do_local_nodes(int fd, int argc, char *argv[]);
01180 static int rpt_do_reload(int fd, int argc, char *argv[]);
01181 static int rpt_do_restart(int fd, int argc, char *argv[]);
01182 static int rpt_do_fun(int fd, int argc, char *argv[]);
01183 static int rpt_do_fun1(int fd, int argc, char *argv[]);
01184 static int rpt_do_cmd(int fd, int argc, char *argv[]);
01185
01186 static char debug_usage[] =
01187 "Usage: rpt debug level {0-7}\n"
01188 " Enables debug messages in app_rpt\n";
01189
01190 static char dump_usage[] =
01191 "Usage: rpt dump <nodename>\n"
01192 " Dumps struct debug info to log\n";
01193
01194 static char dump_stats[] =
01195 "Usage: rpt stats <nodename>\n"
01196 " Dumps node statistics to console\n";
01197
01198 static char dump_lstats[] =
01199 "Usage: rpt lstats <nodename>\n"
01200 " Dumps link statistics to console\n";
01201
01202 static char dump_nodes[] =
01203 "Usage: rpt nodes <nodename>\n"
01204 " Dumps a list of directly and indirectly connected nodes to the console\n";
01205
01206 static char usage_local_nodes[] =
01207 "Usage: rpt localnodes\n"
01208 " Dumps a list of the locally configured node numbers to the console.\n";
01209
01210 static char reload_usage[] =
01211 "Usage: rpt reload\n"
01212 " Reloads app_rpt running config parameters\n";
01213
01214 static char restart_usage[] =
01215 "Usage: rpt restart\n"
01216 " Restarts app_rpt\n";
01217
01218 static char fun_usage[] =
01219 "Usage: rpt fun <nodename> <command>\n"
01220 " Send a DTMF function to a node\n";
01221
01222 static char cmd_usage[] =
01223 "Usage: rpt cmd <nodename> <cmd-name> <cmd-index> <cmd-args.\n"
01224 " Send a command to a node.\n i.e. rpt cmd 2000 ilink 3 2001\n";
01225
01226 #ifndef NEW_ASTERISK
01227
01228 static struct ast_cli_entry cli_debug =
01229 { { "rpt", "debug", "level" }, rpt_do_debug,
01230 "Enable app_rpt debugging", debug_usage };
01231
01232 static struct ast_cli_entry cli_dump =
01233 { { "rpt", "dump" }, rpt_do_dump,
01234 "Dump app_rpt structs for debugging", dump_usage };
01235
01236 static struct ast_cli_entry cli_stats =
01237 { { "rpt", "stats" }, rpt_do_stats,
01238 "Dump node statistics", dump_stats };
01239
01240 static struct ast_cli_entry cli_nodes =
01241 { { "rpt", "nodes" }, rpt_do_nodes,
01242 "Dump node list", dump_nodes };
01243
01244 static struct ast_cli_entry cli_local_nodes =
01245 { { "rpt", "localnodes" }, rpt_do_local_nodes,
01246 "Dump list of local node numbers", usage_local_nodes };
01247
01248 static struct ast_cli_entry cli_lstats =
01249 { { "rpt", "lstats" }, rpt_do_lstats,
01250 "Dump link statistics", dump_lstats };
01251
01252 static struct ast_cli_entry cli_reload =
01253 { { "rpt", "reload" }, rpt_do_reload,
01254 "Reload app_rpt config", reload_usage };
01255
01256 static struct ast_cli_entry cli_restart =
01257 { { "rpt", "restart" }, rpt_do_restart,
01258 "Restart app_rpt", restart_usage };
01259
01260 static struct ast_cli_entry cli_fun =
01261 { { "rpt", "fun" }, rpt_do_fun,
01262 "Execute a DTMF function", fun_usage };
01263
01264 static struct ast_cli_entry cli_fun1 =
01265 { { "rpt", "fun1" }, rpt_do_fun1,
01266 "Execute a DTMF function", fun_usage };
01267
01268 static struct ast_cli_entry cli_cmd =
01269 { { "rpt", "cmd" }, rpt_do_cmd,
01270 "Execute a DTMF function", cmd_usage };
01271
01272 #endif
01273
01274
01275
01276
01277
01278
01279 static struct telem_defaults tele_defs[] = {
01280 {"ct1","|t(350,0,100,3072)(500,0,100,3072)(660,0,100,3072)"},
01281 {"ct2","|t(660,880,150,3072)"},
01282 {"ct3","|t(440,0,150,3072)"},
01283 {"ct4","|t(550,0,150,3072)"},
01284 {"ct5","|t(660,0,150,3072)"},
01285 {"ct6","|t(880,0,150,3072)"},
01286 {"ct7","|t(660,440,150,3072)"},
01287 {"ct8","|t(700,1100,150,3072)"},
01288 {"remotemon","|t(1600,0,75,2048)"},
01289 {"remotetx","|t(2000,0,75,2048)(0,0,75,0)(1600,0,75,2048)"},
01290 {"cmdmode","|t(900,904,200,2048)"},
01291 {"functcomplete","|t(1000,0,100,2048)(0,0,100,0)(1000,0,100,2048)"}
01292 } ;
01293
01294
01295
01296
01297
01298 static int setrbi(struct rpt *myrpt);
01299 static int set_ft897(struct rpt *myrpt);
01300 static int set_ic706(struct rpt *myrpt);
01301 static int setkenwood(struct rpt *myrpt);
01302 static int set_tm271(struct rpt *myrpt);
01303 static int setrbi_check(struct rpt *myrpt);
01304
01305
01306
01307
01308
01309
01310
01311 static int function_ilink(struct rpt *myrpt, char *param, char *digitbuf, int command_source, struct rpt_link *mylink);
01312 static int function_autopatchup(struct rpt *myrpt, char *param, char *digitbuf, int command_source, struct rpt_link *mylink);
01313 static int function_autopatchdn(struct rpt *myrpt, char *param, char *digitbuf, int command_source, struct rpt_link *mylink);
01314 static int function_status(struct rpt *myrpt, char *param, char *digitbuf, int command_source, struct rpt_link *mylink);
01315 static int function_cop(struct rpt *myrpt, char *param, char *digitbuf, int command_source, struct rpt_link *mylink);
01316 static int function_remote(struct rpt *myrpt, char *param, char *digitbuf, int command_source, struct rpt_link *mylink);
01317 static int function_macro(struct rpt *myrpt, char *param, char *digitbuf, int command_source, struct rpt_link *mylink);
01318 static int function_playback(struct rpt *myrpt, char *param, char *digitbuf, int command_source, struct rpt_link *mylink);
01319
01320
01321
01322
01323 static struct function_table_tag function_table[] = {
01324 {"cop", function_cop},
01325 {"autopatchup", function_autopatchup},
01326 {"autopatchdn", function_autopatchdn},
01327 {"ilink", function_ilink},
01328 {"status", function_status},
01329 {"remote", function_remote},
01330 {"macro", function_macro},
01331 {"playback", function_playback}
01332 } ;
01333
01334 static long diskavail(struct rpt *myrpt)
01335 {
01336 struct statfs statfsbuf;
01337
01338 if (!myrpt->p.archivedir) return(0);
01339 if (statfs(myrpt->p.archivedir,&statfsbuf) == -1)
01340 {
01341 ast_log(LOG_WARNING,"Cannot get filesystem size for %s node %s\n",
01342 myrpt->p.archivedir,myrpt->name);
01343 return(-1);
01344 }
01345 return(statfsbuf.f_bavail);
01346 }
01347
01348 static void flush_telem(struct rpt *myrpt)
01349 {
01350 struct rpt_tele *telem;
01351 if(debug > 2)
01352 ast_log(LOG_NOTICE, "flush_telem()!!");
01353 rpt_mutex_lock(&myrpt->lock);
01354 telem = myrpt->tele.next;
01355 while(telem != &myrpt->tele)
01356 {
01357 if (telem->mode != SETREMOTE) ast_softhangup(telem->chan,AST_SOFTHANGUP_DEV);
01358 telem = telem->next;
01359 }
01360 rpt_mutex_unlock(&myrpt->lock);
01361 }
01362
01363
01364
01365 static int priority_jump(struct rpt *myrpt, struct ast_channel *chan)
01366 {
01367 int res=0;
01368
01369
01370 if (ast_goto_if_exists(chan, chan->context, chan->exten, chan->priority + 101) == 0){
01371 res = 0;
01372 } else {
01373 res = -1;
01374 }
01375 return res;
01376 }
01377
01378
01379 static int linkcount(struct rpt *myrpt)
01380 {
01381 struct rpt_link *l;
01382 char *reverse_patch_state;
01383 int numoflinks;
01384
01385 reverse_patch_state = "DOWN";
01386 numoflinks = 0;
01387 l = myrpt->links.next;
01388 while(l && (l != &myrpt->links)){
01389 if(numoflinks >= MAX_STAT_LINKS){
01390 ast_log(LOG_WARNING,
01391 "maximum number of links exceeds %d in rpt_do_stats()!",MAX_STAT_LINKS);
01392 break;
01393 }
01394
01395
01396
01397
01398
01399 numoflinks++;
01400
01401 l = l->next;
01402 }
01403 ast_log(LOG_NOTICE, "numoflinks=%i\n",numoflinks);
01404 return numoflinks;
01405 }
01406
01407
01408
01409
01410
01411
01412 static int retreive_memory(struct rpt *myrpt, char *memory)
01413 {
01414 char tmp[30], *s, *s1, *val;
01415
01416 if (debug)ast_log(LOG_NOTICE, "memory=%s block=%s\n",memory,myrpt->p.memory);
01417
01418 val = (char *) ast_variable_retrieve(myrpt->cfg, myrpt->p.memory, memory);
01419 if (!val){
01420 return -1;
01421 }
01422 strncpy(tmp,val,sizeof(tmp) - 1);
01423 tmp[sizeof(tmp)-1] = 0;
01424
01425 s = strchr(tmp,',');
01426 if (!s)
01427 return 1;
01428 *s++ = 0;
01429 s1 = strchr(s,',');
01430 if (!s1)
01431 return 1;
01432 *s1++ = 0;
01433 strncpy(myrpt->freq, tmp, sizeof(myrpt->freq) - 1);
01434 strncpy(myrpt->rxpl, s, sizeof(myrpt->rxpl) - 1);
01435 strncpy(myrpt->txpl, s, sizeof(myrpt->rxpl) - 1);
01436 myrpt->remmode = REM_MODE_FM;
01437 myrpt->offset = REM_SIMPLEX;
01438 myrpt->powerlevel = REM_MEDPWR;
01439 myrpt->txplon = myrpt->rxplon = 0;
01440 while(*s1){
01441 switch(*s1++){
01442 case 'A':
01443 case 'a':
01444 strcpy(myrpt->rxpl, "100.0");
01445 strcpy(myrpt->txpl, "100.0");
01446 myrpt->remmode = REM_MODE_AM;
01447 break;
01448 case 'B':
01449 case 'b':
01450 strcpy(myrpt->rxpl, "100.0");
01451 strcpy(myrpt->txpl, "100.0");
01452 myrpt->remmode = REM_MODE_LSB;
01453 break;
01454 case 'F':
01455 myrpt->remmode = REM_MODE_FM;
01456 break;
01457 case 'L':
01458 case 'l':
01459 myrpt->powerlevel = REM_LOWPWR;
01460 break;
01461 case 'H':
01462 case 'h':
01463 myrpt->powerlevel = REM_HIPWR;
01464 break;
01465
01466 case 'M':
01467 case 'm':
01468 myrpt->powerlevel = REM_MEDPWR;
01469 break;
01470
01471 case '-':
01472 myrpt->offset = REM_MINUS;
01473 break;
01474
01475 case '+':
01476 myrpt->offset = REM_PLUS;
01477 break;
01478
01479 case 'S':
01480 case 's':
01481 myrpt->offset = REM_SIMPLEX;
01482 break;
01483
01484 case 'T':
01485 case 't':
01486 myrpt->txplon = 1;
01487 break;
01488
01489 case 'R':
01490 case 'r':
01491 myrpt->rxplon = 1;
01492 break;
01493
01494 case 'U':
01495 case 'u':
01496 strcpy(myrpt->rxpl, "100.0");
01497 strcpy(myrpt->txpl, "100.0");
01498 myrpt->remmode = REM_MODE_USB;
01499 break;
01500 default:
01501 return 1;
01502 }
01503 }
01504 return 0;
01505 }
01506
01507
01508
01509 static void birdbath(struct rpt *myrpt)
01510 {
01511 struct rpt_tele *telem;
01512 if(debug > 2)
01513 ast_log(LOG_NOTICE, "birdbath!!");
01514 rpt_mutex_lock(&myrpt->lock);
01515 telem = myrpt->tele.next;
01516 while(telem != &myrpt->tele)
01517 {
01518 if (telem->mode == PARROT) ast_softhangup(telem->chan,AST_SOFTHANGUP_DEV);
01519 telem = telem->next;
01520 }
01521 rpt_mutex_unlock(&myrpt->lock);
01522 }
01523
01524 static void do_dtmf_phone(struct rpt *myrpt, struct rpt_link *mylink, char c)
01525 {
01526 struct rpt_link *l;
01527
01528 l = myrpt->links.next;
01529
01530 while(l != &myrpt->links)
01531 {
01532 if (!l->phonemode)
01533 {
01534 l = l->next;
01535 continue;
01536 }
01537
01538 if (mylink && (l == mylink))
01539 {
01540 l = l->next;
01541 continue;
01542 }
01543 #ifdef NEW_ASTERISK
01544 if (l->chan) ast_senddigit(l->chan,c,0);
01545 #else
01546 if (l->chan) ast_senddigit(l->chan,c);
01547 #endif
01548 l = l->next;
01549 }
01550 return;
01551 }
01552
01553
01554 static void donodelog(struct rpt *myrpt,char *str)
01555 {
01556 struct nodelog *nodep;
01557 char datestr[100];
01558
01559 if (!myrpt->p.archivedir) return;
01560 nodep = (struct nodelog *)ast_malloc(sizeof(struct nodelog));
01561 if (nodep == NULL)
01562 {
01563 ast_log(LOG_ERROR,"Cannot get memory for node log");
01564 return;
01565 }
01566 time(&nodep->timestamp);
01567 strncpy(nodep->archivedir,myrpt->p.archivedir,
01568 sizeof(nodep->archivedir) - 1);
01569 strftime(datestr,sizeof(datestr) - 1,"%Y%m%d%H%M%S",
01570 localtime(&nodep->timestamp));
01571 snprintf(nodep->str,sizeof(nodep->str) - 1,"%s %s,%s\n",
01572 myrpt->name,datestr,str);
01573 ast_mutex_lock(&nodeloglock);
01574 insque((struct qelem *) nodep, (struct qelem *) nodelog.prev);
01575 ast_mutex_unlock(&nodeloglock);
01576 }
01577
01578
01579 static void do_dtmf_local(struct rpt *myrpt, char c)
01580 {
01581 int i;
01582 char digit;
01583 static const char* dtmf_tones[] = {
01584 "!941+1336/200,!0/200",
01585 "!697+1209/200,!0/200",
01586 "!697+1336/200,!0/200",
01587 "!697+1477/200,!0/200",
01588 "!770+1209/200,!0/200",
01589 "!770+1336/200,!0/200",
01590 "!770+1477/200,!0/200",
01591 "!852+1209/200,!0/200",
01592 "!852+1336/200,!0/200",
01593 "!852+1477/200,!0/200",
01594 "!697+1633/200,!0/200",
01595 "!770+1633/200,!0/200",
01596 "!852+1633/200,!0/200",
01597 "!941+1633/200,!0/200",
01598 "!941+1209/200,!0/200",
01599 "!941+1477/200,!0/200" };
01600
01601
01602 if (c)
01603 {
01604 snprintf(myrpt->dtmf_local_str + strlen(myrpt->dtmf_local_str),sizeof(myrpt->dtmf_local_str) - 1,"%c",c);
01605 if (!myrpt->dtmf_local_timer)
01606 myrpt->dtmf_local_timer = DTMF_LOCAL_STARTTIME;
01607 }
01608
01609 if (myrpt->dtmf_local_timer == 1)
01610 {
01611 if(debug > 6)
01612 ast_log(LOG_NOTICE,"time out dtmf_local_timer=%i\n",myrpt->dtmf_local_timer);
01613
01614
01615 if (myrpt->dtmf_local_str[0])
01616 {
01617 digit = myrpt->dtmf_local_str[0];
01618 myrpt->dtmf_local_str[0] = 0;
01619 for(i = 1; myrpt->dtmf_local_str[i]; i++)
01620 {
01621 myrpt->dtmf_local_str[i - 1] =
01622 myrpt->dtmf_local_str[i];
01623 }
01624 myrpt->dtmf_local_str[i - 1] = 0;
01625 myrpt->dtmf_local_timer = DTMF_LOCAL_TIME;
01626 rpt_mutex_unlock(&myrpt->lock);
01627 if (digit >= '0' && digit <='9')
01628 ast_playtones_start(myrpt->txchannel, 0, dtmf_tones[digit-'0'], 0);
01629 else if (digit >= 'A' && digit <= 'D')
01630 ast_playtones_start(myrpt->txchannel, 0, dtmf_tones[digit-'A'+10], 0);
01631 else if (digit == '*')
01632 ast_playtones_start(myrpt->txchannel, 0, dtmf_tones[14], 0);
01633 else if (digit == '#')
01634 ast_playtones_start(myrpt->txchannel, 0, dtmf_tones[15], 0);
01635 else {
01636
01637 ast_log(LOG_DEBUG, "Unable to generate DTMF tone '%c' for '%s'\n", digit, myrpt->txchannel->name);
01638 }
01639 rpt_mutex_lock(&myrpt->lock);
01640 }
01641 else
01642 {
01643 myrpt->dtmf_local_timer = 0;
01644 }
01645 }
01646 }
01647
01648 static int setdtr(int fd, int enable)
01649 {
01650 struct termios mode;
01651
01652 if (fd < 0) return -1;
01653 if (tcgetattr(fd, &mode)) {
01654 ast_log(LOG_WARNING, "Unable to get serial parameters for dtr: %s\n", strerror(errno));
01655 return -1;
01656 }
01657 if (enable)
01658 {
01659 cfsetspeed(&mode, B9600);
01660 }
01661 else
01662 {
01663 cfsetspeed(&mode, B0);
01664 usleep(100000);
01665 }
01666 if (tcsetattr(fd, TCSADRAIN, &mode)) {
01667 ast_log(LOG_WARNING, "Unable to set serial parameters for dtr: %s\n", strerror(errno));
01668 return -1;
01669 }
01670 if (enable) usleep(100000);
01671 return 0;
01672 }
01673
01674 static int openserial(struct rpt *myrpt,char *fname)
01675 {
01676 struct termios mode;
01677 int fd;
01678
01679 fd = open(fname,O_RDWR);
01680 if (fd == -1)
01681 {
01682 ast_log(LOG_WARNING,"Cannot open serial port %s\n",fname);
01683 return -1;
01684 }
01685 memset(&mode, 0, sizeof(mode));
01686 if (tcgetattr(fd, &mode)) {
01687 ast_log(LOG_WARNING, "Unable to get serial parameters on %s: %s\n", fname, strerror(errno));
01688 return -1;
01689 }
01690 #ifndef SOLARIS
01691 cfmakeraw(&mode);
01692 #else
01693 mode.c_iflag &= ~(IGNBRK|BRKINT|PARMRK|ISTRIP
01694 |INLCR|IGNCR|ICRNL|IXON);
01695 mode.c_lflag &= ~(ECHO|ECHONL|ICANON|ISIG|IEXTEN);
01696 mode.c_cflag &= ~(CSIZE|PARENB|CRTSCTS);
01697 mode.c_cflag |= CS8;
01698 mode.c_cc[VTIME] = 3;
01699 mode.c_cc[VMIN] = 1;
01700 #endif
01701
01702 cfsetispeed(&mode, B9600);
01703 cfsetospeed(&mode, B9600);
01704 if (tcsetattr(fd, TCSANOW, &mode))
01705 ast_log(LOG_WARNING, "Unable to set serial parameters on %s: %s\n", fname, strerror(errno));
01706 if(!strcmp(myrpt->remoterig, remote_rig_kenwood)) setdtr(fd,0);
01707 usleep(100000);
01708 if (debug)ast_log(LOG_NOTICE,"Opened serial port %s\n",fname);
01709 return(fd);
01710 }
01711
01712 static void mdc1200_notify(struct rpt *myrpt,char *fromnode, unsigned int unit)
01713 {
01714 if (!fromnode)
01715 {
01716 ast_verbose("Got MDC-1200 ID %04X from local system (%s)\n",
01717 unit,myrpt->name);
01718 }
01719 else
01720 {
01721 ast_verbose("Got MDC-1200 ID %04X from node %s (%s)\n",
01722 unit,fromnode,myrpt->name);
01723 }
01724 }
01725
01726 #ifdef _MDC_DECODE_H_
01727
01728 static void mdc1200_send(struct rpt *myrpt, unsigned int unit)
01729 {
01730 struct rpt_link *l;
01731 struct ast_frame wf;
01732 char str[200];
01733
01734
01735 sprintf(str,"I %s %04X",myrpt->name,unit);
01736
01737 wf.frametype = AST_FRAME_TEXT;
01738 wf.subclass = 0;
01739 wf.offset = 0;
01740 wf.mallocd = 0;
01741 wf.datalen = strlen(str) + 1;
01742 wf.samples = 0;
01743
01744
01745 l = myrpt->links.next;
01746
01747 while(l != &myrpt->links)
01748 {
01749 if (l->name[0] == '0')
01750 {
01751 l = l->next;
01752 continue;
01753 }
01754 wf.data = str;
01755 if (l->chan) ast_write(l->chan,&wf);
01756 l = l->next;
01757 }
01758 return;
01759 }
01760
01761 #endif
01762
01763 static char func_xlat(struct rpt *myrpt,char c,struct rpt_xlat *xlat)
01764 {
01765 time_t now;
01766 int gotone;
01767
01768 time(&now);
01769 gotone = 0;
01770
01771 if ((now - xlat->lastone) > MAXXLATTIME)
01772 {
01773 xlat->funcindex = xlat->endindex = 0;
01774 }
01775 if (xlat->funccharseq[0] && (c == xlat->funccharseq[xlat->funcindex++]))
01776 {
01777 time(&xlat->lastone);
01778 gotone = 1;
01779 if (!xlat->funccharseq[xlat->funcindex])
01780 {
01781 xlat->funcindex = xlat->endindex = 0;
01782 return(myrpt->p.funcchar);
01783 }
01784 } else xlat->funcindex = 0;
01785 if (xlat->endcharseq[0] && (c == xlat->endcharseq[xlat->endindex++]))
01786 {
01787 time(&xlat->lastone);
01788 gotone = 1;
01789 if (!xlat->endcharseq[xlat->endindex])
01790 {
01791 xlat->funcindex = xlat->endindex = 0;
01792 return(myrpt->p.endchar);
01793 }
01794 } else xlat->endindex = 0;
01795
01796 if (gotone) return(0);
01797
01798 if (!xlat->passchars[0]) return(c);
01799
01800 if (strchr(xlat->passchars,c)) return(c);
01801 return(0);
01802 }
01803
01804
01805
01806
01807
01808 static char *eatwhite(char *s)
01809 {
01810 while((*s == ' ') || (*s == 0x09)){
01811 if(!*s)
01812 break;
01813 s++;
01814 }
01815 return s;
01816 }
01817
01818
01819
01820
01821
01822
01823
01824
01825
01826
01827
01828 static int finddelim(char *str, char *strp[], int limit)
01829 {
01830 int i,l,inquo;
01831
01832 inquo = 0;
01833 i = 0;
01834 strp[i++] = str;
01835 if (!*str)
01836 {
01837 strp[0] = 0;
01838 return(0);
01839 }
01840 for(l = 0; *str && (l < limit) ; str++)
01841 {
01842 if (*str == QUOTECHR)
01843 {
01844 if (inquo)
01845 {
01846 *str = 0;
01847 inquo = 0;
01848 }
01849 else
01850 {
01851 strp[i - 1] = str + 1;
01852 inquo = 1;
01853 }
01854 }
01855 if ((*str == DELIMCHR) && (!inquo))
01856 {
01857 *str = 0;
01858 l++;
01859 strp[i++] = str + 1;
01860 }
01861 }
01862 strp[i] = 0;
01863 return(i);
01864
01865 }
01866
01867
01868
01869 static int send_usb_txt(struct rpt *myrpt, char *txt)
01870 {
01871 struct ast_frame wf;
01872
01873 if (debug)ast_log(LOG_NOTICE, "send_usb_txt %s\n",txt);
01874 wf.frametype = AST_FRAME_TEXT;
01875 wf.subclass = 0;
01876 wf.offset = 0;
01877 wf.mallocd = 0;
01878 wf.datalen = strlen(txt) + 1;
01879 wf.data.ptr = txt;
01880 wf.samples = 0;
01881 ast_write(myrpt->txchannel,&wf);
01882 return 0;
01883 }
01884
01885 static void __mklinklist(struct rpt *myrpt, struct rpt_link *mylink, char *buf)
01886 {
01887 struct rpt_link *l;
01888 char mode;
01889 int i,spos;
01890
01891 buf[0] = 0;
01892 if (myrpt->remote) return;
01893
01894 for(l = myrpt->links.next; l != &myrpt->links; l = l->next)
01895 {
01896
01897 if (l->name[0] == '0') continue;
01898
01899 if (l == mylink) continue;
01900 if (mylink && (!strcmp(l->name,mylink->name))) continue;
01901
01902 mode = 'T';
01903 if (!l->mode) mode = 'R';
01904 if (!l->thisconnected) mode = 'C';
01905 spos = strlen(buf);
01906 if (spos)
01907 {
01908 strcat(buf,",");
01909 spos++;
01910 }
01911
01912 if (l->linklist[0])
01913 {
01914 snprintf(buf + spos,MAXLINKLIST - spos,
01915 "%c%s,%s",mode,l->name,l->linklist);
01916 }
01917 else
01918 {
01919 snprintf(buf + spos,MAXLINKLIST - spos,
01920 "%c%s",mode,l->name);
01921 }
01922
01923 if (mode == 'T') continue;
01924
01925 for(i = spos; buf[i]; i++)
01926 {
01927 if (buf[i] == 'T') buf[i] = mode;
01928 if ((buf[i] == 'R') && (mode == 'C')) buf[i] = mode;
01929 }
01930 }
01931 return;
01932 }
01933
01934
01935 static void __kickshort(struct rpt *myrpt)
01936 {
01937 struct rpt_link *l;
01938
01939 for(l = myrpt->links.next; l != &myrpt->links; l = l->next)
01940 {
01941
01942 if (l->name[0] == '0') continue;
01943 l->linklisttimer = LINKLISTSHORTTIME;
01944 }
01945 myrpt->linkposttimer = LINKPOSTSHORTTIME;
01946 return;
01947 }
01948
01949 static void statpost(struct rpt *myrpt,char *pairs)
01950 {
01951 char *str,*astr;
01952 char *astrs[100];
01953 int n,pid;
01954 time_t now;
01955 unsigned int seq;
01956
01957 if (!myrpt->p.statpost_url) return;
01958 str = ast_malloc(strlen(pairs) + strlen(myrpt->p.statpost_url) + 200);
01959 astr = ast_strdup(myrpt->p.statpost_program);
01960 if ((!str) || (!astr)) return;
01961 n = finddelim(astr,astrs,100);
01962 if (n < 1) return;
01963 ast_mutex_lock(&myrpt->statpost_lock);
01964 seq = ++myrpt->statpost_seqno;
01965 ast_mutex_unlock(&myrpt->statpost_lock);
01966 astrs[n++] = str;
01967 astrs[n] = NULL;
01968 time(&now);
01969 sprintf(str,"%s?node=%s&time=%u&seqno=%u",myrpt->p.statpost_url,
01970 myrpt->name,(unsigned int) now,seq);
01971 if (pairs) sprintf(str + strlen(str),"&%s",pairs);
01972 if (!(pid = ast_safe_fork(0)))
01973 {
01974 execv(astrs[0],astrs);
01975 ast_log(LOG_ERROR, "exec of %s failed.\n", astrs[0]);
01976 perror("asterisk");
01977 exit(0);
01978 }
01979 ast_free(astr);
01980 ast_free(str);
01981 return;
01982 }
01983
01984 static char *node_lookup(struct rpt *myrpt,char *digitbuf)
01985 {
01986
01987 char *val;
01988 int longestnode,j;
01989 struct stat mystat;
01990 static time_t last = 0;
01991 static struct ast_config *ourcfg = NULL;
01992 struct ast_variable *vp;
01993
01994
01995 val = (char *) ast_variable_retrieve(myrpt->cfg, myrpt->p.nodes, digitbuf);
01996 if (val) return(val);
01997 ast_mutex_lock(&nodelookuplock);
01998
01999 if (stat(myrpt->p.extnodefile,&mystat) == -1)
02000 {
02001 if (ourcfg) ast_config_destroy(ourcfg);
02002 ourcfg = NULL;
02003 ast_mutex_unlock(&nodelookuplock);
02004 return(NULL);
02005 }
02006
02007 if (mystat.st_mtime > last)
02008 {
02009 if (ourcfg) ast_config_destroy(ourcfg);
02010 #ifdef NEW_ASTERISK
02011 ourcfg = ast_config_load(myrpt->p.extnodefile,config_flags);
02012 #else
02013 ourcfg = ast_config_load(myrpt->p.extnodefile);
02014 #endif
02015
02016 if (!ourcfg || ourcfg == CONFIG_STATUS_FILEINVALID)
02017 {
02018 ast_mutex_unlock(&nodelookuplock);
02019 return(NULL);
02020 }
02021
02022 last = mystat.st_mtime;
02023
02024
02025 longestnode = 0;
02026 vp = ast_variable_browse(myrpt->cfg, myrpt->p.nodes);
02027 while(vp){
02028 j = strlen(vp->name);
02029 if (j > longestnode)
02030 longestnode = j;
02031 vp = vp->next;
02032 }
02033
02034 vp = ast_variable_browse(ourcfg, myrpt->p.extnodes);
02035 while(vp){
02036 j = strlen(vp->name);
02037 if (j > longestnode)
02038 longestnode = j;
02039 vp = vp->next;
02040 }
02041
02042 myrpt->longestnode = longestnode;
02043 }
02044 val = NULL;
02045 if (ourcfg)
02046 val = (char *) ast_variable_retrieve(ourcfg, myrpt->p.extnodes, digitbuf);
02047 ast_mutex_unlock(&nodelookuplock);
02048 return(val);
02049 }
02050
02051
02052
02053
02054
02055
02056 static int matchkeyword(char *string, char **param, char *keywords[])
02057 {
02058 int i,ls;
02059 for( i = 0 ; keywords[i] ; i++){
02060 ls = strlen(keywords[i]);
02061 if(!ls){
02062 *param = NULL;
02063 return 0;
02064 }
02065 if(!strncmp(string, keywords[i], ls)){
02066 if(param)
02067 *param = string + ls;
02068 return i + 1;
02069 }
02070 }
02071 *param = NULL;
02072 return 0;
02073 }
02074
02075
02076
02077
02078
02079
02080 static char *skipchars(char *string, char *charlist)
02081 {
02082 int i;
02083 while(*string){
02084 for(i = 0; charlist[i] ; i++){
02085 if(*string == charlist[i]){
02086 string++;
02087 break;
02088 }
02089 }
02090 if(!charlist[i])
02091 return string;
02092 }
02093 return string;
02094 }
02095
02096
02097
02098 static int myatoi(char *str)
02099 {
02100 int ret;
02101
02102 if (str == NULL) return -1;
02103
02104 if (sscanf(str, "%30i", &ret) != 1) {
02105 return -1;
02106 }
02107
02108 return ret;
02109 }
02110
02111 static int mycompar(const void *a, const void *b)
02112 {
02113 char **x = (char **) a;
02114 char **y = (char **) b;
02115 int xoff,yoff;
02116
02117 if ((**x < '0') || (**x > '9')) xoff = 1; else xoff = 0;
02118 if ((**y < '0') || (**y > '9')) yoff = 1; else yoff = 0;
02119 return(strcmp((*x) + xoff,(*y) + yoff));
02120 }
02121
02122 static int topcompar(const void *a, const void *b)
02123 {
02124 struct rpt_topkey *x = (struct rpt_topkey *) a;
02125 struct rpt_topkey *y = (struct rpt_topkey *) b;
02126
02127 return(x->timesince - y->timesince);
02128 }
02129
02130 #ifdef __RPT_NOTCH
02131
02132
02133 static void rpt_filter(struct rpt *myrpt, volatile short *buf, int len)
02134 {
02135 int i,j;
02136 struct rptfilter *f;
02137
02138 for(i = 0; i < len; i++)
02139 {
02140 for(j = 0; j < MAXFILTERS; j++)
02141 {
02142 f = &myrpt->filters[j];
02143 if (!*f->desc) continue;
02144 f->x0 = f->x1; f->x1 = f->x2;
02145 f->x2 = ((float)buf[i]) / f->gain;
02146 f->y0 = f->y1; f->y1 = f->y2;
02147 f->y2 = (f->x0 + f->x2) + f->const0 * f->x1
02148 + (f->const1 * f->y0) + (f->const2 * f->y1);
02149 buf[i] = (short)f->y2;
02150 }
02151 }
02152 }
02153
02154 #endif
02155
02156
02157
02158
02159
02160
02161
02162
02163
02164
02165
02166
02167
02168
02169
02170
02171
02172
02173 #ifdef NEW_ASTERISK
02174 static void rpt_localtime( time_t * t, struct ast_tm *lt)
02175 {
02176 struct timeval when;
02177
02178 when.tv_sec = *t;
02179 when.tv_usec = 0;
02180 ast_localtime(&when, lt, NULL);
02181 }
02182
02183 #else
02184 static void rpt_localtime( time_t * t, struct tm *lt)
02185 {
02186 #ifdef OLD_ASTERISK
02187 localtime_r(t, lt);
02188 #else
02189 ast_localtime(t, lt, NULL);
02190 #endif
02191 }
02192 #endif
02193
02194
02195
02196
02197 static int retrieve_astcfgint(struct rpt *myrpt,char *category, char *name, int min, int max, int defl)
02198 {
02199 char *var;
02200 int ret;
02201 char include_zero = 0;
02202
02203 if(min < 0){
02204 min = -min;
02205 include_zero = 1;
02206 }
02207
02208 var = (char *) ast_variable_retrieve(myrpt->cfg, category, name);
02209 if(var){
02210 ret = myatoi(var);
02211 if(include_zero && !ret)
02212 return 0;
02213 if(ret < min)
02214 ret = min;
02215 if(ret > max)
02216 ret = max;
02217 }
02218 else
02219 ret = defl;
02220 return ret;
02221 }
02222
02223
02224 static void load_rpt_vars(int n,int init)
02225 {
02226 char *this,*val;
02227 int i,j,longestnode;
02228 struct ast_variable *vp;
02229 struct ast_config *cfg;
02230 char *strs[100];
02231 char s1[256];
02232 static char *cs_keywords[] = {"rptena","rptdis","apena","apdis","lnkena","lnkdis","totena","totdis","skena","skdis",
02233 "ufena","ufdis","atena","atdis",NULL};
02234
02235 if (option_verbose > 2)
02236 ast_verbose(VERBOSE_PREFIX_3 "%s config for repeater %s\n",
02237 (init) ? "Loading initial" : "Re-Loading",rpt_vars[n].name);
02238 ast_mutex_lock(&rpt_vars[n].lock);
02239 if (rpt_vars[n].cfg) ast_config_destroy(rpt_vars[n].cfg);
02240 #ifdef NEW_ASTERISK
02241 cfg = ast_config_load("rpt.conf",config_flags);
02242 #else
02243 cfg = ast_config_load("rpt.conf");
02244 #endif
02245 if (!cfg || cfg == CONFIG_STATUS_FILEINVALID) {
02246 ast_mutex_unlock(&rpt_vars[n].lock);
02247 ast_log(LOG_NOTICE, "Unable to open radio repeater configuration rpt.conf. Radio Repeater disabled.\n");
02248 pthread_exit(NULL);
02249 }
02250 rpt_vars[n].cfg = cfg;
02251 this = rpt_vars[n].name;
02252 memset(&rpt_vars[n].p,0,sizeof(rpt_vars[n].p));
02253 if (init)
02254 {
02255 char *cp;
02256 int savearea = (char *)&rpt_vars[n].p - (char *)&rpt_vars[n];
02257
02258 cp = (char *) &rpt_vars[n].p;
02259 memset(cp + sizeof(rpt_vars[n].p),0,
02260 sizeof(rpt_vars[n]) - (sizeof(rpt_vars[n].p) + savearea));
02261 rpt_vars[n].tele.next = &rpt_vars[n].tele;
02262 rpt_vars[n].tele.prev = &rpt_vars[n].tele;
02263 rpt_vars[n].rpt_thread = AST_PTHREADT_NULL;
02264 rpt_vars[n].tailmessagen = 0;
02265 }
02266 #ifdef __RPT_NOTCH
02267
02268 memset(&rpt_vars[n].filters,0,sizeof(rpt_vars[n].filters));
02269 #endif
02270 val = (char *) ast_variable_retrieve(cfg,this,"context");
02271 if (val) rpt_vars[n].p.ourcontext = val;
02272 else rpt_vars[n].p.ourcontext = this;
02273 val = (char *) ast_variable_retrieve(cfg,this,"callerid");
02274 if (val) rpt_vars[n].p.ourcallerid = val;
02275 val = (char *) ast_variable_retrieve(cfg,this,"accountcode");
02276 if (val) rpt_vars[n].p.acctcode = val;
02277 val = (char *) ast_variable_retrieve(cfg,this,"idrecording");
02278 if (val) rpt_vars[n].p.ident = val;
02279 val = (char *) ast_variable_retrieve(cfg,this,"hangtime");
02280 if (val) rpt_vars[n].p.hangtime = atoi(val);
02281 else rpt_vars[n].p.hangtime = HANGTIME;
02282 val = (char *) ast_variable_retrieve(cfg,this,"althangtime");
02283 if (val) rpt_vars[n].p.althangtime = atoi(val);
02284 else rpt_vars[n].p.althangtime = HANGTIME;
02285 val = (char *) ast_variable_retrieve(cfg,this,"totime");
02286 if (val) rpt_vars[n].p.totime = atoi(val);
02287 else rpt_vars[n].p.totime = TOTIME;
02288 val = (char *) ast_variable_retrieve(cfg,this,"voxtimeout");
02289 if (val) rpt_vars[n].p.voxtimeout_ms = atoi(val);
02290 else rpt_vars[n].p.voxtimeout_ms = VOX_TIMEOUT_MS;
02291 val = (char *) ast_variable_retrieve(cfg,this,"voxrecover");
02292 if (val) rpt_vars[n].p.voxrecover_ms = atoi(val);
02293 else rpt_vars[n].p.voxrecover_ms = VOX_RECOVER_MS;
02294 val = (char *) ast_variable_retrieve(cfg,this,"simplexpatchdelay");
02295 if (val) rpt_vars[n].p.simplexpatchdelay = atoi(val);
02296 else rpt_vars[n].p.simplexpatchdelay = SIMPLEX_PATCH_DELAY;
02297 val = (char *) ast_variable_retrieve(cfg,this,"simplexphonedelay");
02298 if (val) rpt_vars[n].p.simplexphonedelay = atoi(val);
02299 else rpt_vars[n].p.simplexphonedelay = SIMPLEX_PHONE_DELAY;
02300 val = (char *) ast_variable_retrieve(cfg,this,"statpost_program");
02301 if (val) rpt_vars[n].p.statpost_program = val;
02302 else rpt_vars[n].p.statpost_program = STATPOST_PROGRAM;
02303 rpt_vars[n].p.statpost_url =
02304 (char *) ast_variable_retrieve(cfg,this,"statpost_url");
02305 rpt_vars[n].p.tailmessagetime = retrieve_astcfgint(&rpt_vars[n],this, "tailmessagetime", 0, 2400000, 0);
02306 rpt_vars[n].p.tailsquashedtime = retrieve_astcfgint(&rpt_vars[n],this, "tailsquashedtime", 0, 2400000, 0);
02307 rpt_vars[n].p.duplex = retrieve_astcfgint(&rpt_vars[n],this,"duplex",0,4,2);
02308 rpt_vars[n].p.idtime = retrieve_astcfgint(&rpt_vars[n],this, "idtime", -60000, 2400000, IDTIME);
02309 rpt_vars[n].p.politeid = retrieve_astcfgint(&rpt_vars[n],this, "politeid", 30000, 300000, POLITEID);
02310 val = (char *) ast_variable_retrieve(cfg,this,"tonezone");
02311 if (val) rpt_vars[n].p.tonezone = val;
02312 rpt_vars[n].p.tailmessages[0] = 0;
02313 rpt_vars[n].p.tailmessagemax = 0;
02314 val = (char *) ast_variable_retrieve(cfg,this,"tailmessagelist");
02315 if (val) rpt_vars[n].p.tailmessagemax = finddelim(val, rpt_vars[n].p.tailmessages, 500);
02316 val = (char *) ast_variable_retrieve(cfg,this,"memory");
02317 if (!val) val = MEMORY;
02318 rpt_vars[n].p.memory = val;
02319 val = (char *) ast_variable_retrieve(cfg,this,"macro");
02320 if (!val) val = MACRO;
02321 rpt_vars[n].p.macro = val;
02322 val = (char *) ast_variable_retrieve(cfg,this,"tonemacro");
02323 if (!val) val = TONEMACRO;
02324 rpt_vars[n].p.tonemacro = val;
02325 val = (char *) ast_variable_retrieve(cfg,this,"startup_macro");
02326 if (val) rpt_vars[n].p.startupmacro = val;
02327 val = (char *) ast_variable_retrieve(cfg,this,"iobase");
02328
02329
02330
02331 if ((!val) || (sscanf(val,"%30i",&rpt_vars[n].p.iobase) != 1))
02332 rpt_vars[n].p.iobase = DEFAULT_IOBASE;
02333 val = (char *) ast_variable_retrieve(cfg,this,"ioport");
02334 rpt_vars[n].p.ioport = val;
02335 val = (char *) ast_variable_retrieve(cfg,this,"functions");
02336 if (!val)
02337 {
02338 val = FUNCTIONS;
02339 rpt_vars[n].p.simple = 1;
02340 }
02341 rpt_vars[n].p.functions = val;
02342 val = (char *) ast_variable_retrieve(cfg,this,"link_functions");
02343 if (val) rpt_vars[n].p.link_functions = val;
02344 else
02345 rpt_vars[n].p.link_functions = rpt_vars[n].p.functions;
02346 val = (char *) ast_variable_retrieve(cfg,this,"phone_functions");
02347 if (val) rpt_vars[n].p.phone_functions = val;
02348 val = (char *) ast_variable_retrieve(cfg,this,"dphone_functions");
02349 if (val) rpt_vars[n].p.dphone_functions = val;
02350 val = (char *) ast_variable_retrieve(cfg,this,"alt_functions");
02351 if (val) rpt_vars[n].p.alt_functions = val;
02352 val = (char *) ast_variable_retrieve(cfg,this,"funcchar");
02353 if (!val) rpt_vars[n].p.funcchar = FUNCCHAR; else
02354 rpt_vars[n].p.funcchar = *val;
02355 val = (char *) ast_variable_retrieve(cfg,this,"endchar");
02356 if (!val) rpt_vars[n].p.endchar = ENDCHAR; else
02357 rpt_vars[n].p.endchar = *val;
02358 val = (char *) ast_variable_retrieve(cfg,this,"nobusyout");
02359 if (val) rpt_vars[n].p.nobusyout = ast_true(val);
02360 val = (char *) ast_variable_retrieve(cfg,this,"notelemtx");
02361 if (val) rpt_vars[n].p.notelemtx = ast_true(val);
02362 val = (char *) ast_variable_retrieve(cfg,this,"propagate_dtmf");
02363 if (val) rpt_vars[n].p.propagate_dtmf = ast_true(val);
02364 val = (char *) ast_variable_retrieve(cfg,this,"propagate_phonedtmf");
02365 if (val) rpt_vars[n].p.propagate_phonedtmf = ast_true(val);
02366 val = (char *) ast_variable_retrieve(cfg,this,"linktolink");
02367 if (val) rpt_vars[n].p.linktolink = ast_true(val);
02368 val = (char *) ast_variable_retrieve(cfg,this,"nodes");
02369 if (!val) val = NODES;
02370 rpt_vars[n].p.nodes = val;
02371 val = (char *) ast_variable_retrieve(cfg,this,"extnodes");
02372 if (!val) val = EXTNODES;
02373 rpt_vars[n].p.extnodes = val;
02374 val = (char *) ast_variable_retrieve(cfg,this,"extnodefile");
02375 if (!val) val = EXTNODEFILE;
02376 rpt_vars[n].p.extnodefile = val;
02377 val = (char *) ast_variable_retrieve(cfg,this,"archivedir");
02378 if (val) rpt_vars[n].p.archivedir = val;
02379 val = (char *) ast_variable_retrieve(cfg,this,"authlevel");
02380 if (val) rpt_vars[n].p.authlevel = atoi(val);
02381 else rpt_vars[n].p.authlevel = 0;
02382 val = (char *) ast_variable_retrieve(cfg,this,"parrot");
02383 if (val) rpt_vars[n].p.parrotmode = ast_true(val) * 2;
02384 else rpt_vars[n].p.parrotmode = 0;
02385 val = (char *) ast_variable_retrieve(cfg,this,"parrottime");
02386 if (val) rpt_vars[n].p.parrottime = atoi(val);
02387 else rpt_vars[n].p.parrottime = PARROTTIME;
02388 val = (char *) ast_variable_retrieve(cfg,this,"rptnode");
02389 rpt_vars[n].p.rptnode = val;
02390 val = (char *) ast_variable_retrieve(cfg,this,"mars");
02391 if (val) rpt_vars[n].p.remote_mars = atoi(val);
02392 else rpt_vars[n].p.remote_mars = 0;
02393 val = (char *) ast_variable_retrieve(cfg,this,"monminblocks");
02394 if (val) rpt_vars[n].p.monminblocks = atol(val);
02395 else rpt_vars[n].p.monminblocks = DEFAULT_MONITOR_MIN_DISK_BLOCKS;
02396 val = (char *) ast_variable_retrieve(cfg,this,"remote_inact_timeout");
02397 if (val) rpt_vars[n].p.remoteinacttimeout = atoi(val);
02398 else rpt_vars[n].p.remoteinacttimeout = DEFAULT_REMOTE_INACT_TIMEOUT;
02399 val = (char *) ast_variable_retrieve(cfg,this,"civaddr");
02400 if (val) rpt_vars[n].p.civaddr = atoi(val);
02401 else rpt_vars[n].p.civaddr = DEFAULT_CIV_ADDR;
02402 val = (char *) ast_variable_retrieve(cfg,this,"remote_timeout");
02403 if (val) rpt_vars[n].p.remotetimeout = atoi(val);
02404 else rpt_vars[n].p.remotetimeout = DEFAULT_REMOTE_TIMEOUT;
02405 val = (char *) ast_variable_retrieve(cfg,this,"remote_timeout_warning");
02406 if (val) rpt_vars[n].p.remotetimeoutwarning = atoi(val);
02407 else rpt_vars[n].p.remotetimeoutwarning = DEFAULT_REMOTE_TIMEOUT_WARNING;
02408 val = (char *) ast_variable_retrieve(cfg,this,"remote_timeout_warning_freq");
02409 if (val) rpt_vars[n].p.remotetimeoutwarningfreq = atoi(val);
02410 else rpt_vars[n].p.remotetimeoutwarningfreq = DEFAULT_REMOTE_TIMEOUT_WARNING_FREQ;
02411 #ifdef __RPT_NOTCH
02412 val = (char *) ast_variable_retrieve(cfg,this,"rxnotch");
02413 if (val) {
02414 i = finddelim(val,strs,MAXFILTERS * 2);
02415 i &= ~1;
02416 if (i >= 2) for(j = 0; j < i; j += 2)
02417 {
02418 rpt_mknotch(atof(strs[j]),atof(strs[j + 1]),
02419 &rpt_vars[n].filters[j >> 1].gain,
02420 &rpt_vars[n].filters[j >> 1].const0,
02421 &rpt_vars[n].filters[j >> 1].const1,
02422 &rpt_vars[n].filters[j >> 1].const2);
02423 sprintf(rpt_vars[n].filters[j >> 1].desc,"%s Hz, BW = %s",
02424 strs[j],strs[j + 1]);
02425 }
02426
02427 }
02428 #endif
02429 val = (char *) ast_variable_retrieve(cfg,this,"inxlat");
02430 if (val) {
02431 memset(&rpt_vars[n].p.inxlat,0,sizeof(struct rpt_xlat));
02432 i = finddelim(val,strs,3);
02433 if (i) strncpy(rpt_vars[n].p.inxlat.funccharseq,strs[0],MAXXLAT - 1);
02434 if (i > 1) strncpy(rpt_vars[n].p.inxlat.endcharseq,strs[1],MAXXLAT - 1);
02435 if (i > 2) strncpy(rpt_vars[n].p.inxlat.passchars,strs[2],MAXXLAT - 1);
02436 }
02437 val = (char *) ast_variable_retrieve(cfg,this,"outxlat");
02438 if (val) {
02439 memset(&rpt_vars[n].p.outxlat,0,sizeof(struct rpt_xlat));
02440 i = finddelim(val,strs,3);
02441 if (i) strncpy(rpt_vars[n].p.outxlat.funccharseq,strs[0],MAXXLAT - 1);
02442 if (i > 1) strncpy(rpt_vars[n].p.outxlat.endcharseq,strs[1],MAXXLAT - 1);
02443 if (i > 2) strncpy(rpt_vars[n].p.outxlat.passchars,strs[2],MAXXLAT - 1);
02444 }
02445
02446 val = (char *) ast_variable_retrieve(cfg,this,"controlstates");
02447 rpt_vars[n].p.csstanzaname = val;
02448
02449
02450 val = (char *) ast_variable_retrieve(cfg,this,"scheduler");
02451 rpt_vars[n].p.skedstanzaname = val;
02452
02453
02454 val = (char *) ast_variable_retrieve(cfg,this,"txlimits");
02455 rpt_vars[n].p.txlimitsstanzaname = val;
02456
02457 longestnode = 0;
02458
02459 vp = ast_variable_browse(cfg, rpt_vars[n].p.nodes);
02460
02461 while(vp){
02462 j = strlen(vp->name);
02463 if (j > longestnode)
02464 longestnode = j;
02465 vp = vp->next;
02466 }
02467
02468 rpt_vars[n].longestnode = longestnode;
02469
02470
02471
02472
02473 rpt_vars[n].longestfunc = 0;
02474 vp = ast_variable_browse(cfg, rpt_vars[n].p.functions);
02475 while(vp){
02476 j = strlen(vp->name);
02477 if (j > rpt_vars[n].longestfunc)
02478 rpt_vars[n].longestfunc = j;
02479 vp = vp->next;
02480 }
02481
02482
02483
02484 rpt_vars[n].link_longestfunc = 0;
02485 vp = ast_variable_browse(cfg, rpt_vars[n].p.link_functions);
02486 while(vp){
02487 j = strlen(vp->name);
02488 if (j > rpt_vars[n].link_longestfunc)
02489 rpt_vars[n].link_longestfunc = j;
02490 vp = vp->next;
02491 }
02492 rpt_vars[n].phone_longestfunc = 0;
02493 if (rpt_vars[n].p.phone_functions)
02494 {
02495 vp = ast_variable_browse(cfg, rpt_vars[n].p.phone_functions);
02496 while(vp){
02497 j = strlen(vp->name);
02498 if (j > rpt_vars[n].phone_longestfunc)
02499 rpt_vars[n].phone_longestfunc = j;
02500 vp = vp->next;
02501 }
02502 }
02503 rpt_vars[n].dphone_longestfunc = 0;
02504 if (rpt_vars[n].p.dphone_functions)
02505 {
02506 vp = ast_variable_browse(cfg, rpt_vars[n].p.dphone_functions);
02507 while(vp){
02508 j = strlen(vp->name);
02509 if (j > rpt_vars[n].dphone_longestfunc)
02510 rpt_vars[n].dphone_longestfunc = j;
02511 vp = vp->next;
02512 }
02513 }
02514 rpt_vars[n].alt_longestfunc = 0;
02515 if (rpt_vars[n].p.alt_functions)
02516 {
02517 vp = ast_variable_browse(cfg, rpt_vars[n].p.alt_functions);
02518 while(vp){
02519 j = strlen(vp->name);
02520 if (j > rpt_vars[n].alt_longestfunc)
02521 rpt_vars[n].alt_longestfunc = j;
02522 vp = vp->next;
02523 }
02524 }
02525 rpt_vars[n].macro_longest = 1;
02526 vp = ast_variable_browse(cfg, rpt_vars[n].p.macro);
02527 while(vp){
02528 j = strlen(vp->name);
02529 if (j > rpt_vars[n].macro_longest)
02530 rpt_vars[n].macro_longest = j;
02531 vp = vp->next;
02532 }
02533
02534
02535 if(rpt_vars[n].p.csstanzaname)
02536 vp = ast_variable_browse(cfg, rpt_vars[n].p.csstanzaname);
02537 else
02538 vp = NULL;
02539 for( i = 0 ; vp && (i < MAX_SYSSTATES) ; i++){
02540 int k,nukw,statenum;
02541 statenum=atoi(vp->name);
02542 strncpy(s1, vp->value, 255);
02543 s1[255] = 0;
02544 nukw = finddelim(s1,strs,32);
02545
02546 for (k = 0 ; k < nukw ; k++){
02547 for(j = 0 ; cs_keywords[j] != NULL ; j++){
02548 if(!strcmp(strs[k],cs_keywords[j])){
02549 switch(j){
02550 case 0:
02551 rpt_vars[n].p.s[statenum].txdisable = 0;
02552 break;
02553 case 1:
02554 rpt_vars[n].p.s[statenum].txdisable = 1;
02555 break;
02556
02557 case 2:
02558 rpt_vars[n].p.s[statenum].autopatchdisable = 0;
02559 break;
02560
02561 case 3:
02562 rpt_vars[n].p.s[statenum].autopatchdisable = 1;
02563 break;
02564
02565 case 4:
02566 rpt_vars[n].p.s[statenum].linkfundisable = 0;
02567 break;
02568
02569 case 5:
02570 rpt_vars[n].p.s[statenum].linkfundisable = 1;
02571 break;
02572
02573 case 6:
02574 rpt_vars[n].p.s[statenum].totdisable = 0;
02575 break;
02576
02577 case 7:
02578 rpt_vars[n].p.s[statenum].totdisable = 1;
02579 break;
02580
02581 case 8:
02582 rpt_vars[n].p.s[statenum].schedulerdisable = 0;
02583 break;
02584
02585 case 9:
02586 rpt_vars[n].p.s[statenum].schedulerdisable = 1;
02587 break;
02588
02589 case 10:
02590 rpt_vars[n].p.s[statenum].userfundisable = 0;
02591 break;
02592
02593 case 11:
02594 rpt_vars[n].p.s[statenum].userfundisable = 1;
02595 break;
02596
02597 case 12:
02598 rpt_vars[n].p.s[statenum].alternatetail = 1;
02599 break;
02600
02601 case 13:
02602 rpt_vars[n].p.s[statenum].alternatetail = 0;
02603 break;
02604
02605 default:
02606 ast_log(LOG_WARNING,
02607 "Unhandled control state keyword %s", cs_keywords[i]);
02608 break;
02609 }
02610 }
02611 }
02612 }
02613 vp = vp->next;
02614 }
02615 ast_mutex_unlock(&rpt_vars[n].lock);
02616 }
02617
02618
02619
02620
02621
02622 static int rpt_do_debug(int fd, int argc, char *argv[])
02623 {
02624 int newlevel;
02625
02626 if (argc != 4)
02627 return RESULT_SHOWUSAGE;
02628 newlevel = myatoi(argv[3]);
02629 if((newlevel < 0) || (newlevel > 7))
02630 return RESULT_SHOWUSAGE;
02631 if(newlevel)
02632 ast_cli(fd, "app_rpt Debugging enabled, previous level: %d, new level: %d\n", debug, newlevel);
02633 else
02634 ast_cli(fd, "app_rpt Debugging disabled\n");
02635
02636 debug = newlevel;
02637 return RESULT_SUCCESS;
02638 }
02639
02640
02641
02642
02643
02644 static int rpt_do_dump(int fd, int argc, char *argv[])
02645 {
02646 int i;
02647
02648 if (argc != 3)
02649 return RESULT_SHOWUSAGE;
02650
02651 for(i = 0; i < nrpts; i++)
02652 {
02653 if (!strcmp(argv[2],rpt_vars[i].name))
02654 {
02655 rpt_vars[i].disgorgetime = time(NULL) + 10;
02656 ast_cli(fd, "app_rpt struct dump requested for node %s\n",argv[2]);
02657 return RESULT_SUCCESS;
02658 }
02659 }
02660 return RESULT_FAILURE;
02661 }
02662
02663
02664
02665
02666
02667 static int rpt_do_stats(int fd, int argc, char *argv[])
02668 {
02669 int i,j,numoflinks;
02670 int dailytxtime, dailykerchunks;
02671 time_t now;
02672 int totalkerchunks, dailykeyups, totalkeyups, timeouts;
02673 int totalexecdcommands, dailyexecdcommands, hours, minutes, seconds;
02674 int uptime;
02675 long long totaltxtime;
02676 struct rpt_link *l;
02677 char *listoflinks[MAX_STAT_LINKS];
02678 char *lastdtmfcommand,*parrot_ena;
02679 char *tot_state, *ider_state, *patch_state;
02680 char *reverse_patch_state, *sys_ena, *tot_ena, *link_ena, *patch_ena;
02681 char *sch_ena, *input_signal, *called_number, *user_funs, *tail_type;
02682 struct rpt *myrpt;
02683
02684 static char *not_applicable = "N/A";
02685
02686 if(argc != 3)
02687 return RESULT_SHOWUSAGE;
02688
02689 tot_state = ider_state =
02690 patch_state = reverse_patch_state =
02691 input_signal = not_applicable;
02692 called_number = lastdtmfcommand = NULL;
02693
02694 time(&now);
02695 for(i = 0; i < nrpts; i++)
02696 {
02697 if (!strcmp(argv[2],rpt_vars[i].name)){
02698
02699 myrpt = &rpt_vars[i];
02700 rpt_mutex_lock(&myrpt->lock);
02701 uptime = (int)(now - starttime);
02702 dailytxtime = myrpt->dailytxtime;
02703 totaltxtime = myrpt->totaltxtime;
02704 dailykeyups = myrpt->dailykeyups;
02705 totalkeyups = myrpt->totalkeyups;
02706 dailykerchunks = myrpt->dailykerchunks;
02707 totalkerchunks = myrpt->totalkerchunks;
02708 dailyexecdcommands = myrpt->dailyexecdcommands;
02709 totalexecdcommands = myrpt->totalexecdcommands;
02710 timeouts = myrpt->timeouts;
02711
02712
02713 reverse_patch_state = "DOWN";
02714 numoflinks = 0;
02715 l = myrpt->links.next;
02716 while(l && (l != &myrpt->links)){
02717 if(numoflinks >= MAX_STAT_LINKS){
02718 ast_log(LOG_NOTICE,
02719 "maximum number of links exceeds %d in rpt_do_stats()!",MAX_STAT_LINKS);
02720 break;
02721 }
02722 if (l->name[0] == '0'){
02723 reverse_patch_state = "UP";
02724 l = l->next;
02725 continue;
02726 }
02727 listoflinks[numoflinks] = ast_strdup(l->name);
02728 if(listoflinks[numoflinks] == NULL){
02729 break;
02730 }
02731 else{
02732 numoflinks++;
02733 }
02734 l = l->next;
02735 }
02736
02737 if(myrpt->keyed)
02738 input_signal = "YES";
02739 else
02740 input_signal = "NO";
02741
02742 if(myrpt->p.parrotmode)
02743 parrot_ena = "ENABLED";
02744 else
02745 parrot_ena = "DISABLED";
02746
02747 if(myrpt->p.s[myrpt->p.sysstate_cur].txdisable)
02748 sys_ena = "DISABLED";
02749 else
02750 sys_ena = "ENABLED";
02751
02752 if(myrpt->p.s[myrpt->p.sysstate_cur].totdisable)
02753 tot_ena = "DISABLED";
02754 else
02755 tot_ena = "ENABLED";
02756
02757 if(myrpt->p.s[myrpt->p.sysstate_cur].linkfundisable)
02758 link_ena = "DISABLED";
02759 else
02760 link_ena = "ENABLED";
02761
02762 if(myrpt->p.s[myrpt->p.sysstate_cur].autopatchdisable)
02763 patch_ena = "DISABLED";
02764 else
02765 patch_ena = "ENABLED";
02766
02767 if(myrpt->p.s[myrpt->p.sysstate_cur].schedulerdisable)
02768 sch_ena = "DISABLED";
02769 else
02770 sch_ena = "ENABLED";
02771
02772 if(myrpt->p.s[myrpt->p.sysstate_cur].userfundisable)
02773 user_funs = "DISABLED";
02774 else
02775 user_funs = "ENABLED";
02776
02777 if(myrpt->p.s[myrpt->p.sysstate_cur].alternatetail)
02778 tail_type = "ALTERNATE";
02779 else
02780 tail_type = "STANDARD";
02781
02782 if(!myrpt->totimer)
02783 tot_state = "TIMED OUT!";
02784 else if(myrpt->totimer != myrpt->p.totime)
02785 tot_state = "ARMED";
02786 else
02787 tot_state = "RESET";
02788
02789 if(myrpt->tailid)
02790 ider_state = "QUEUED IN TAIL";
02791 else if(myrpt->mustid)
02792 ider_state = "QUEUED FOR CLEANUP";
02793 else
02794 ider_state = "CLEAN";
02795
02796 switch(myrpt->callmode){
02797 case 1:
02798 patch_state = "DIALING";
02799 break;
02800 case 2:
02801 patch_state = "CONNECTING";
02802 break;
02803 case 3:
02804 patch_state = "UP";
02805 break;
02806
02807 case 4:
02808 patch_state = "CALL FAILED";
02809 break;
02810
02811 default:
02812 patch_state = "DOWN";
02813 }
02814
02815 if(strlen(myrpt->exten)){
02816 called_number = ast_strdup(myrpt->exten);
02817 }
02818
02819 if(strlen(myrpt->lastdtmfcommand)){
02820 lastdtmfcommand = ast_strdup(myrpt->lastdtmfcommand);
02821 }
02822 rpt_mutex_unlock(&myrpt->lock);
02823
02824 ast_cli(fd, "************************ NODE %s STATISTICS *************************\n\n", myrpt->name);
02825 ast_cli(fd, "Selected system state............................: %d\n", myrpt->p.sysstate_cur);
02826 ast_cli(fd, "Signal on input..................................: %s\n", input_signal);
02827 ast_cli(fd, "System...........................................: %s\n", sys_ena);
02828 ast_cli(fd, "Parrot Mode......................................: %s\n", parrot_ena);
02829 ast_cli(fd, "Scheduler........................................: %s\n", sch_ena);
02830 ast_cli(fd, "Tail Time........................................: %s\n", tail_type);
02831 ast_cli(fd, "Time out timer...................................: %s\n", tot_ena);
02832 ast_cli(fd, "Time out timer state.............................: %s\n", tot_state);
02833 ast_cli(fd, "Time outs since system initialization............: %d\n", timeouts);
02834 ast_cli(fd, "Identifier state.................................: %s\n", ider_state);
02835 ast_cli(fd, "Kerchunks today..................................: %d\n", dailykerchunks);
02836 ast_cli(fd, "Kerchunks since system initialization............: %d\n", totalkerchunks);
02837 ast_cli(fd, "Keyups today.....................................: %d\n", dailykeyups);
02838 ast_cli(fd, "Keyups since system initialization...............: %d\n", totalkeyups);
02839 ast_cli(fd, "DTMF commands today..............................: %d\n", dailyexecdcommands);
02840 ast_cli(fd, "DTMF commands since system initialization........: %d\n", totalexecdcommands);
02841 ast_cli(fd, "Last DTMF command executed.......................: %s\n",
02842 (lastdtmfcommand && strlen(lastdtmfcommand)) ? lastdtmfcommand : not_applicable);
02843 hours = dailytxtime/3600000;
02844 dailytxtime %= 3600000;
02845 minutes = dailytxtime/60000;
02846 dailytxtime %= 60000;
02847 seconds = dailytxtime/1000;
02848 dailytxtime %= 1000;
02849
02850 ast_cli(fd, "TX time today....................................: %02d:%02d:%02d.%d\n",
02851 hours, minutes, seconds, dailytxtime);
02852
02853 hours = (int) totaltxtime/3600000;
02854 totaltxtime %= 3600000;
02855 minutes = (int) totaltxtime/60000;
02856 totaltxtime %= 60000;
02857 seconds = (int) totaltxtime/1000;
02858 totaltxtime %= 1000;
02859
02860 ast_cli(fd, "TX time since system initialization..............: %02d:%02d:%02d.%d\n",
02861 hours, minutes, seconds, (int) totaltxtime);
02862
02863 hours = uptime/3600;
02864 uptime %= 3600;
02865 minutes = uptime/60;
02866 uptime %= 60;
02867
02868 ast_cli(fd, "Uptime...........................................: %02d:%02d:%02d\n",
02869 hours, minutes, uptime);
02870
02871 ast_cli(fd, "Nodes currently connected to us..................: ");
02872 if(!numoflinks){
02873 ast_cli(fd,"<NONE>");
02874 }
02875 else{
02876 for(j = 0 ;j < numoflinks; j++){
02877 ast_cli(fd, "%s", listoflinks[j]);
02878 if(j % 4 == 3){
02879 ast_cli(fd, "\n");
02880 ast_cli(fd, " : ");
02881 }
02882 else{
02883 if((numoflinks - 1) - j > 0)
02884 ast_cli(fd, ", ");
02885 }
02886 }
02887 }
02888 ast_cli(fd,"\n");
02889
02890 ast_cli(fd, "Autopatch........................................: %s\n", patch_ena);
02891 ast_cli(fd, "Autopatch state..................................: %s\n", patch_state);
02892 ast_cli(fd, "Autopatch called number..........................: %s\n",
02893 (called_number && strlen(called_number)) ? called_number : not_applicable);
02894 ast_cli(fd, "Reverse patch/IAXRPT connected...................: %s\n", reverse_patch_state);
02895 ast_cli(fd, "User linking commands............................: %s\n", link_ena);
02896 ast_cli(fd, "User functions...................................: %s\n\n", user_funs);
02897
02898 for(j = 0; j < numoflinks; j++){
02899 ast_free(listoflinks[j]);
02900 }
02901 if(called_number){
02902 ast_free(called_number);
02903 }
02904 if(lastdtmfcommand){
02905 ast_free(lastdtmfcommand);
02906 }
02907 return RESULT_SUCCESS;
02908 }
02909 }
02910 return RESULT_FAILURE;
02911 }
02912
02913
02914
02915
02916
02917 static int rpt_do_lstats(int fd, int argc, char *argv[])
02918 {
02919 int i,j;
02920 char *connstate;
02921 struct rpt *myrpt;
02922 struct rpt_link *l;
02923 struct rpt_lstat *s,*t;
02924 struct rpt_lstat s_head;
02925 if(argc != 3)
02926 return RESULT_SHOWUSAGE;
02927
02928 s = NULL;
02929 s_head.next = &s_head;
02930 s_head.prev = &s_head;
02931
02932 for(i = 0; i < nrpts; i++)
02933 {
02934 if (!strcmp(argv[2],rpt_vars[i].name)){
02935
02936 myrpt = &rpt_vars[i];
02937 rpt_mutex_lock(&myrpt->lock);
02938
02939 j = 0;
02940 l = myrpt->links.next;
02941 while(l && (l != &myrpt->links)){
02942 if (l->name[0] == '0'){
02943 l = l->next;
02944 continue;
02945 }
02946 if((s = (struct rpt_lstat *) ast_malloc(sizeof(struct rpt_lstat))) == NULL){
02947 ast_log(LOG_ERROR, "Malloc failed in rpt_do_lstats\n");
02948 rpt_mutex_unlock(&myrpt->lock);
02949 return RESULT_FAILURE;
02950 }
02951 memset(s, 0, sizeof(struct rpt_lstat));
02952 strncpy(s->name, l->name, MAXREMSTR - 1);
02953 if (l->chan) pbx_substitute_variables_helper(l->chan, "${IAXPEER(CURRENTCHANNEL)}", s->peer, MAXPEERSTR - 1);
02954 else strcpy(s->peer,"(none)");
02955 s->mode = l->mode;
02956 s->outbound = l->outbound;
02957 s->reconnects = l->reconnects;
02958 s->connecttime = l->connecttime;
02959 s->thisconnected = l->thisconnected;
02960 memcpy(s->chan_stat,l->chan_stat,NRPTSTAT * sizeof(struct rpt_chan_stat));
02961 insque((struct qelem *) s, (struct qelem *) s_head.next);
02962 memset(l->chan_stat,0,NRPTSTAT * sizeof(struct rpt_chan_stat));
02963 l = l->next;
02964 }
02965 rpt_mutex_unlock(&myrpt->lock);
02966 ast_cli(fd, "NODE PEER RECONNECTS DIRECTION CONNECT TIME CONNECT STATE\n");
02967 ast_cli(fd, "---- ---- ---------- --------- ------------ -------------\n");
02968
02969 for(s = s_head.next; s != &s_head; s = s->next){
02970 int hours, minutes, seconds;
02971 long long connecttime = s->connecttime;
02972 char conntime[21];
02973 hours = (int) connecttime/3600000;
02974 connecttime %= 3600000;
02975 minutes = (int) connecttime/60000;
02976 connecttime %= 60000;
02977 seconds = (int) connecttime/1000;
02978 connecttime %= 1000;
02979 snprintf(conntime, 20, "%02d:%02d:%02d.%d",
02980 hours, minutes, seconds, (int) connecttime);
02981 conntime[20] = 0;
02982 if(s->thisconnected)
02983 connstate = "ESTABLISHED";
02984 else
02985 connstate = "CONNECTING";
02986 ast_cli(fd, "%-10s%-20s%-12d%-11s%-20s%-20s\n",
02987 s->name, s->peer, s->reconnects, (s->outbound)? "OUT":"IN", conntime, connstate);
02988 }
02989
02990 s = s_head.next;
02991 while(s != &s_head){
02992 t = s;
02993 s = s->next;
02994 remque((struct qelem *)t);
02995 ast_free(t);
02996 }
02997 return RESULT_SUCCESS;
02998 }
02999 }
03000 return RESULT_FAILURE;
03001 }
03002
03003
03004
03005
03006
03007 static int rpt_do_nodes(int fd, int argc, char *argv[])
03008 {
03009 int i,j;
03010 char ns;
03011 char lbuf[MAXLINKLIST],*strs[MAXLINKLIST];
03012 struct rpt *myrpt;
03013 if(argc != 3)
03014 return RESULT_SHOWUSAGE;
03015
03016 for(i = 0; i < nrpts; i++)
03017 {
03018 if (!strcmp(argv[2],rpt_vars[i].name)){
03019
03020 myrpt = &rpt_vars[i];
03021 rpt_mutex_lock(&myrpt->lock);
03022 __mklinklist(myrpt,NULL,lbuf);
03023 rpt_mutex_unlock(&myrpt->lock);
03024
03025 ns = finddelim(lbuf,strs,MAXLINKLIST);
03026
03027 if (ns) qsort((void *)strs,ns,sizeof(char *),mycompar);
03028 ast_cli(fd,"\n");
03029 ast_cli(fd, "************************* CONNECTED NODES *************************\n\n");
03030 for(j = 0 ;; j++){
03031 if(!strs[j]){
03032 if(!j){
03033 ast_cli(fd,"<NONE>");
03034 }
03035 break;
03036 }
03037 ast_cli(fd, "%s", strs[j]);
03038 if(j % 8 == 7){
03039 ast_cli(fd, "\n");
03040 }
03041 else{
03042 if(strs[j + 1])
03043 ast_cli(fd, ", ");
03044 }
03045 }
03046 ast_cli(fd,"\n\n");
03047 return RESULT_SUCCESS;
03048 }
03049 }
03050 return RESULT_FAILURE;
03051 }
03052
03053
03054
03055
03056
03057 static int rpt_do_local_nodes(int fd, int argc, char *argv[])
03058 {
03059
03060 int i;
03061 ast_cli(fd, "\nNode\n----\n");
03062 for (i=0; i< nrpts; i++)
03063 {
03064 ast_cli(fd, "%s\n", rpt_vars[i].name);
03065 }
03066 ast_cli(fd,"\n");
03067 return RESULT_SUCCESS;
03068 }
03069
03070
03071
03072
03073
03074
03075 static int rpt_do_reload(int fd, int argc, char *argv[])
03076 {
03077 int n;
03078
03079 if (argc > 2) return RESULT_SHOWUSAGE;
03080
03081 for(n = 0; n < nrpts; n++) rpt_vars[n].reload = 1;
03082
03083 return RESULT_FAILURE;
03084 }
03085
03086
03087
03088
03089
03090 static int rpt_do_restart(int fd, int argc, char *argv[])
03091 {
03092 int i;
03093
03094 if (argc > 2) return RESULT_SHOWUSAGE;
03095 for(i = 0; i < nrpts; i++)
03096 {
03097 if (rpt_vars[i].rxchannel) ast_softhangup(rpt_vars[i].rxchannel,AST_SOFTHANGUP_DEV);
03098 }
03099 return RESULT_FAILURE;
03100 }
03101
03102
03103
03104
03105
03106
03107 static int rpt_do_fun(int fd, int argc, char *argv[])
03108 {
03109 int i,busy=0;
03110
03111 if (argc != 4) return RESULT_SHOWUSAGE;
03112
03113 for(i = 0; i < nrpts; i++){
03114 if(!strcmp(argv[2], rpt_vars[i].name)){
03115 struct rpt *myrpt = &rpt_vars[i];
03116 rpt_mutex_lock(&myrpt->lock);
03117 if ((MAXMACRO - strlen(myrpt->macrobuf)) < strlen(argv[3])){
03118 rpt_mutex_unlock(&myrpt->lock);
03119 busy=1;
03120 }
03121 if(!busy){
03122 myrpt->macrotimer = MACROTIME;
03123 strncat(myrpt->macrobuf,argv[3],MAXMACRO - 1);
03124 }
03125 rpt_mutex_unlock(&myrpt->lock);
03126 }
03127 }
03128 if(busy){
03129 ast_cli(fd, "Function decoder busy");
03130 }
03131 return RESULT_FAILURE;
03132 }
03133
03134
03135
03136
03137
03138
03139
03140
03141 static int rpt_push_alt_macro(struct rpt *myrpt, char *sptr)
03142 {
03143 int busy=0;
03144
03145 rpt_mutex_lock(&myrpt->lock);
03146 if ((MAXMACRO - strlen(myrpt->macrobuf)) < strlen(sptr)){
03147 rpt_mutex_unlock(&myrpt->lock);
03148 busy=1;
03149 }
03150 if(!busy){
03151 int x;
03152 if (debug)ast_log(LOG_NOTICE, "rpt_push_alt_macro %s\n",sptr);
03153 myrpt->macrotimer = MACROTIME;
03154 for(x = 0; *(sptr + x); x++)
03155 myrpt->macrobuf[x] = *(sptr + x) | 0x80;
03156 *(sptr + x) = 0;
03157 }
03158 rpt_mutex_unlock(&myrpt->lock);
03159
03160 if(busy)ast_log(LOG_WARNING, "Function decoder busy on app_rpt command macro.\n");
03161
03162 return busy;
03163 }
03164
03165
03166
03167 static int rpt_do_fun1(int fd, int argc, char *argv[])
03168 {
03169 int i;
03170
03171 if (argc != 4) return RESULT_SHOWUSAGE;
03172
03173 for(i = 0; i < nrpts; i++){
03174 if(!strcmp(argv[2], rpt_vars[i].name)){
03175 struct rpt *myrpt = &rpt_vars[i];
03176 rpt_push_alt_macro(myrpt,argv[3]);
03177 }
03178 }
03179 return RESULT_FAILURE;
03180 }
03181
03182
03183
03184
03185 static int rpt_do_cmd(int fd, int argc, char *argv[])
03186 {
03187 int i, l;
03188 int busy=0;
03189 int maxActions = sizeof(function_table)/sizeof(struct function_table_tag);
03190
03191 int thisRpt = -1;
03192 int thisAction = -1;
03193 struct rpt *myrpt = NULL;
03194 if (argc != 6) return RESULT_SHOWUSAGE;
03195
03196 for(i = 0; i < nrpts; i++)
03197 {
03198 if(!strcmp(argv[2], rpt_vars[i].name))
03199 {
03200 thisRpt = i;
03201 myrpt = &rpt_vars[i];
03202 break;
03203 }
03204 }
03205
03206 if (thisRpt < 0)
03207 {
03208 ast_cli(fd, "Unknown node number %s.\n", argv[2]);
03209 return RESULT_FAILURE;
03210 }
03211
03212
03213 l = strlen(argv[3]);
03214 for(i = 0 ; i < maxActions; i++)
03215 {
03216 if(!strncasecmp(argv[3], function_table[i].action, l))
03217 {
03218 thisAction = i;
03219 break;
03220 }
03221 }
03222
03223 if (thisAction < 0)
03224 {
03225 ast_cli(fd, "Unknown action name %s.\n", argv[3]);
03226 return RESULT_FAILURE;
03227 }
03228
03229
03230
03231 rpt_mutex_lock(&myrpt->lock);
03232
03233 if (rpt_vars[thisRpt].cmdAction.state == CMD_STATE_IDLE)
03234 {
03235 rpt_vars[thisRpt].cmdAction.state = CMD_STATE_BUSY;
03236 rpt_vars[thisRpt].cmdAction.functionNumber = thisAction;
03237 strncpy(rpt_vars[thisRpt].cmdAction.param, argv[4], MAXDTMF);
03238 strncpy(rpt_vars[thisRpt].cmdAction.digits, argv[5], MAXDTMF);
03239 rpt_vars[thisRpt].cmdAction.command_source = SOURCE_RPT;
03240 rpt_vars[thisRpt].cmdAction.state = CMD_STATE_READY;
03241 }
03242 else
03243 {
03244 busy = 1;
03245 }
03246 rpt_mutex_unlock(&myrpt->lock);
03247
03248 return (busy ? RESULT_FAILURE : RESULT_SUCCESS);
03249 }
03250
03251 static int play_tone_pair(struct ast_channel *chan, int f1, int f2, int duration, int amplitude)
03252 {
03253 int res;
03254
03255 if ((res = ast_tonepair_start(chan, f1, f2, duration, amplitude)))
03256 return res;
03257
03258 while(chan->generatordata) {
03259 if (ast_safe_sleep(chan,1)) return -1;
03260 }
03261
03262 return 0;
03263 }
03264
03265 static int play_tone(struct ast_channel *chan, int freq, int duration, int amplitude)
03266 {
03267 return play_tone_pair(chan, freq, 0, duration, amplitude);
03268 }
03269
03270 static int play_silence(struct ast_channel *chan, int duration)
03271 {
03272 return play_tone_pair(chan, 0, 0, duration, 0);
03273 }
03274
03275 #ifdef NEW_ASTERISK
03276
03277 static char *res2cli(int r)
03278
03279 {
03280 switch (r)
03281 {
03282 case RESULT_SUCCESS:
03283 return(CLI_SUCCESS);
03284 case RESULT_SHOWUSAGE:
03285 return(CLI_SHOWUSAGE);
03286 default:
03287 return(CLI_FAILURE);
03288 }
03289 }
03290
03291 static char *handle_cli_debug(struct ast_cli_entry *e,
03292 int cmd, struct ast_cli_args *a)
03293 {
03294 switch (cmd) {
03295 case CLI_INIT:
03296 e->command = "rpt debug level";
03297 e->usage = debug_usage;
03298 return NULL;
03299 case CLI_GENERATE:
03300 return NULL;
03301 }
03302 return res2cli(rpt_do_debug(a->fd,a->argc,a->argv));
03303 }
03304
03305 static char *handle_cli_dump(struct ast_cli_entry *e,
03306 int cmd, struct ast_cli_args *a)
03307 {
03308 switch (cmd) {
03309 case CLI_INIT:
03310 e->command = "rpt dump level";
03311 e->usage = dump_usage;
03312 return NULL;
03313 case CLI_GENERATE:
03314 return NULL;
03315 }
03316 return res2cli(rpt_do_dump(a->fd,a->argc,a->argv));
03317 }
03318
03319
03320 static char *handle_cli_stats(struct ast_cli_entry *e,
03321 int cmd, struct ast_cli_args *a)
03322 {
03323 switch (cmd) {
03324 case CLI_INIT:
03325 e->command = "rpt stats";
03326 e->usage = dump_stats;
03327 return NULL;
03328 case CLI_GENERATE:
03329 return NULL;
03330 }
03331 return res2cli(rpt_do_stats(a->fd,a->argc,a->argv));
03332 }
03333
03334 static char *handle_cli_nodes(struct ast_cli_entry *e,
03335 int cmd, struct ast_cli_args *a)
03336 {
03337 switch (cmd) {
03338 case CLI_INIT:
03339 e->command = "rpt nodes";
03340 e->usage = dump_nodes;
03341 return NULL;
03342 case CLI_GENERATE:
03343 return NULL;
03344 }
03345 return res2cli(rpt_do_nodes(a->fd,a->argc,a->argv));
03346 }
03347
03348 static char *handle_cli_local_nodes(struct ast_cli_entry *e,
03349 int cmd, struct ast_cli_args *a)
03350 {
03351 switch (cmd) {
03352 case CLI_INIT:
03353 e->command = "rpt localnodes";
03354 e->usage = usage_local_nodes;
03355 return NULL;
03356 case CLI_GENERATE:
03357 return NULL;
03358 }
03359 return res2cli(rpt_do_local_nodes(a->fd,a->argc,a->argv));
03360 }
03361
03362 static char *handle_cli_lstats(struct ast_cli_entry *e,
03363 int cmd, struct ast_cli_args *a)
03364 {
03365 switch (cmd) {
03366 case CLI_INIT:
03367 e->command = "rpt lstats";
03368 e->usage = dump_lstats;
03369 return NULL;
03370 case CLI_GENERATE:
03371 return NULL;
03372 }
03373 return res2cli(rpt_do_lstats(a->fd,a->argc,a->argv));
03374 }
03375
03376 static char *handle_cli_reload(struct ast_cli_entry *e,
03377 int cmd, struct ast_cli_args *a)
03378 {
03379 switch (cmd) {
03380 case CLI_INIT:
03381 e->command = "rpt reload";
03382 e->usage = reload_usage;
03383 return NULL;
03384 case CLI_GENERATE:
03385 return NULL;
03386 }
03387 return res2cli(rpt_do_reload(a->fd,a->argc,a->argv));
03388 }
03389
03390 static char *handle_cli_restart(struct ast_cli_entry *e,
03391 int cmd, struct ast_cli_args *a)
03392 {
03393 switch (cmd) {
03394 case CLI_INIT:
03395 e->command = "rpt restart";
03396 e->usage = restart_usage;
03397 return NULL;
03398 case CLI_GENERATE:
03399 return NULL;
03400 }
03401 return res2cli(rpt_do_restart(a->fd,a->argc,a->argv));
03402 }
03403
03404 static char *handle_cli_fun(struct ast_cli_entry *e,
03405 int cmd, struct ast_cli_args *a)
03406 {
03407 switch (cmd) {
03408 case CLI_INIT:
03409 e->command = "rpt fun";
03410 e->usage = fun_usage;
03411 return NULL;
03412 case CLI_GENERATE:
03413 return NULL;
03414 }
03415 return res2cli(rpt_do_fun(a->fd,a->argc,a->argv));
03416 }
03417
03418 static char *handle_cli_fun1(struct ast_cli_entry *e,
03419 int cmd, struct ast_cli_args *a)
03420 {
03421 switch (cmd) {
03422 case CLI_INIT:
03423 e->command = "rpt fun1";
03424 e->usage = fun_usage;
03425 return NULL;
03426 case CLI_GENERATE:
03427 return NULL;
03428 }
03429 return res2cli(rpt_do_fun1(a->fd,a->argc,a->argv));
03430 }
03431
03432 static char *handle_cli_cmd(struct ast_cli_entry *e,
03433 int cmd, struct ast_cli_args *a)
03434 {
03435 switch (cmd) {
03436 case CLI_INIT:
03437 e->command = "rpt cmd";
03438 e->usage = cmd_usage;
03439 return NULL;
03440 case CLI_GENERATE:
03441 return NULL;
03442 }
03443 return res2cli(rpt_do_cmd(a->fd,a->argc,a->argv));
03444 }
03445
03446 static struct ast_cli_entry rpt_cli[] = {
03447 AST_CLI_DEFINE(handle_cli_debug,"Enable app_rpt debugging"),
03448 AST_CLI_DEFINE(handle_cli_dump,"Dump app_rpt structs for debugging"),
03449 AST_CLI_DEFINE(handle_cli_stats,"Dump node statistics"),
03450 AST_CLI_DEFINE(handle_cli_nodes,"Dump node list"),
03451 AST_CLI_DEFINE(handle_cli_local_nodes, "Dump list of local node numbers"),
03452 AST_CLI_DEFINE(handle_cli_lstats,"Dump link statistics"),
03453 AST_CLI_DEFINE(handle_cli_reload,"Reload app_rpt config"),
03454 AST_CLI_DEFINE(handle_cli_restart,"Restart app_rpt"),
03455 AST_CLI_DEFINE(handle_cli_fun,"Execute a DTMF function"),
03456 AST_CLI_DEFINE(handle_cli_fun1,"Execute a DTMF function"),
03457 AST_CLI_DEFINE(handle_cli_cmd,"Execute a DTMF function")
03458 };
03459
03460 #endif
03461
03462 static int send_morse(struct ast_channel *chan, char *string, int speed, int freq, int amplitude)
03463 {
03464
03465 static struct morse_bits mbits[] = {
03466 {0, 0},
03467 {0, 0},
03468 {6, 18},
03469 {0, 0},
03470 {7, 72},
03471 {0, 0},
03472 {0, 0},
03473 {6, 30},
03474 {5, 13},
03475 {6, 29},
03476 {0, 0},
03477 {5, 10},
03478 {6, 51},
03479 {6, 33},
03480 {6, 42},
03481 {5, 9},
03482 {5, 31},
03483 {5, 30},
03484 {5, 28},
03485 {5, 24},
03486 {5, 16},
03487 {5, 0},
03488 {5, 1},
03489 {5, 3},
03490 {5, 7},
03491 {5, 15},
03492 {6, 7},
03493 {6, 21},
03494 {0, 0},
03495 {5, 33},
03496 {0, 0},
03497 {6, 12},
03498 {0, 0},
03499 {2, 2},
03500 {4, 1},
03501 {4, 5},
03502 {3, 1},
03503 {1, 0},
03504 {4, 4},
03505 {3, 3},
03506 {4, 0},
03507 {2, 0},
03508 {4, 14},
03509 {3, 5},
03510 {4, 2},
03511 {2, 3},
03512 {2, 1},
03513 {3, 7},
03514 {4, 6},
03515 {4, 11},
03516 {3, 2},
03517 {3, 0},
03518 {1, 1},
03519 {3, 4},
03520 {4, 8},
03521 {3, 6},
03522 {4, 9},
03523 {4, 13},
03524 {4, 3}
03525 };
03526
03527
03528 int dottime;
03529 int dashtime;
03530 int intralettertime;
03531 int interlettertime;
03532 int interwordtime;
03533 int len, ddcomb;
03534 int res;
03535 int c;
03536 int i;
03537 int flags;
03538
03539 res = 0;
03540
03541
03542
03543 dottime = 900/speed;
03544
03545
03546
03547 dashtime = 3 * dottime;
03548 intralettertime = dottime;
03549 interlettertime = dottime * 4 ;
03550 interwordtime = dottime * 7;
03551
03552 for(;(*string) && (!res); string++){
03553
03554 c = *string;
03555
03556
03557
03558 if((c >= 'a') && (c <= 'z'))
03559 c -= 0x20;
03560
03561
03562
03563 if(c > 'Z')
03564 continue;
03565
03566
03567
03568 if(c == ' '){
03569 if(!res)
03570 res = play_silence(chan, interwordtime);
03571 continue;
03572 }
03573
03574
03575
03576 c -= 0x20;
03577
03578
03579
03580 len = mbits[c].len;
03581 ddcomb = mbits[c].ddcomb;
03582
03583
03584
03585 for(; len ; len--){
03586 if(!res)
03587 res = play_tone(chan, freq, (ddcomb & 1) ? dashtime : dottime, amplitude);
03588 if(!res)
03589 res = play_silence(chan, intralettertime);
03590 ddcomb >>= 1;
03591 }
03592
03593
03594
03595 if(!res)
03596 res = play_silence(chan, interlettertime - intralettertime);
03597 }
03598
03599
03600
03601 if (!res)
03602 res = ast_waitstream(chan, "");
03603 ast_stopstream(chan);
03604
03605
03606
03607
03608
03609 for(i = 0; i < 20 ; i++){
03610 flags = DAHDI_IOMUX_WRITEEMPTY | DAHDI_IOMUX_NOWAIT;
03611 res = ioctl(chan->fds[0], DAHDI_IOMUX, &flags);
03612 if(flags & DAHDI_IOMUX_WRITEEMPTY)
03613 break;
03614 if( ast_safe_sleep(chan, 50)){
03615 res = -1;
03616 break;
03617 }
03618 }
03619
03620
03621 return res;
03622 }
03623
03624 static int send_tone_telemetry(struct ast_channel *chan, char *tonestring)
03625 {
03626 char *p,*stringp;
03627 char *tonesubset;
03628 int f1,f2;
03629 int duration;
03630 int amplitude;
03631 int res;
03632 int i;
03633 int flags;
03634
03635 res = 0;
03636
03637 if(!tonestring)
03638 return res;
03639
03640 p = stringp = ast_strdup(tonestring);
03641
03642 for(;tonestring;){
03643 tonesubset = strsep(&stringp,")");
03644 if(!tonesubset)
03645 break;
03646 if(sscanf(tonesubset,"(%30d,%30d,%30d,%30d", &f1, &f2, &duration, &litude) != 4)
03647 break;
03648 res = play_tone_pair(chan, f1, f2, duration, amplitude);
03649 if(res)
03650 break;
03651 }
03652 if(p)
03653 ast_free(p);
03654 if(!res)
03655 res = play_tone_pair(chan, 0, 0, 100, 0);
03656
03657 if (!res)
03658 res = ast_waitstream(chan, "");
03659
03660 ast_stopstream(chan);
03661
03662
03663
03664
03665
03666 for(i = 0; i < 20 ; i++){
03667 flags = DAHDI_IOMUX_WRITEEMPTY | DAHDI_IOMUX_NOWAIT;
03668 res = ioctl(chan->fds[0], DAHDI_IOMUX, &flags);
03669 if(flags & DAHDI_IOMUX_WRITEEMPTY)
03670 break;
03671 if( ast_safe_sleep(chan, 50)){
03672 res = -1;
03673 break;
03674 }
03675 }
03676
03677 return res;
03678
03679 }
03680
03681 static int sayfile(struct ast_channel *mychannel,char *fname)
03682 {
03683 int res;
03684
03685 res = ast_streamfile(mychannel, fname, mychannel->language);
03686 if (!res)
03687 res = ast_waitstream(mychannel, "");
03688 else
03689 ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", mychannel->name);
03690 ast_stopstream(mychannel);
03691 return res;
03692 }
03693
03694 static int saycharstr(struct ast_channel *mychannel,char *str)
03695 {
03696 int res;
03697
03698 res = ast_say_character_str(mychannel,str,NULL,mychannel->language);
03699 if (!res)
03700 res = ast_waitstream(mychannel, "");
03701 else
03702 ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", mychannel->name);
03703 ast_stopstream(mychannel);
03704 return res;
03705 }
03706
03707 static int saynum(struct ast_channel *mychannel, int num)
03708 {
03709 int res;
03710 res = ast_say_number(mychannel, num, NULL, mychannel->language, NULL);
03711 if(!res)
03712 res = ast_waitstream(mychannel, "");
03713 else
03714 ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", mychannel->name);
03715 ast_stopstream(mychannel);
03716 return res;
03717 }
03718
03719
03720
03721
03722 static int saynode(struct rpt *myrpt, struct ast_channel *mychannel, char *name)
03723 {
03724 int res;
03725 char *val,fname[300];
03726
03727 val = (char *) ast_variable_retrieve(myrpt->cfg, myrpt->name, "nodenames");
03728 if (!val) val = NODENAMES;
03729 snprintf(fname,sizeof(fname) - 1,"%s/%s",val,name);
03730 if (ast_fileexists(fname,NULL,mychannel->language) > 0)
03731 return(sayfile(mychannel,fname));
03732 res = sayfile(mychannel,"rpt/node");
03733 if (!res)
03734 res = ast_say_character_str(mychannel,name,NULL,mychannel->language);
03735 return res;
03736 }
03737
03738 static int telem_any(struct rpt *myrpt,struct ast_channel *chan, char *entry)
03739 {
03740 int res;
03741 char c;
03742
03743 static int morsespeed;
03744 static int morsefreq;
03745 static int morseampl;
03746 static int morseidfreq = 0;
03747 static int morseidampl;
03748 static char mcat[] = MORSE;
03749
03750 res = 0;
03751
03752 if(!morseidfreq){
03753 morsespeed = retrieve_astcfgint(myrpt, mcat, "speed", 5, 20, 20);
03754 morsefreq = retrieve_astcfgint(myrpt, mcat, "frequency", 300, 3000, 800);
03755 morseampl = retrieve_astcfgint(myrpt, mcat, "amplitude", 200, 8192, 4096);
03756 morseidampl = retrieve_astcfgint(myrpt, mcat, "idamplitude", 200, 8192, 2048);
03757 morseidfreq = retrieve_astcfgint(myrpt, mcat, "idfrequency", 300, 3000, 330);
03758 }
03759
03760
03761
03762 if(entry[0] == '|'){
03763 c = entry[1];
03764 if((c >= 'a')&&(c <= 'z'))
03765 c -= 0x20;
03766
03767 switch(c){
03768 case 'I':
03769 res = send_morse(chan, entry + 2, morsespeed, morseidfreq, morseidampl);
03770 break;
03771
03772 case 'M':
03773 res = send_morse(chan, entry + 2, morsespeed, morsefreq, morseampl);
03774 break;
03775
03776 case 'T':
03777 res = send_tone_telemetry(chan, entry + 2);
03778 break;
03779 default:
03780 res = -1;
03781 }
03782 }
03783 else
03784 res = sayfile(chan, entry);
03785 return res;
03786 }
03787
03788
03789
03790
03791
03792
03793
03794 static int telem_lookup(struct rpt *myrpt,struct ast_channel *chan, char *node, char *name)
03795 {
03796
03797 int res;
03798 int i;
03799 char *entry;
03800 char *telemetry;
03801 char *telemetry_save;
03802
03803 res = 0;
03804 telemetry_save = NULL;
03805 entry = NULL;
03806
03807
03808 telemetry = (char *) ast_variable_retrieve(myrpt->cfg, node, TELEMETRY);
03809 if(telemetry ){
03810 telemetry_save = ast_strdup(telemetry);
03811 if(!telemetry_save){
03812 ast_log(LOG_WARNING,"ast_strdup() failed in telem_lookup()\n");
03813 return res;
03814 }
03815 entry = (char *) ast_variable_retrieve(myrpt->cfg, telemetry_save, name);
03816 }
03817
03818
03819
03820 if(!entry){
03821
03822 for(i = 0; i < sizeof(tele_defs)/sizeof(struct telem_defaults) ; i++){
03823 if(!strcasecmp(tele_defs[i].name, name))
03824 entry = tele_defs[i].value;
03825 }
03826 }
03827 if(entry){
03828 if(strlen(entry))
03829 if (chan) telem_any(myrpt,chan, entry);
03830 }
03831 else{
03832 res = -1;
03833 }
03834 if(telemetry_save)
03835 ast_free(telemetry_save);
03836 return res;
03837 }
03838
03839
03840
03841
03842
03843 static int get_wait_interval(struct rpt *myrpt, int type)
03844 {
03845 int interval;
03846 char *wait_times;
03847 char *wait_times_save;
03848
03849 wait_times_save = NULL;
03850 wait_times = (char *) ast_variable_retrieve(myrpt->cfg, myrpt->name, "wait_times");
03851
03852 if(wait_times){
03853 wait_times_save = ast_strdup(wait_times);
03854 if(!wait_times_save)
03855 return 0;
03856
03857 }
03858
03859 switch(type){
03860 case DLY_TELEM:
03861 if(wait_times)
03862 interval = retrieve_astcfgint(myrpt,wait_times_save, "telemwait", 500, 5000, 1000);
03863 else
03864 interval = 1000;
03865 break;
03866
03867 case DLY_ID:
03868 if(wait_times)
03869 interval = retrieve_astcfgint(myrpt,wait_times_save, "idwait",250,5000,500);
03870 else
03871 interval = 500;
03872 break;
03873
03874 case DLY_UNKEY:
03875 if(wait_times)
03876 interval = retrieve_astcfgint(myrpt,wait_times_save, "unkeywait",50,5000,1000);
03877 else
03878 interval = 1000;
03879 break;
03880
03881 case DLY_LINKUNKEY:
03882 if(wait_times)
03883 interval = retrieve_astcfgint(myrpt,wait_times_save, "linkunkeywait",500,5000,1000);
03884 else
03885 interval = 1000;
03886 break;
03887
03888 case DLY_CALLTERM:
03889 if(wait_times)
03890 interval = retrieve_astcfgint(myrpt,wait_times_save, "calltermwait",500,5000,1500);
03891 else
03892 interval = 1500;
03893 break;
03894
03895 case DLY_COMP:
03896 if(wait_times)
03897 interval = retrieve_astcfgint(myrpt,wait_times_save, "compwait",500,5000,200);
03898 else
03899 interval = 200;
03900 break;
03901
03902 case DLY_PARROT:
03903 if(wait_times)
03904 interval = retrieve_astcfgint(myrpt,wait_times_save, "parrotwait",500,5000,200);
03905 else
03906 interval = 200;
03907 break;
03908
03909 default:
03910 interval = 0;
03911 break;
03912 }
03913 if(wait_times_save)
03914 ast_free(wait_times_save);
03915 return interval;
03916 }
03917
03918
03919
03920
03921
03922 static void wait_interval(struct rpt *myrpt, int type, struct ast_channel *chan)
03923 {
03924 int interval;
03925 interval = get_wait_interval(myrpt, type);
03926 if(debug)
03927 ast_log(LOG_NOTICE,"Delay interval = %d\n", interval);
03928 if(interval)
03929 ast_safe_sleep(chan,interval);
03930 if(debug)
03931 ast_log(LOG_NOTICE,"Delay complete\n");
03932 return;
03933 }
03934
03935 static int split_freq(char *mhz, char *decimals, char *freq);
03936
03937 static void *rpt_tele_thread(void *this)
03938 {
03939 struct dahdi_confinfo ci;
03940 int res = 0,haslink,hastx,hasremote,imdone = 0, unkeys_queued, x;
03941 struct rpt_tele *mytele = (struct rpt_tele *)this;
03942 struct rpt_tele *tlist;
03943 struct rpt *myrpt;
03944 struct rpt_link *l,*l1,linkbase;
03945 struct ast_channel *mychannel;
03946 int vmajor, vminor, m;
03947 char *p,*ct,*ct_copy,*ident, *nodename,*cp;
03948 time_t t;
03949 #ifdef NEW_ASTERISK
03950 struct ast_tm localtm;
03951 #else
03952 struct tm localtm;
03953 #endif
03954 char lbuf[MAXLINKLIST],*strs[MAXLINKLIST];
03955 int i,ns,rbimode;
03956 char mhz[MAXREMSTR];
03957 char decimals[MAXREMSTR];
03958 char mystr[200];
03959 struct dahdi_params par;
03960
03961
03962
03963 myrpt = mytele->rpt;
03964
03965
03966 rpt_mutex_lock(&myrpt->lock);
03967 nodename = ast_strdup(myrpt->name);
03968 if(!nodename)
03969 {
03970 fprintf(stderr,"rpt:Sorry unable strdup nodename\n");
03971 rpt_mutex_lock(&myrpt->lock);
03972 remque((struct qelem *)mytele);
03973 ast_log(LOG_NOTICE,"Telemetry thread aborted at line %d, mode: %d\n",__LINE__, mytele->mode);
03974 rpt_mutex_unlock(&myrpt->lock);
03975 ast_free(mytele);
03976 pthread_exit(NULL);
03977 }
03978
03979 if (myrpt->p.ident){
03980 ident = ast_strdup(myrpt->p.ident);
03981 if(!ident)
03982 {
03983 fprintf(stderr,"rpt:Sorry unable strdup ident\n");
03984 rpt_mutex_lock(&myrpt->lock);
03985 remque((struct qelem *)mytele);
03986 ast_log(LOG_NOTICE,"Telemetry thread aborted at line %d, mode: %d\n",
03987 __LINE__, mytele->mode);
03988 rpt_mutex_unlock(&myrpt->lock);
03989 ast_free(nodename);
03990 ast_free(mytele);
03991 pthread_exit(NULL);
03992 }
03993 }
03994 else
03995 {
03996 ident = "";
03997 }
03998 rpt_mutex_unlock(&myrpt->lock);
03999
04000
04001
04002
04003 mychannel = ast_request("DAHDI",AST_FORMAT_SLINEAR,"pseudo",NULL);
04004 if (!mychannel)
04005 {
04006 fprintf(stderr,"rpt:Sorry unable to obtain pseudo channel\n");
04007 rpt_mutex_lock(&myrpt->lock);
04008 remque((struct qelem *)mytele);
04009 ast_log(LOG_NOTICE,"Telemetry thread aborted at line %d, mode: %d\n",__LINE__, mytele->mode);
04010 rpt_mutex_unlock(&myrpt->lock);
04011 ast_free(nodename);
04012 ast_free(ident);
04013 ast_free(mytele);
04014 pthread_exit(NULL);
04015 }
04016 #ifdef AST_CDR_FLAG_POST_DISABLED
04017 if (mychannel->cdr)
04018 ast_set_flag(mychannel->cdr,AST_CDR_FLAG_POST_DISABLED);
04019 #endif
04020 rpt_mutex_lock(&myrpt->lock);
04021 mytele->chan = mychannel;
04022 rpt_mutex_unlock(&myrpt->lock);
04023
04024 while((mytele->mode != SETREMOTE) && (mytele->mode != UNKEY) &&
04025 (mytele->mode != LINKUNKEY))
04026 {
04027 rpt_mutex_lock(&myrpt->lock);
04028 if (!myrpt->active_telem)
04029 {
04030 myrpt->active_telem = mytele;
04031 rpt_mutex_unlock(&myrpt->lock);
04032 break;
04033 }
04034 rpt_mutex_unlock(&myrpt->lock);
04035 usleep(100000);
04036 }
04037
04038
04039 ci.chan = 0;
04040
04041
04042
04043 ci.confno = (((mytele->mode == ID) || (mytele->mode == IDTALKOVER) || (mytele->mode == UNKEY) ||
04044 (mytele->mode == TAILMSG) || (mytele->mode == LINKUNKEY) || (mytele->mode == TIMEOUT) ||
04045 (mytele->mode == PARROT) || (mytele->mode == STATS_TIME_LOCAL)) ?
04046 myrpt->txconf : myrpt->conf);
04047 ci.confmode = DAHDI_CONF_CONFANN;
04048
04049 if (ioctl(mychannel->fds[0],DAHDI_SETCONF,&ci) == -1)
04050 {
04051 ast_log(LOG_WARNING, "Unable to set conference mode to Announce\n");
04052 rpt_mutex_lock(&myrpt->lock);
04053 myrpt->active_telem = NULL;
04054 remque((struct qelem *)mytele);
04055 rpt_mutex_unlock(&myrpt->lock);
04056 ast_log(LOG_NOTICE,"Telemetry thread aborted at line %d, mode: %d\n",__LINE__, mytele->mode);
04057 ast_free(nodename);
04058 ast_free(ident);
04059 ast_free(mytele);
04060 ast_hangup(mychannel);
04061 pthread_exit(NULL);
04062 }
04063 ast_stopstream(mychannel);
04064 switch(mytele->mode)
04065 {
04066 case ID:
04067 case ID1:
04068
04069 wait_interval(myrpt, (mytele->mode == ID) ? DLY_ID : DLY_TELEM,mychannel);
04070 res = telem_any(myrpt,mychannel, ident);
04071 imdone=1;
04072 break;
04073
04074 case TAILMSG:
04075 res = ast_streamfile(mychannel, myrpt->p.tailmessages[myrpt->tailmessagen], mychannel->language);
04076 break;
04077
04078 case IDTALKOVER:
04079 p = (char *) ast_variable_retrieve(myrpt->cfg, nodename, "idtalkover");
04080 if(p)
04081 res = telem_any(myrpt,mychannel, p);
04082 imdone=1;
04083 break;
04084
04085 case PROC:
04086
04087 wait_interval(myrpt, DLY_TELEM, mychannel);
04088 res = telem_lookup(myrpt, mychannel, myrpt->name, "patchup");
04089 if(res < 0){
04090 res = ast_streamfile(mychannel, "rpt/callproceeding", mychannel->language);
04091 }
04092 break;
04093 case TERM:
04094
04095 wait_interval(myrpt, DLY_CALLTERM, mychannel);
04096 res = telem_lookup(myrpt, mychannel, myrpt->name, "patchdown");
04097 if(res < 0){
04098 res = ast_streamfile(mychannel, "rpt/callterminated", mychannel->language);
04099 }
04100 break;
04101 case COMPLETE:
04102
04103 wait_interval(myrpt, DLY_TELEM, mychannel);
04104 res = telem_lookup(myrpt,mychannel, myrpt->name, "functcomplete");
04105 break;
04106 case MACRO_NOTFOUND:
04107
04108 wait_interval(myrpt, DLY_TELEM, mychannel);
04109 res = ast_streamfile(mychannel, "rpt/macro_notfound", mychannel->language);
04110 break;
04111 case MACRO_BUSY:
04112
04113 wait_interval(myrpt, DLY_TELEM, mychannel);
04114 res = ast_streamfile(mychannel, "rpt/macro_busy", mychannel->language);
04115 break;
04116 case UNKEY:
04117 if(myrpt->patchnoct && myrpt->callmode){
04118 imdone = 1;
04119 break;
04120 }
04121
04122
04123
04124
04125
04126 x = get_wait_interval(myrpt, DLY_UNKEY);
04127 rpt_mutex_lock(&myrpt->lock);
04128 myrpt->unkeytocttimer = x;
04129 rpt_mutex_unlock(&myrpt->lock);
04130
04131
04132
04133
04134
04135 tlist = myrpt->tele.next;
04136 unkeys_queued = 0;
04137 if (tlist != &myrpt->tele)
04138 {
04139 rpt_mutex_lock(&myrpt->lock);
04140 while(tlist != &myrpt->tele){
04141 if (tlist->mode == UNKEY) unkeys_queued++;
04142 tlist = tlist->next;
04143 }
04144 rpt_mutex_unlock(&myrpt->lock);
04145 }
04146 if( unkeys_queued > 1){
04147 imdone = 1;
04148 break;
04149 }
04150
04151
04152
04153 while(myrpt->unkeytocttimer)
04154 {
04155 int ctint;
04156 if(myrpt->unkeytocttimer > 100)
04157 ctint = 100;
04158 else
04159 ctint = myrpt->unkeytocttimer;
04160 ast_safe_sleep(mychannel, ctint);
04161 rpt_mutex_lock(&myrpt->lock);
04162 if(myrpt->unkeytocttimer < ctint)
04163 myrpt->unkeytocttimer = 0;
04164 else
04165 myrpt->unkeytocttimer -= ctint;
04166 rpt_mutex_unlock(&myrpt->lock);
04167 }
04168
04169
04170
04171
04172
04173 if(myrpt->keyed){
04174 imdone = 1;
04175 break;
04176 }
04177
04178 rpt_mutex_lock(&myrpt->lock);
04179 myrpt->dailykerchunks++;
04180 myrpt->totalkerchunks++;
04181 rpt_mutex_unlock(&myrpt->lock);
04182
04183 haslink = 0;
04184 hastx = 0;
04185 hasremote = 0;
04186 l = myrpt->links.next;
04187 if (l != &myrpt->links)
04188 {
04189 rpt_mutex_lock(&myrpt->lock);
04190 while(l != &myrpt->links)
04191 {
04192 if (l->name[0] == '0')
04193 {
04194 l = l->next;
04195 continue;
04196 }
04197 haslink = 1;
04198 if (l->mode) {
04199 hastx++;
04200 if (l->isremote) hasremote++;
04201 }
04202 l = l->next;
04203 }
04204 rpt_mutex_unlock(&myrpt->lock);
04205 }
04206 if (haslink)
04207 {
04208
04209 res = telem_lookup(myrpt,mychannel, myrpt->name, (!hastx) ? "remotemon" : "remotetx");
04210 if(res)
04211 ast_log(LOG_WARNING, "telem_lookup:remotexx failed on %s\n", mychannel->name);
04212
04213
04214
04215 if (myrpt->cmdnode[0])
04216 {
04217 ast_safe_sleep(mychannel,200);
04218 res = telem_lookup(myrpt,mychannel, myrpt->name, "cmdmode");
04219 if(res)
04220 ast_log(LOG_WARNING, "telem_lookup:cmdmode failed on %s\n", mychannel->name);
04221 ast_stopstream(mychannel);
04222 }
04223 }
04224 else if((ct = (char *) ast_variable_retrieve(myrpt->cfg, nodename, "unlinkedct"))){
04225 ct_copy = ast_strdup(ct);
04226 if(ct_copy)
04227 {
04228 res = telem_lookup(myrpt,mychannel, myrpt->name, ct_copy);
04229 ast_free(ct_copy);
04230 }
04231 else
04232 res = -1;
04233 if(res)
04234 ast_log(LOG_WARNING, "telem_lookup:ctx failed on %s\n", mychannel->name);
04235 }
04236 if (hasremote && (!myrpt->cmdnode[0]))
04237 {
04238
04239 ci.chan = 0;
04240 ci.confno = myrpt->conf;
04241 ci.confmode = DAHDI_CONF_CONFANN;
04242
04243 if (ioctl(mychannel->fds[0],DAHDI_SETCONF,&ci) == -1)
04244 {
04245 ast_log(LOG_WARNING, "Unable to set conference mode to Announce\n");
04246 rpt_mutex_lock(&myrpt->lock);
04247 myrpt->active_telem = NULL;
04248 remque((struct qelem *)mytele);
04249 rpt_mutex_unlock(&myrpt->lock);
04250 ast_log(LOG_NOTICE,"Telemetry thread aborted at line %d, mode: %d\n",__LINE__, mytele->mode);
04251 ast_free(nodename);
04252 ast_free(ident);
04253 ast_free(mytele);
04254 ast_hangup(mychannel);
04255 pthread_exit(NULL);
04256 }
04257 if((ct = (char *) ast_variable_retrieve(myrpt->cfg, nodename, "remotect"))){
04258 ast_safe_sleep(mychannel,200);
04259 ct_copy = ast_strdup(ct);
04260 if(ct_copy)
04261 {
04262 res = telem_lookup(myrpt,mychannel, myrpt->name, ct_copy);
04263 ast_free(ct_copy);
04264 }
04265 else
04266 res = -1;
04267
04268 if(res)
04269 ast_log(LOG_WARNING, "telem_lookup:ctx failed on %s\n", mychannel->name);
04270 }
04271 }
04272 #if defined(_MDC_DECODE_H_) && defined(MDC_SAY_WHEN_DOING_CT)
04273 if (myrpt->lastunit)
04274 {
04275 char mystr[10];
04276
04277 ast_safe_sleep(mychannel,200);
04278
04279 ci.chan = 0;
04280 ci.confno = myrpt->txconf;
04281 ci.confmode = DAHDI_CONF_CONFANN;
04282
04283 if (ioctl(mychannel->fds[0],DAHDI_SETCONF,&ci) == -1)
04284 {
04285 ast_log(LOG_WARNING, "Unable to set conference mode to Announce\n");
04286 rpt_mutex_lock(&myrpt->lock);
04287 myrpt->active_telem = NULL;
04288 remque((struct qelem *)mytele);
04289 rpt_mutex_unlock(&myrpt->lock);
04290 ast_log(LOG_NOTICE,"Telemetry thread aborted at line %d, mode: %d\n",__LINE__, mytele->mode);
04291 ast_free(nodename);
04292 ast_free(ident);
04293 ast_free(mytele);
04294 ast_hangup(mychannel);
04295 pthread_exit(NULL);
04296 }
04297 sprintf(mystr,"%04x",myrpt->lastunit);
04298 myrpt->lastunit = 0;
04299 ast_say_character_str(mychannel,mystr,NULL,mychannel->language);
04300 break;
04301 }
04302 #endif
04303 imdone = 1;
04304 break;
04305 case LINKUNKEY:
04306 if(myrpt->patchnoct && myrpt->callmode){
04307 imdone = 1;
04308 break;
04309 }
04310
04311
04312
04313
04314
04315 x = get_wait_interval(myrpt, DLY_LINKUNKEY);
04316 mytele->mylink.linkunkeytocttimer = x;
04317
04318
04319
04320
04321
04322 tlist = myrpt->tele.next;
04323 unkeys_queued = 0;
04324 if (tlist != &myrpt->tele)
04325 {
04326 rpt_mutex_lock(&myrpt->lock);
04327 while(tlist != &myrpt->tele){
04328 if (tlist->mode == LINKUNKEY) unkeys_queued++;
04329 tlist = tlist->next;
04330 }
04331 rpt_mutex_unlock(&myrpt->lock);
04332 }
04333 if( unkeys_queued > 1){
04334 imdone = 1;
04335 break;
04336 }
04337
04338
04339
04340 while(mytele->mylink.linkunkeytocttimer)
04341 {
04342 int ctint;
04343 if(mytele->mylink.linkunkeytocttimer > 100)
04344 ctint = 100;
04345 else
04346 ctint = mytele->mylink.linkunkeytocttimer;
04347 ast_safe_sleep(mychannel, ctint);
04348 rpt_mutex_lock(&myrpt->lock);
04349 if(mytele->mylink.linkunkeytocttimer < ctint)
04350 mytele->mylink.linkunkeytocttimer = 0;
04351 else
04352 mytele->mylink.linkunkeytocttimer -= ctint;
04353 rpt_mutex_unlock(&myrpt->lock);
04354 }
04355
04356 if((ct = (char *) ast_variable_retrieve(myrpt->cfg, nodename, "linkunkeyct"))){
04357 ct_copy = ast_strdup(ct);
04358 if(ct_copy){
04359 res = telem_lookup(myrpt,mychannel, myrpt->name, ct_copy);
04360 ast_free(ct_copy);
04361 }
04362 else
04363 res = -1;
04364 if(res)
04365 ast_log(LOG_WARNING, "telem_lookup:ctx failed on %s\n", mychannel->name);
04366 }
04367 imdone = 1;
04368 break;
04369 case REMDISC:
04370
04371 wait_interval(myrpt, DLY_TELEM, mychannel);
04372 l = myrpt->links.next;
04373 haslink = 0;
04374
04375 if (l != &myrpt->links)
04376 {
04377 rpt_mutex_lock(&myrpt->lock);
04378 while(l != &myrpt->links)
04379 {
04380 if (l->name[0] == '0')
04381 {
04382 l = l->next;
04383 continue;
04384 }
04385 if (!strcmp(l->name,mytele->mylink.name))
04386 {
04387 haslink = 1;
04388 break;
04389 }
04390 l = l->next;
04391 }
04392 rpt_mutex_unlock(&myrpt->lock);
04393 }
04394 if (haslink)
04395 {
04396 imdone = 1;
04397 break;
04398 }
04399 res = saynode(myrpt,mychannel,mytele->mylink.name);
04400 if (!res)
04401 res = ast_streamfile(mychannel, ((mytele->mylink.hasconnected) ?
04402 "rpt/remote_disc" : "rpt/remote_busy"), mychannel->language);
04403 break;
04404 case REMALREADY:
04405
04406 wait_interval(myrpt, DLY_TELEM, mychannel);
04407 res = ast_streamfile(mychannel, "rpt/remote_already", mychannel->language);
04408 break;
04409 case REMNOTFOUND:
04410
04411 wait_interval(myrpt, DLY_TELEM, mychannel);
04412 res = ast_streamfile(mychannel, "rpt/remote_notfound", mychannel->language);
04413 break;
04414 case REMGO:
04415
04416 wait_interval(myrpt, DLY_TELEM, mychannel);
04417 res = ast_streamfile(mychannel, "rpt/remote_go", mychannel->language);
04418 break;
04419 case CONNECTED:
04420
04421 wait_interval(myrpt, DLY_TELEM, mychannel);
04422 res = saynode(myrpt,mychannel,mytele->mylink.name);
04423 if (!res)
04424 res = ast_streamfile(mychannel, "rpt/connected", mychannel->language);
04425 if (!res)
04426 res = ast_waitstream(mychannel, "");
04427 else
04428 ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", mychannel->name);
04429 ast_stopstream(mychannel);
04430 res = ast_streamfile(mychannel, "digits/2", mychannel->language);
04431 if (!res)
04432 res = ast_waitstream(mychannel, "");
04433 else
04434 ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", mychannel->name);
04435 ast_stopstream(mychannel);
04436 res = saynode(myrpt,mychannel,myrpt->name);
04437 imdone = 1;
04438 break;
04439 case CONNFAIL:
04440 res = saynode(myrpt,mychannel,mytele->mylink.name);
04441 if (!res)
04442 res = ast_streamfile(mychannel, "rpt/connection_failed", mychannel->language);
04443 break;
04444 case MEMNOTFOUND:
04445
04446 wait_interval(myrpt, DLY_TELEM, mychannel);
04447 res = ast_streamfile(mychannel, "rpt/memory_notfound", mychannel->language);
04448 break;
04449 case PLAYBACK:
04450
04451 wait_interval(myrpt, DLY_TELEM, mychannel);
04452 res = ast_streamfile(mychannel, mytele->param, mychannel->language);
04453 break;
04454 case TOPKEY:
04455
04456 wait_interval(myrpt, DLY_TELEM, mychannel);
04457 for(i = 0; i < TOPKEYN; i++)
04458 {
04459 if (!myrpt->topkey[i].node[0]) continue;
04460 if ((!myrpt->topkeylong) && (myrpt->topkey[i].keyed)) continue;
04461 res = saynode(myrpt, mychannel, myrpt->topkey[i].node);
04462 if (!res) res = sayfile(mychannel,(myrpt->topkey[i].keyed) ?
04463 "rpt/keyedfor" : "rpt/unkeyedfor");
04464 if (!res) res = saynum(mychannel,
04465 myrpt->topkey[i].timesince);
04466 if (!res) res = sayfile(mychannel,"rpt/seconds");
04467 if (!myrpt->topkeylong) break;
04468 }
04469 imdone = 1;
04470 break;
04471 case SETREMOTE:
04472 ast_mutex_lock(&myrpt->remlock);
04473 res = 0;
04474 if(!strcmp(myrpt->remoterig, remote_rig_ft897))
04475 {
04476 res = set_ft897(myrpt);
04477 }
04478 else if(!strcmp(myrpt->remoterig, remote_rig_tm271))
04479 {
04480 res = set_tm271(myrpt);
04481 }
04482 else if(!strcmp(myrpt->remoterig, remote_rig_ic706))
04483 {
04484 res = set_ic706(myrpt);
04485 }
04486 #ifdef HAVE_IOPERM
04487 else if(!strcmp(myrpt->remoterig, remote_rig_rbi)||!strcmp(myrpt->remoterig, remote_rig_ppp16))
04488 {
04489 if (ioperm(myrpt->p.iobase,1,1) == -1)
04490 {
04491 rpt_mutex_unlock(&myrpt->lock);
04492 ast_log(LOG_WARNING, "Cant get io permission on IO port %x hex\n",myrpt->p.iobase);
04493 res = -1;
04494 }
04495 else res = setrbi(myrpt);
04496 }
04497 #endif
04498 else if(!strcmp(myrpt->remoterig, remote_rig_kenwood))
04499 {
04500 if (myrpt->iofd >= 0) setdtr(myrpt->iofd,1);
04501 res = setkenwood(myrpt);
04502 if (myrpt->iofd >= 0) setdtr(myrpt->iofd,0);
04503 if (ast_safe_sleep(mychannel,200) == -1)
04504 {
04505 ast_mutex_unlock(&myrpt->remlock);
04506 res = -1;
04507 break;
04508 }
04509 if (myrpt->iofd < 0)
04510 {
04511 i = DAHDI_FLUSH_EVENT;
04512 if (ioctl(myrpt->dahditxchannel->fds[0],DAHDI_FLUSH,&i) == -1)
04513 {
04514 ast_mutex_unlock(&myrpt->remlock);
04515 ast_log(LOG_ERROR,"Cant flush events");
04516 res = -1;
04517 break;
04518 }
04519 if (ioctl(myrpt->dahdirxchannel->fds[0],DAHDI_GET_PARAMS,&par) == -1)
04520 {
04521 ast_mutex_unlock(&myrpt->remlock);
04522 ast_log(LOG_ERROR,"Cant get params");
04523 res = -1;
04524 break;
04525 }
04526 myrpt->remoterx =
04527 (par.rxisoffhook || (myrpt->tele.next != &myrpt->tele));
04528 }
04529 }
04530
04531 ast_mutex_unlock(&myrpt->remlock);
04532 if (!res)
04533 {
04534 imdone = 1;
04535 break;
04536 }
04537
04538 case INVFREQ:
04539
04540 wait_interval(myrpt, DLY_TELEM, mychannel);
04541 res = ast_streamfile(mychannel, "rpt/invalid-freq", mychannel->language);
04542 break;
04543 case REMMODE:
04544 cp = 0;
04545 wait_interval(myrpt, DLY_TELEM, mychannel);
04546 switch(myrpt->remmode)
04547 {
04548 case REM_MODE_FM:
04549 saycharstr(mychannel,"FM");
04550 break;
04551 case REM_MODE_USB:
04552 saycharstr(mychannel,"USB");
04553 break;
04554 case REM_MODE_LSB:
04555 saycharstr(mychannel,"LSB");
04556 break;
04557 case REM_MODE_AM:
04558 saycharstr(mychannel,"AM");
04559 break;
04560 }
04561 wait_interval(myrpt, DLY_COMP, mychannel);
04562 if (!res) res = telem_lookup(myrpt,mychannel, myrpt->name, "functcomplete");
04563 break;
04564 case LOGINREQ:
04565 wait_interval(myrpt, DLY_TELEM, mychannel);
04566 sayfile(mychannel,"rpt/login");
04567 saycharstr(mychannel,myrpt->name);
04568 break;
04569 case REMLOGIN:
04570 wait_interval(myrpt, DLY_TELEM, mychannel);
04571 saycharstr(mychannel,myrpt->loginuser);
04572 saynode(myrpt,mychannel,myrpt->name);
04573 wait_interval(myrpt, DLY_COMP, mychannel);
04574 if (!res) res = telem_lookup(myrpt,mychannel, myrpt->name, "functcomplete");
04575 break;
04576 case REMXXX:
04577 wait_interval(myrpt, DLY_TELEM, mychannel);
04578 res = 0;
04579 switch(mytele->submode)
04580 {
04581 case 100:
04582 sayfile(mychannel, "rpt/rxpl");
04583 sayfile(mychannel, "rpt/off");
04584 break;
04585 case 101:
04586 sayfile(mychannel, "rpt/rxpl");
04587 sayfile(mychannel, "rpt/on");
04588 break;
04589 case 102:
04590 sayfile(mychannel, "rpt/txpl");
04591 sayfile(mychannel, "rpt/off");
04592 break;
04593 case 103:
04594 sayfile(mychannel, "rpt/txpl");
04595 sayfile(mychannel, "rpt/on");
04596 break;
04597 case 104:
04598 sayfile(mychannel, "rpt/lopwr");
04599 break;
04600 case 105:
04601 sayfile(mychannel, "rpt/medpwr");
04602 break;
04603 case 106:
04604 sayfile(mychannel, "rpt/hipwr");
04605 break;
04606 case 113:
04607 sayfile(mychannel,"rpt/down");
04608 sayfile(mychannel, "rpt/slow");
04609 break;
04610 case 114:
04611 sayfile(mychannel,"rpt/down");
04612 sayfile(mychannel, "rpt/quick");
04613 break;
04614 case 115:
04615 sayfile(mychannel,"rpt/down");
04616 sayfile(mychannel, "rpt/fast");
04617 break;
04618 case 116:
04619 sayfile(mychannel,"rpt/up");
04620 sayfile(mychannel, "rpt/slow");
04621 break;
04622 case 117:
04623 sayfile(mychannel,"rpt/up");
04624 sayfile(mychannel, "rpt/quick");
04625 break;
04626 case 118:
04627 sayfile(mychannel,"rpt/up");
04628 sayfile(mychannel, "rpt/fast");
04629 break;
04630 default:
04631 res = -1;
04632 }
04633 wait_interval(myrpt, DLY_COMP, mychannel);
04634 if (!res) res = telem_lookup(myrpt,mychannel, myrpt->name, "functcomplete");
04635 break;
04636 case SCAN:
04637 ast_mutex_lock(&myrpt->remlock);
04638 if (myrpt->hfscanstop)
04639 {
04640 myrpt->hfscanstatus = 0;
04641 myrpt->hfscanmode = 0;
04642 myrpt->hfscanstop = 0;
04643 mytele->mode = SCANSTAT;
04644 ast_mutex_unlock(&myrpt->remlock);
04645 if (ast_safe_sleep(mychannel,1000) == -1) break;
04646 sayfile(mychannel, "rpt/stop");
04647 imdone = 1;
04648 break;
04649 }
04650 if (myrpt->hfscanstatus > -2) service_scan(myrpt);
04651 i = myrpt->hfscanstatus;
04652 myrpt->hfscanstatus = 0;
04653 if (i) mytele->mode = SCANSTAT;
04654 ast_mutex_unlock(&myrpt->remlock);
04655 if (i < 0) sayfile(mychannel, "rpt/stop");
04656 else if (i > 0) saynum(mychannel,i);
04657 imdone = 1;
04658 break;
04659 case TUNE:
04660 ast_mutex_lock(&myrpt->remlock);
04661 if (!strcmp(myrpt->remoterig,remote_rig_ic706))
04662 {
04663 set_mode_ic706(myrpt, REM_MODE_AM);
04664 if(play_tone(mychannel, 800, 6000, 8192) == -1) break;
04665 ast_safe_sleep(mychannel,500);
04666 set_mode_ic706(myrpt, myrpt->remmode);
04667 myrpt->tunerequest = 0;
04668 ast_mutex_unlock(&myrpt->remlock);
04669 imdone = 1;
04670 break;
04671 }
04672 set_mode_ft897(myrpt, REM_MODE_AM);
04673 simple_command_ft897(myrpt, 8);
04674 if(play_tone(mychannel, 800, 6000, 8192) == -1) break;
04675 simple_command_ft897(myrpt, 0x88);
04676 ast_safe_sleep(mychannel,500);
04677 set_mode_ft897(myrpt, myrpt->remmode);
04678 myrpt->tunerequest = 0;
04679 ast_mutex_unlock(&myrpt->remlock);
04680 imdone = 1;
04681 break;
04682 case REMSHORTSTATUS:
04683 case REMLONGSTATUS:
04684 wait_interval(myrpt, DLY_TELEM, mychannel);
04685 res = saynode(myrpt,mychannel,myrpt->name);
04686 if(!res)
04687 res = sayfile(mychannel,"rpt/frequency");
04688 if(!res)
04689 res = split_freq(mhz, decimals, myrpt->freq);
04690 if (!multimode_capable(myrpt)) decimals[3] = 0;
04691 if(!res){
04692 m = atoi(mhz);
04693 if(m < 100)
04694 res = saynum(mychannel, m);
04695 else
04696 res = saycharstr(mychannel, mhz);
04697 }
04698 if(!res)
04699 res = sayfile(mychannel, "letters/dot");
04700 if(!res)
04701 res = saycharstr(mychannel, decimals);
04702
04703 if(res) break;
04704 if(myrpt->remmode == REM_MODE_FM){
04705 switch(myrpt->offset){
04706
04707 case REM_MINUS:
04708 res = sayfile(mychannel,"rpt/minus");
04709 break;
04710
04711 case REM_SIMPLEX:
04712 res = sayfile(mychannel,"rpt/simplex");
04713 break;
04714
04715 case REM_PLUS:
04716 res = sayfile(mychannel,"rpt/plus");
04717 break;
04718
04719 default:
04720 break;
04721 }
04722 }
04723 else{
04724 switch(myrpt->remmode){
04725
04726 case REM_MODE_USB:
04727 res = saycharstr(mychannel, "USB");
04728 break;
04729
04730 case REM_MODE_LSB:
04731 res = saycharstr(mychannel, "LSB");
04732 break;
04733
04734 case REM_MODE_AM:
04735 res = saycharstr(mychannel, "AM");
04736 break;
04737
04738
04739 default:
04740 break;
04741 }
04742 }
04743
04744 if (res == -1) break;
04745
04746 if(mytele->mode == REMSHORTSTATUS){
04747 wait_interval(myrpt, DLY_COMP, mychannel);
04748 if (!res) res = telem_lookup(myrpt,mychannel, myrpt->name, "functcomplete");
04749 break;
04750 }
04751
04752 if (strcmp(myrpt->remoterig,remote_rig_ic706))
04753 {
04754 switch(myrpt->powerlevel){
04755
04756 case REM_LOWPWR:
04757 res = sayfile(mychannel,"rpt/lopwr") ;
04758 break;
04759 case REM_MEDPWR:
04760 res = sayfile(mychannel,"rpt/medpwr");
04761 break;
04762 case REM_HIPWR:
04763 res = sayfile(mychannel,"rpt/hipwr");
04764 break;
04765 }
04766 }
04767
04768 rbimode = ((!strncmp(myrpt->remoterig,remote_rig_rbi,3))
04769 || (!strncmp(myrpt->remoterig,remote_rig_ic706,3)));
04770 if (res || (sayfile(mychannel,"rpt/rxpl") == -1)) break;
04771 if (rbimode && (sayfile(mychannel,"rpt/txpl") == -1)) break;
04772 if ((sayfile(mychannel,"rpt/frequency") == -1) ||
04773 (saycharstr(mychannel,myrpt->rxpl) == -1)) break;
04774 if ((!rbimode) && ((sayfile(mychannel,"rpt/txpl") == -1) ||
04775 (sayfile(mychannel,"rpt/frequency") == -1) ||
04776 (saycharstr(mychannel,myrpt->txpl) == -1))) break;
04777 if(myrpt->remmode == REM_MODE_FM){
04778 if ((sayfile(mychannel,"rpt/rxpl") == -1) ||
04779 (sayfile(mychannel,((myrpt->rxplon) ? "rpt/on" : "rpt/off")) == -1) ||
04780 (sayfile(mychannel,"rpt/txpl") == -1) ||
04781 (sayfile(mychannel,((myrpt->txplon) ? "rpt/on" : "rpt/off")) == -1))
04782 {
04783 break;
04784 }
04785 }
04786 wait_interval(myrpt, DLY_COMP, mychannel);
04787 if (!res) res = telem_lookup(myrpt,mychannel, myrpt->name, "functcomplete");
04788 break;
04789 case STATUS:
04790
04791 wait_interval(myrpt, DLY_TELEM, mychannel);
04792 hastx = 0;
04793 linkbase.next = &linkbase;
04794 linkbase.prev = &linkbase;
04795 rpt_mutex_lock(&myrpt->lock);
04796
04797 l = myrpt->links.next;
04798 while(l != &myrpt->links)
04799 {
04800 if (l->name[0] == '0')
04801 {
04802 l = l->next;
04803 continue;
04804 }
04805 l1 = ast_malloc(sizeof(struct rpt_link));
04806 if (!l1)
04807 {
04808 ast_log(LOG_WARNING, "Cannot alloc memory on %s\n", mychannel->name);
04809 remque((struct qelem *)mytele);
04810 myrpt->active_telem = NULL;
04811 rpt_mutex_unlock(&myrpt->lock);
04812 ast_log(LOG_NOTICE,"Telemetry thread aborted at line %d, mode: %d\n",__LINE__, mytele->mode);
04813 ast_free(nodename);
04814 ast_free(ident);
04815 ast_free(mytele);
04816 ast_hangup(mychannel);
04817 pthread_exit(NULL);
04818 }
04819 memcpy(l1,l,sizeof(struct rpt_link));
04820 l1->next = l1->prev = NULL;
04821 insque((struct qelem *)l1,(struct qelem *)linkbase.next);
04822 l = l->next;
04823 }
04824 rpt_mutex_unlock(&myrpt->lock);
04825 res = saynode(myrpt,mychannel,myrpt->name);
04826 if (myrpt->callmode)
04827 {
04828 hastx = 1;
04829 res = ast_streamfile(mychannel, "rpt/autopatch_on", mychannel->language);
04830 if (!res)
04831 res = ast_waitstream(mychannel, "");
04832 else
04833 ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", mychannel->name);
04834 ast_stopstream(mychannel);
04835 }
04836 l = linkbase.next;
04837 while(l != &linkbase)
04838 {
04839 char *s;
04840
04841 hastx = 1;
04842 res = saynode(myrpt,mychannel,l->name);
04843 s = "rpt/tranceive";
04844 if (!l->mode) s = "rpt/monitor";
04845 if (!l->thisconnected) s = "rpt/connecting";
04846 res = ast_streamfile(mychannel, s, mychannel->language);
04847 if (!res)
04848 res = ast_waitstream(mychannel, "");
04849 else
04850 ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", mychannel->name);
04851 ast_stopstream(mychannel);
04852 l = l->next;
04853 }
04854 if (!hastx)
04855 {
04856 res = ast_streamfile(mychannel, "rpt/repeat_only", mychannel->language);
04857 if (!res)
04858 res = ast_waitstream(mychannel, "");
04859 else
04860 ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", mychannel->name);
04861 ast_stopstream(mychannel);
04862 }
04863
04864 l = linkbase.next;
04865 while(l != &linkbase)
04866 {
04867 l1 = l;
04868 l = l->next;
04869 remque((struct qelem *)l1);
04870 ast_free(l1);
04871 }
04872 imdone = 1;
04873 break;
04874 case FULLSTATUS:
04875 rpt_mutex_lock(&myrpt->lock);
04876
04877 __mklinklist(myrpt,NULL,lbuf);
04878 rpt_mutex_unlock(&myrpt->lock);
04879
04880 ns = finddelim(lbuf,strs,MAXLINKLIST);
04881
04882 if (ns) qsort((void *)strs,ns,sizeof(char *),mycompar);
04883
04884 wait_interval(myrpt, DLY_TELEM, mychannel);
04885 hastx = 0;
04886 res = saynode(myrpt,mychannel,myrpt->name);
04887 if (myrpt->callmode)
04888 {
04889 hastx = 1;
04890 res = ast_streamfile(mychannel, "rpt/autopatch_on", mychannel->language);
04891 if (!res)
04892 res = ast_waitstream(mychannel, "");
04893 else
04894 ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", mychannel->name);
04895 ast_stopstream(mychannel);
04896 }
04897
04898 for(i = 0; i < ns; i++)
04899 {
04900 char *s,mode = 'T';
04901
04902
04903 if ((*strs[i] < '0') || (*strs[i] > '9'))
04904 {
04905 mode = *strs[i];
04906 strs[i]++;
04907 }
04908
04909 hastx = 1;
04910 res = saynode(myrpt,mychannel,strs[i]);
04911 s = "rpt/tranceive";
04912 if (mode == 'R') s = "rpt/monitor";
04913 if (mode == 'C') s = "rpt/connecting";
04914 res = ast_streamfile(mychannel, s, mychannel->language);
04915 if (!res)
04916 res = ast_waitstream(mychannel, "");
04917 else
04918 ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", mychannel->name);
04919 ast_stopstream(mychannel);
04920 }
04921 if (!hastx)
04922 {
04923 res = ast_streamfile(mychannel, "rpt/repeat_only", 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 imdone = 1;
04931 break;
04932
04933 case LASTNODEKEY:
04934 rpt_mutex_lock(&myrpt->lock);
04935 if(myrpt->lastnodewhichkeyedusup){
04936 p = ast_strdup(myrpt->lastnodewhichkeyedusup);
04937 if(!p){
04938 ast_log(LOG_WARNING, "ast_strdup failed in telemetery LASTNODEKEY");
04939 imdone = 1;
04940 break;
04941 }
04942 }
04943 else
04944 p = NULL;
04945 rpt_mutex_unlock(&myrpt->lock);
04946 if(!p){
04947 imdone = 1;
04948 break;
04949 }
04950 wait_interval(myrpt, DLY_TELEM, mychannel);
04951 res = saynode(myrpt,mychannel,p);
04952 ast_free(p);
04953 imdone = 1;
04954 break;
04955
04956 case UNAUTHTX:
04957 wait_interval(myrpt, DLY_TELEM, mychannel);
04958 res = ast_streamfile(mychannel, "rpt/unauthtx", mychannel->language);
04959 if (!res)
04960 res = ast_waitstream(mychannel, "");
04961 else
04962 ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", mychannel->name);
04963 ast_stopstream(mychannel);
04964 imdone = 1;
04965 break;
04966
04967 case PARROT:
04968
04969 sprintf(mystr,PARROTFILE,myrpt->name,(unsigned int)mytele->parrot);
04970 if (ast_fileexists(mystr,NULL,mychannel->language) <= 0)
04971 {
04972 imdone = 1;
04973 myrpt->parrotstate = 0;
04974 break;
04975 }
04976 wait_interval(myrpt, DLY_PARROT, mychannel);
04977 sprintf(mystr,PARROTFILE,myrpt->name,(unsigned int)mytele->parrot);
04978 res = ast_streamfile(mychannel, mystr, mychannel->language);
04979 if (!res)
04980 res = ast_waitstream(mychannel, "");
04981 else
04982 ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", mychannel->name);
04983 ast_stopstream(mychannel);
04984 sprintf(mystr,PARROTFILE,myrpt->name,(unsigned int)mytele->parrot);
04985 strcat(mystr,".wav");
04986 unlink(mystr);
04987 imdone = 1;
04988 myrpt->parrotstate = 0;
04989 break;
04990
04991 case TIMEOUT:
04992 res = saynode(myrpt,mychannel,myrpt->name);
04993 if (!res)
04994 res = ast_streamfile(mychannel, "rpt/timeout", mychannel->language);
04995 break;
04996
04997 case TIMEOUT_WARNING:
04998 time(&t);
04999 res = saynode(myrpt,mychannel,myrpt->name);
05000 if (!res)
05001 res = ast_streamfile(mychannel, "rpt/timeout-warning", mychannel->language);
05002 if (!res)
05003 res = ast_waitstream(mychannel, "");
05004 else
05005 ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", mychannel->name);
05006 ast_stopstream(mychannel);
05007 if(!res)
05008 ast_say_number(mychannel, myrpt->p.remotetimeout -
05009 (t - myrpt->last_activity_time),
05010 "", mychannel->language, (char *) NULL);
05011 if (!res)
05012 res = ast_waitstream(mychannel, "");
05013 ast_stopstream(mychannel);
05014 res = ast_streamfile(mychannel, "queue-seconds", mychannel->language);
05015 break;
05016
05017 case ACT_TIMEOUT_WARNING:
05018 time(&t);
05019 res = saynode(myrpt,mychannel,myrpt->name);
05020 if (!res)
05021 res = ast_streamfile(mychannel, "rpt/act-timeout-warning", mychannel->language);
05022 if (!res)
05023 res = ast_waitstream(mychannel, "");
05024 else
05025 ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", mychannel->name);
05026 ast_stopstream(mychannel);
05027 if(!res)
05028 ast_say_number(mychannel, myrpt->p.remoteinacttimeout -
05029 (t - myrpt->last_activity_time),
05030 "", mychannel->language, (char *) NULL);
05031 if (!res)
05032 res = ast_waitstream(mychannel, "");
05033 ast_stopstream(mychannel);
05034 res = ast_streamfile(mychannel, "queue-seconds", mychannel->language);
05035 break;
05036
05037 case STATS_TIME:
05038 case STATS_TIME_LOCAL:
05039 wait_interval(myrpt, DLY_TELEM, mychannel);
05040 t = time(NULL);
05041 rpt_localtime(&t, &localtm);
05042
05043 if((localtm.tm_hour >= 0) && (localtm.tm_hour < 12))
05044 p = "rpt/goodmorning";
05045 else if((localtm.tm_hour >= 12) && (localtm.tm_hour < 18))
05046 p = "rpt/goodafternoon";
05047 else
05048 p = "rpt/goodevening";
05049 if (sayfile(mychannel,p) == -1)
05050 {
05051 imdone = 1;
05052 break;
05053 }
05054
05055 if (sayfile(mychannel,"rpt/thetimeis") == -1)
05056 {
05057 imdone = 1;
05058 break;
05059 }
05060
05061 res = ast_say_time(mychannel, t, "", mychannel->language);
05062 if (!res)
05063 res = ast_waitstream(mychannel, "");
05064 ast_stopstream(mychannel);
05065 imdone = 1;
05066 break;
05067 case STATS_VERSION:
05068 p = strstr(tdesc, "version");
05069 if(!p)
05070 break;
05071 if(sscanf(p, "version %30d.%30d", &vmajor, &vminor) != 2)
05072 break;
05073 wait_interval(myrpt, DLY_TELEM, mychannel);
05074
05075 if (sayfile(mychannel,"rpt/version") == -1)
05076 {
05077 imdone = 1;
05078 break;
05079 }
05080 if(!res)
05081 ast_say_number(mychannel, vmajor, "", mychannel->language, (char *) NULL);
05082 if (!res)
05083 res = ast_waitstream(mychannel, "");
05084 ast_stopstream(mychannel);
05085 if (saycharstr(mychannel,".") == -1)
05086 {
05087 imdone = 1;
05088 break;
05089 }
05090 if(!res)
05091 ast_say_number(mychannel, vminor, "", mychannel->language, (char *) NULL);
05092 if (!res){
05093 res = ast_waitstream(mychannel, "");
05094 ast_stopstream(mychannel);
05095 }
05096 else
05097 ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", mychannel->name);
05098 imdone = 1;
05099 break;
05100 case ARB_ALPHA:
05101 wait_interval(myrpt, DLY_TELEM, mychannel);
05102 if(mytele->param)
05103 saycharstr(mychannel, mytele->param);
05104 imdone = 1;
05105 break;
05106 case REV_PATCH:
05107 wait_interval(myrpt, DLY_TELEM, mychannel);
05108 if(mytele->param) {
05109
05110
05111 char *tpl_working, *tpl_current;
05112 char *tmp[100], *myparm;
05113 int looptemp=0,idx=0, dres = 0;
05114
05115
05116 tpl_working = ast_strdup(mytele->param);
05117 myparm = strsep(&tpl_working,",");
05118 tpl_current=strsep(&tpl_working, ":");
05119
05120 while(tpl_current && looptemp < sizeof(tmp)) {
05121 tmp[looptemp]=tpl_current;
05122 looptemp++;
05123 tpl_current=strsep(&tpl_working,":");
05124 }
05125
05126 for(idx=0; idx<looptemp; idx++) {
05127 if(!strcmp(tmp[idx], "PARKED")) {
05128 ast_say_digits(mychannel, atoi(myparm), "", mychannel->language);
05129 } else if(!strcmp(tmp[idx], "NODE")) {
05130 ast_say_digits(mychannel, atoi(myrpt->name), "", mychannel->language);
05131 } else {
05132 dres = ast_streamfile(mychannel, tmp[idx], mychannel->language);
05133 if(!dres) {
05134 dres = ast_waitstream(mychannel, "");
05135 } else {
05136 ast_log(LOG_WARNING, "ast_streamfile of %s failed on %s\n", tmp[idx], mychannel->name);
05137 dres = 0;
05138 }
05139 }
05140 }
05141 ast_free(tpl_working);
05142 }
05143 imdone = 1;
05144 break;
05145 case TEST_TONE:
05146 imdone = 1;
05147 if (myrpt->stopgen) break;
05148 myrpt->stopgen = -1;
05149 if ((res = ast_tonepair_start(mychannel, 1004.0, 0, 99999999, 7200.0)))
05150 {
05151 myrpt->stopgen = 0;
05152 break;
05153 }
05154 while(mychannel->generatordata && (myrpt->stopgen <= 0)) {
05155 if (ast_safe_sleep(mychannel,1)) break;
05156 imdone = 1;
05157 }
05158 myrpt->stopgen = 0;
05159 break;
05160 default:
05161 break;
05162 }
05163 if (!imdone)
05164 {
05165 if (!res)
05166 res = ast_waitstream(mychannel, "");
05167 else {
05168 ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", mychannel->name);
05169 res = 0;
05170 }
05171 }
05172 ast_stopstream(mychannel);
05173 rpt_mutex_lock(&myrpt->lock);
05174 if (mytele->mode == TAILMSG)
05175 {
05176 if (!res)
05177 {
05178 myrpt->tailmessagen++;
05179 if(myrpt->tailmessagen >= myrpt->p.tailmessagemax) myrpt->tailmessagen = 0;
05180 }
05181 else
05182 {
05183 myrpt->tmsgtimer = myrpt->p.tailsquashedtime;
05184 }
05185 }
05186 remque((struct qelem *)mytele);
05187 myrpt->active_telem = NULL;
05188 rpt_mutex_unlock(&myrpt->lock);
05189 ast_free(nodename);
05190 ast_free(ident);
05191 ast_free(mytele);
05192 ast_hangup(mychannel);
05193 #ifdef APP_RPT_LOCK_DEBUG
05194 {
05195 struct lockthread *t;
05196
05197 sleep(5);
05198 ast_mutex_lock(&locklock);
05199 t = get_lockthread(pthread_self());
05200 if (t) memset(t,0,sizeof(struct lockthread));
05201 ast_mutex_unlock(&locklock);
05202 }
05203 #endif
05204 pthread_exit(NULL);
05205 }
05206
05207 static void rpt_telemetry(struct rpt *myrpt,int mode, void *data)
05208 {
05209 struct rpt_tele *tele;
05210 struct rpt_link *mylink = NULL;
05211 int res;
05212 pthread_attr_t attr;
05213 char *v1, *v2;
05214
05215 if(debug > 6)
05216 ast_log(LOG_NOTICE,"mode=%i data=%s\n",mode, (char *)data);
05217
05218 switch(mode)
05219 {
05220 case UNKEY:
05221
05222
05223 v1 = (char *) ast_variable_retrieve(myrpt->cfg, myrpt->name,
05224 "unlinkedct");
05225 v2 = (char *) ast_variable_retrieve(myrpt->cfg, myrpt->name,
05226 "remotect");
05227 if (telem_lookup(myrpt,NULL, myrpt->name, "remotemon") &&
05228 telem_lookup(myrpt,NULL, myrpt->name, "remotetx") &&
05229 telem_lookup(myrpt,NULL, myrpt->name, "cmdmode") &&
05230 (!(v1 && telem_lookup(myrpt,NULL, myrpt->name, v1))) &&
05231 (!(v2 && telem_lookup(myrpt,NULL, myrpt->name, v2)))) return;
05232 break;
05233 case LINKUNKEY:
05234 if (!ast_variable_retrieve(myrpt->cfg, myrpt->name, "linkunkeyct"))
05235 return;
05236 break;
05237 default:
05238 break;
05239 }
05240 tele = ast_malloc(sizeof(struct rpt_tele));
05241 if (!tele)
05242 {
05243 ast_log(LOG_WARNING, "Unable to allocate memory\n");
05244 pthread_exit(NULL);
05245 return;
05246 }
05247
05248 memset((char *)tele,0,sizeof(struct rpt_tele));
05249 tele->rpt = myrpt;
05250 tele->mode = mode;
05251 if (mode == PARROT) tele->parrot = (uintptr_t) data;
05252 else mylink = (struct rpt_link *) data;
05253 rpt_mutex_lock(&myrpt->lock);
05254 if((mode == CONNFAIL) || (mode == REMDISC) || (mode == CONNECTED) ||
05255 (mode == LINKUNKEY)){
05256 memset(&tele->mylink,0,sizeof(struct rpt_link));
05257 if (mylink){
05258 memcpy(&tele->mylink,mylink,sizeof(struct rpt_link));
05259 }
05260 }
05261 else if ((mode == ARB_ALPHA) || (mode == REV_PATCH) || (mode == PLAYBACK)) {
05262 strncpy(tele->param, (char *) data, TELEPARAMSIZE - 1);
05263 tele->param[TELEPARAMSIZE - 1] = 0;
05264 }
05265 if (mode == REMXXX) tele->submode = (intptr_t) data;
05266 insque((struct qelem *)tele, (struct qelem *)myrpt->tele.next);
05267 rpt_mutex_unlock(&myrpt->lock);
05268 pthread_attr_init(&attr);
05269 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
05270 res = ast_pthread_create(&tele->threadid,&attr,rpt_tele_thread,(void *) tele);
05271 if(res < 0){
05272 rpt_mutex_lock(&myrpt->lock);
05273 remque((struct qlem *) tele);
05274 rpt_mutex_unlock(&myrpt->lock);
05275 ast_log(LOG_WARNING, "Could not create telemetry thread: %s",strerror(res));
05276 }
05277 return;
05278 }
05279
05280 static void *rpt_call(void *this)
05281 {
05282 struct dahdi_confinfo ci;
05283 struct rpt *myrpt = (struct rpt *)this;
05284 int res;
05285 int stopped,congstarted,dialtimer,lastcidx,aborted;
05286 struct ast_channel *mychannel,*genchannel;
05287
05288 myrpt->mydtmf = 0;
05289
05290 mychannel = ast_request("DAHDI",AST_FORMAT_SLINEAR,"pseudo",NULL);
05291 if (!mychannel)
05292 {
05293 fprintf(stderr,"rpt:Sorry unable to obtain pseudo channel\n");
05294 pthread_exit(NULL);
05295 }
05296 #ifdef AST_CDR_FLAG_POST_DISABLED
05297 if (mychannel->cdr)
05298 ast_set_flag(mychannel->cdr,AST_CDR_FLAG_POST_DISABLED);
05299 #endif
05300 ci.chan = 0;
05301 ci.confno = myrpt->conf;
05302 #if 0
05303 ci.confmode = DAHDI_CONF_REALANDPSEUDO | DAHDI_CONF_TALKER | DAHDI_CONF_LISTENER
05304 | DAHDI_CONF_PSEUDO_TALKER | DAHDI_CONF_PSEUDO_LISTENER;
05305 #endif
05306 ci.confmode = DAHDI_CONF_CONF | DAHDI_CONF_TALKER | DAHDI_CONF_LISTENER;
05307
05308 if (ioctl(mychannel->fds[0],DAHDI_SETCONF,&ci) == -1)
05309 {
05310 ast_log(LOG_WARNING, "Unable to set conference mode to Announce\n");
05311 ast_hangup(mychannel);
05312 myrpt->callmode = 0;
05313 pthread_exit(NULL);
05314 }
05315
05316 genchannel = ast_request("DAHDI",AST_FORMAT_SLINEAR,"pseudo",NULL);
05317 if (!genchannel)
05318 {
05319 fprintf(stderr,"rpt:Sorry unable to obtain pseudo channel\n");
05320 ast_hangup(mychannel);
05321 pthread_exit(NULL);
05322 }
05323 #ifdef AST_CDR_FLAG_POST_DISABLED
05324 if (genchannel->cdr)
05325 ast_set_flag(genchannel->cdr,AST_CDR_FLAG_POST_DISABLED);
05326 #endif
05327 ci.chan = 0;
05328 ci.confno = myrpt->conf;
05329 ci.confmode = DAHDI_CONF_REALANDPSEUDO | DAHDI_CONF_TALKER | DAHDI_CONF_LISTENER
05330 | DAHDI_CONF_PSEUDO_TALKER | DAHDI_CONF_PSEUDO_LISTENER;
05331
05332 if (ioctl(genchannel->fds[0],DAHDI_SETCONF,&ci) == -1)
05333 {
05334 ast_log(LOG_WARNING, "Unable to set conference mode to Announce\n");
05335 ast_hangup(mychannel);
05336 ast_hangup(genchannel);
05337 myrpt->callmode = 0;
05338 pthread_exit(NULL);
05339 }
05340 if (myrpt->p.tonezone && (tone_zone_set_zone(mychannel->fds[0],myrpt->p.tonezone) == -1))
05341 {
05342 ast_log(LOG_WARNING, "Unable to set tone zone %s\n",myrpt->p.tonezone);
05343 ast_hangup(mychannel);
05344 ast_hangup(genchannel);
05345 myrpt->callmode = 0;
05346 pthread_exit(NULL);
05347 }
05348 if (myrpt->p.tonezone && (tone_zone_set_zone(genchannel->fds[0],myrpt->p.tonezone) == -1))
05349 {
05350 ast_log(LOG_WARNING, "Unable to set tone zone %s\n",myrpt->p.tonezone);
05351 ast_hangup(mychannel);
05352 ast_hangup(genchannel);
05353 myrpt->callmode = 0;
05354 pthread_exit(NULL);
05355 }
05356
05357 if ((!myrpt->patchquiet) && (tone_zone_play_tone(genchannel->fds[0],DAHDI_TONE_DIALTONE) < 0))
05358 {
05359 ast_log(LOG_WARNING, "Cannot start dialtone\n");
05360 ast_hangup(mychannel);
05361 ast_hangup(genchannel);
05362 myrpt->callmode = 0;
05363 pthread_exit(NULL);
05364 }
05365 stopped = 0;
05366 congstarted = 0;
05367 dialtimer = 0;
05368 lastcidx = 0;
05369 myrpt->calldigittimer = 0;
05370 aborted = 0;
05371
05372 while ((myrpt->callmode == 1) || (myrpt->callmode == 4))
05373 {
05374 if((myrpt->patchdialtime)&&(myrpt->callmode == 1)&&(myrpt->cidx != lastcidx)){
05375 dialtimer = 0;
05376 lastcidx = myrpt->cidx;
05377 }
05378
05379 if((myrpt->patchdialtime)&&(dialtimer >= myrpt->patchdialtime)){
05380 if(debug)
05381 ast_log(LOG_NOTICE, "dialtimer %i > patchdialtime %i\n", dialtimer,myrpt->patchdialtime);
05382 rpt_mutex_lock(&myrpt->lock);
05383 aborted = 1;
05384 myrpt->callmode = 0;
05385 rpt_mutex_unlock(&myrpt->lock);
05386 break;
05387 }
05388
05389 if ((!myrpt->patchquiet) && (!stopped) && (myrpt->callmode == 1) && (myrpt->cidx > 0))
05390 {
05391 stopped = 1;
05392
05393 tone_zone_play_tone(genchannel->fds[0],-1);
05394 }
05395 if (myrpt->callmode == 1)
05396 {
05397 if(myrpt->calldigittimer > PATCH_DIALPLAN_TIMEOUT)
05398 {
05399 myrpt->callmode = 2;
05400 break;
05401 }
05402
05403 if (myrpt->calldigittimer)
05404 myrpt->calldigittimer += MSWAIT;
05405 }
05406 if (myrpt->callmode == 4)
05407 {
05408 if(!congstarted){
05409 congstarted = 1;
05410
05411 tone_zone_play_tone(genchannel->fds[0],DAHDI_TONE_CONGESTION);
05412 }
05413 }
05414 res = ast_safe_sleep(mychannel, MSWAIT);
05415 if (res < 0)
05416 {
05417 if(debug)
05418 ast_log(LOG_NOTICE, "ast_safe_sleep=%i\n", res);
05419 ast_hangup(mychannel);
05420 ast_hangup(genchannel);
05421 rpt_mutex_lock(&myrpt->lock);
05422 myrpt->callmode = 0;
05423 rpt_mutex_unlock(&myrpt->lock);
05424 pthread_exit(NULL);
05425 }
05426 dialtimer += MSWAIT;
05427 }
05428
05429 tone_zone_play_tone(genchannel->fds[0],-1);
05430
05431 if (!myrpt->callmode)
05432 {
05433 if(debug)
05434 ast_log(LOG_NOTICE, "callmode==0\n");
05435 ast_hangup(mychannel);
05436 ast_hangup(genchannel);
05437 rpt_mutex_lock(&myrpt->lock);
05438 myrpt->callmode = 0;
05439 myrpt->macropatch=0;
05440 channel_revert(myrpt);
05441 rpt_mutex_unlock(&myrpt->lock);
05442 if((!myrpt->patchquiet) && aborted)
05443 rpt_telemetry(myrpt, TERM, NULL);
05444 pthread_exit(NULL);
05445 }
05446
05447 if (myrpt->p.ourcallerid && *myrpt->p.ourcallerid){
05448 char *name, *loc, *instr;
05449 instr = ast_strdup(myrpt->p.ourcallerid);
05450 if(instr){
05451 ast_callerid_parse(instr, &name, &loc);
05452 if(loc){
05453 if(mychannel->cid.cid_num)
05454 ast_free(mychannel->cid.cid_num);
05455 mychannel->cid.cid_num = ast_strdup(loc);
05456 }
05457 if(name){
05458 if(mychannel->cid.cid_name)
05459 ast_free(mychannel->cid.cid_name);
05460 mychannel->cid.cid_name = ast_strdup(name);
05461 }
05462 ast_free(instr);
05463 }
05464 }
05465
05466 ast_copy_string(mychannel->exten, myrpt->exten, sizeof(mychannel->exten) - 1);
05467 ast_copy_string(mychannel->context, myrpt->patchcontext, sizeof(mychannel->context) - 1);
05468
05469 if (myrpt->p.acctcode)
05470 ast_cdr_setaccount(mychannel,myrpt->p.acctcode);
05471 mychannel->priority = 1;
05472 ast_channel_undefer_dtmf(mychannel);
05473 if (ast_pbx_start(mychannel) < 0)
05474 {
05475 ast_log(LOG_WARNING, "Unable to start PBX!!\n");
05476 ast_hangup(mychannel);
05477 ast_hangup(genchannel);
05478 rpt_mutex_lock(&myrpt->lock);
05479 myrpt->callmode = 0;
05480 rpt_mutex_unlock(&myrpt->lock);
05481 pthread_exit(NULL);
05482 }
05483 usleep(10000);
05484 rpt_mutex_lock(&myrpt->lock);
05485 myrpt->callmode = 3;
05486
05487 ci.chan = 0;
05488 ci.confno = myrpt->conf;
05489 ci.confmode = (myrpt->p.duplex == 2) ? DAHDI_CONF_CONFANNMON :
05490 (DAHDI_CONF_CONF | DAHDI_CONF_LISTENER | DAHDI_CONF_TALKER);
05491
05492 if (ioctl(myrpt->pchannel->fds[0],DAHDI_SETCONF,&ci) == -1)
05493 {
05494 ast_log(LOG_WARNING, "Unable to set conference mode to Announce\n");
05495 ast_hangup(mychannel);
05496 ast_hangup(genchannel);
05497 myrpt->callmode = 0;
05498 pthread_exit(NULL);
05499 }
05500
05501 if (ioctl(mychannel->fds[0],DAHDI_CHANNO,&res) == -1)
05502 {
05503 ast_log(LOG_WARNING, "Unable to get autopatch channel number\n");
05504 ast_hangup(mychannel);
05505 myrpt->callmode = 0;
05506 pthread_exit(NULL);
05507 }
05508 ci.chan = 0;
05509 ci.confno = res;
05510 ci.confmode = DAHDI_CONF_MONITOR;
05511
05512 if (ioctl(myrpt->voxchannel->fds[0],DAHDI_SETCONF,&ci) == -1)
05513 {
05514 ast_log(LOG_WARNING, "Unable to set conference mode to Announce\n");
05515 ast_hangup(mychannel);
05516 myrpt->callmode = 0;
05517 pthread_exit(NULL);
05518 }
05519 while(myrpt->callmode)
05520 {
05521 if ((!mychannel->pbx) && (myrpt->callmode != 4))
05522 {
05523
05524 if(myrpt->patchfarenddisconnect || (myrpt->p.duplex < 2)){
05525 if(debug)ast_log(LOG_NOTICE,"callmode=%i, patchfarenddisconnect=%i, duplex=%i\n",\
05526 myrpt->callmode,myrpt->patchfarenddisconnect,myrpt->p.duplex);
05527 myrpt->callmode = 0;
05528 myrpt->macropatch=0;
05529 if(!myrpt->patchquiet){
05530 rpt_mutex_unlock(&myrpt->lock);
05531 rpt_telemetry(myrpt, TERM, NULL);
05532 rpt_mutex_lock(&myrpt->lock);
05533 }
05534 }
05535 else{
05536 myrpt->callmode = 4;
05537 rpt_mutex_unlock(&myrpt->lock);
05538
05539 tone_zone_play_tone(genchannel->fds[0],DAHDI_TONE_CONGESTION);
05540 rpt_mutex_lock(&myrpt->lock);
05541 }
05542 }
05543 if (myrpt->mydtmf)
05544 {
05545 struct ast_frame wf = {AST_FRAME_DTMF, } ;
05546 wf.subclass = myrpt->mydtmf;
05547 rpt_mutex_unlock(&myrpt->lock);
05548 ast_queue_frame(mychannel,&wf);
05549 #ifdef NEW_ASTERISK
05550 ast_senddigit(genchannel,myrpt->mydtmf,0);
05551 #else
05552 ast_senddigit(genchannel,myrpt->mydtmf);
05553 #endif
05554 rpt_mutex_lock(&myrpt->lock);
05555 myrpt->mydtmf = 0;
05556 }
05557 rpt_mutex_unlock(&myrpt->lock);
05558 usleep(MSWAIT * 1000);
05559 rpt_mutex_lock(&myrpt->lock);
05560 }
05561 if(debug)
05562 ast_log(LOG_NOTICE, "exit channel loop\n");
05563 rpt_mutex_unlock(&myrpt->lock);
05564 tone_zone_play_tone(genchannel->fds[0],-1);
05565 if (mychannel->pbx) ast_softhangup(mychannel,AST_SOFTHANGUP_DEV);
05566 ast_hangup(genchannel);
05567 rpt_mutex_lock(&myrpt->lock);
05568 myrpt->callmode = 0;
05569 myrpt->macropatch=0;
05570 channel_revert(myrpt);
05571 rpt_mutex_unlock(&myrpt->lock);
05572
05573 ci.chan = 0;
05574 ci.confno = myrpt->conf;
05575 ci.confmode = ((myrpt->p.duplex == 2) || (myrpt->p.duplex == 4)) ? DAHDI_CONF_CONFANNMON :
05576 (DAHDI_CONF_CONF | DAHDI_CONF_LISTENER | DAHDI_CONF_TALKER);
05577
05578 if (ioctl(myrpt->pchannel->fds[0],DAHDI_SETCONF,&ci) == -1)
05579 {
05580 ast_log(LOG_WARNING, "Unable to set conference mode to Announce\n");
05581 }
05582 pthread_exit(NULL);
05583 }
05584
05585 static void send_link_dtmf(struct rpt *myrpt,char c)
05586 {
05587 char str[300];
05588 struct ast_frame wf;
05589 struct rpt_link *l;
05590
05591 snprintf(str, sizeof(str), "D %s %s %d %c", myrpt->cmdnode, myrpt->name, ++(myrpt->dtmfidx), c);
05592 wf.frametype = AST_FRAME_TEXT;
05593 wf.subclass = 0;
05594 wf.offset = 0;
05595 wf.mallocd = 0;
05596 wf.datalen = strlen(str) + 1;
05597 wf.samples = 0;
05598 l = myrpt->links.next;
05599
05600 while(l != &myrpt->links)
05601 {
05602 if (l->name[0] == '0')
05603 {
05604 l = l->next;
05605 continue;
05606 }
05607
05608 if (!strcmp(l->name,myrpt->cmdnode))
05609 {
05610 wf.data.ptr = str;
05611 if (l->chan) ast_write(l->chan,&wf);
05612 return;
05613 }
05614 l = l->next;
05615 }
05616 l = myrpt->links.next;
05617
05618 while(l != &myrpt->links)
05619 {
05620 wf.data.ptr = str;
05621 if (l->chan) ast_write(l->chan,&wf);
05622 l = l->next;
05623 }
05624 return;
05625 }
05626
05627 static void send_link_keyquery(struct rpt *myrpt)
05628 {
05629 char str[300];
05630 struct ast_frame wf;
05631 struct rpt_link *l;
05632
05633 rpt_mutex_lock(&myrpt->lock);
05634 memset(myrpt->topkey,0,sizeof(myrpt->topkey));
05635 myrpt->topkeystate = 1;
05636 time(&myrpt->topkeytime);
05637 rpt_mutex_unlock(&myrpt->lock);
05638 snprintf(str, sizeof(str), "K? * %s 0 0", myrpt->name);
05639 wf.frametype = AST_FRAME_TEXT;
05640 wf.subclass = 0;
05641 wf.offset = 0;
05642 wf.mallocd = 0;
05643 wf.datalen = strlen(str) + 1;
05644 wf.samples = 0;
05645 l = myrpt->links.next;
05646
05647 while(l != &myrpt->links)
05648 {
05649 wf.data.ptr = str;
05650 if (l->chan) ast_write(l->chan,&wf);
05651 l = l->next;
05652 }
05653 return;
05654 }
05655
05656
05657
05658 static void send_newkey(struct ast_channel *chan)
05659 {
05660
05661
05662 ast_sendtext(chan,newkeystr);
05663 return;
05664 }
05665
05666
05667
05668
05669
05670
05671
05672
05673
05674
05675
05676
05677
05678 static int connect_link(struct rpt *myrpt, char* node, int mode, int perma)
05679 {
05680 char *val, *s, *s1, *s2, *tele;
05681 char lstr[MAXLINKLIST],*strs[MAXLINKLIST];
05682 char tmp[300], deststr[300] = "",modechange = 0;
05683 char sx[320],*sy;
05684 struct rpt_link *l;
05685 int reconnects = 0;
05686 int i,n;
05687 struct dahdi_confinfo ci;
05688
05689 val = node_lookup(myrpt,node);
05690 if (!val){
05691 if(strlen(node) >= myrpt->longestnode)
05692 return -1;
05693 return 1;
05694 }
05695
05696 if(!strcmp(myrpt->name,node))
05697 return -2;
05698
05699 if(debug > 3){
05700 ast_log(LOG_NOTICE,"Connect attempt to node %s\n", node);
05701 ast_log(LOG_NOTICE,"Mode: %s\n",(mode)?"Transceive":"Monitor");
05702 ast_log(LOG_NOTICE,"Connection type: %s\n",(perma)?"Permalink":"Normal");
05703 }
05704
05705 strncpy(tmp,val,sizeof(tmp) - 1);
05706 s = tmp;
05707 s1 = strsep(&s,",");
05708 if (!strchr(s1,':') && strchr(s1,'/') && strncasecmp(s1, "local/", 6))
05709 {
05710 sy = strchr(s1,'/');
05711 *sy = 0;
05712 sprintf(sx,"%s:4569/%s",s1,sy + 1);
05713 s1 = sx;
05714 }
05715 s2 = strsep(&s,",");
05716 rpt_mutex_lock(&myrpt->lock);
05717 l = myrpt->links.next;
05718
05719 while(l != &myrpt->links){
05720 if (l->name[0] == '0')
05721 {
05722 l = l->next;
05723 continue;
05724 }
05725
05726 if (!strcmp(l->name, node))
05727 break;
05728 l = l->next;
05729 }
05730
05731 if (l != &myrpt->links){
05732
05733 if ((l->mode) || (!l->chan)) {
05734 rpt_mutex_unlock(&myrpt->lock);
05735 return 2;
05736 }
05737 reconnects = l->reconnects;
05738 rpt_mutex_unlock(&myrpt->lock);
05739 if (l->chan) ast_softhangup(l->chan, AST_SOFTHANGUP_DEV);
05740 l->retries = l->max_retries + 1;
05741 l->disced = 2;
05742 modechange = 1;
05743 } else
05744 {
05745 __mklinklist(myrpt,NULL,lstr);
05746 rpt_mutex_unlock(&myrpt->lock);
05747 n = finddelim(lstr,strs,MAXLINKLIST);
05748 for(i = 0; i < n; i++)
05749 {
05750 if ((*strs[i] < '0') ||
05751 (*strs[i] > '9')) strs[i]++;
05752 if (!strcmp(strs[i],node))
05753 {
05754 return 2;
05755 }
05756 }
05757 }
05758 strncpy(myrpt->lastlinknode,node,MAXNODESTR - 1);
05759
05760 l = ast_malloc(sizeof(struct rpt_link));
05761 if (!l)
05762 {
05763 ast_log(LOG_WARNING, "Unable to malloc\n");
05764 return -1;
05765 }
05766
05767 memset((char *)l,0,sizeof(struct rpt_link));
05768 l->mode = mode;
05769 l->outbound = 1;
05770 l->thisconnected = 0;
05771 voxinit_link(l,1);
05772 strncpy(l->name, node, MAXNODESTR - 1);
05773 l->isremote = (s && ast_true(s));
05774 if (modechange) l->connected = 1;
05775 l->hasconnected = l->perma = perma;
05776 #ifdef ALLOW_LOCAL_CHANNELS
05777 if ((strncasecmp(s1,"iax2/", 5) == 0) || (strncasecmp(s1, "local/", 6) == 0))
05778 strncpy(deststr, s1, sizeof(deststr));
05779 else
05780 snprintf(deststr, sizeof(deststr), "IAX2/%s", s1);
05781 #else
05782 snprintf(deststr, sizeof(deststr), "IAX2/%s", s1);
05783 #endif
05784 tele = strchr(deststr, '/');
05785 if (!tele){
05786 ast_log(LOG_WARNING,"link3:Dial number (%s) must be in format tech/number\n",deststr);
05787 ast_free(l);
05788 return -1;
05789 }
05790 *tele++ = 0;
05791 l->chan = ast_request(deststr, AST_FORMAT_SLINEAR, tele,NULL);
05792 if (l->chan){
05793 ast_set_read_format(l->chan, AST_FORMAT_SLINEAR);
05794 ast_set_write_format(l->chan, AST_FORMAT_SLINEAR);
05795 #ifdef AST_CDR_FLAG_POST_DISABLED
05796 if (l->chan->cdr)
05797 ast_set_flag(l->chan->cdr,AST_CDR_FLAG_POST_DISABLED);
05798 #endif
05799 #ifndef NEW_ASTERISK
05800 l->chan->whentohangup = 0;
05801 #endif
05802 l->chan->appl = "Apprpt";
05803 l->chan->data = "(Remote Rx)";
05804 if (debug > 3)
05805 ast_log(LOG_NOTICE, "rpt (remote) initiating call to %s/%s on %s\n",
05806 deststr, tele, l->chan->name);
05807 if(l->chan->cid.cid_num)
05808 ast_free(l->chan->cid.cid_num);
05809 l->chan->cid.cid_num = ast_strdup(myrpt->name);
05810 ast_call(l->chan,tele,999);
05811 }
05812 else {
05813 if(debug > 3)
05814 ast_log(LOG_NOTICE, "Unable to place call to %s/%s on %s\n",
05815 deststr,tele,l->chan->name);
05816 if (myrpt->p.archivedir)
05817 {
05818 char str[100];
05819 sprintf(str,"LINKFAIL,%s",l->name);
05820 donodelog(myrpt,str);
05821 }
05822 ast_free(l);
05823 return -1;
05824 }
05825
05826 l->pchan = ast_request("DAHDI",AST_FORMAT_SLINEAR,"pseudo",NULL);
05827 if (!l->pchan){
05828 ast_log(LOG_WARNING,"rpt connect: Sorry unable to obtain pseudo channel\n");
05829 ast_hangup(l->chan);
05830 ast_free(l);
05831 return -1;
05832 }
05833 ast_set_read_format(l->pchan, AST_FORMAT_SLINEAR);
05834 ast_set_write_format(l->pchan, AST_FORMAT_SLINEAR);
05835 #ifdef AST_CDR_FLAG_POST_DISABLED
05836 if (l->pchan->cdr)
05837 ast_set_flag(l->pchan->cdr,AST_CDR_FLAG_POST_DISABLED);
05838 #endif
05839
05840 ci.chan = 0;
05841 ci.confno = myrpt->conf;
05842 ci.confmode = DAHDI_CONF_CONF | DAHDI_CONF_LISTENER | DAHDI_CONF_TALKER;
05843
05844 if (ioctl(l->pchan->fds[0], DAHDI_SETCONF, &ci) == -1)
05845 {
05846 ast_log(LOG_WARNING, "Unable to set conference mode to Announce\n");
05847 ast_hangup(l->chan);
05848 ast_hangup(l->pchan);
05849 ast_free(l);
05850 return -1;
05851 }
05852 rpt_mutex_lock(&myrpt->lock);
05853 l->reconnects = reconnects;
05854
05855 l->max_retries = MAX_RETRIES;
05856 if (perma)
05857 l->max_retries = MAX_RETRIES_PERM;
05858 if (l->isremote) l->retries = l->max_retries + 1;
05859 insque((struct qelem *)l,(struct qelem *)myrpt->links.next);
05860 __kickshort(myrpt);
05861 rpt_mutex_unlock(&myrpt->lock);
05862 if (!l->phonemode) send_newkey(l->chan);
05863 return 0;
05864 }
05865
05866
05867
05868
05869
05870
05871
05872 static int function_ilink(struct rpt *myrpt, char *param, char *digits, int command_source, struct rpt_link *mylink)
05873 {
05874
05875 char *val, *s, *s1, *s2;
05876 char tmp[300];
05877 char digitbuf[MAXNODESTR],*strs[MAXLINKLIST];
05878 char mode,perma;
05879 char sx[320],*sy;
05880 struct rpt_link *l;
05881 int i,r;
05882
05883 if(!param)
05884 return DC_ERROR;
05885
05886
05887 if (myrpt->p.s[myrpt->p.sysstate_cur].txdisable || myrpt->p.s[myrpt->p.sysstate_cur].linkfundisable )
05888 return DC_ERROR;
05889
05890 strncpy(digitbuf,digits,MAXNODESTR - 1);
05891
05892 if(debug > 6)
05893 printf("@@@@ ilink param = %s, digitbuf = %s\n", (param)? param : "(null)", digitbuf);
05894
05895 switch(myatoi(param)){
05896 case 11:
05897 case 1:
05898 if ((digitbuf[0] == '0') && (myrpt->lastlinknode[0]))
05899 strcpy(digitbuf,myrpt->lastlinknode);
05900 val = node_lookup(myrpt,digitbuf);
05901 if (!val){
05902 if(strlen(digitbuf) >= myrpt->longestnode)
05903 return DC_ERROR;
05904 break;
05905 }
05906 strncpy(tmp,val,sizeof(tmp) - 1);
05907 s = tmp;
05908 s1 = strsep(&s,",");
05909 if (!strchr(s1,':') && strchr(s1,'/') && strncasecmp(s1, "local/", 6))
05910 {
05911 sy = strchr(s1,'/');
05912 *sy = 0;
05913 sprintf(sx,"%s:4569/%s",s1,sy + 1);
05914 s1 = sx;
05915 }
05916 s2 = strsep(&s,",");
05917 rpt_mutex_lock(&myrpt->lock);
05918 l = myrpt->links.next;
05919
05920 while(l != &myrpt->links){
05921 if (l->name[0] == '0')
05922 {
05923 l = l->next;
05924 continue;
05925 }
05926
05927 if (!strcmp(l->name, digitbuf))
05928 break;
05929 l = l->next;
05930 }
05931 if (l != &myrpt->links){
05932 struct ast_frame wf;
05933
05934
05935 if ((myatoi(param) < 10) &&
05936 (l->max_retries > MAX_RETRIES))
05937 {
05938 rpt_mutex_unlock(&myrpt->lock);
05939 return DC_COMPLETE;
05940 }
05941 strncpy(myrpt->lastlinknode,digitbuf,MAXNODESTR - 1);
05942 l->retries = l->max_retries + 1;
05943 l->disced = 1;
05944 rpt_mutex_unlock(&myrpt->lock);
05945 wf.frametype = AST_FRAME_TEXT;
05946 wf.subclass = 0;
05947 wf.offset = 0;
05948 wf.mallocd = 0;
05949 wf.datalen = strlen(discstr) + 1;
05950 wf.samples = 0;
05951 wf.data.ptr = discstr;
05952 if (l->chan)
05953 {
05954 ast_write(l->chan,&wf);
05955 if (ast_safe_sleep(l->chan,250) == -1) return DC_ERROR;
05956 ast_softhangup(l->chan,AST_SOFTHANGUP_DEV);
05957 }
05958 rpt_telemetry(myrpt, COMPLETE, NULL);
05959 return DC_COMPLETE;
05960 }
05961 rpt_mutex_unlock(&myrpt->lock);
05962 return DC_COMPLETE;
05963 case 2:
05964 case 3:
05965 case 12:
05966 case 13:
05967 if ((digitbuf[0] == '0') && (myrpt->lastlinknode[0]))
05968 strcpy(digitbuf,myrpt->lastlinknode);
05969
05970 perma = (atoi(param) > 10) ? 1 : 0;
05971 mode = (atoi(param) & 1) ? 1 : 0;
05972 r = connect_link(myrpt, digitbuf, mode, perma);
05973 switch(r){
05974 case -2:
05975 return DC_COMPLETE;
05976
05977 case 0:
05978 rpt_telemetry(myrpt, COMPLETE, NULL);
05979 return DC_COMPLETE;
05980
05981 case 1:
05982 break;
05983
05984 case 2:
05985 rpt_telemetry(myrpt, REMALREADY, NULL);
05986 return DC_COMPLETE;
05987
05988 default:
05989 rpt_telemetry(myrpt, CONNFAIL, NULL);
05990 return DC_COMPLETE;
05991 }
05992 break;
05993
05994 case 4:
05995
05996
05997 if (((command_source != SOURCE_RPT) &&
05998 (command_source != SOURCE_PHONE) &&
05999 (command_source != SOURCE_ALT) &&
06000 (command_source != SOURCE_DPHONE)) ||
06001 (myrpt->links.next == &myrpt->links))
06002 return DC_COMPLETE;
06003
06004
06005 if ((myrpt->cmdnode[0]) || (!strcmp(myrpt->name, digitbuf))){
06006
06007 rpt_telemetry(myrpt, REMALREADY, NULL);
06008 return DC_COMPLETE;
06009 }
06010 if ((digitbuf[0] == '0') && (myrpt->lastlinknode[0]))
06011 strcpy(digitbuf,myrpt->lastlinknode);
06012
06013 val = node_lookup(myrpt,digitbuf);
06014 if (!val){
06015 if(strlen(digitbuf) >= myrpt->longestnode)
06016 return DC_ERROR;
06017 break;
06018
06019 }
06020 rpt_mutex_lock(&myrpt->lock);
06021 strcpy(myrpt->lastlinknode,digitbuf);
06022 strncpy(myrpt->cmdnode, digitbuf, sizeof(myrpt->cmdnode) - 1);
06023 rpt_mutex_unlock(&myrpt->lock);
06024 rpt_telemetry(myrpt, REMGO, NULL);
06025 return DC_COMPLETE;
06026
06027 case 5:
06028 rpt_telemetry(myrpt, STATUS, NULL);
06029 return DC_COMPLETE;
06030
06031 case 15:
06032 rpt_telemetry(myrpt, FULLSTATUS, NULL);
06033 return DC_COMPLETE;
06034
06035
06036 case 6:
06037 rpt_mutex_lock(&myrpt->lock);
06038 myrpt->savednodes[0] = 0;
06039 l = myrpt->links.next;
06040
06041 while(l != &myrpt->links){
06042 struct ast_frame wf;
06043 if (l->name[0] == '0')
06044 {
06045 l = l->next;
06046 continue;
06047 }
06048
06049 sprintf(tmp,"%c%c%s",(l->mode) ? 'X' : 'M',(l->perma) ? 'P':'T',l->name);
06050 if(strlen(tmp) + strlen(myrpt->savednodes) + 1 < MAXNODESTR){
06051 if(myrpt->savednodes[0])
06052 strcat(myrpt->savednodes, ",");
06053 strcat(myrpt->savednodes, tmp);
06054 }
06055 l->retries = l->max_retries + 1;
06056 l->disced = 2;
06057 rpt_mutex_unlock(&myrpt->lock);
06058
06059
06060 wf.frametype = AST_FRAME_TEXT;
06061 wf.subclass = 0;
06062 wf.offset = 0;
06063 wf.mallocd = 0;
06064 wf.datalen = strlen(discstr) + 1;
06065 wf.samples = 0;
06066 wf.data.ptr = discstr;
06067 if (l->chan)
06068 {
06069 ast_write(l->chan,&wf);
06070 ast_safe_sleep(l->chan,250);
06071 ast_softhangup(l->chan,AST_SOFTHANGUP_DEV);
06072 }
06073 rpt_mutex_lock(&myrpt->lock);
06074 l = l->next;
06075 }
06076 rpt_mutex_unlock(&myrpt->lock);
06077 if(debug > 3)
06078 ast_log(LOG_NOTICE,"Nodes disconnected: %s\n",myrpt->savednodes);
06079 rpt_telemetry(myrpt, COMPLETE, NULL);
06080 return DC_COMPLETE;
06081
06082 case 7:
06083 rpt_telemetry(myrpt, LASTNODEKEY, NULL);
06084 break;
06085
06086
06087 #ifdef _MDC_DECODE_H_
06088 case 8:
06089 myrpt->lastunit = 0xd00d;
06090 mdc1200_notify(myrpt,NULL,myrpt->lastunit);
06091 mdc1200_send(myrpt,myrpt->lastunit);
06092 break;
06093 #endif
06094
06095 case 16:
06096 strcpy(tmp, myrpt->savednodes);
06097 finddelim(tmp, strs, MAXLINKLIST);
06098 for(i = 0; tmp[0] && strs[i] != NULL && i < MAXLINKLIST; i++){
06099 s1 = strs[i];
06100 mode = (s1[0] == 'X') ? 1 : 0;
06101 perma = (s1[1] == 'P') ? 1 : 0;
06102 connect_link(myrpt, s1 + 2, mode, perma);
06103 }
06104 rpt_telemetry(myrpt, COMPLETE, NULL);
06105 break;
06106
06107 case 200:
06108 case 201:
06109 case 202:
06110 case 203:
06111 case 204:
06112 case 205:
06113 case 206:
06114 case 207:
06115 case 208:
06116 case 209:
06117 case 210:
06118 case 211:
06119 case 212:
06120 case 213:
06121 case 214:
06122 case 215:
06123 if (((myrpt->p.propagate_dtmf) &&
06124 (command_source == SOURCE_LNK)) ||
06125 ((myrpt->p.propagate_phonedtmf) &&
06126 ((command_source == SOURCE_PHONE) ||
06127 (command_source == SOURCE_ALT) ||
06128 (command_source == SOURCE_DPHONE))))
06129 do_dtmf_local(myrpt,
06130 remdtmfstr[myatoi(param) - 200]);
06131 default:
06132 return DC_ERROR;
06133
06134 }
06135
06136 return DC_INDETERMINATE;
06137 }
06138
06139
06140
06141
06142
06143 static int function_autopatchup(struct rpt *myrpt, char *param, char *digitbuf, int command_source, struct rpt_link *mylink)
06144 {
06145 pthread_attr_t attr;
06146 int i, idx, paramlength;
06147 char *lparam;
06148 char *value = NULL;
06149 char *paramlist[20];
06150
06151 static char *keywords[] = {
06152 "context",
06153 "dialtime",
06154 "farenddisconnect",
06155 "noct",
06156 "quiet",
06157 NULL
06158 };
06159
06160 if (myrpt->p.s[myrpt->p.sysstate_cur].txdisable || myrpt->p.s[myrpt->p.sysstate_cur].autopatchdisable)
06161 return DC_ERROR;
06162
06163 if(debug)
06164 printf("@@@@ Autopatch up\n");
06165
06166 if(!myrpt->callmode){
06167
06168 myrpt->patchnoct = 0;
06169 myrpt->patchdialtime = 0;
06170 myrpt->patchfarenddisconnect = 0;
06171 myrpt->patchquiet = 0;
06172 strncpy(myrpt->patchcontext, myrpt->p.ourcontext, MAXPATCHCONTEXT);
06173
06174 if(param){
06175
06176 lparam = ast_strdup(param);
06177 if(!lparam){
06178 ast_log(LOG_ERROR,"App_rpt out of memory on line %d\n",__LINE__);
06179 return DC_ERROR;
06180 }
06181 paramlength = finddelim(lparam, paramlist, 20);
06182 for(i = 0; i < paramlength; i++){
06183 idx = matchkeyword(paramlist[i], &value, keywords);
06184 if(value)
06185 value = skipchars(value, "= ");
06186 switch(idx){
06187
06188 case 1:
06189 strncpy(myrpt->patchcontext, value, MAXPATCHCONTEXT - 1) ;
06190 break;
06191
06192 case 2:
06193 myrpt->patchdialtime = atoi(value);
06194 break;
06195
06196 case 3:
06197 myrpt->patchfarenddisconnect = atoi(value);
06198 break;
06199
06200 case 4:
06201 myrpt->patchnoct = atoi(value);
06202 break;
06203
06204 case 5:
06205 myrpt->patchquiet = atoi(value);
06206 break;
06207
06208 default:
06209 break;
06210 }
06211 }
06212 ast_free(lparam);
06213 }
06214 }
06215
06216 rpt_mutex_lock(&myrpt->lock);
06217
06218
06219
06220 if ((myrpt->callmode == 2) || (myrpt->callmode == 3)){
06221 myrpt->mydtmf = myrpt->p.endchar;
06222 }
06223 if (myrpt->callmode){
06224 rpt_mutex_unlock(&myrpt->lock);
06225 return DC_COMPLETE;
06226 }
06227 myrpt->callmode = 1;
06228 myrpt->cidx = 0;
06229 myrpt->exten[myrpt->cidx] = 0;
06230 rpt_mutex_unlock(&myrpt->lock);
06231 pthread_attr_init(&attr);
06232 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
06233 ast_pthread_create(&myrpt->rpt_call_thread,&attr,rpt_call,(void *) myrpt);
06234 return DC_COMPLETE;
06235 }
06236
06237
06238
06239
06240
06241 static int function_autopatchdn(struct rpt *myrpt, char *param, char *digitbuf, int command_source, struct rpt_link *mylink)
06242 {
06243 if (myrpt->p.s[myrpt->p.sysstate_cur].txdisable || myrpt->p.s[myrpt->p.sysstate_cur].autopatchdisable)
06244 return DC_ERROR;
06245
06246 if(debug)
06247 printf("@@@@ Autopatch down\n");
06248
06249 rpt_mutex_lock(&myrpt->lock);
06250
06251 myrpt->macropatch=0;
06252
06253 if (!myrpt->callmode){
06254 rpt_mutex_unlock(&myrpt->lock);
06255 return DC_COMPLETE;
06256 }
06257
06258 myrpt->callmode = 0;
06259 channel_revert(myrpt);
06260 rpt_mutex_unlock(&myrpt->lock);
06261 rpt_telemetry(myrpt, TERM, NULL);
06262 return DC_COMPLETE;
06263 }
06264
06265
06266
06267
06268
06269 static int function_status(struct rpt *myrpt, char *param, char *digitbuf, int command_source, struct rpt_link *mylink)
06270 {
06271
06272 if (!param)
06273 return DC_ERROR;
06274
06275 if ((myrpt->p.s[myrpt->p.sysstate_cur].txdisable) || (myrpt->p.s[myrpt->p.sysstate_cur].userfundisable))
06276 return DC_ERROR;
06277
06278 if(debug)
06279 printf("@@@@ status param = %s, digitbuf = %s\n", (param)? param : "(null)", digitbuf);
06280
06281 switch(myatoi(param)){
06282 case 1:
06283 rpt_telemetry(myrpt, ID1, NULL);
06284 return DC_COMPLETE;
06285 case 2:
06286 rpt_telemetry(myrpt, STATS_TIME, NULL);
06287 return DC_COMPLETE;
06288 case 3:
06289 rpt_telemetry(myrpt, STATS_VERSION, NULL);
06290 return DC_COMPLETE;
06291 case 11:
06292 rpt_telemetry(myrpt, ID , NULL);
06293 return DC_COMPLETE;
06294 case 12:
06295 rpt_telemetry(myrpt, STATS_TIME_LOCAL, NULL);
06296 return DC_COMPLETE;
06297 default:
06298 return DC_ERROR;
06299 }
06300 return DC_INDETERMINATE;
06301 }
06302
06303
06304
06305 static int function_macro(struct rpt *myrpt, char *param, char *digitbuf, int command_source, struct rpt_link *mylink)
06306 {
06307 char *val;
06308 int i;
06309 if (myrpt->remote)
06310 return DC_ERROR;
06311
06312 if(debug)
06313 printf("@@@@ macro-oni param = %s, digitbuf = %s\n", (param)? param : "(null)", digitbuf);
06314
06315 if(strlen(digitbuf) < 1)
06316 return DC_INDETERMINATE;
06317
06318 for(i = 0 ; i < digitbuf[i] ; i++) {
06319 if((digitbuf[i] < '0') || (digitbuf[i] > '9'))
06320 return DC_ERROR;
06321 }
06322
06323 if (*digitbuf == '0') val = myrpt->p.startupmacro;
06324 else val = (char *) ast_variable_retrieve(myrpt->cfg, myrpt->p.macro, digitbuf);
06325
06326 if (!val){
06327 if (strlen(digitbuf) < myrpt->macro_longest)
06328 return DC_INDETERMINATE;
06329 rpt_telemetry(myrpt, MACRO_NOTFOUND, NULL);
06330 return DC_COMPLETE;
06331 }
06332 rpt_mutex_lock(&myrpt->lock);
06333 if ((MAXMACRO - strlen(myrpt->macrobuf)) < strlen(val))
06334 {
06335 rpt_mutex_unlock(&myrpt->lock);
06336 rpt_telemetry(myrpt, MACRO_BUSY, NULL);
06337 return DC_ERROR;
06338 }
06339 myrpt->macrotimer = MACROTIME;
06340 strncat(myrpt->macrobuf,val,MAXMACRO - 1);
06341 rpt_mutex_unlock(&myrpt->lock);
06342 return DC_COMPLETE;
06343 }
06344
06345
06346
06347
06348
06349 static int function_playback(struct rpt *myrpt, char *param, char *digitbuf, int command_source, struct rpt_link *mylink)
06350 {
06351
06352 if (myrpt->remote)
06353 return DC_ERROR;
06354
06355 if(debug)
06356 printf("@@@@ playback param = %s, digitbuf = %s\n", (param)? param : "(null)", digitbuf);
06357
06358 if (ast_fileexists(param,NULL,myrpt->rxchannel->language) <= 0)
06359 return DC_ERROR;
06360
06361 rpt_telemetry(myrpt,PLAYBACK,param);
06362 return DC_COMPLETE;
06363 }
06364
06365
06366
06367
06368
06369 static int function_cop(struct rpt *myrpt, char *param, char *digitbuf, int command_source, struct rpt_link *mylink)
06370 {
06371 char string[16];
06372 int res;
06373
06374 int i, r;
06375
06376 if(!param)
06377 return DC_ERROR;
06378
06379 switch(myatoi(param)){
06380 case 1:
06381 res = system("killall -9 asterisk");
06382 return DC_COMPLETE;
06383
06384 case 2:
06385 myrpt->p.s[myrpt->p.sysstate_cur].txdisable = 0;
06386 rpt_telemetry(myrpt, ARB_ALPHA, (void *) "RPTENA");
06387 return DC_COMPLETE;
06388
06389 case 3:
06390 myrpt->p.s[myrpt->p.sysstate_cur].txdisable = 1;
06391 return DC_COMPLETE;
06392
06393 case 4:
06394 if (myrpt->stopgen < 0)
06395 {
06396 myrpt->stopgen = 1;
06397 }
06398 else
06399 {
06400 myrpt->stopgen = 0;
06401 rpt_telemetry(myrpt, TEST_TONE, NULL);
06402 }
06403 return DC_COMPLETE;
06404
06405 case 5:
06406 myrpt->disgorgetime = time(NULL) + 10;
06407 return DC_COMPLETE;
06408
06409 case 6:
06410 if (command_source != SOURCE_PHONE) return DC_INDETERMINATE;
06411 return DC_DOKEY;
06412
06413
06414 case 7:
06415 myrpt->p.s[myrpt->p.sysstate_cur].totdisable = 0;
06416 rpt_telemetry(myrpt, ARB_ALPHA, (void *) "TOTENA");
06417 return DC_COMPLETE;
06418
06419 case 8:
06420 myrpt->p.s[myrpt->p.sysstate_cur].totdisable = 1;
06421 rpt_telemetry(myrpt, ARB_ALPHA, (void *) "TOTDIS");
06422 return DC_COMPLETE;
06423
06424 case 9:
06425 myrpt->p.s[myrpt->p.sysstate_cur].autopatchdisable = 0;
06426 rpt_telemetry(myrpt, ARB_ALPHA, (void *) "APENA");
06427 return DC_COMPLETE;
06428
06429 case 10:
06430 myrpt->p.s[myrpt->p.sysstate_cur].autopatchdisable = 1;
06431 rpt_telemetry(myrpt, ARB_ALPHA, (void *) "APDIS");
06432 return DC_COMPLETE;
06433
06434 case 11:
06435 myrpt->p.s[myrpt->p.sysstate_cur].linkfundisable = 0;
06436 rpt_telemetry(myrpt, ARB_ALPHA, (void *) "LNKENA");
06437 return DC_COMPLETE;
06438
06439 case 12:
06440 myrpt->p.s[myrpt->p.sysstate_cur].linkfundisable = 1;
06441 rpt_telemetry(myrpt, ARB_ALPHA, (void *) "LNKDIS");
06442 return DC_COMPLETE;
06443
06444 case 13:
06445 string[0] = string[1] = 'S';
06446 string[2] = myrpt->p.sysstate_cur + '0';
06447 string[3] = '\0';
06448 rpt_telemetry(myrpt, ARB_ALPHA, (void *) string);
06449 return DC_COMPLETE;
06450
06451 case 14:
06452 if(strlen(digitbuf) == 0)
06453 break;
06454 if((digitbuf[0] < '0') || (digitbuf[0] > '9'))
06455 return DC_ERROR;
06456 myrpt->p.sysstate_cur = digitbuf[0] - '0';
06457 string[0] = string[1] = 'S';
06458 string[2] = myrpt->p.sysstate_cur + '0';
06459 string[3] = '\0';
06460 rpt_telemetry(myrpt, ARB_ALPHA, (void *) string);
06461 return DC_COMPLETE;
06462
06463 case 15:
06464 myrpt->p.s[myrpt->p.sysstate_cur].schedulerdisable = 0;
06465 rpt_telemetry(myrpt, ARB_ALPHA, (void *) "SKENA");
06466 return DC_COMPLETE;
06467
06468 case 16:
06469 myrpt->p.s[myrpt->p.sysstate_cur].schedulerdisable = 1;
06470 rpt_telemetry(myrpt, ARB_ALPHA, (void *) "SKDIS");
06471 return DC_COMPLETE;
06472
06473 case 17:
06474 myrpt->p.s[myrpt->p.sysstate_cur].userfundisable = 0;
06475 rpt_telemetry(myrpt, ARB_ALPHA, (void *) "UFENA");
06476 return DC_COMPLETE;
06477
06478 case 18:
06479 myrpt->p.s[myrpt->p.sysstate_cur].userfundisable = 1;
06480 rpt_telemetry(myrpt, ARB_ALPHA, (void *) "UFDIS");
06481 return DC_COMPLETE;
06482
06483 case 19:
06484 myrpt->p.s[myrpt->p.sysstate_cur].alternatetail = 1;
06485 rpt_telemetry(myrpt, ARB_ALPHA, (void *) "ATENA");
06486 return DC_COMPLETE;
06487
06488 case 20:
06489 myrpt->p.s[myrpt->p.sysstate_cur].alternatetail = 0;
06490 rpt_telemetry(myrpt, ARB_ALPHA, (void *) "ATDIS");
06491 return DC_COMPLETE;
06492
06493 case 21:
06494 birdbath(myrpt);
06495 if (myrpt->p.parrotmode < 2)
06496 {
06497 myrpt->p.parrotmode = 0;
06498 rpt_telemetry(myrpt,COMPLETE,NULL);
06499 return DC_COMPLETE;
06500 }
06501 break;
06502
06503 case 22:
06504 birdbath(myrpt);
06505 if (myrpt->p.parrotmode < 2)
06506 {
06507 myrpt->p.parrotmode = 1;
06508 rpt_telemetry(myrpt,COMPLETE,NULL);
06509 return DC_COMPLETE;
06510 }
06511 break;
06512 case 23:
06513 birdbath(myrpt);
06514 rpt_telemetry(myrpt,COMPLETE,NULL);
06515 return DC_COMPLETE;
06516 case 24:
06517 flush_telem(myrpt);
06518 rpt_telemetry(myrpt,COMPLETE,NULL);
06519 return DC_COMPLETE;
06520 case 25:
06521 send_link_keyquery(myrpt);
06522 myrpt->topkeylong = 0;
06523 rpt_telemetry(myrpt,COMPLETE,NULL);
06524 return DC_COMPLETE;
06525 case 26:
06526 send_link_keyquery(myrpt);
06527 myrpt->topkeylong = 1;
06528 rpt_telemetry(myrpt,COMPLETE,NULL);
06529 return DC_COMPLETE;
06530
06531 case 30:
06532
06533 if(strlen(digitbuf) < 2)
06534 break;
06535
06536 for(i = 0 ; i < 2 ; i++){
06537 if((digitbuf[i] < '0') || (digitbuf[i] > '9'))
06538 return DC_ERROR;
06539 }
06540
06541 r = retreive_memory(myrpt, digitbuf);
06542 if (r < 0){
06543 rpt_telemetry(myrpt,MEMNOTFOUND,NULL);
06544 return DC_COMPLETE;
06545 }
06546 if (r > 0){
06547 return DC_ERROR;
06548 }
06549 if (setrem(myrpt) == -1) return DC_ERROR;
06550 return DC_COMPLETE;
06551
06552 case 31:
06553
06554
06555 if(strlen(digitbuf) < 2)
06556 break;
06557
06558 for(i = 0 ; i < 2 ; i++){
06559 if((digitbuf[i] < '0') || (digitbuf[i] > '9'))
06560 return DC_ERROR;
06561 }
06562 channel_steer(myrpt,digitbuf);
06563 return DC_COMPLETE;
06564
06565 case 32:
06566 i = strlen(digitbuf);
06567 if(!i){
06568 if(debug > 3)
06569 ast_log(LOG_NOTICE,"Padtest entered");
06570 myrpt->inpadtest = 1;
06571 }
06572 else{
06573 if(debug > 3)
06574 ast_log(LOG_NOTICE,"Padtest len= %d digits=%s",i,digitbuf);
06575 if(digitbuf[i-1] != myrpt->p.endchar)
06576 break;
06577 rpt_telemetry(myrpt, ARB_ALPHA, digitbuf);
06578 myrpt->inpadtest = 0;
06579 if(debug > 3)
06580 ast_log(LOG_NOTICE,"Padtest exited");
06581 return DC_COMPLETE;
06582 }
06583 }
06584 return DC_INDETERMINATE;
06585 }
06586
06587
06588
06589 static int collect_function_digits(struct rpt *myrpt, char *digits,
06590 int command_source, struct rpt_link *mylink)
06591 {
06592 int i,rv;
06593 char *stringp,*action,*param,*functiondigits;
06594 char function_table_name[30] = "";
06595 char workstring[200];
06596
06597 struct ast_variable *vp;
06598
06599 if (debug > 6) ast_log(LOG_NOTICE,"digits=%s source=%d\n",digits, command_source);
06600
06601
06602
06603
06604 if (command_source == SOURCE_DPHONE) {
06605 if (!myrpt->p.dphone_functions) return DC_INDETERMINATE;
06606 strncpy(function_table_name, myrpt->p.dphone_functions, sizeof(function_table_name) - 1);
06607 }
06608 else if (command_source == SOURCE_ALT) {
06609 if (!myrpt->p.alt_functions) return DC_INDETERMINATE;
06610 strncpy(function_table_name, myrpt->p.alt_functions, sizeof(function_table_name) - 1);
06611 }
06612 else if (command_source == SOURCE_PHONE) {
06613 if (!myrpt->p.phone_functions) return DC_INDETERMINATE;
06614 strncpy(function_table_name, myrpt->p.phone_functions, sizeof(function_table_name) - 1);
06615 }
06616 else if (command_source == SOURCE_LNK)
06617 strncpy(function_table_name, myrpt->p.link_functions, sizeof(function_table_name) - 1);
06618 else
06619 strncpy(function_table_name, myrpt->p.functions, sizeof(function_table_name) - 1);
06620
06621 vp = ast_variable_browse(myrpt->cfg, function_table_name);
06622 while(vp) {
06623 if(!strncasecmp(vp->name, digits, strlen(vp->name)))
06624 break;
06625 vp = vp->next;
06626 }
06627
06628 if(!vp) {
06629 int n;
06630
06631 n = myrpt->longestfunc;
06632 if (command_source == SOURCE_LNK) n = myrpt->link_longestfunc;
06633 else
06634 if (command_source == SOURCE_PHONE) n = myrpt->phone_longestfunc;
06635 else
06636 if (command_source == SOURCE_ALT) n = myrpt->alt_longestfunc;
06637 else
06638 if (command_source == SOURCE_DPHONE) n = myrpt->dphone_longestfunc;
06639
06640 if(strlen(digits) >= n)
06641 return DC_ERROR;
06642 else
06643 return DC_INDETERMINATE;
06644 }
06645
06646 strncpy(workstring, vp->value, sizeof(workstring) - 1 );
06647 stringp = workstring;
06648 action = strsep(&stringp, ",");
06649 param = stringp;
06650 if(debug)
06651 printf("@@@@ action: %s, param = %s\n",action, (param) ? param : "(null)");
06652
06653 for(i = 0 ; i < (sizeof(function_table)/sizeof(struct function_table_tag)); i++){
06654 if(!strncasecmp(action, function_table[i].action, strlen(action)))
06655 break;
06656 }
06657 if(debug)
06658 printf("@@@@ table index i = %d\n",i);
06659 if(i == (sizeof(function_table)/sizeof(struct function_table_tag))){
06660
06661 return DC_ERROR;
06662 }
06663 if(function_table[i].function == NULL){
06664
06665 if(debug)
06666 printf("@@@@ NULL for action: %s\n",action);
06667 return DC_ERROR;
06668 }
06669 functiondigits = digits + strlen(vp->name);
06670 rv=(*function_table[i].function)(myrpt, param, functiondigits, command_source, mylink);
06671 if (debug > 6) ast_log(LOG_NOTICE,"rv=%i\n",rv);
06672 return(rv);
06673 }
06674
06675
06676 static void handle_link_data(struct rpt *myrpt, struct rpt_link *mylink,
06677 char *str)
06678 {
06679
06680
06681 char tmp[512],tmp1[512],cmd[300] = "",dest[300],src[300],c;
06682 int i,seq, res, ts;
06683 struct rpt_link *l;
06684 struct ast_frame wf;
06685
06686 wf.frametype = AST_FRAME_TEXT;
06687 wf.subclass = 0;
06688 wf.offset = 0;
06689 wf.mallocd = 0;
06690 wf.datalen = strlen(str) + 1;
06691 wf.samples = 0;
06692
06693 strncpy(tmp,str,sizeof(tmp) - 1);
06694
06695 if (!strcmp(tmp,discstr))
06696 {
06697 mylink->disced = 1;
06698 mylink->retries = mylink->max_retries + 1;
06699 ast_softhangup(mylink->chan,AST_SOFTHANGUP_DEV);
06700 return;
06701 }
06702 if (!strcmp(tmp,newkeystr))
06703 {
06704 mylink->newkey = 1;
06705 return;
06706 }
06707 if (tmp[0] == 'L')
06708 {
06709 rpt_mutex_lock(&myrpt->lock);
06710 strcpy(mylink->linklist,tmp + 2);
06711 time(&mylink->linklistreceived);
06712 rpt_mutex_unlock(&myrpt->lock);
06713 if (debug > 6) ast_log(LOG_NOTICE,"@@@@ node %s received node list %s from node %s\n",
06714 myrpt->name,tmp,mylink->name);
06715 return;
06716 }
06717 if (tmp[0] == 'K')
06718 {
06719 if (sscanf(tmp, "%299s %299s %299s %30d %30d", cmd, dest, src, &seq, &ts) != 5)
06720 {
06721 ast_log(LOG_WARNING, "Unable to parse keying string %s\n",str);
06722 return;
06723 }
06724 if (dest[0] == '0')
06725 {
06726 strcpy(dest,myrpt->name);
06727 }
06728
06729 if (strcmp(dest,myrpt->name))
06730 {
06731 l = myrpt->links.next;
06732
06733 while(l != &myrpt->links)
06734 {
06735 if (l->name[0] == '0')
06736 {
06737 l = l->next;
06738 continue;
06739 }
06740
06741 if ((l == mylink) || (!strcmp(l->name,mylink->name)))
06742 {
06743 l = l->next;
06744 continue;
06745 }
06746
06747 if (!strcmp(l->name,dest))
06748 {
06749
06750 if (strcmp(l->name,src)) {
06751 wf.data.ptr = str;
06752 if (l->chan) ast_write(l->chan,&wf);
06753 }
06754 return;
06755 }
06756 l = l->next;
06757 }
06758 }
06759
06760 if ((strcmp(dest,myrpt->name)) || (dest[0] == '*'))
06761 {
06762 l = myrpt->links.next;
06763
06764 while(l != &myrpt->links)
06765 {
06766 if (l->name[0] == '0')
06767 {
06768 l = l->next;
06769 continue;
06770 }
06771
06772 if ((l == mylink) || (!strcmp(l->name,mylink->name)))
06773 {
06774 l = l->next;
06775 continue;
06776 }
06777
06778 if (strcmp(l->name,src)) {
06779 wf.data.ptr = str;
06780 if (l->chan) ast_write(l->chan,&wf);
06781 }
06782 l = l->next;
06783 }
06784 }
06785
06786 if (strcmp(dest,myrpt->name) && (dest[0] != '*')) return;
06787 if (cmd[1] == '?')
06788 {
06789 time_t now;
06790 int n = 0;
06791
06792 time(&now);
06793 if (myrpt->lastkeyedtime)
06794 {
06795 n = (int)(now - myrpt->lastkeyedtime);
06796 }
06797 sprintf(tmp1,"K %s %s %d %d",src,myrpt->name,myrpt->keyed,n);
06798 wf.data.ptr = tmp1;
06799 wf.datalen = strlen(tmp1) + 1;
06800 if (mylink->chan) ast_write(mylink->chan,&wf);
06801 return;
06802 }
06803 if (myrpt->topkeystate != 1) return;
06804 rpt_mutex_lock(&myrpt->lock);
06805 for(i = 0; i < TOPKEYN; i++)
06806 {
06807 if (!strcmp(myrpt->topkey[i].node,src)) break;
06808 }
06809 if (i >= TOPKEYN)
06810 {
06811 for(i = 0; i < TOPKEYN; i++)
06812 {
06813 if (!myrpt->topkey[i].node[0]) break;
06814 }
06815 }
06816 if (i < TOPKEYN)
06817 {
06818 strncpy(myrpt->topkey[i].node,src,TOPKEYMAXSTR - 1);
06819 myrpt->topkey[i].timesince = ts;
06820 myrpt->topkey[i].keyed = seq;
06821 }
06822 rpt_mutex_unlock(&myrpt->lock);
06823 return;
06824 }
06825 if (tmp[0] == 'I')
06826 {
06827
06828
06829 if (sscanf(tmp,"%299s %299s %30x",cmd,src,&seq) != 3)
06830 {
06831 ast_log(LOG_WARNING, "Unable to parse ident string %s\n",str);
06832 return;
06833 }
06834 mdc1200_notify(myrpt,src,seq);
06835 strcpy(dest,"*");
06836 }
06837 else
06838 {
06839
06840
06841 if (sscanf(tmp,"%299s %299s %299s %30d %1c",cmd,dest,src,&seq,&c) != 5)
06842 {
06843 ast_log(LOG_WARNING, "Unable to parse link string %s\n",str);
06844 return;
06845 }
06846 if (strcmp(cmd,"D"))
06847 {
06848 ast_log(LOG_WARNING, "Unable to parse link string %s\n",str);
06849 return;
06850 }
06851 }
06852 if (dest[0] == '0')
06853 {
06854 strcpy(dest,myrpt->name);
06855 }
06856
06857
06858 if (strcmp(dest,myrpt->name))
06859 {
06860 l = myrpt->links.next;
06861
06862 while(l != &myrpt->links)
06863 {
06864 if (l->name[0] == '0')
06865 {
06866 l = l->next;
06867 continue;
06868 }
06869
06870 if ((l == mylink) || (!strcmp(l->name,mylink->name)))
06871 {
06872 l = l->next;
06873 continue;
06874 }
06875
06876 if (!strcmp(l->name,dest))
06877 {
06878
06879 if (strcmp(l->name,src)) {
06880 wf.data.ptr = str;
06881 if (l->chan) ast_write(l->chan,&wf);
06882 }
06883 return;
06884 }
06885 l = l->next;
06886 }
06887 l = myrpt->links.next;
06888
06889 while(l != &myrpt->links)
06890 {
06891 if (l->name[0] == '0')
06892 {
06893 l = l->next;
06894 continue;
06895 }
06896
06897 if ((l == mylink) || (!strcmp(l->name,mylink->name)))
06898 {
06899 l = l->next;
06900 continue;
06901 }
06902
06903 if (strcmp(l->name,src)) {
06904 wf.data.ptr = str;
06905 if (l->chan) ast_write(l->chan,&wf);
06906 }
06907 l = l->next;
06908 }
06909 return;
06910 }
06911 if (myrpt->p.archivedir)
06912 {
06913 char dtmfstr[100];
06914
06915 sprintf(dtmfstr,"DTMF,%s,%c",mylink->name,c);
06916 donodelog(myrpt,dtmfstr);
06917 }
06918 c = func_xlat(myrpt,c,&myrpt->p.outxlat);
06919 if (!c) return;
06920 rpt_mutex_lock(&myrpt->lock);
06921 if (c == myrpt->p.endchar) myrpt->stopgen = 1;
06922 if (myrpt->callmode == 1)
06923 {
06924 myrpt->exten[myrpt->cidx++] = c;
06925 myrpt->exten[myrpt->cidx] = 0;
06926
06927 if (ast_exists_extension(myrpt->pchannel,myrpt->patchcontext,myrpt->exten,1,NULL))
06928 {
06929
06930 if (!ast_matchmore_extension(myrpt->pchannel,myrpt->patchcontext,
06931 myrpt->exten,1,NULL))
06932 {
06933 myrpt->callmode = 2;
06934 if(!myrpt->patchquiet)
06935 {
06936 rpt_mutex_unlock(&myrpt->lock);
06937 rpt_telemetry(myrpt,PROC,NULL);
06938 rpt_mutex_lock(&myrpt->lock);
06939 }
06940 }
06941 else
06942 {
06943 myrpt->calldigittimer = 1;
06944 }
06945 }
06946
06947 if (!ast_canmatch_extension(myrpt->pchannel,myrpt->patchcontext,myrpt->exten,1,NULL))
06948 {
06949
06950 myrpt->callmode = 4;
06951 }
06952 }
06953 if ((!myrpt->inpadtest) &&(c == myrpt->p.funcchar))
06954 {
06955 myrpt->rem_dtmfidx = 0;
06956 myrpt->rem_dtmfbuf[myrpt->rem_dtmfidx] = 0;
06957 time(&myrpt->rem_dtmf_time);
06958 rpt_mutex_unlock(&myrpt->lock);
06959 return;
06960 }
06961 else if (myrpt->rem_dtmfidx < 0)
06962 {
06963 if ((myrpt->callmode == 2) || (myrpt->callmode == 3))
06964 {
06965 myrpt->mydtmf = c;
06966 }
06967 if (myrpt->p.propagate_dtmf) do_dtmf_local(myrpt,c);
06968 if (myrpt->p.propagate_phonedtmf) do_dtmf_phone(myrpt,mylink,c);
06969 rpt_mutex_unlock(&myrpt->lock);
06970 return;
06971 }
06972 else if (((myrpt->inpadtest) || (c != myrpt->p.endchar)) && (myrpt->rem_dtmfidx >= 0))
06973 {
06974 time(&myrpt->rem_dtmf_time);
06975 if (myrpt->rem_dtmfidx < MAXDTMF)
06976 {
06977 myrpt->rem_dtmfbuf[myrpt->rem_dtmfidx++] = c;
06978 myrpt->rem_dtmfbuf[myrpt->rem_dtmfidx] = 0;
06979
06980 rpt_mutex_unlock(&myrpt->lock);
06981 strncpy(cmd, myrpt->rem_dtmfbuf, sizeof(cmd) - 1);
06982 res = collect_function_digits(myrpt, cmd, SOURCE_LNK, mylink);
06983 rpt_mutex_lock(&myrpt->lock);
06984
06985 switch(res){
06986
06987 case DC_INDETERMINATE:
06988 break;
06989
06990 case DC_REQ_FLUSH:
06991 myrpt->rem_dtmfidx = 0;
06992 myrpt->rem_dtmfbuf[0] = 0;
06993 break;
06994
06995
06996 case DC_COMPLETE:
06997 case DC_COMPLETEQUIET:
06998 myrpt->totalexecdcommands++;
06999 myrpt->dailyexecdcommands++;
07000 strncpy(myrpt->lastdtmfcommand, cmd, MAXDTMF-1);
07001 myrpt->lastdtmfcommand[MAXDTMF-1] = '\0';
07002 myrpt->rem_dtmfbuf[0] = 0;
07003 myrpt->rem_dtmfidx = -1;
07004 myrpt->rem_dtmf_time = 0;
07005 break;
07006
07007 case DC_ERROR:
07008 default:
07009 myrpt->rem_dtmfbuf[0] = 0;
07010 myrpt->rem_dtmfidx = -1;
07011 myrpt->rem_dtmf_time = 0;
07012 break;
07013 }
07014 }
07015
07016 }
07017 rpt_mutex_unlock(&myrpt->lock);
07018 return;
07019 }
07020
07021 static void handle_link_phone_dtmf(struct rpt *myrpt, struct rpt_link *mylink,
07022 char c)
07023 {
07024
07025 char cmd[300];
07026 int res;
07027
07028 if (myrpt->p.archivedir)
07029 {
07030 char str[100];
07031
07032 sprintf(str,"DTMF(P),%s,%c",mylink->name,c);
07033 donodelog(myrpt,str);
07034 }
07035 rpt_mutex_lock(&myrpt->lock);
07036
07037 if (mylink->phonemode == 3)
07038 {
07039 if(c == myrpt->p.endchar)
07040 {
07041 mylink->lastrealrx = 0;
07042 rpt_mutex_unlock(&myrpt->lock);
07043 return;
07044 }
07045
07046 if(c == myrpt->p.funcchar)
07047 {
07048 mylink->lastrealrx = !mylink->lastrealrx;
07049 rpt_mutex_unlock(&myrpt->lock);
07050 return;
07051 }
07052 }
07053 else
07054 {
07055 if (c == myrpt->p.endchar)
07056 {
07057 if (mylink->lastrx)
07058 {
07059 mylink->lastrealrx = 0;
07060 rpt_mutex_unlock(&myrpt->lock);
07061 return;
07062 }
07063 myrpt->stopgen = 1;
07064 if (myrpt->cmdnode[0])
07065 {
07066 myrpt->cmdnode[0] = 0;
07067 myrpt->dtmfidx = -1;
07068 myrpt->dtmfbuf[0] = 0;
07069 rpt_mutex_unlock(&myrpt->lock);
07070 rpt_telemetry(myrpt,COMPLETE,NULL);
07071 return;
07072 }
07073 }
07074 }
07075 if (myrpt->cmdnode[0])
07076 {
07077 rpt_mutex_unlock(&myrpt->lock);
07078 send_link_dtmf(myrpt,c);
07079 return;
07080 }
07081 if (myrpt->callmode == 1)
07082 {
07083 myrpt->exten[myrpt->cidx++] = c;
07084 myrpt->exten[myrpt->cidx] = 0;
07085
07086 if (ast_exists_extension(myrpt->pchannel,myrpt->patchcontext,myrpt->exten,1,NULL))
07087 {
07088
07089 if (!ast_matchmore_extension(myrpt->pchannel,myrpt->patchcontext,
07090 myrpt->exten,1,NULL))
07091 {
07092 myrpt->callmode = 2;
07093 if(!myrpt->patchquiet)
07094 {
07095 rpt_mutex_unlock(&myrpt->lock);
07096 rpt_telemetry(myrpt,PROC,NULL);
07097 rpt_mutex_lock(&myrpt->lock);
07098 }
07099 }
07100 else
07101 {
07102 myrpt->calldigittimer = 1;
07103 }
07104 }
07105
07106 if (!ast_canmatch_extension(myrpt->pchannel,myrpt->patchcontext,myrpt->exten,1,NULL))
07107 {
07108
07109 myrpt->callmode = 4;
07110 }
07111 }
07112 if ((myrpt->callmode == 2) || (myrpt->callmode == 3))
07113 {
07114 myrpt->mydtmf = c;
07115 }
07116 if ((!myrpt->inpadtest) && (c == myrpt->p.funcchar))
07117 {
07118 myrpt->rem_dtmfidx = 0;
07119 myrpt->rem_dtmfbuf[myrpt->rem_dtmfidx] = 0;
07120 time(&myrpt->rem_dtmf_time);
07121 rpt_mutex_unlock(&myrpt->lock);
07122 return;
07123 }
07124 else if (((myrpt->inpadtest) || (c != myrpt->p.endchar)) && (myrpt->rem_dtmfidx >= 0))
07125 {
07126 time(&myrpt->rem_dtmf_time);
07127 if (myrpt->rem_dtmfidx < MAXDTMF)
07128 {
07129 myrpt->rem_dtmfbuf[myrpt->rem_dtmfidx++] = c;
07130 myrpt->rem_dtmfbuf[myrpt->rem_dtmfidx] = 0;
07131
07132 rpt_mutex_unlock(&myrpt->lock);
07133 strncpy(cmd, myrpt->rem_dtmfbuf, sizeof(cmd) - 1);
07134 switch(mylink->phonemode)
07135 {
07136 case 1:
07137 res = collect_function_digits(myrpt, cmd,
07138 SOURCE_PHONE, mylink);
07139 break;
07140 case 2:
07141 res = collect_function_digits(myrpt, cmd,
07142 SOURCE_DPHONE,mylink);
07143 break;
07144 case 4:
07145 res = collect_function_digits(myrpt, cmd,
07146 SOURCE_ALT,mylink);
07147 break;
07148 default:
07149 res = collect_function_digits(myrpt, cmd,
07150 SOURCE_LNK, mylink);
07151 break;
07152 }
07153
07154 rpt_mutex_lock(&myrpt->lock);
07155
07156 switch(res){
07157
07158 case DC_INDETERMINATE:
07159 break;
07160
07161 case DC_DOKEY:
07162 mylink->lastrealrx = 1;
07163 break;
07164
07165 case DC_REQ_FLUSH:
07166 myrpt->rem_dtmfidx = 0;
07167 myrpt->rem_dtmfbuf[0] = 0;
07168 break;
07169
07170
07171 case DC_COMPLETE:
07172 case DC_COMPLETEQUIET:
07173 myrpt->totalexecdcommands++;
07174 myrpt->dailyexecdcommands++;
07175 strncpy(myrpt->lastdtmfcommand, cmd, MAXDTMF-1);
07176 myrpt->lastdtmfcommand[MAXDTMF-1] = '\0';
07177 myrpt->rem_dtmfbuf[0] = 0;
07178 myrpt->rem_dtmfidx = -1;
07179 myrpt->rem_dtmf_time = 0;
07180 break;
07181
07182 case DC_ERROR:
07183 default:
07184 myrpt->rem_dtmfbuf[0] = 0;
07185 myrpt->rem_dtmfidx = -1;
07186 myrpt->rem_dtmf_time = 0;
07187 break;
07188 }
07189 }
07190
07191 }
07192 rpt_mutex_unlock(&myrpt->lock);
07193 return;
07194 }
07195
07196
07197
07198
07199
07200
07201
07202
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 static int rbi_mhztoband(char *str)
07228 {
07229 int i;
07230
07231 i = atoi(str) / 10;
07232 switch(i)
07233 {
07234 case 2:
07235 return 10;
07236 case 5:
07237 return 11;
07238 case 14:
07239 return 2;
07240 case 22:
07241 return 3;
07242 case 44:
07243 return 4;
07244 case 124:
07245 return 0;
07246 case 125:
07247 return 1;
07248 case 126:
07249 return 8;
07250 case 127:
07251 return 5;
07252 case 128:
07253 return 6;
07254 case 129:
07255 return 7;
07256 default:
07257 break;
07258 }
07259 return -1;
07260 }
07261
07262
07263 static int rbi_pltocode(char *str)
07264 {
07265 int i;
07266 char *s;
07267
07268 s = strchr(str,'.');
07269 i = 0;
07270 if (s) i = atoi(s + 1);
07271 i += atoi(str) * 10;
07272 switch(i)
07273 {
07274 case 670:
07275 return 0;
07276 case 719:
07277 return 1;
07278 case 744:
07279 return 2;
07280 case 770:
07281 return 3;
07282 case 797:
07283 return 4;
07284 case 825:
07285 return 5;
07286 case 854:
07287 return 6;
07288 case 885:
07289 return 7;
07290 case 915:
07291 return 8;
07292 case 948:
07293 return 9;
07294 case 974:
07295 return 10;
07296 case 1000:
07297 return 11;
07298 case 1035:
07299 return 12;
07300 case 1072:
07301 return 13;
07302 case 1109:
07303 return 14;
07304 case 1148:
07305 return 15;
07306 case 1188:
07307 return 16;
07308 case 1230:
07309 return 17;
07310 case 1273:
07311 return 18;
07312 case 1318:
07313 return 19;
07314 case 1365:
07315 return 20;
07316 case 1413:
07317 return 21;
07318 case 1462:
07319 return 22;
07320 case 1514:
07321 return 23;
07322 case 1567:
07323 return 24;
07324 case 1622:
07325 return 25;
07326 case 1679:
07327 return 26;
07328 case 1738:
07329 return 27;
07330 case 1799:
07331 return 28;
07332 case 1862:
07333 return 29;
07334 case 1928:
07335 return 30;
07336 case 2035:
07337 return 31;
07338 case 2107:
07339 return 32;
07340 case 2181:
07341 return 33;
07342 case 2257:
07343 return 34;
07344 case 2336:
07345 return 35;
07346 case 2418:
07347 return 36;
07348 case 2503:
07349 return 37;
07350 }
07351 return -1;
07352 }
07353
07354
07355
07356
07357
07358 static void rbi_out_parallel(struct rpt *myrpt,unsigned char *data)
07359 {
07360 #ifdef __i386__
07361 int i,j;
07362 unsigned char od,d;
07363 static volatile long long delayvar;
07364
07365 for(i = 0 ; i < 5 ; i++){
07366 od = *data++;
07367 for(j = 0 ; j < 8 ; j++){
07368 d = od & 1;
07369 outb(d,myrpt->p.iobase);
07370
07371 for(delayvar = 1; delayvar < 15000; delayvar++);
07372 od >>= 1;
07373 outb(d | 2,myrpt->p.iobase);
07374
07375 for(delayvar = 1; delayvar < 30000; delayvar++);
07376 outb(d,myrpt->p.iobase);
07377
07378 for(delayvar = 1; delayvar < 10000; delayvar++);
07379 }
07380 }
07381
07382 for(delayvar = 1; delayvar < 50000; delayvar++);
07383 #endif
07384 }
07385
07386 static void rbi_out(struct rpt *myrpt,unsigned char *data)
07387 {
07388 struct dahdi_radio_param r;
07389
07390 memset(&r,0,sizeof(struct dahdi_radio_param));
07391 r.radpar = DAHDI_RADPAR_REMMODE;
07392 r.data = DAHDI_RADPAR_REM_RBI1;
07393
07394 if (ioctl(myrpt->dahdirxchannel->fds[0],DAHDI_RADIO_SETPARAM,&r) == -1)
07395 {
07396 rbi_out_parallel(myrpt,data);
07397 return;
07398 }
07399 r.radpar = DAHDI_RADPAR_REMCOMMAND;
07400 memcpy(&r.data,data,5);
07401 if (ioctl(myrpt->dahdirxchannel->fds[0],DAHDI_RADIO_SETPARAM,&r) == -1)
07402 {
07403 ast_log(LOG_WARNING,"Cannot send RBI command for channel %s\n",myrpt->dahdirxchannel->name);
07404 return;
07405 }
07406 }
07407
07408 static int serial_remote_io(struct rpt *myrpt, unsigned char *txbuf, int txbytes,
07409 unsigned char *rxbuf, int rxmaxbytes, int asciiflag)
07410 {
07411 int i,j,idx,oldmode,olddata;
07412 struct dahdi_radio_param prm;
07413 char c;
07414
07415 if(debug) {
07416 ast_log(LOG_NOTICE, "ioport=%s iofd=0x%x\n",myrpt->p.ioport,myrpt->iofd);
07417 printf("String output was:\n");
07418 for(i = 0; i < txbytes; i++)
07419 printf("%02X ", (unsigned char ) txbuf[i]);
07420 printf("\n");
07421 }
07422
07423 if (myrpt->iofd >= 0)
07424 {
07425 if (write(myrpt->iofd,txbuf,txbytes) != txbytes)
07426 {
07427 return -1;
07428 }
07429 if ((!rxmaxbytes) || (rxbuf == NULL))
07430 {
07431 return(0);
07432 }
07433 memset(rxbuf,0,rxmaxbytes);
07434 for(i = 0; i < rxmaxbytes; i++)
07435 {
07436 j = read(myrpt->iofd,&c,1);
07437 if (j < 1)
07438 {
07439 return(i);
07440 }
07441 rxbuf[i] = c;
07442 if (asciiflag & 1)
07443 {
07444 rxbuf[i + 1] = 0;
07445 if (c == '\r') break;
07446 }
07447 }
07448 if(debug) {
07449 printf("String returned was:\n");
07450 for(j = 0; j < i; j++)
07451 printf("%02X ", (unsigned char ) rxbuf[j]);
07452 printf("\n");
07453 }
07454 return(i);
07455 }
07456
07457
07458 if (myrpt->rxchannel != myrpt->dahdirxchannel) return -1;
07459
07460 prm.radpar = DAHDI_RADPAR_UIOMODE;
07461 if (ioctl(myrpt->dahdirxchannel->fds[0],DAHDI_RADIO_GETPARAM,&prm) == -1) return -1;
07462 oldmode = prm.data;
07463 prm.radpar = DAHDI_RADPAR_UIODATA;
07464 if (ioctl(myrpt->dahdirxchannel->fds[0],DAHDI_RADIO_GETPARAM,&prm) == -1) return -1;
07465 olddata = prm.data;
07466 prm.radpar = DAHDI_RADPAR_REMMODE;
07467 if (asciiflag & 1) prm.data = DAHDI_RADPAR_REM_SERIAL_ASCII;
07468 else prm.data = DAHDI_RADPAR_REM_SERIAL;
07469 if (ioctl(myrpt->dahdirxchannel->fds[0],DAHDI_RADIO_SETPARAM,&prm) == -1) return -1;
07470 if (asciiflag & 2)
07471 {
07472 i = DAHDI_ONHOOK;
07473 if (ioctl(myrpt->dahdirxchannel->fds[0],DAHDI_HOOK,&i) == -1) return -1;
07474 usleep(100000);
07475 }
07476 prm.radpar = DAHDI_RADPAR_REMCOMMAND;
07477 prm.data = rxmaxbytes;
07478 memcpy(prm.buf,txbuf,txbytes);
07479 prm.index = txbytes;
07480 if (ioctl(myrpt->dahdirxchannel->fds[0],DAHDI_RADIO_SETPARAM,&prm) == -1) return -1;
07481 if (rxbuf)
07482 {
07483 *rxbuf = 0;
07484 memcpy(rxbuf,prm.buf,prm.index);
07485 }
07486 idx = prm.index;
07487 prm.radpar = DAHDI_RADPAR_REMMODE;
07488 prm.data = DAHDI_RADPAR_REM_NONE;
07489 if (ioctl(myrpt->dahdirxchannel->fds[0],DAHDI_RADIO_SETPARAM,&prm) == -1) return -1;
07490 if (asciiflag & 2)
07491 {
07492 i = DAHDI_OFFHOOK;
07493 if (ioctl(myrpt->dahdirxchannel->fds[0],DAHDI_HOOK,&i) == -1) return -1;
07494 }
07495 prm.radpar = DAHDI_RADPAR_UIOMODE;
07496 prm.data = oldmode;
07497 if (ioctl(myrpt->dahdirxchannel->fds[0],DAHDI_RADIO_SETPARAM,&prm) == -1) return -1;
07498 prm.radpar = DAHDI_RADPAR_UIODATA;
07499 prm.data = olddata;
07500 if (ioctl(myrpt->dahdirxchannel->fds[0],DAHDI_RADIO_SETPARAM,&prm) == -1) return -1;
07501 return(idx);
07502 }
07503
07504 static int civ_cmd(struct rpt *myrpt,unsigned char *cmd, int cmdlen)
07505 {
07506 unsigned char rxbuf[100];
07507 int i,rv ;
07508
07509 rv = serial_remote_io(myrpt,cmd,cmdlen,rxbuf,cmdlen + 6,0);
07510 if (rv == -1) return(-1);
07511 if (rv != (cmdlen + 6)) return(1);
07512 for(i = 0; i < 6; i++)
07513 if (rxbuf[i] != cmd[i]) return(1);
07514 if (rxbuf[cmdlen] != 0xfe) return(1);
07515 if (rxbuf[cmdlen + 1] != 0xfe) return(1);
07516 if (rxbuf[cmdlen + 4] != 0xfb) return(1);
07517 if (rxbuf[cmdlen + 5] != 0xfd) return(1);
07518 return(0);
07519 }
07520
07521 static int sendkenwood(struct rpt *myrpt,char *txstr, char *rxstr)
07522 {
07523 int i;
07524
07525 ast_log(LOG_NOTICE,"Sent to kenwood: %s\n",txstr);
07526 if (debug) printf("Send to kenwood: %s\n",txstr);
07527 i = serial_remote_io(myrpt, (unsigned char *)txstr, strlen(txstr),
07528 (unsigned char *)rxstr,RAD_SERIAL_BUFLEN - 1,3);
07529 if (i < 0) return -1;
07530 if ((i > 0) && (rxstr[i - 1] == '\r'))
07531 rxstr[i-- - 1] = 0;
07532 if (debug) printf("Got from kenwood: %s\n",rxstr);
07533 ast_log(LOG_NOTICE,"Got from kenwood: %s\n",rxstr);
07534 return(i);
07535 }
07536
07537
07538 static int kenwood_pltocode(char *str)
07539 {
07540 int i;
07541 char *s;
07542
07543 s = strchr(str,'.');
07544 i = 0;
07545 if (s) i = atoi(s + 1);
07546 i += atoi(str) * 10;
07547 switch(i)
07548 {
07549 case 670:
07550 return 1;
07551 case 719:
07552 return 3;
07553 case 744:
07554 return 4;
07555 case 770:
07556 return 5;
07557 case 797:
07558 return 6;
07559 case 825:
07560 return 7;
07561 case 854:
07562 return 8;
07563 case 885:
07564 return 9;
07565 case 915:
07566 return 10;
07567 case 948:
07568 return 11;
07569 case 974:
07570 return 12;
07571 case 1000:
07572 return 13;
07573 case 1035:
07574 return 14;
07575 case 1072:
07576 return 15;
07577 case 1109:
07578 return 16;
07579 case 1148:
07580 return 17;
07581 case 1188:
07582 return 18;
07583 case 1230:
07584 return 19;
07585 case 1273:
07586 return 20;
07587 case 1318:
07588 return 21;
07589 case 1365:
07590 return 22;
07591 case 1413:
07592 return 23;
07593 case 1462:
07594 return 24;
07595 case 1514:
07596 return 25;
07597 case 1567:
07598 return 26;
07599 case 1622:
07600 return 27;
07601 case 1679:
07602 return 28;
07603 case 1738:
07604 return 29;
07605 case 1799:
07606 return 30;
07607 case 1862:
07608 return 31;
07609 case 1928:
07610 return 32;
07611 case 2035:
07612 return 33;
07613 case 2107:
07614 return 34;
07615 case 2181:
07616 return 35;
07617 case 2257:
07618 return 36;
07619 case 2336:
07620 return 37;
07621 case 2418:
07622 return 38;
07623 case 2503:
07624 return 39;
07625 }
07626 return -1;
07627 }
07628
07629 static int sendrxkenwood(struct rpt *myrpt, char *txstr, char *rxstr,
07630 char *cmpstr)
07631 {
07632 int i,j;
07633
07634 for(i = 0;i < KENWOOD_RETRIES;i++)
07635 {
07636 j = sendkenwood(myrpt,txstr,rxstr);
07637 if (j < 0) return(j);
07638 if (j == 0) continue;
07639 if (!strncmp(rxstr,cmpstr,strlen(cmpstr))) return(0);
07640 }
07641 return(-1);
07642 }
07643
07644 static int setkenwood(struct rpt *myrpt)
07645 {
07646 char rxstr[RAD_SERIAL_BUFLEN],txstr[RAD_SERIAL_BUFLEN],freq[20];
07647 char mhz[MAXREMSTR],offset[20],band,decimals[MAXREMSTR],band1,band2;
07648 int myrxpl;
07649
07650 int offsets[] = {0,2,1};
07651 int powers[] = {2,1,0};
07652
07653 if (sendrxkenwood(myrpt,"VMC 0,0\r",rxstr,"VMC") < 0) return -1;
07654 split_freq(mhz, decimals, myrpt->freq);
07655 if (atoi(mhz) > 400)
07656 {
07657 band = '6';
07658 band1 = '1';
07659 band2 = '5';
07660 strcpy(offset,"005000000");
07661 }
07662 else
07663 {
07664 band = '2';
07665 band1 = '0';
07666 band2 = '2';
07667 strcpy(offset,"000600000");
07668 }
07669 strcpy(freq,"000000");
07670 strncpy(freq,decimals,strlen(decimals));
07671 myrxpl = myrpt->rxplon;
07672 if (IS_XPMR(myrpt)) myrxpl = 0;
07673 sprintf(txstr,"VW %c,%05d%s,0,%d,0,%d,%d,,%02d,,%02d,%s\r",
07674 band,atoi(mhz),freq,offsets[(int)myrpt->offset],
07675 (myrpt->txplon != 0),myrxpl,
07676 kenwood_pltocode(myrpt->txpl),kenwood_pltocode(myrpt->rxpl),
07677 offset);
07678 if (sendrxkenwood(myrpt,txstr,rxstr,"VW") < 0) return -1;
07679 sprintf(txstr,"RBN %c\r",band2);
07680 if (sendrxkenwood(myrpt,txstr,rxstr,"RBN") < 0) return -1;
07681 sprintf(txstr,"PC %c,%d\r",band1,powers[(int)myrpt->powerlevel]);
07682 if (sendrxkenwood(myrpt,txstr,rxstr,"PC") < 0) return -1;
07683 return 0;
07684 }
07685
07686 static int set_tm271(struct rpt *myrpt)
07687 {
07688 char rxstr[RAD_SERIAL_BUFLEN],txstr[RAD_SERIAL_BUFLEN],freq[20];
07689 char mhz[MAXREMSTR],decimals[MAXREMSTR];
07690
07691 int offsets[] = {0,2,1};
07692 int powers[] = {2,1,0};
07693
07694 split_freq(mhz, decimals, myrpt->freq);
07695 strcpy(freq,"000000");
07696 strncpy(freq,decimals,strlen(decimals));
07697
07698 sprintf(txstr,"VF %04d%s,4,%d,0,%d,0,0,%d,%d,000,00600000,0,0\r",
07699 atoi(mhz),freq,offsets[(int)myrpt->offset],
07700 (myrpt->txplon != 0),kenwood_pltocode(myrpt->txpl),
07701 kenwood_pltocode(myrpt->rxpl));
07702
07703 if (sendrxkenwood(myrpt,txstr,rxstr,"VF") < 0) return -1;
07704 if (sendrxkenwood(myrpt,"VM 0\r",rxstr,"VM") < 0) return -1;
07705 sprintf(txstr,"PC %d\r",powers[(int)myrpt->powerlevel]);
07706 if (sendrxkenwood(myrpt,txstr,rxstr,"PC") < 0) return -1;
07707 return 0;
07708 }
07709
07710 static int setrbi(struct rpt *myrpt)
07711 {
07712 char tmp[MAXREMSTR] = "",*s;
07713 unsigned char rbicmd[5];
07714 int band,txoffset = 0,txpower = 0,rxpl;
07715
07716
07717 if (!myrpt->remoterig) return(0);
07718 if (!myrpt->remoterig[0]) return(0);
07719
07720 if (strncmp(myrpt->remoterig,remote_rig_rbi,3)) return(0);
07721 if (setrbi_check(myrpt) == -1) return(-1);
07722 strncpy(tmp, myrpt->freq, sizeof(tmp) - 1);
07723 s = strchr(tmp,'.');
07724
07725
07726 if (s == NULL){
07727 if(debug)
07728 printf("@@@@ Frequency needs a decimal\n");
07729 return -1;
07730 }
07731
07732 *s++ = 0;
07733 if (strlen(tmp) < 2){
07734 if(debug)
07735 printf("@@@@ Bad MHz digits: %s\n", tmp);
07736 return -1;
07737 }
07738
07739 if (strlen(s) < 3){
07740 if(debug)
07741 printf("@@@@ Bad KHz digits: %s\n", s);
07742 return -1;
07743 }
07744
07745 if ((s[2] != '0') && (s[2] != '5')){
07746 if(debug)
07747 printf("@@@@ KHz must end in 0 or 5: %c\n", s[2]);
07748 return -1;
07749 }
07750
07751 band = rbi_mhztoband(tmp);
07752 if (band == -1){
07753 if(debug)
07754 printf("@@@@ Bad Band: %s\n", tmp);
07755 return -1;
07756 }
07757
07758 rxpl = rbi_pltocode(myrpt->rxpl);
07759
07760 if (rxpl == -1){
07761 if(debug)
07762 printf("@@@@ Bad TX PL: %s\n", myrpt->rxpl);
07763 return -1;
07764 }
07765
07766
07767 switch(myrpt->offset)
07768 {
07769 case REM_MINUS:
07770 txoffset = 0;
07771 break;
07772 case REM_PLUS:
07773 txoffset = 0x10;
07774 break;
07775 case REM_SIMPLEX:
07776 txoffset = 0x20;
07777 break;
07778 }
07779 switch(myrpt->powerlevel)
07780 {
07781 case REM_LOWPWR:
07782 txpower = 0;
07783 break;
07784 case REM_MEDPWR:
07785 txpower = 0x20;
07786 break;
07787 case REM_HIPWR:
07788 txpower = 0x10;
07789 break;
07790 }
07791 rbicmd[0] = 0;
07792 rbicmd[1] = band | txpower | 0xc0;
07793 rbicmd[2] = (*(s - 2) - '0') | txoffset | 0x80;
07794 if (s[2] == '5') rbicmd[2] |= 0x40;
07795 rbicmd[3] = ((*s - '0') << 4) + (s[1] - '0');
07796 rbicmd[4] = rxpl;
07797 if (myrpt->txplon) rbicmd[4] |= 0x40;
07798 if (myrpt->rxplon) rbicmd[4] |= 0x80;
07799 rbi_out(myrpt,rbicmd);
07800 return 0;
07801 }
07802
07803 static int setrtx(struct rpt *myrpt)
07804 {
07805 char tmp[MAXREMSTR] = "",*s,rigstr[200],pwr,res = 0;
07806 int band,txoffset = 0,txpower = 0,rxpl,txpl;
07807 float ofac;
07808 double txfreq;
07809
07810
07811 if (!myrpt->remoterig) return(0);
07812 if (!myrpt->remoterig[0]) return(0);
07813
07814 if (!ISRIG_RTX(myrpt->remoterig)) return(0);
07815
07816 if (!IS_XPMR(myrpt)) return(0);
07817 strncpy(tmp, myrpt->freq, sizeof(tmp) - 1);
07818 s = strchr(tmp,'.');
07819
07820
07821 if(debug)printf("setrtx() %s %s\n",myrpt->name,myrpt->remoterig);
07822
07823 if (s == NULL){
07824 if(debug)
07825 printf("@@@@ Frequency needs a decimal\n");
07826 return -1;
07827 }
07828 *s++ = 0;
07829 if (strlen(tmp) < 2){
07830 if(debug)
07831 printf("@@@@ Bad MHz digits: %s\n", tmp);
07832 return -1;
07833 }
07834
07835 if (strlen(s) < 3){
07836 if(debug)
07837 printf("@@@@ Bad KHz digits: %s\n", s);
07838 return -1;
07839 }
07840
07841 if ((s[2] != '0') && (s[2] != '5')){
07842 if(debug)
07843 printf("@@@@ KHz must end in 0 or 5: %c\n", s[2]);
07844 return -1;
07845 }
07846
07847 band = rbi_mhztoband(tmp);
07848 if (band == -1){
07849 if(debug)
07850 printf("@@@@ Bad Band: %s\n", tmp);
07851 return -1;
07852 }
07853
07854 rxpl = rbi_pltocode(myrpt->rxpl);
07855
07856 if (rxpl == -1){
07857 if(debug)
07858 printf("@@@@ Bad RX PL: %s\n", myrpt->rxpl);
07859 return -1;
07860 }
07861
07862 txpl = rbi_pltocode(myrpt->txpl);
07863
07864 if (txpl == -1){
07865 if(debug)
07866 printf("@@@@ Bad TX PL: %s\n", myrpt->txpl);
07867 return -1;
07868 }
07869
07870 switch(myrpt->offset)
07871 {
07872 case REM_MINUS:
07873 txoffset = 0;
07874 break;
07875 case REM_PLUS:
07876 txoffset = 0x10;
07877 break;
07878 case REM_SIMPLEX:
07879 txoffset = 0x20;
07880 break;
07881 }
07882 switch(myrpt->powerlevel)
07883 {
07884 case REM_LOWPWR:
07885 txpower = 0;
07886 break;
07887 case REM_MEDPWR:
07888 txpower = 0x20;
07889 break;
07890 case REM_HIPWR:
07891 txpower = 0x10;
07892 break;
07893 }
07894
07895 res = setrtx_check(myrpt);
07896 if (res < 0) return res;
07897 ofac = 0.0;
07898 if (myrpt->offset == REM_MINUS) ofac = -1.0;
07899 if (myrpt->offset == REM_PLUS) ofac = 1.0;
07900
07901 if (!strcmp(myrpt->remoterig,remote_rig_rtx450))
07902 txfreq = atof(myrpt->freq) + (ofac * 5.0);
07903 else
07904 txfreq = atof(myrpt->freq) + (ofac * 0.6);
07905
07906 pwr = 'L';
07907 if (myrpt->powerlevel == REM_HIPWR) pwr = 'H';
07908 if (!res)
07909 {
07910 sprintf(rigstr,"SETFREQ %s %f %s %s %c",myrpt->freq,txfreq,
07911 (myrpt->rxplon) ? myrpt->rxpl : "0.0",
07912 (myrpt->txplon) ? myrpt->txpl : "0.0",pwr);
07913 send_usb_txt(myrpt,rigstr);
07914 rpt_telemetry(myrpt,COMPLETE,NULL);
07915 res = 0;
07916 }
07917 return 0;
07918 }
07919 #if 0
07920
07921
07922
07923
07924 static int setxpmr(struct rpt *myrpt)
07925 {
07926 char rigstr[200];
07927 int rxpl,txpl;
07928
07929
07930 if (!myrpt->remoterig) return(0);
07931 if (!myrpt->remoterig[0]) return(0);
07932
07933 if (ISRIG_RTX(myrpt->remoterig)) return(0);
07934
07935 if (!IS_XPMR(myrpt)) return(0);
07936
07937 if(debug)printf("setxpmr() %s %s\n",myrpt->name,myrpt->remoterig );
07938
07939 rxpl = rbi_pltocode(myrpt->rxpl);
07940
07941 if (rxpl == -1){
07942 if(debug)
07943 printf("@@@@ Bad RX PL: %s\n", myrpt->rxpl);
07944 return -1;
07945 }
07946
07947 txpl = rbi_pltocode(myrpt->txpl);
07948 if (txpl == -1){
07949 if(debug)
07950 printf("@@@@ Bad TX PL: %s\n", myrpt->txpl);
07951 return -1;
07952 }
07953 sprintf(rigstr,"SETFREQ 0.0 0.0 %s %s L",
07954 (myrpt->rxplon) ? myrpt->rxpl : "0.0",
07955 (myrpt->txplon) ? myrpt->txpl : "0.0");
07956 send_usb_txt(myrpt,rigstr);
07957 return 0;
07958 }
07959 #endif
07960
07961 static int setrbi_check(struct rpt *myrpt)
07962 {
07963 char tmp[MAXREMSTR] = "",*s;
07964 int band,txpl;
07965
07966
07967 if (!myrpt->remote) return(0);
07968
07969 if (strncmp(myrpt->remoterig,remote_rig_rbi,3)) return(0);
07970 strncpy(tmp, myrpt->freq, sizeof(tmp) - 1);
07971 s = strchr(tmp,'.');
07972
07973
07974 if (s == NULL){
07975 if(debug)
07976 printf("@@@@ Frequency needs a decimal\n");
07977 return -1;
07978 }
07979
07980 *s++ = 0;
07981 if (strlen(tmp) < 2){
07982 if(debug)
07983 printf("@@@@ Bad MHz digits: %s\n", tmp);
07984 return -1;
07985 }
07986
07987 if (strlen(s) < 3){
07988 if(debug)
07989 printf("@@@@ Bad KHz digits: %s\n", s);
07990 return -1;
07991 }
07992
07993 if ((s[2] != '0') && (s[2] != '5')){
07994 if(debug)
07995 printf("@@@@ KHz must end in 0 or 5: %c\n", s[2]);
07996 return -1;
07997 }
07998
07999 band = rbi_mhztoband(tmp);
08000 if (band == -1){
08001 if(debug)
08002 printf("@@@@ Bad Band: %s\n", tmp);
08003 return -1;
08004 }
08005
08006 txpl = rbi_pltocode(myrpt->txpl);
08007
08008 if (txpl == -1){
08009 if(debug)
08010 printf("@@@@ Bad TX PL: %s\n", myrpt->txpl);
08011 return -1;
08012 }
08013 return 0;
08014 }
08015
08016 static int setrtx_check(struct rpt *myrpt)
08017 {
08018 char tmp[MAXREMSTR] = "",*s;
08019 int band,txpl,rxpl;
08020
08021
08022 if (!myrpt->remote) return(0);
08023
08024 if (strncmp(myrpt->remoterig,remote_rig_rbi,3)) return(0);
08025 strncpy(tmp, myrpt->freq, sizeof(tmp) - 1);
08026 s = strchr(tmp,'.');
08027
08028
08029 if (s == NULL){
08030 if(debug)
08031 printf("@@@@ Frequency needs a decimal\n");
08032 return -1;
08033 }
08034
08035 *s++ = 0;
08036 if (strlen(tmp) < 2){
08037 if(debug)
08038 printf("@@@@ Bad MHz digits: %s\n", tmp);
08039 return -1;
08040 }
08041
08042 if (strlen(s) < 3){
08043 if(debug)
08044 printf("@@@@ Bad KHz digits: %s\n", s);
08045 return -1;
08046 }
08047
08048 if ((s[2] != '0') && (s[2] != '5')){
08049 if(debug)
08050 printf("@@@@ KHz must end in 0 or 5: %c\n", s[2]);
08051 return -1;
08052 }
08053
08054 band = rbi_mhztoband(tmp);
08055 if (band == -1){
08056 if(debug)
08057 printf("@@@@ Bad Band: %s\n", tmp);
08058 return -1;
08059 }
08060
08061 txpl = rbi_pltocode(myrpt->txpl);
08062
08063 if (txpl == -1){
08064 if(debug)
08065 printf("@@@@ Bad TX PL: %s\n", myrpt->txpl);
08066 return -1;
08067 }
08068
08069 rxpl = rbi_pltocode(myrpt->rxpl);
08070
08071 if (rxpl == -1){
08072 if(debug)
08073 printf("@@@@ Bad RX PL: %s\n", myrpt->rxpl);
08074 return -1;
08075 }
08076 return 0;
08077 }
08078
08079 static int check_freq_kenwood(int m, int d, int *defmode)
08080 {
08081 int dflmd = REM_MODE_FM;
08082
08083 if (m == 144){
08084 if(d < 10100)
08085 return -1;
08086 }
08087 else if((m >= 145) && (m < 148)){
08088 ;
08089 }
08090 else if((m >= 430) && (m < 450)){
08091 ;
08092 }
08093 else
08094 return -1;
08095
08096 if(defmode)
08097 *defmode = dflmd;
08098
08099
08100 return 0;
08101 }
08102
08103
08104 static int check_freq_tm271(int m, int d, int *defmode)
08105 {
08106 int dflmd = REM_MODE_FM;
08107
08108 if (m == 144){
08109 if(d < 10100)
08110 return -1;
08111 }
08112 else if((m >= 145) && (m < 148)){
08113 ;
08114 }
08115 return -1;
08116
08117 if(defmode)
08118 *defmode = dflmd;
08119
08120
08121 return 0;
08122 }
08123
08124
08125
08126
08127
08128 static int check_freq_rbi(int m, int d, int *defmode)
08129 {
08130 int dflmd = REM_MODE_FM;
08131
08132 if(m == 50){
08133 if(d < 10100)
08134 return -1;
08135 }
08136 else if((m >= 51) && ( m < 54)){
08137 ;
08138 }
08139 else if(m == 144){
08140 if(d < 10100)
08141 return -1;
08142 }
08143 else if((m >= 145) && (m < 148)){
08144 ;
08145 }
08146 else if((m >= 222) && (m < 225)){
08147 ;
08148 }
08149 else if((m >= 430) && (m < 450)){
08150 ;
08151 }
08152 else if((m >= 1240) && (m < 1300)){
08153 ;
08154 }
08155 else
08156 return -1;
08157
08158 if(defmode)
08159 *defmode = dflmd;
08160
08161
08162 return 0;
08163 }
08164
08165
08166
08167
08168 static int check_freq_rtx(int m, int d, int *defmode, struct rpt *myrpt)
08169 {
08170 int dflmd = REM_MODE_FM;
08171
08172 if (!strcmp(myrpt->remoterig,remote_rig_rtx150))
08173 {
08174
08175 if(m == 144){
08176 if(d < 10100)
08177 return -1;
08178 }
08179 else if((m >= 145) && (m < 148)){
08180 ;
08181 }
08182 else
08183 return -1;
08184 }
08185 else
08186 {
08187 if((m >= 430) && (m < 450)){
08188 ;
08189 }
08190 else
08191 return -1;
08192 }
08193 if(defmode)
08194 *defmode = dflmd;
08195
08196
08197 return 0;
08198 }
08199
08200
08201
08202
08203
08204 static int decimals2int(char *fraction)
08205 {
08206 int i;
08207 char len = strlen(fraction);
08208 int multiplier = 100000;
08209 int res = 0;
08210
08211 if(!len)
08212 return 0;
08213 for( i = 0 ; i < len ; i++, multiplier /= 10)
08214 res += (fraction[i] - '0') * multiplier;
08215 return res;
08216 }
08217
08218
08219
08220
08221
08222
08223 static int split_freq(char *mhz, char *decimals, char *freq)
08224 {
08225 char freq_copy[MAXREMSTR];
08226 char *decp;
08227
08228 decp = strchr(strncpy(freq_copy, freq, MAXREMSTR),'.');
08229 if(decp){
08230 *decp++ = 0;
08231 strncpy(mhz, freq_copy, MAXREMSTR);
08232 strcpy(decimals, "00000");
08233 strncpy(decimals, decp, strlen(decp));
08234 decimals[5] = 0;
08235 return 0;
08236 }
08237 else
08238 return -1;
08239
08240 }
08241
08242
08243
08244
08245
08246 static int split_ctcss_freq(char *hertz, char *decimal, char *freq)
08247 {
08248 char freq_copy[MAXREMSTR];
08249 char *decp;
08250
08251 decp = strchr(strncpy(freq_copy, freq, MAXREMSTR),'.');
08252 if(decp){
08253 *decp++ = 0;
08254 strncpy(hertz, freq_copy, MAXREMSTR);
08255 strncpy(decimal, decp, strlen(decp));
08256 decimal[strlen(decp)] = '\0';
08257 return 0;
08258 }
08259 else
08260 return -1;
08261 }
08262
08263
08264
08265
08266
08267
08268
08269
08270
08271
08272
08273 static int check_freq_ft897(int m, int d, int *defmode)
08274 {
08275 int dflmd = REM_MODE_FM;
08276
08277 if(m == 1){
08278 dflmd = REM_MODE_LSB;
08279 if(d < 80000)
08280 return -1;
08281 }
08282 else if(m == 3){
08283 dflmd = REM_MODE_LSB;
08284 if(d < 50000)
08285 return -1;
08286 }
08287 else if(m == 7){
08288 dflmd = REM_MODE_LSB;
08289 if(d > 30000)
08290 return -1;
08291 }
08292 else if(m == 14){
08293 dflmd = REM_MODE_USB;
08294 if(d > 35000)
08295 return -1;
08296 }
08297 else if(m == 18){
08298 dflmd = REM_MODE_USB;
08299 if((d < 6800) || (d > 16800))
08300 return -1;
08301 }
08302 else if(m == 21){
08303 dflmd = REM_MODE_USB;
08304 if((d < 20000) || (d > 45000))
08305 return -1;
08306 }
08307 else if(m == 24){
08308 dflmd = REM_MODE_USB;
08309 if((d < 89000) || (d > 99000))
08310 return -1;
08311 }
08312 else if(m == 28){
08313 dflmd = REM_MODE_USB;
08314 }
08315 else if(m == 29){
08316 if(d >= 51000)
08317 dflmd = REM_MODE_FM;
08318 else
08319 dflmd = REM_MODE_USB;
08320 if(d > 70000)
08321 return -1;
08322 }
08323 else if(m == 50){
08324 if(d >= 30000)
08325 dflmd = REM_MODE_FM;
08326 else
08327 dflmd = REM_MODE_USB;
08328
08329 }
08330 else if((m >= 51) && ( m < 54)){
08331 dflmd = REM_MODE_FM;
08332 }
08333 else if(m == 144){
08334 if(d >= 30000)
08335 dflmd = REM_MODE_FM;
08336 else
08337 dflmd = REM_MODE_USB;
08338 }
08339 else if((m >= 145) && (m < 148)){
08340 dflmd = REM_MODE_FM;
08341 }
08342 else if((m >= 430) && (m < 450)){
08343 if(m < 438)
08344 dflmd = REM_MODE_USB;
08345 else
08346 dflmd = REM_MODE_FM;
08347 ;
08348 }
08349 else
08350 return -1;
08351
08352 if(defmode)
08353 *defmode = dflmd;
08354
08355 return 0;
08356 }
08357
08358
08359
08360
08361
08362 static int set_freq_ft897(struct rpt *myrpt, char *newfreq)
08363 {
08364 unsigned char cmdstr[5];
08365 int fd,m,d;
08366 char mhz[MAXREMSTR];
08367 char decimals[MAXREMSTR];
08368
08369 fd = 0;
08370 if(debug)
08371 printf("New frequency: %s\n",newfreq);
08372
08373 if(split_freq(mhz, decimals, newfreq))
08374 return -1;
08375
08376 m = atoi(mhz);
08377 d = atoi(decimals);
08378
08379
08380
08381 cmdstr[0] = ((m / 100) << 4) + ((m % 100)/10);
08382 cmdstr[1] = ((m % 10) << 4) + (d / 10000);
08383 cmdstr[2] = (((d % 10000)/1000) << 4) + ((d % 1000)/ 100);
08384 cmdstr[3] = (((d % 100)/10) << 4) + (d % 10);
08385 cmdstr[4] = 0x01;
08386
08387 return serial_remote_io(myrpt, cmdstr, 5, NULL, 0, 0);
08388
08389 }
08390
08391
08392
08393 static int simple_command_ft897(struct rpt *myrpt, char command)
08394 {
08395 unsigned char cmdstr[5];
08396
08397 memset(cmdstr, 0, 5);
08398
08399 cmdstr[4] = command;
08400
08401 return serial_remote_io(myrpt, cmdstr, 5, NULL, 0, 0);
08402
08403 }
08404
08405
08406
08407 static int set_offset_ft897(struct rpt *myrpt, char offset)
08408 {
08409 unsigned char cmdstr[5];
08410
08411 memset(cmdstr, 0, 5);
08412
08413 switch(offset){
08414 case REM_SIMPLEX:
08415 cmdstr[0] = 0x89;
08416 break;
08417
08418 case REM_MINUS:
08419 cmdstr[0] = 0x09;
08420 break;
08421
08422 case REM_PLUS:
08423 cmdstr[0] = 0x49;
08424 break;
08425
08426 default:
08427 return -1;
08428 }
08429
08430 cmdstr[4] = 0x09;
08431
08432 return serial_remote_io(myrpt, cmdstr, 5, NULL, 0, 0);
08433 }
08434
08435
08436
08437 static int set_mode_ft897(struct rpt *myrpt, char newmode)
08438 {
08439 unsigned char cmdstr[5];
08440
08441 memset(cmdstr, 0, 5);
08442
08443 switch(newmode){
08444 case REM_MODE_FM:
08445 cmdstr[0] = 0x08;
08446 break;
08447
08448 case REM_MODE_USB:
08449 cmdstr[0] = 0x01;
08450 break;
08451
08452 case REM_MODE_LSB:
08453 cmdstr[0] = 0x00;
08454 break;
08455
08456 case REM_MODE_AM:
08457 cmdstr[0] = 0x04;
08458 break;
08459
08460 default:
08461 return -1;
08462 }
08463 cmdstr[4] = 0x07;
08464
08465 return serial_remote_io(myrpt, cmdstr, 5, NULL, 0, 0);
08466 }
08467
08468
08469
08470 static int set_ctcss_mode_ft897(struct rpt *myrpt, char txplon, char rxplon)
08471 {
08472 unsigned char cmdstr[5];
08473
08474 memset(cmdstr, 0, 5);
08475
08476 if(rxplon && txplon)
08477 cmdstr[0] = 0x2A;
08478 else if (!rxplon && txplon)
08479 cmdstr[0] = 0x4A;
08480 else if (rxplon && !txplon)
08481 cmdstr[0] = 0x3A;
08482 else
08483 cmdstr[0] = 0x8A;
08484
08485 cmdstr[4] = 0x0A;
08486
08487 return serial_remote_io(myrpt, cmdstr, 5, NULL, 0, 0);
08488 }
08489
08490
08491
08492
08493 static int set_ctcss_freq_ft897(struct rpt *myrpt, char *txtone, char *rxtone)
08494 {
08495 unsigned char cmdstr[5];
08496 char hertz[MAXREMSTR],decimal[MAXREMSTR];
08497 int h,d;
08498
08499 memset(cmdstr, 0, 5);
08500
08501 if(split_ctcss_freq(hertz, decimal, txtone))
08502 return -1;
08503
08504 h = atoi(hertz);
08505 d = atoi(decimal);
08506
08507 cmdstr[0] = ((h / 100) << 4) + (h % 100)/ 10;
08508 cmdstr[1] = ((h % 10) << 4) + (d % 10);
08509
08510 if(rxtone){
08511
08512 if(split_ctcss_freq(hertz, decimal, rxtone))
08513 return -1;
08514
08515 h = atoi(hertz);
08516 d = atoi(decimal);
08517
08518 cmdstr[2] = ((h / 100) << 4) + (h % 100)/ 10;
08519 cmdstr[3] = ((h % 10) << 4) + (d % 10);
08520 }
08521 cmdstr[4] = 0x0B;
08522
08523 return serial_remote_io(myrpt, cmdstr, 5, NULL, 0, 0);
08524 }
08525
08526
08527
08528 static int set_ft897(struct rpt *myrpt)
08529 {
08530 int res;
08531
08532 if(debug)
08533 printf("@@@@ lock on\n");
08534
08535 res = simple_command_ft897(myrpt, 0x00);
08536
08537 if(debug)
08538 printf("@@@@ ptt off\n");
08539
08540 if(!res)
08541 res = simple_command_ft897(myrpt, 0x88);
08542
08543 if(debug)
08544 printf("Modulation mode\n");
08545
08546 if(!res)
08547 res = set_mode_ft897(myrpt, myrpt->remmode);
08548
08549 if(debug)
08550 printf("Split off\n");
08551
08552 if(!res)
08553 simple_command_ft897(myrpt, 0x82);
08554
08555 if(debug)
08556 printf("Frequency\n");
08557
08558 if(!res)
08559 res = set_freq_ft897(myrpt, myrpt->freq);
08560 if((myrpt->remmode == REM_MODE_FM)){
08561 if(debug)
08562 printf("Offset\n");
08563 if(!res)
08564 res = set_offset_ft897(myrpt, myrpt->offset);
08565 if((!res)&&(myrpt->rxplon || myrpt->txplon)){
08566 if(debug)
08567 printf("CTCSS tone freqs.\n");
08568 res = set_ctcss_freq_ft897(myrpt, myrpt->txpl, myrpt->rxpl);
08569 }
08570 if(!res){
08571 if(debug)
08572 printf("CTCSS mode\n");
08573 res = set_ctcss_mode_ft897(myrpt, myrpt->txplon, myrpt->rxplon);
08574 }
08575 }
08576 if((myrpt->remmode == REM_MODE_USB)||(myrpt->remmode == REM_MODE_LSB)){
08577 if(debug)
08578 printf("Clarifier off\n");
08579 simple_command_ft897(myrpt, 0x85);
08580 }
08581 return res;
08582 }
08583
08584 static int closerem_ft897(struct rpt *myrpt)
08585 {
08586 simple_command_ft897(myrpt, 0x88);
08587 return 0;
08588 }
08589
08590
08591
08592
08593
08594
08595
08596 static int multimode_bump_freq_ft897(struct rpt *myrpt, int interval)
08597 {
08598 int m,d;
08599 char mhz[MAXREMSTR], decimals[MAXREMSTR];
08600
08601 if(debug)
08602 printf("Before bump: %s\n", myrpt->freq);
08603
08604 if(split_freq(mhz, decimals, myrpt->freq))
08605 return -1;
08606
08607 m = atoi(mhz);
08608 d = atoi(decimals);
08609
08610 d += (interval / 10);
08611 if(d < 0){
08612 m--;
08613 d += 100000;
08614 }
08615 else if(d >= 100000){
08616 m++;
08617 d -= 100000;
08618 }
08619
08620 if(check_freq_ft897(m, d, NULL)){
08621 if(debug)
08622 printf("Bump freq invalid\n");
08623 return -1;
08624 }
08625
08626 snprintf(myrpt->freq, MAXREMSTR, "%d.%05d", m, d);
08627
08628 if(debug)
08629 printf("After bump: %s\n", myrpt->freq);
08630
08631 return set_freq_ft897(myrpt, myrpt->freq);
08632 }
08633
08634
08635
08636
08637
08638
08639
08640
08641
08642
08643 static int check_freq_ic706(int m, int d, int *defmode, char mars)
08644 {
08645 int dflmd = REM_MODE_FM;
08646 int rv=0;
08647
08648 if(debug > 6)
08649 ast_log(LOG_NOTICE,"(%i,%i,%i,%i)\n",m,d,*defmode,mars);
08650
08651
08652
08653 if(m == 1){
08654 dflmd = REM_MODE_LSB;
08655 if(d < 80000)rv=-1;
08656 }
08657 else if(m == 3){
08658 dflmd = REM_MODE_LSB;
08659 if(d < 50000)rv=-1;
08660 }
08661 else if(m == 7){
08662 dflmd = REM_MODE_LSB;
08663 if(d > 30000)rv=-1;
08664 }
08665 else if(m == 14){
08666 dflmd = REM_MODE_USB;
08667 if(d > 35000)rv=-1;
08668 }
08669 else if(m == 18){
08670 dflmd = REM_MODE_USB;
08671 if((d < 6800) || (d > 16800))rv=-1;
08672 }
08673 else if(m == 21){
08674 dflmd = REM_MODE_USB;
08675 if((d < 20000) || (d > 45000))rv=-1;
08676 }
08677 else if(m == 24){
08678 dflmd = REM_MODE_USB;
08679 if((d < 89000) || (d > 99000))rv=-1;
08680 }
08681 else if(m == 28){
08682 dflmd = REM_MODE_USB;
08683 }
08684 else if(m == 29){
08685 if(d >= 51000)
08686 dflmd = REM_MODE_FM;
08687 else
08688 dflmd = REM_MODE_USB;
08689 if(d > 70000)rv=-1;
08690 }
08691 else if(m == 50){
08692 if(d >= 30000)
08693 dflmd = REM_MODE_FM;
08694 else
08695 dflmd = REM_MODE_USB;
08696 }
08697 else if((m >= 51) && ( m < 54)){
08698 dflmd = REM_MODE_FM;
08699 }
08700 else if(m == 144){
08701 if(d >= 30000)
08702 dflmd = REM_MODE_FM;
08703 else
08704 dflmd = REM_MODE_USB;
08705 }
08706 else if((m >= 145) && (m < 148)){
08707 dflmd = REM_MODE_FM;
08708 }
08709 else if((m >= 430) && (m < 450)){
08710 if(m < 438)
08711 dflmd = REM_MODE_USB;
08712 else
08713 dflmd = REM_MODE_FM;
08714 }
08715
08716
08717 if(mars && rv<0){
08718 if((m >= 450) && (m < 470)){
08719 dflmd = REM_MODE_FM;
08720 rv=0;
08721 }
08722 else if((m >= 148) && (m < 174)){
08723 dflmd = REM_MODE_FM;
08724 rv=0;
08725 }
08726 else if((m >= 138) && (m < 144)){
08727 dflmd = REM_MODE_AM;
08728 rv=0;
08729 }
08730 else if((m >= 108) && (m < 138)){
08731 dflmd = REM_MODE_AM;
08732 rv=0;
08733 }
08734 else if( (m==0 && d>=55000) || (m==1 && d<=75000) ){
08735 dflmd = REM_MODE_AM;
08736 rv=0;
08737 }
08738 else if( (m == 1 && d>75000) || (m>1 && m<30) ){
08739 dflmd = REM_MODE_AM;
08740 rv=0;
08741 }
08742 }
08743
08744 if(defmode)
08745 *defmode = dflmd;
08746
08747 if(debug > 1)
08748 ast_log(LOG_NOTICE,"(%i,%i,%i,%i) returning %i\n",m,d,*defmode,mars,rv);
08749
08750 return rv;
08751 }
08752
08753
08754 static int ic706_pltocode(char *str)
08755 {
08756 int i;
08757 char *s;
08758 int rv=-1;
08759
08760 s = strchr(str,'.');
08761 i = 0;
08762 if (s) i = atoi(s + 1);
08763 i += atoi(str) * 10;
08764 switch(i)
08765 {
08766 case 670:
08767 rv=0;
08768 case 693:
08769 rv=1;
08770 case 719:
08771 rv=2;
08772 case 744:
08773 rv=3;
08774 case 770:
08775 rv=4;
08776 case 797:
08777 rv=5;
08778 case 825:
08779 rv=6;
08780 case 854:
08781 rv=7;
08782 case 885:
08783 rv=8;
08784 case 915:
08785 rv=9;
08786 case 948:
08787 rv=10;
08788 case 974:
08789 rv=11;
08790 case 1000:
08791 rv=12;
08792 case 1035:
08793 rv=13;
08794 case 1072:
08795 rv=14;
08796 case 1109:
08797 rv=15;
08798 case 1148:
08799 rv=16;
08800 case 1188:
08801 rv=17;
08802 case 1230:
08803 rv=18;
08804 case 1273:
08805 rv=19;
08806 case 1318:
08807 rv=20;
08808 case 1365:
08809 rv=21;
08810 case 1413:
08811 rv=22;
08812 case 1462:
08813 rv=23;
08814 case 1514:
08815 rv=24;
08816 case 1567:
08817 rv=25;
08818 case 1598:
08819 rv=26;
08820 case 1622:
08821 rv=27;
08822 case 1655:
08823 rv=28;
08824 case 1679:
08825 rv=29;
08826 case 1713:
08827 rv=30;
08828 case 1738:
08829 rv=31;
08830 case 1773:
08831 rv=32;
08832 case 1799:
08833 rv=33;
08834 case 1835:
08835 rv=34;
08836 case 1862:
08837 rv=35;
08838 case 1899:
08839 rv=36;
08840 case 1928:
08841 rv=37;
08842 case 1966:
08843 rv=38;
08844 case 1995:
08845 rv=39;
08846 case 2035:
08847 rv=40;
08848 case 2065:
08849 rv=41;
08850 case 2107:
08851 rv=42;
08852 case 2181:
08853 rv=43;
08854 case 2257:
08855 rv=44;
08856 case 2291:
08857 rv=45;
08858 case 2336:
08859 rv=46;
08860 case 2418:
08861 rv=47;
08862 case 2503:
08863 rv=48;
08864 case 2541:
08865 rv=49;
08866 }
08867 if(debug > 1)
08868 ast_log(LOG_NOTICE,"%i rv=%i\n",i, rv);
08869
08870 return rv;
08871 }
08872
08873
08874
08875 static int simple_command_ic706(struct rpt *myrpt, char command, char subcommand)
08876 {
08877 unsigned char cmdstr[10];
08878
08879 cmdstr[0] = cmdstr[1] = 0xfe;
08880 cmdstr[2] = myrpt->p.civaddr;
08881 cmdstr[3] = 0xe0;
08882 cmdstr[4] = command;
08883 cmdstr[5] = subcommand;
08884 cmdstr[6] = 0xfd;
08885
08886 return(civ_cmd(myrpt,cmdstr,7));
08887 }
08888
08889
08890
08891
08892
08893 static int set_freq_ic706(struct rpt *myrpt, char *newfreq)
08894 {
08895 unsigned char cmdstr[20];
08896 char mhz[MAXREMSTR], decimals[MAXREMSTR];
08897 int fd,m,d;
08898
08899 fd = 0;
08900 if(debug)
08901 ast_log(LOG_NOTICE,"newfreq:%s\n",newfreq);
08902
08903 if(split_freq(mhz, decimals, newfreq))
08904 return -1;
08905
08906 m = atoi(mhz);
08907 d = atoi(decimals);
08908
08909
08910
08911 cmdstr[0] = cmdstr[1] = 0xfe;
08912 cmdstr[2] = myrpt->p.civaddr;
08913 cmdstr[3] = 0xe0;
08914 cmdstr[4] = 5;
08915 cmdstr[5] = ((d % 10) << 4);
08916 cmdstr[6] = (((d % 1000)/ 100) << 4) + ((d % 100)/10);
08917 cmdstr[7] = ((d / 10000) << 4) + ((d % 10000)/1000);
08918 cmdstr[8] = (((m % 100)/10) << 4) + (m % 10);
08919 cmdstr[9] = (m / 100);
08920 cmdstr[10] = 0xfd;
08921
08922 return(civ_cmd(myrpt,cmdstr,11));
08923 }
08924
08925
08926
08927 static int set_offset_ic706(struct rpt *myrpt, char offset)
08928 {
08929 unsigned char c;
08930
08931 if(debug > 6)
08932 ast_log(LOG_NOTICE,"offset=%i\n",offset);
08933
08934 switch(offset){
08935 case REM_SIMPLEX:
08936 c = 0x10;
08937 break;
08938
08939 case REM_MINUS:
08940 c = 0x11;
08941 break;
08942
08943 case REM_PLUS:
08944 c = 0x12;
08945 break;
08946
08947 default:
08948 return -1;
08949 }
08950
08951 return simple_command_ic706(myrpt,0x0f,c);
08952
08953 }
08954
08955
08956
08957 static int set_mode_ic706(struct rpt *myrpt, char newmode)
08958 {
08959 unsigned char c;
08960
08961 if(debug > 6)
08962 ast_log(LOG_NOTICE,"newmode=%i\n",newmode);
08963
08964 switch(newmode){
08965 case REM_MODE_FM:
08966 c = 5;
08967 break;
08968
08969 case REM_MODE_USB:
08970 c = 1;
08971 break;
08972
08973 case REM_MODE_LSB:
08974 c = 0;
08975 break;
08976
08977 case REM_MODE_AM:
08978 c = 2;
08979 break;
08980
08981 default:
08982 return -1;
08983 }
08984 return simple_command_ic706(myrpt,6,c);
08985 }
08986
08987
08988
08989 static int set_ctcss_mode_ic706(struct rpt *myrpt, char txplon, char rxplon)
08990 {
08991 unsigned char cmdstr[10];
08992 int rv;
08993
08994 if(debug > 6)
08995 ast_log(LOG_NOTICE,"txplon=%i rxplon=%i \n",txplon,rxplon);
08996
08997 cmdstr[0] = cmdstr[1] = 0xfe;
08998 cmdstr[2] = myrpt->p.civaddr;
08999 cmdstr[3] = 0xe0;
09000 cmdstr[4] = 0x16;
09001 cmdstr[5] = 0x42;
09002 cmdstr[6] = (txplon != 0);
09003 cmdstr[7] = 0xfd;
09004
09005 rv = civ_cmd(myrpt,cmdstr,8);
09006 if (rv) return(-1);
09007
09008 cmdstr[0] = cmdstr[1] = 0xfe;
09009 cmdstr[2] = myrpt->p.civaddr;
09010 cmdstr[3] = 0xe0;
09011 cmdstr[4] = 0x16;
09012 cmdstr[5] = 0x43;
09013 cmdstr[6] = (rxplon != 0);
09014 cmdstr[7] = 0xfd;
09015
09016 return(civ_cmd(myrpt,cmdstr,8));
09017 }
09018
09019 #if 0
09020
09021
09022 static int set_ctcss_freq_ic706(struct rpt *myrpt, char *txtone, char *rxtone)
09023 {
09024 unsigned char cmdstr[10];
09025 char hertz[MAXREMSTR],decimal[MAXREMSTR];
09026 int h,d,rv;
09027
09028 memset(cmdstr, 0, 5);
09029
09030 if(debug > 6)
09031 ast_log(LOG_NOTICE,"txtone=%s rxtone=%s \n",txtone,rxtone);
09032
09033 if(split_ctcss_freq(hertz, decimal, txtone))
09034 return -1;
09035
09036 h = atoi(hertz);
09037 d = atoi(decimal);
09038
09039 cmdstr[0] = cmdstr[1] = 0xfe;
09040 cmdstr[2] = myrpt->p.civaddr;
09041 cmdstr[3] = 0xe0;
09042 cmdstr[4] = 0x1b;
09043 cmdstr[5] = 0;
09044 cmdstr[6] = ((h / 100) << 4) + (h % 100)/ 10;
09045 cmdstr[7] = ((h % 10) << 4) + (d % 10);
09046 cmdstr[8] = 0xfd;
09047
09048 rv = civ_cmd(myrpt,cmdstr,9);
09049 if (rv) return(-1);
09050
09051 if (!rxtone) return(0);
09052
09053 if(split_ctcss_freq(hertz, decimal, rxtone))
09054 return -1;
09055
09056 h = atoi(hertz);
09057 d = atoi(decimal);
09058
09059 cmdstr[0] = cmdstr[1] = 0xfe;
09060 cmdstr[2] = myrpt->p.civaddr;
09061 cmdstr[3] = 0xe0;
09062 cmdstr[4] = 0x1b;
09063 cmdstr[5] = 1;
09064 cmdstr[6] = ((h / 100) << 4) + (h % 100)/ 10;
09065 cmdstr[7] = ((h % 10) << 4) + (d % 10);
09066 cmdstr[8] = 0xfd;
09067 return(civ_cmd(myrpt,cmdstr,9));
09068 }
09069 #endif
09070
09071 static int vfo_ic706(struct rpt *myrpt)
09072 {
09073 unsigned char cmdstr[10];
09074
09075 cmdstr[0] = cmdstr[1] = 0xfe;
09076 cmdstr[2] = myrpt->p.civaddr;
09077 cmdstr[3] = 0xe0;
09078 cmdstr[4] = 7;
09079 cmdstr[5] = 0xfd;
09080
09081 return(civ_cmd(myrpt,cmdstr,6));
09082 }
09083
09084 static int mem2vfo_ic706(struct rpt *myrpt)
09085 {
09086 unsigned char cmdstr[10];
09087
09088 cmdstr[0] = cmdstr[1] = 0xfe;
09089 cmdstr[2] = myrpt->p.civaddr;
09090 cmdstr[3] = 0xe0;
09091 cmdstr[4] = 0x0a;
09092 cmdstr[5] = 0xfd;
09093
09094 return(civ_cmd(myrpt,cmdstr,6));
09095 }
09096
09097 static int select_mem_ic706(struct rpt *myrpt, int slot)
09098 {
09099 unsigned char cmdstr[10];
09100
09101 cmdstr[0] = cmdstr[1] = 0xfe;
09102 cmdstr[2] = myrpt->p.civaddr;
09103 cmdstr[3] = 0xe0;
09104 cmdstr[4] = 8;
09105 cmdstr[5] = 0;
09106 cmdstr[6] = ((slot / 10) << 4) + (slot % 10);
09107 cmdstr[7] = 0xfd;
09108
09109 return(civ_cmd(myrpt,cmdstr,8));
09110 }
09111
09112 static int set_ic706(struct rpt *myrpt)
09113 {
09114 int res = 0,i;
09115
09116 if(debug)ast_log(LOG_NOTICE, "Set to VFO A iobase=%i\n",myrpt->p.iobase);
09117
09118 if (!res)
09119 res = simple_command_ic706(myrpt,7,0);
09120
09121 if((myrpt->remmode == REM_MODE_FM))
09122 {
09123 i = ic706_pltocode(myrpt->rxpl);
09124 if (i == -1) return -1;
09125 if(debug)
09126 printf("Select memory number\n");
09127 if (!res)
09128 res = select_mem_ic706(myrpt,i + IC706_PL_MEMORY_OFFSET);
09129 if(debug)
09130 printf("Transfer memory to VFO\n");
09131 if (!res)
09132 res = mem2vfo_ic706(myrpt);
09133 }
09134
09135 if(debug)
09136 printf("Set to VFO\n");
09137
09138 if (!res)
09139 res = vfo_ic706(myrpt);
09140
09141 if(debug)
09142 printf("Modulation mode\n");
09143
09144 if (!res)
09145 res = set_mode_ic706(myrpt, myrpt->remmode);
09146
09147 if(debug)
09148 printf("Split off\n");
09149
09150 if(!res)
09151 simple_command_ic706(myrpt, 0x82,0);
09152
09153 if(debug)
09154 printf("Frequency\n");
09155
09156 if(!res)
09157 res = set_freq_ic706(myrpt, myrpt->freq);
09158 if((myrpt->remmode == REM_MODE_FM)){
09159 if(debug)
09160 printf("Offset\n");
09161 if(!res)
09162 res = set_offset_ic706(myrpt, myrpt->offset);
09163 if(!res){
09164 if(debug)
09165 printf("CTCSS mode\n");
09166 res = set_ctcss_mode_ic706(myrpt, myrpt->txplon, myrpt->rxplon);
09167 }
09168 }
09169 return res;
09170 }
09171
09172
09173
09174
09175
09176
09177
09178 static int multimode_bump_freq_ic706(struct rpt *myrpt, int interval)
09179 {
09180 int m,d;
09181 char mhz[MAXREMSTR], decimals[MAXREMSTR];
09182 unsigned char cmdstr[20];
09183
09184 if(debug)
09185 printf("Before bump: %s\n", myrpt->freq);
09186
09187 if(split_freq(mhz, decimals, myrpt->freq))
09188 return -1;
09189
09190 m = atoi(mhz);
09191 d = atoi(decimals);
09192
09193 d += (interval / 10);
09194 if(d < 0){
09195 m--;
09196 d += 100000;
09197 }
09198 else if(d >= 100000){
09199 m++;
09200 d -= 100000;
09201 }
09202
09203 if(check_freq_ic706(m, d, NULL,myrpt->p.remote_mars)){
09204 if(debug)
09205 printf("Bump freq invalid\n");
09206 return -1;
09207 }
09208
09209 snprintf(myrpt->freq, MAXREMSTR, "%d.%05d", m, d);
09210
09211 if(debug)
09212 printf("After bump: %s\n", myrpt->freq);
09213
09214
09215
09216 cmdstr[0] = cmdstr[1] = 0xfe;
09217 cmdstr[2] = myrpt->p.civaddr;
09218 cmdstr[3] = 0xe0;
09219 cmdstr[4] = 0;
09220 cmdstr[5] = ((d % 10) << 4);
09221 cmdstr[6] = (((d % 1000)/ 100) << 4) + ((d % 100)/10);
09222 cmdstr[7] = ((d / 10000) << 4) + ((d % 10000)/1000);
09223 cmdstr[8] = (((m % 100)/10) << 4) + (m % 10);
09224 cmdstr[9] = (m / 100);
09225 cmdstr[10] = 0xfd;
09226
09227 return(serial_remote_io(myrpt,cmdstr,11,NULL,0,0));
09228 }
09229
09230
09231
09232
09233
09234
09235 static int setrem(struct rpt *myrpt)
09236 {
09237 char str[300];
09238 char *offsets[] = {"SIMPLEX","MINUS","PLUS"};
09239 char *powerlevels[] = {"LOW","MEDIUM","HIGH"};
09240 char *modes[] = {"FM","USB","LSB","AM"};
09241 int res = -1;
09242
09243 #if 0
09244 printf("FREQ,%s,%s,%s,%s,%s,%s,%d,%d\n",myrpt->freq,
09245 modes[(int)myrpt->remmode],
09246 myrpt->txpl,myrpt->rxpl,offsets[(int)myrpt->offset],
09247 powerlevels[(int)myrpt->powerlevel],myrpt->txplon,
09248 myrpt->rxplon);
09249 #endif
09250 if (myrpt->p.archivedir)
09251 {
09252 sprintf(str,"FREQ,%s,%s,%s,%s,%s,%s,%d,%d",myrpt->freq,
09253 modes[(int)myrpt->remmode],
09254 myrpt->txpl,myrpt->rxpl,offsets[(int)myrpt->offset],
09255 powerlevels[(int)myrpt->powerlevel],myrpt->txplon,
09256 myrpt->rxplon);
09257 donodelog(myrpt,str);
09258 }
09259 if(!strcmp(myrpt->remoterig, remote_rig_ft897))
09260 {
09261 rpt_telemetry(myrpt,SETREMOTE,NULL);
09262 res = 0;
09263 }
09264 if(!strcmp(myrpt->remoterig, remote_rig_ic706))
09265 {
09266 rpt_telemetry(myrpt,SETREMOTE,NULL);
09267 res = 0;
09268 }
09269 if(!strcmp(myrpt->remoterig, remote_rig_tm271))
09270 {
09271 rpt_telemetry(myrpt,SETREMOTE,NULL);
09272 res = 0;
09273 }
09274 else if(!strcmp(myrpt->remoterig, remote_rig_rbi))
09275 {
09276 res = setrbi_check(myrpt);
09277 if (!res)
09278 {
09279 rpt_telemetry(myrpt,SETREMOTE,NULL);
09280 res = 0;
09281 }
09282 }
09283 else if(ISRIG_RTX(myrpt->remoterig))
09284 {
09285 setrtx(myrpt);
09286 res = 0;
09287 }
09288 else if(!strcmp(myrpt->remoterig, remote_rig_kenwood)) {
09289 rpt_telemetry(myrpt,SETREMOTE,NULL);
09290 res = 0;
09291 }
09292 else
09293 res = 0;
09294
09295 if (res < 0) ast_log(LOG_ERROR,"Unable to send remote command on node %s\n",myrpt->name);
09296
09297 return res;
09298 }
09299
09300 static int closerem(struct rpt *myrpt)
09301 {
09302 if(!strcmp(myrpt->remoterig, remote_rig_ft897))
09303 return closerem_ft897(myrpt);
09304 else
09305 return 0;
09306 }
09307
09308
09309
09310
09311
09312 static int check_freq(struct rpt *myrpt, int m, int d, int *defmode)
09313 {
09314 if(!strcmp(myrpt->remoterig, remote_rig_ft897))
09315 return check_freq_ft897(m, d, defmode);
09316 else if(!strcmp(myrpt->remoterig, remote_rig_ic706))
09317 return check_freq_ic706(m, d, defmode,myrpt->p.remote_mars);
09318 else if(!strcmp(myrpt->remoterig, remote_rig_rbi))
09319 return check_freq_rbi(m, d, defmode);
09320 else if(!strcmp(myrpt->remoterig, remote_rig_kenwood))
09321 return check_freq_kenwood(m, d, defmode);
09322 else if(!strcmp(myrpt->remoterig, remote_rig_tm271))
09323 return check_freq_tm271(m, d, defmode);
09324 else if(ISRIG_RTX(myrpt->remoterig))
09325 return check_freq_rtx(m, d, defmode, myrpt);
09326 else
09327 return -1;
09328 }
09329
09330
09331
09332
09333
09334
09335 static char check_tx_freq(struct rpt *myrpt)
09336 {
09337 int i,rv=0;
09338 int radio_mhz, radio_decimals, ulimit_mhz, ulimit_decimals, llimit_mhz, llimit_decimals;
09339 char radio_mhz_char[MAXREMSTR];
09340 char radio_decimals_char[MAXREMSTR];
09341 char limit_mhz_char[MAXREMSTR];
09342 char limit_decimals_char[MAXREMSTR];
09343 char limits[256];
09344 char *limit_ranges[40];
09345 struct ast_variable *limitlist;
09346
09347 if(debug > 3){
09348 ast_log(LOG_NOTICE, "myrpt->freq = %s\n", myrpt->freq);
09349 }
09350
09351
09352
09353 if(!myrpt->p.txlimitsstanzaname || !myrpt->loginuser[0] || !myrpt->loginlevel[0]){
09354 if(debug > 3){
09355 ast_log(LOG_NOTICE, "No tx band table defined, or no user logged in. rv=1\n");
09356 }
09357 rv=1;
09358 return 1;
09359 }
09360
09361
09362 limitlist = ast_variable_browse(myrpt->cfg, myrpt->p.txlimitsstanzaname);
09363
09364 if(!limitlist){
09365 ast_log(LOG_WARNING, "No entries in %s band table stanza. rv=0\n", myrpt->p.txlimitsstanzaname);
09366 rv=0;
09367 return 0;
09368 }
09369
09370 split_freq(radio_mhz_char, radio_decimals_char, myrpt->freq);
09371 radio_mhz = atoi(radio_mhz_char);
09372 radio_decimals = decimals2int(radio_decimals_char);
09373
09374 if(debug > 3){
09375 ast_log(LOG_NOTICE, "Login User = %s, login level = %s\n", myrpt->loginuser, myrpt->loginlevel);
09376 }
09377
09378
09379
09380 for(;limitlist; limitlist=limitlist->next){
09381 if(!strcmp(limitlist->name, myrpt->loginlevel))
09382 break;
09383 }
09384
09385 if(!limitlist){
09386 ast_log(LOG_WARNING, "Can't find %s entry in band table stanza %s. rv=0\n", myrpt->loginlevel, myrpt->p.txlimitsstanzaname);
09387 rv=0;
09388 return 0;
09389 }
09390
09391 if(debug > 3){
09392 ast_log(LOG_NOTICE, "Auth: %s = %s\n", limitlist->name, limitlist->value);
09393 }
09394
09395
09396
09397 strncpy(limits, limitlist->value, 256);
09398 limits[255] = 0;
09399 finddelim(limits, limit_ranges, 40);
09400 for(i = 0; i < 40 && limit_ranges[i] ; i++){
09401 char range[40];
09402 char *r,*s;
09403 strncpy(range, limit_ranges[i], 40);
09404 range[39] = 0;
09405 if(debug > 3)
09406 ast_log(LOG_NOTICE, "Check %s within %s\n", myrpt->freq, range);
09407
09408 r = strchr(range, '-');
09409 if(!r){
09410 ast_log(LOG_WARNING, "Malformed range in %s tx band table entry. rv=0\n", limitlist->name);
09411 rv=0;
09412 break;
09413 }
09414 *r++ = 0;
09415 s = eatwhite(range);
09416 r = eatwhite(r);
09417 split_freq(limit_mhz_char, limit_decimals_char, s);
09418 llimit_mhz = atoi(limit_mhz_char);
09419 llimit_decimals = decimals2int(limit_decimals_char);
09420 split_freq(limit_mhz_char, limit_decimals_char, r);
09421 ulimit_mhz = atoi(limit_mhz_char);
09422 ulimit_decimals = decimals2int(limit_decimals_char);
09423
09424 if((radio_mhz >= llimit_mhz) && (radio_mhz <= ulimit_mhz)){
09425 if(radio_mhz == llimit_mhz){
09426 if(radio_decimals >= llimit_decimals){
09427 if(llimit_mhz == ulimit_mhz){
09428 if(radio_decimals <= ulimit_decimals){
09429 rv=1;
09430 break;
09431 }
09432 else{
09433 if(debug > 3)
09434 ast_log(LOG_NOTICE, "Invalid TX frequency, debug msg 1\n");
09435 rv=0;
09436 break;
09437 }
09438 }
09439 else{
09440 rv=1;
09441 break;
09442 }
09443 }
09444 else{
09445 if(debug > 3)
09446 ast_log(LOG_NOTICE, "Invalid TX frequency, debug msg 2\n");
09447 rv=0;
09448 break;
09449 }
09450 }
09451 else if(radio_mhz == ulimit_mhz){
09452 if(radio_decimals <= ulimit_decimals){
09453 if(debug > 3)
09454 ast_log(LOG_NOTICE, "radio_decimals <= ulimit_decimals\n");
09455 rv=1;
09456 break;
09457 }
09458 else{
09459 if(debug > 3)
09460 ast_log(LOG_NOTICE, "Invalid TX frequency, debug msg 3\n");
09461 rv=0;
09462 break;
09463 }
09464 }
09465 else
09466 if(debug > 3)
09467 ast_log(LOG_NOTICE, "Valid TX freq within a multi-Mhz band and ok.\n");
09468 rv=1;
09469 break;
09470 }
09471 }
09472 if(debug > 3)
09473 ast_log(LOG_NOTICE, "rv=%i\n",rv);
09474
09475 return rv;
09476 }
09477
09478
09479
09480
09481
09482
09483 static int multimode_bump_freq(struct rpt *myrpt, int interval)
09484 {
09485 if(!strcmp(myrpt->remoterig, remote_rig_ft897))
09486 return multimode_bump_freq_ft897(myrpt, interval);
09487 else if(!strcmp(myrpt->remoterig, remote_rig_ic706))
09488 return multimode_bump_freq_ic706(myrpt, interval);
09489 else
09490 return -1;
09491 }
09492
09493
09494
09495
09496
09497
09498 static void stop_scan(struct rpt *myrpt)
09499 {
09500 myrpt->hfscanstop = 1;
09501 rpt_telemetry(myrpt,SCAN,0);
09502 }
09503
09504
09505
09506
09507
09508
09509 static int service_scan(struct rpt *myrpt)
09510 {
09511 int res, interval;
09512 char mhz[MAXREMSTR], decimals[MAXREMSTR], k10=0i, k100=0;
09513
09514 switch(myrpt->hfscanmode){
09515
09516 case HF_SCAN_DOWN_SLOW:
09517 interval = -10;
09518 break;
09519
09520 case HF_SCAN_DOWN_QUICK:
09521 interval = -50;
09522 break;
09523
09524 case HF_SCAN_DOWN_FAST:
09525 interval = -200;
09526 break;
09527
09528 case HF_SCAN_UP_SLOW:
09529 interval = 10;
09530 break;
09531
09532 case HF_SCAN_UP_QUICK:
09533 interval = 50;
09534 break;
09535
09536 case HF_SCAN_UP_FAST:
09537 interval = 200;
09538 break;
09539
09540 default:
09541 myrpt->hfscanmode = 0;
09542 return -1;
09543 }
09544
09545 res = split_freq(mhz, decimals, myrpt->freq);
09546
09547 if(!res){
09548 k100 =decimals[0];
09549 k10 = decimals[1];
09550 res = multimode_bump_freq(myrpt, interval);
09551 }
09552
09553 if(!res)
09554 res = split_freq(mhz, decimals, myrpt->freq);
09555
09556
09557 if(res){
09558 myrpt->hfscanmode = 0;
09559 myrpt->hfscanstatus = -2;
09560 return -1;
09561 }
09562
09563
09564 if(k10 != decimals[1]){
09565 int myhund = (interval < 0) ? k100 : decimals[0];
09566 int myten = (interval < 0) ? k10 : decimals[1];
09567 myrpt->hfscanstatus = (myten == '0') ? (myhund - '0') * 100 : (myten - '0') * 10;
09568 } else myrpt->hfscanstatus = 0;
09569 return res;
09570
09571 }
09572
09573
09574
09575 static int get_mem_set(struct rpt *myrpt, char *digitbuf)
09576 {
09577 int res=0;
09578 if(debug)ast_log(LOG_NOTICE," digitbuf=%s\n", digitbuf);
09579 res = retreive_memory(myrpt, digitbuf);
09580 if(!res)res=setrem(myrpt);
09581 if(debug)ast_log(LOG_NOTICE," freq=%s res=%i\n", myrpt->freq, res);
09582 return res;
09583 }
09584
09585
09586
09587
09588 static int channel_steer(struct rpt *myrpt, char *data)
09589 {
09590 int res=0;
09591
09592 if(debug)ast_log(LOG_NOTICE,"remoterig=%s, data=%s\n",myrpt->remoterig,data);
09593 if (!myrpt->remoterig) return(0);
09594 if(data<=0)
09595 {
09596 res=-1;
09597 }
09598 else
09599 {
09600 myrpt->nowchan=strtod(data,NULL);
09601 if(!strcmp(myrpt->remoterig, remote_rig_ppp16))
09602 {
09603 char string[16];
09604 sprintf(string,"SETCHAN %d ",myrpt->nowchan);
09605 send_usb_txt(myrpt,string);
09606 }
09607 else
09608 {
09609 if(get_mem_set(myrpt, data))res=-1;
09610 }
09611 }
09612 if(debug)ast_log(LOG_NOTICE,"nowchan=%i res=%i\n",myrpt->nowchan, res);
09613 return res;
09614 }
09615
09616
09617 static int channel_revert(struct rpt *myrpt)
09618 {
09619 int res=0;
09620 if(debug)ast_log(LOG_NOTICE,"remoterig=%s, nowchan=%02d, waschan=%02d\n",myrpt->remoterig,myrpt->nowchan,myrpt->waschan);
09621 if (!myrpt->remoterig) return(0);
09622 if(myrpt->nowchan!=myrpt->waschan)
09623 {
09624 char data[8];
09625 if(debug)ast_log(LOG_NOTICE,"reverting.\n");
09626 sprintf(data,"%02d",myrpt->waschan);
09627 myrpt->nowchan=myrpt->waschan;
09628 channel_steer(myrpt,data);
09629 res=1;
09630 }
09631 return(res);
09632 }
09633
09634
09635
09636
09637 static int function_remote(struct rpt *myrpt, char *param, char *digitbuf, int command_source, struct rpt_link *mylink)
09638 {
09639 char *s,*s1,*s2;
09640 int i,j,r,ht,k,l,ls2,m,d,offset,offsave, modesave, defmode=0;
09641 intptr_t p;
09642 char multimode = 0;
09643 char oc,*cp,*cp1,*cp2;
09644 char tmp[20], freq[20] = "", savestr[20] = "";
09645 char mhz[MAXREMSTR], decimals[MAXREMSTR];
09646
09647 if(debug > 6) {
09648 ast_log(LOG_NOTICE,"%s param=%s digitbuf=%s source=%i\n",myrpt->name,param,digitbuf,command_source);
09649 }
09650
09651 if((!param) || (command_source == SOURCE_RPT) || (command_source == SOURCE_LNK))
09652 return DC_ERROR;
09653
09654 p = myatoi(param);
09655
09656 if ((p != 99) && (p != 5) && (p != 140) && myrpt->p.authlevel &&
09657 (!myrpt->loginlevel[0])) return DC_ERROR;
09658 multimode = multimode_capable(myrpt);
09659
09660 switch(p){
09661
09662 case 1:
09663 if(strlen(digitbuf) < 2)
09664 break;
09665
09666 for(i = 0 ; i < 2 ; i++){
09667 if((digitbuf[i] < '0') || (digitbuf[i] > '9'))
09668 return DC_ERROR;
09669 }
09670 r=get_mem_set(myrpt, digitbuf);
09671 if (r < 0){
09672 rpt_telemetry(myrpt,MEMNOTFOUND,NULL);
09673 return DC_COMPLETE;
09674 }
09675 else if (r > 0){
09676 return DC_ERROR;
09677 }
09678 return DC_COMPLETE;
09679
09680 case 2:
09681
09682
09683 for(i = 0, j = 0, k = 0, l = 0 ; digitbuf[i] ; i++){
09684 if(digitbuf[i] == '*'){
09685 j++;
09686 continue;
09687 }
09688 if((digitbuf[i] < '0') || (digitbuf[i] > '9'))
09689 goto invalid_freq;
09690 else{
09691 if(j == 0)
09692 l++;
09693 if(j == 1)
09694 k++;
09695 }
09696 }
09697
09698 i = strlen(digitbuf) - 1;
09699 if(multimode){
09700 if((j > 2) || (l > 3) || (k > 6))
09701 goto invalid_freq;
09702 }
09703 else{
09704 if((j > 2) || (l > 4) || (k > 3))
09705 goto invalid_freq;
09706 }
09707
09708
09709
09710 if(j < 2)
09711 break;
09712
09713
09714
09715 strncpy(tmp, digitbuf ,sizeof(tmp) - 1);
09716
09717 s = tmp;
09718 s1 = strsep(&s, "*");
09719 s2 = strsep(&s,"*");
09720 ls2 = strlen(s2);
09721
09722 switch(ls2){
09723 case 1:
09724 ht = 0;
09725 k = 100 * atoi(s2);
09726 break;
09727
09728 case 2:
09729 ht = 0;
09730 k = 10 * atoi(s2);
09731 break;
09732
09733 case 3:
09734 if(!multimode){
09735 if((s2[2] != '0')&&(s2[2] != '5'))
09736 goto invalid_freq;
09737 }
09738 ht = 0;
09739 k = atoi(s2);
09740 break;
09741 case 4:
09742 k = atoi(s2)/10;
09743 ht = 10 * (atoi(s2+(ls2-1)));
09744 break;
09745
09746 case 5:
09747 k = atoi(s2)/100;
09748 ht = (atoi(s2+(ls2-2)));
09749 break;
09750
09751 default:
09752 goto invalid_freq;
09753 }
09754
09755
09756
09757 snprintf(freq, sizeof(freq), "%s.%03d%02d",s1, k, ht);
09758
09759 if(debug)
09760 ast_log(LOG_NOTICE, "New frequency: %s\n", freq);
09761
09762 split_freq(mhz, decimals, freq);
09763 m = atoi(mhz);
09764 d = atoi(decimals);
09765
09766 if(check_freq(myrpt, m, d, &defmode))
09767 goto invalid_freq;
09768
09769
09770 if((defmode == REM_MODE_FM) && (digitbuf[i] == '*'))
09771 break;
09772
09773
09774 offset = REM_SIMPLEX;
09775
09776 if(defmode == REM_MODE_FM){
09777 oc = *s;
09778
09779 if (oc){
09780 switch(oc){
09781 case '1':
09782 offset = REM_MINUS;
09783 break;
09784
09785 case '2':
09786 offset = REM_SIMPLEX;
09787 break;
09788
09789 case '3':
09790 offset = REM_PLUS;
09791 break;
09792
09793 default:
09794 goto invalid_freq;
09795 }
09796 }
09797 }
09798 offsave = myrpt->offset;
09799 modesave = myrpt->remmode;
09800 strncpy(savestr, myrpt->freq, sizeof(savestr) - 1);
09801 strncpy(myrpt->freq, freq, sizeof(myrpt->freq) - 1);
09802 myrpt->offset = offset;
09803 myrpt->remmode = defmode;
09804
09805 if (setrem(myrpt) == -1){
09806 myrpt->offset = offsave;
09807 myrpt->remmode = modesave;
09808 strncpy(myrpt->freq, savestr, sizeof(myrpt->freq) - 1);
09809 goto invalid_freq;
09810 }
09811
09812 return DC_COMPLETE;
09813
09814 invalid_freq:
09815 rpt_telemetry(myrpt,INVFREQ,NULL);
09816 return DC_ERROR;
09817
09818 case 3:
09819 for(i = 0, j = 0, k = 0, l = 0 ; digitbuf[i] ; i++){
09820 if(digitbuf[i] == '*'){
09821 j++;
09822 continue;
09823 }
09824 if((digitbuf[i] < '0') || (digitbuf[i] > '9'))
09825 return DC_ERROR;
09826 else{
09827 if(j)
09828 l++;
09829 else
09830 k++;
09831 }
09832 }
09833 if((j > 1) || (k > 3) || (l > 1))
09834 return DC_ERROR;
09835 i = strlen(digitbuf) - 1;
09836 if((j != 1) || (k < 2)|| (l != 1))
09837 break;
09838 if(debug)
09839 printf("PL digits entered %s\n", digitbuf);
09840
09841 strncpy(tmp, digitbuf, sizeof(tmp) - 1);
09842
09843 s = strchr(tmp,'*');
09844 if(s)
09845 *s = '.';
09846 strncpy(savestr, myrpt->rxpl, sizeof(savestr) - 1);
09847 strncpy(myrpt->rxpl, tmp, sizeof(myrpt->rxpl) - 1);
09848 if(!strcmp(myrpt->remoterig, remote_rig_rbi))
09849 {
09850 strncpy(myrpt->txpl, tmp, sizeof(myrpt->txpl) - 1);
09851 }
09852 if (setrem(myrpt) == -1){
09853 strncpy(myrpt->rxpl, savestr, sizeof(myrpt->rxpl) - 1);
09854 return DC_ERROR;
09855 }
09856 return DC_COMPLETE;
09857
09858 case 4:
09859
09860 if(!strcmp(myrpt->remoterig, remote_rig_rbi))
09861 return DC_ERROR;
09862
09863
09864
09865
09866
09867 if(!strcmp(myrpt->remoterig, remote_rig_ic706))
09868 {
09869 if(debug)
09870 ast_log(LOG_WARNING,"Setting IC706 Tx CTCSS Code Not Supported. Set Rx Code for both.\n");
09871 return DC_ERROR;
09872 }
09873 for(i = 0, j = 0, k = 0, l = 0 ; digitbuf[i] ; i++){
09874 if(digitbuf[i] == '*'){
09875 j++;
09876 continue;
09877 }
09878 if((digitbuf[i] < '0') || (digitbuf[i] > '9'))
09879 return DC_ERROR;
09880 else{
09881 if(j)
09882 l++;
09883 else
09884 k++;
09885 }
09886 }
09887 if((j > 1) || (k > 3) || (l > 1))
09888 return DC_ERROR;
09889 i = strlen(digitbuf) - 1;
09890 if((j != 1) || (k < 2)|| (l != 1))
09891 break;
09892 if(debug)
09893 printf("PL digits entered %s\n", digitbuf);
09894
09895 strncpy(tmp, digitbuf, sizeof(tmp) - 1);
09896
09897 s = strchr(tmp,'*');
09898 if(s)
09899 *s = '.';
09900 strncpy(savestr, myrpt->txpl, sizeof(savestr) - 1);
09901 strncpy(myrpt->txpl, tmp, sizeof(myrpt->txpl) - 1);
09902
09903 if (setrem(myrpt) == -1){
09904 strncpy(myrpt->txpl, savestr, sizeof(myrpt->txpl) - 1);
09905 return DC_ERROR;
09906 }
09907 return DC_COMPLETE;
09908
09909
09910 case 6:
09911 if(strlen(digitbuf) < 1)
09912 break;
09913
09914 if(!multimode)
09915 return DC_ERROR;
09916
09917 switch(*digitbuf){
09918 case '1':
09919 split_freq(mhz, decimals, myrpt->freq);
09920 m=atoi(mhz);
09921 if(m < 29)
09922 return DC_ERROR;
09923 myrpt->remmode = REM_MODE_FM;
09924
09925 rpt_telemetry(myrpt,REMMODE,NULL);
09926 break;
09927
09928 case '2':
09929 myrpt->remmode = REM_MODE_USB;
09930 rpt_telemetry(myrpt,REMMODE,NULL);
09931 break;
09932
09933 case '3':
09934 myrpt->remmode = REM_MODE_LSB;
09935 rpt_telemetry(myrpt,REMMODE,NULL);
09936 break;
09937
09938 case '4':
09939 myrpt->remmode = REM_MODE_AM;
09940 rpt_telemetry(myrpt,REMMODE,NULL);
09941 break;
09942
09943 default:
09944 return DC_ERROR;
09945 }
09946
09947 if(setrem(myrpt))
09948 return DC_ERROR;
09949 return DC_COMPLETEQUIET;
09950 case 99:
09951
09952 if (myrpt->loginlevel[0])
09953 return DC_ERROR;
09954 *myrpt->loginuser = 0;
09955 myrpt->loginlevel[0] = 0;
09956 cp = ast_strdup(param);
09957 cp1 = strchr(cp,',');
09958 ast_mutex_lock(&myrpt->lock);
09959 if (cp1)
09960 {
09961 *cp1 = 0;
09962 cp2 = strchr(cp1 + 1,',');
09963 if (cp2)
09964 {
09965 *cp2 = 0;
09966 strncpy(myrpt->loginlevel,cp2 + 1,
09967 sizeof(myrpt->loginlevel) - 1);
09968 }
09969 strncpy(myrpt->loginuser,cp1 + 1,sizeof(myrpt->loginuser));
09970 ast_mutex_unlock(&myrpt->lock);
09971 if (myrpt->p.archivedir)
09972 {
09973 char str[100];
09974
09975 sprintf(str,"LOGIN,%s,%s",
09976 myrpt->loginuser,myrpt->loginlevel);
09977 donodelog(myrpt,str);
09978 }
09979 if (debug)
09980 printf("loginuser %s level %s\n",myrpt->loginuser,myrpt->loginlevel);
09981 rpt_telemetry(myrpt,REMLOGIN,NULL);
09982 }
09983 ast_free(cp);
09984 return DC_COMPLETEQUIET;
09985 case 100:
09986 myrpt->rxplon = 0;
09987 setrem(myrpt);
09988 rpt_telemetry(myrpt,REMXXX,(void *)p);
09989 return DC_COMPLETEQUIET;
09990 case 101:
09991 myrpt->rxplon = 1;
09992 setrem(myrpt);
09993 rpt_telemetry(myrpt,REMXXX,(void *)p);
09994 return DC_COMPLETEQUIET;
09995 case 102:
09996 myrpt->txplon = 0;
09997 setrem(myrpt);
09998 rpt_telemetry(myrpt,REMXXX,(void *)p);
09999 return DC_COMPLETEQUIET;
10000 case 103:
10001 myrpt->txplon = 1;
10002 setrem(myrpt);
10003 rpt_telemetry(myrpt,REMXXX,(void *)p);
10004 return DC_COMPLETEQUIET;
10005 case 104:
10006 if(!strcmp(myrpt->remoterig, remote_rig_ic706))
10007 return DC_ERROR;
10008 myrpt->powerlevel = REM_LOWPWR;
10009 setrem(myrpt);
10010 rpt_telemetry(myrpt,REMXXX,(void *)p);
10011 return DC_COMPLETEQUIET;
10012 case 105:
10013 if(!strcmp(myrpt->remoterig, remote_rig_ic706))
10014 return DC_ERROR;
10015 if (ISRIG_RTX(myrpt->remoterig)) return DC_ERROR;
10016 myrpt->powerlevel = REM_MEDPWR;
10017 setrem(myrpt);
10018 rpt_telemetry(myrpt,REMXXX,(void *)p);
10019 return DC_COMPLETEQUIET;
10020 case 106:
10021 if(!strcmp(myrpt->remoterig, remote_rig_ic706))
10022 return DC_ERROR;
10023 myrpt->powerlevel = REM_HIPWR;
10024 setrem(myrpt);
10025 rpt_telemetry(myrpt,REMXXX,(void *)p);
10026 return DC_COMPLETEQUIET;
10027 case 107:
10028 multimode_bump_freq(myrpt, -20);
10029 return DC_COMPLETE;
10030 case 108:
10031 multimode_bump_freq(myrpt, -100);
10032 return DC_COMPLETE;
10033 case 109:
10034 multimode_bump_freq(myrpt, -500);
10035 return DC_COMPLETE;
10036 case 110:
10037 multimode_bump_freq(myrpt, 20);
10038 return DC_COMPLETE;
10039 case 111:
10040 multimode_bump_freq(myrpt, 100);
10041 return DC_COMPLETE;
10042 case 112:
10043 multimode_bump_freq(myrpt, 500);
10044 return DC_COMPLETE;
10045 case 113:
10046 myrpt->scantimer = REM_SCANTIME;
10047 myrpt->hfscanmode = HF_SCAN_DOWN_SLOW;
10048 rpt_telemetry(myrpt,REMXXX,(void *)p);
10049 return DC_COMPLETEQUIET;
10050 case 114:
10051 myrpt->scantimer = REM_SCANTIME;
10052 myrpt->hfscanmode = HF_SCAN_DOWN_QUICK;
10053 rpt_telemetry(myrpt,REMXXX,(void *)p);
10054 return DC_COMPLETEQUIET;
10055 case 115:
10056 myrpt->scantimer = REM_SCANTIME;
10057 myrpt->hfscanmode = HF_SCAN_DOWN_FAST;
10058 rpt_telemetry(myrpt,REMXXX,(void *)p);
10059 return DC_COMPLETEQUIET;
10060 case 116:
10061 myrpt->scantimer = REM_SCANTIME;
10062 myrpt->hfscanmode = HF_SCAN_UP_SLOW;
10063 rpt_telemetry(myrpt,REMXXX,(void *)p);
10064 return DC_COMPLETEQUIET;
10065 case 117:
10066 myrpt->scantimer = REM_SCANTIME;
10067 myrpt->hfscanmode = HF_SCAN_UP_QUICK;
10068 rpt_telemetry(myrpt,REMXXX,(void *)p);
10069 return DC_COMPLETEQUIET;
10070 case 118:
10071 myrpt->scantimer = REM_SCANTIME;
10072 myrpt->hfscanmode = HF_SCAN_UP_FAST;
10073 rpt_telemetry(myrpt,REMXXX,(void *)p);
10074 return DC_COMPLETEQUIET;
10075 case 119:
10076 if(debug > 3)
10077 ast_log(LOG_NOTICE,"TUNE REQUEST\n");
10078
10079 if((!myrpt->tunerequest) &&
10080 ((!strcmp(myrpt->remoterig, remote_rig_ft897) ||
10081 !strcmp(myrpt->remoterig, remote_rig_ic706)) )) {
10082 myrpt->remotetx = 0;
10083 ast_indicate(myrpt->txchannel,AST_CONTROL_RADIO_UNKEY);
10084 myrpt->tunerequest = 1;
10085 rpt_telemetry(myrpt,TUNE,NULL);
10086 return DC_COMPLETEQUIET;
10087 }
10088 return DC_ERROR;
10089 case 5:
10090 rpt_telemetry(myrpt,REMLONGSTATUS,NULL);
10091 return DC_COMPLETEQUIET;
10092 case 140:
10093 rpt_telemetry(myrpt,REMSHORTSTATUS,NULL);
10094 return DC_COMPLETEQUIET;
10095 case 200:
10096 case 201:
10097 case 202:
10098 case 203:
10099 case 204:
10100 case 205:
10101 case 206:
10102 case 207:
10103 case 208:
10104 case 209:
10105 case 210:
10106 case 211:
10107 case 212:
10108 case 213:
10109 case 214:
10110 case 215:
10111 do_dtmf_local(myrpt,remdtmfstr[p - 200]);
10112 return DC_COMPLETEQUIET;
10113 default:
10114 break;
10115 }
10116 return DC_INDETERMINATE;
10117 }
10118
10119
10120 static int handle_remote_dtmf_digit(struct rpt *myrpt,char c, char *keyed, int phonemode)
10121 {
10122 time_t now;
10123 int ret,res = 0,src;
10124
10125 if(debug > 6)
10126 ast_log(LOG_NOTICE,"c=%c phonemode=%i dtmfidx=%i\n",c,phonemode,myrpt->dtmfidx);
10127
10128 time(&myrpt->last_activity_time);
10129
10130 if(myrpt->hfscanmode){
10131 stop_scan(myrpt);
10132 return 0;
10133 }
10134
10135 time(&now);
10136
10137 if ((myrpt->dtmf_time_rem + DTMF_TIMEOUT) < now)
10138 {
10139 myrpt->dtmfidx = -1;
10140 myrpt->dtmfbuf[0] = 0;
10141 myrpt->dtmf_time_rem = 0;
10142 }
10143
10144 if (myrpt->dtmfidx == -1)
10145 {
10146
10147 if (c != myrpt->p.funcchar)
10148 {
10149 if (!myrpt->p.propagate_dtmf)
10150 {
10151 rpt_mutex_lock(&myrpt->lock);
10152 do_dtmf_local(myrpt,c);
10153 rpt_mutex_unlock(&myrpt->lock);
10154 }
10155 return 0;
10156 }
10157 myrpt->dtmfidx = 0;
10158 myrpt->dtmfbuf[0] = 0;
10159 myrpt->dtmf_time_rem = now;
10160 return 0;
10161 }
10162
10163 if (myrpt->dtmfidx >= MAXDTMF)
10164 {
10165 myrpt->dtmfidx = 0;
10166 myrpt->dtmfbuf[0] = 0;
10167 myrpt->dtmf_time_rem = now;
10168 }
10169 if (c == myrpt->p.funcchar)
10170 {
10171
10172 if ((myrpt->dtmfidx < 1) ||
10173 (myrpt->dtmfbuf[myrpt->dtmfidx - 1] == myrpt->p.funcchar))
10174 {
10175 myrpt->dtmfidx = 0;
10176 myrpt->dtmfbuf[0] = 0;
10177 myrpt->dtmf_time_rem = now;
10178 return 0;
10179 }
10180 }
10181 myrpt->dtmfbuf[myrpt->dtmfidx++] = c;
10182 myrpt->dtmfbuf[myrpt->dtmfidx] = 0;
10183 myrpt->dtmf_time_rem = now;
10184
10185
10186 src = SOURCE_RMT;
10187 if (phonemode == 2) src = SOURCE_DPHONE;
10188 else if (phonemode) src = SOURCE_PHONE;
10189 else if (phonemode == 4) src = SOURCE_ALT;
10190 ret = collect_function_digits(myrpt, myrpt->dtmfbuf, src, NULL);
10191
10192 switch(ret){
10193
10194 case DC_INDETERMINATE:
10195 res = 0;
10196 break;
10197
10198 case DC_DOKEY:
10199 if (keyed) *keyed = 1;
10200 res = 0;
10201 break;
10202
10203 case DC_REQ_FLUSH:
10204 myrpt->dtmfidx = 0;
10205 myrpt->dtmfbuf[0] = 0;
10206 res = 0;
10207 break;
10208
10209
10210 case DC_COMPLETE:
10211 res = 1;
10212 case DC_COMPLETEQUIET:
10213 myrpt->totalexecdcommands++;
10214 myrpt->dailyexecdcommands++;
10215 strncpy(myrpt->lastdtmfcommand, myrpt->dtmfbuf, MAXDTMF-1);
10216 myrpt->lastdtmfcommand[MAXDTMF-1] = '\0';
10217 myrpt->dtmfbuf[0] = 0;
10218 myrpt->dtmfidx = -1;
10219 myrpt->dtmf_time_rem = 0;
10220 break;
10221
10222 case DC_ERROR:
10223 default:
10224 myrpt->dtmfbuf[0] = 0;
10225 myrpt->dtmfidx = -1;
10226 myrpt->dtmf_time_rem = 0;
10227 res = 0;
10228 break;
10229 }
10230
10231 return res;
10232 }
10233
10234 static int handle_remote_data(struct rpt *myrpt, char *str)
10235 {
10236
10237
10238 char tmp[300],cmd[300],dest[300],src[300],c;
10239 int seq,res;
10240
10241
10242 strncpy(tmp,str,sizeof(tmp) - 1);
10243 if (!strcmp(tmp,discstr)) return 0;
10244 if (!strcmp(tmp,newkeystr))
10245 {
10246 myrpt->newkey = 1;
10247 return 0;
10248 }
10249
10250 #ifndef DO_NOT_NOTIFY_MDC1200_ON_REMOTE_BASES
10251 if (tmp[0] == 'I')
10252 {
10253
10254
10255 if (sscanf(tmp,"%299s %299s %30x",cmd,src,&seq) != 3)
10256 {
10257 ast_log(LOG_WARNING, "Unable to parse ident string %s\n",str);
10258 return 0;
10259 }
10260 mdc1200_notify(myrpt,src,seq);
10261 return 0;
10262 }
10263 #endif
10264
10265
10266 if (sscanf(tmp,"%299s %299s %299s %30d %1c",cmd,dest,src,&seq,&c) != 5)
10267 {
10268 ast_log(LOG_WARNING, "Unable to parse link string %s\n",str);
10269 return 0;
10270 }
10271 if (strcmp(cmd,"D"))
10272 {
10273 ast_log(LOG_WARNING, "Unable to parse link string %s\n",str);
10274 return 0;
10275 }
10276
10277 if (strcmp(dest,myrpt->name)) return 0;
10278 if (myrpt->p.archivedir)
10279 {
10280 char dtmfstr[100];
10281
10282 sprintf(dtmfstr,"DTMF,%c",c);
10283 donodelog(myrpt,dtmfstr);
10284 }
10285 c = func_xlat(myrpt,c,&myrpt->p.outxlat);
10286 if (!c) return(0);
10287 res = handle_remote_dtmf_digit(myrpt,c, NULL, 0);
10288 if (res != 1)
10289 return res;
10290 rpt_telemetry(myrpt,COMPLETE,NULL);
10291 return 0;
10292 }
10293
10294 static int handle_remote_phone_dtmf(struct rpt *myrpt, char c, char *keyed, int phonemode)
10295 {
10296 int res;
10297
10298
10299 if(phonemode == 3)
10300 {
10301 if (keyed && *keyed && ((c == myrpt->p.funcchar) || (c == myrpt->p.endchar)))
10302 {
10303 *keyed = 0;
10304 return 0;
10305 }
10306 else if (keyed && !*keyed && (c = myrpt->p.funcchar))
10307 {
10308 *keyed = 1;
10309 return 0;
10310 }
10311 }
10312 else
10313 {
10314
10315 if (keyed && *keyed && (c == myrpt->p.endchar))
10316 {
10317 *keyed = 0;
10318 return DC_INDETERMINATE;
10319 }
10320 }
10321 if (myrpt->p.archivedir)
10322 {
10323 char str[100];
10324
10325 sprintf(str,"DTMF(P),%c",c);
10326 donodelog(myrpt,str);
10327 }
10328 res = handle_remote_dtmf_digit(myrpt,c,keyed, phonemode);
10329 if (res != 1)
10330 return res;
10331 rpt_telemetry(myrpt,COMPLETE,NULL);
10332 return 0;
10333 }
10334
10335 static int attempt_reconnect(struct rpt *myrpt, struct rpt_link *l)
10336 {
10337 char *val, *s, *s1, *s2, *tele;
10338 char tmp[300], deststr[300] = "";
10339 char sx[320],*sy;
10340
10341
10342 val = node_lookup(myrpt,l->name);
10343 if (!val)
10344 {
10345 fprintf(stderr,"attempt_reconnect: cannot find node %s\n",l->name);
10346 return -1;
10347 }
10348
10349 rpt_mutex_lock(&myrpt->lock);
10350
10351 remque((struct qelem *) l);
10352 rpt_mutex_unlock(&myrpt->lock);
10353 strncpy(tmp,val,sizeof(tmp) - 1);
10354 s = tmp;
10355 s1 = strsep(&s,",");
10356 if (!strchr(s1,':') && strchr(s1,'/') && strncasecmp(s1, "local/", 6))
10357 {
10358 sy = strchr(s1,'/');
10359 *sy = 0;
10360 sprintf(sx,"%s:4569/%s",s1,sy + 1);
10361 s1 = sx;
10362 }
10363 s2 = strsep(&s,",");
10364 snprintf(deststr, sizeof(deststr), "IAX2/%s", s1);
10365 tele = strchr(deststr, '/');
10366 if (!tele) {
10367 fprintf(stderr,"attempt_reconnect:Dial number (%s) must be in format tech/number\n",deststr);
10368 return -1;
10369 }
10370 *tele++ = 0;
10371 l->elaptime = 0;
10372 l->connecttime = 0;
10373 l->thisconnected = 0;
10374 l->newkey = 0;
10375 l->chan = ast_request(deststr, AST_FORMAT_SLINEAR, tele,NULL);
10376 if (l->chan){
10377 ast_set_read_format(l->chan, AST_FORMAT_SLINEAR);
10378 ast_set_write_format(l->chan, AST_FORMAT_SLINEAR);
10379 #ifndef NEW_ASTERISK
10380 l->chan->whentohangup = 0;
10381 #endif
10382 l->chan->appl = "Apprpt";
10383 l->chan->data = "(Remote Rx)";
10384 if (option_verbose > 2)
10385 ast_verbose(VERBOSE_PREFIX_3 "rpt (attempt_reconnect) initiating call to %s/%s on %s\n",
10386 deststr, tele, l->chan->name);
10387 if(l->chan->cid.cid_num)
10388 ast_free(l->chan->cid.cid_num);
10389 l->chan->cid.cid_num = ast_strdup(myrpt->name);
10390 ast_call(l->chan,tele,999);
10391
10392 }
10393 else
10394 {
10395 if (option_verbose > 2)
10396 ast_verbose(VERBOSE_PREFIX_3 "Unable to place call to %s/%s on %s\n",
10397 deststr,tele,l->chan->name);
10398 return -1;
10399 }
10400 rpt_mutex_lock(&myrpt->lock);
10401
10402 insque((struct qelem *)l,(struct qelem *)myrpt->links.next);
10403 rpt_mutex_unlock(&myrpt->lock);
10404 ast_log(LOG_WARNING,"Reconnect Attempt to %s in process\n",l->name);
10405 if (!l->phonemode) send_newkey(l->chan);
10406 return 0;
10407 }
10408
10409
10410 static void local_dtmf_helper(struct rpt *myrpt,char c_in)
10411 {
10412 int res;
10413 pthread_attr_t attr;
10414 char cmd[MAXDTMF+1] = "",c;
10415
10416
10417 c = c_in & 0x7f;
10418 if (myrpt->p.archivedir)
10419 {
10420 char str[100];
10421
10422 sprintf(str,"DTMF,MAIN,%c",c);
10423 donodelog(myrpt,str);
10424 }
10425 if (c == myrpt->p.endchar)
10426 {
10427
10428 if (myrpt->p.simple && myrpt->callmode)
10429 {
10430 if(debug)
10431 ast_log(LOG_WARNING, "simple mode autopatch kill\n");
10432 rpt_mutex_lock(&myrpt->lock);
10433 myrpt->callmode = 0;
10434 myrpt->macropatch=0;
10435 channel_revert(myrpt);
10436 rpt_mutex_unlock(&myrpt->lock);
10437 rpt_telemetry(myrpt,TERM,NULL);
10438 return;
10439 }
10440 rpt_mutex_lock(&myrpt->lock);
10441 myrpt->stopgen = 1;
10442 if (myrpt->cmdnode[0])
10443 {
10444 myrpt->cmdnode[0] = 0;
10445 myrpt->dtmfidx = -1;
10446 myrpt->dtmfbuf[0] = 0;
10447 rpt_mutex_unlock(&myrpt->lock);
10448 rpt_telemetry(myrpt,COMPLETE,NULL);
10449 return;
10450 }
10451 else if(!myrpt->inpadtest)
10452 {
10453 rpt_mutex_unlock(&myrpt->lock);
10454 if (myrpt->p.propagate_phonedtmf)
10455 do_dtmf_phone(myrpt,NULL,c);
10456 return;
10457 }
10458 else
10459 rpt_mutex_unlock(&myrpt->lock);
10460 }
10461 rpt_mutex_lock(&myrpt->lock);
10462 if (myrpt->cmdnode[0])
10463 {
10464 rpt_mutex_unlock(&myrpt->lock);
10465 send_link_dtmf(myrpt,c);
10466 return;
10467 }
10468 if (!myrpt->p.simple)
10469 {
10470 if ((!myrpt->inpadtest)&&(c == myrpt->p.funcchar))
10471 {
10472 myrpt->dtmfidx = 0;
10473 myrpt->dtmfbuf[myrpt->dtmfidx] = 0;
10474 rpt_mutex_unlock(&myrpt->lock);
10475 time(&myrpt->dtmf_time);
10476 return;
10477 }
10478 else if (((myrpt->inpadtest)||(c != myrpt->p.endchar)) && (myrpt->dtmfidx >= 0))
10479 {
10480 time(&myrpt->dtmf_time);
10481
10482 if (myrpt->dtmfidx < MAXDTMF)
10483 {
10484 int src;
10485
10486 myrpt->dtmfbuf[myrpt->dtmfidx++] = c;
10487 myrpt->dtmfbuf[myrpt->dtmfidx] = 0;
10488
10489 strncpy(cmd, myrpt->dtmfbuf, sizeof(cmd) - 1);
10490
10491 rpt_mutex_unlock(&myrpt->lock);
10492 src = SOURCE_RPT;
10493 if (c_in & 0x80) src = SOURCE_ALT;
10494 res = collect_function_digits(myrpt, cmd, src, NULL);
10495 rpt_mutex_lock(&myrpt->lock);
10496 switch(res){
10497 case DC_INDETERMINATE:
10498 break;
10499 case DC_REQ_FLUSH:
10500 myrpt->dtmfidx = 0;
10501 myrpt->dtmfbuf[0] = 0;
10502 break;
10503 case DC_COMPLETE:
10504 case DC_COMPLETEQUIET:
10505 myrpt->totalexecdcommands++;
10506 myrpt->dailyexecdcommands++;
10507 strncpy(myrpt->lastdtmfcommand, cmd, MAXDTMF-1);
10508 myrpt->lastdtmfcommand[MAXDTMF-1] = '\0';
10509 myrpt->dtmfbuf[0] = 0;
10510 myrpt->dtmfidx = -1;
10511 myrpt->dtmf_time = 0;
10512 break;
10513
10514 case DC_ERROR:
10515 default:
10516 myrpt->dtmfbuf[0] = 0;
10517 myrpt->dtmfidx = -1;
10518 myrpt->dtmf_time = 0;
10519 break;
10520 }
10521 if(res != DC_INDETERMINATE) {
10522 rpt_mutex_unlock(&myrpt->lock);
10523 return;
10524 }
10525 }
10526 }
10527 }
10528 else
10529 {
10530 if ((!myrpt->callmode) && (c == myrpt->p.funcchar))
10531 {
10532 myrpt->callmode = 1;
10533 myrpt->patchnoct = 0;
10534 myrpt->patchquiet = 0;
10535 myrpt->patchfarenddisconnect = 0;
10536 myrpt->patchdialtime = 0;
10537 strncpy(myrpt->patchcontext, myrpt->p.ourcontext, MAXPATCHCONTEXT);
10538 myrpt->cidx = 0;
10539 myrpt->exten[myrpt->cidx] = 0;
10540 rpt_mutex_unlock(&myrpt->lock);
10541 pthread_attr_init(&attr);
10542 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
10543 ast_pthread_create(&myrpt->rpt_call_thread,&attr,rpt_call,(void *)myrpt);
10544 return;
10545 }
10546 }
10547 if (myrpt->callmode == 1)
10548 {
10549 myrpt->exten[myrpt->cidx++] = c;
10550 myrpt->exten[myrpt->cidx] = 0;
10551
10552 if (ast_exists_extension(myrpt->pchannel,myrpt->patchcontext,myrpt->exten,1,NULL))
10553 {
10554
10555 if (!ast_matchmore_extension(myrpt->pchannel,myrpt->patchcontext,
10556 myrpt->exten,1,NULL))
10557 {
10558 myrpt->callmode = 2;
10559 rpt_mutex_unlock(&myrpt->lock);
10560 if(!myrpt->patchquiet)
10561 rpt_telemetry(myrpt,PROC,NULL);
10562 return;
10563 }
10564 else
10565 {
10566 myrpt->calldigittimer = 1;
10567 }
10568 }
10569
10570 if (!ast_canmatch_extension(myrpt->pchannel,myrpt->patchcontext,myrpt->exten,1,NULL))
10571 {
10572
10573 myrpt->callmode = 4;
10574 }
10575 rpt_mutex_unlock(&myrpt->lock);
10576 return;
10577 }
10578 if ((myrpt->callmode == 2) || (myrpt->callmode == 3))
10579 {
10580 myrpt->mydtmf = c;
10581 }
10582 rpt_mutex_unlock(&myrpt->lock);
10583 if ((myrpt->dtmfidx < 0) && myrpt->p.propagate_phonedtmf)
10584 do_dtmf_phone(myrpt,NULL,c);
10585 return;
10586 }
10587
10588
10589
10590
10591 static void queue_id(struct rpt *myrpt)
10592 {
10593 if(myrpt->p.idtime){
10594 myrpt->mustid = myrpt->tailid = 0;
10595 myrpt->idtimer = myrpt->p.idtime;
10596 rpt_mutex_unlock(&myrpt->lock);
10597 rpt_telemetry(myrpt,ID,NULL);
10598 rpt_mutex_lock(&myrpt->lock);
10599 }
10600 }
10601
10602
10603
10604
10605 static void do_scheduler(struct rpt *myrpt)
10606 {
10607 int i,res;
10608
10609 #ifdef NEW_ASTERISK
10610 struct ast_tm tmnow;
10611 #else
10612 struct tm tmnow;
10613 #endif
10614 struct ast_variable *skedlist;
10615 char *strs[5],*vp,*val,value[100];
10616
10617 memcpy(&myrpt->lasttv, &myrpt->curtv, sizeof(struct timeval));
10618
10619 if( (res = gettimeofday(&myrpt->curtv, NULL)) < 0)
10620 ast_log(LOG_NOTICE, "Scheduler gettime of day returned: %s\n", strerror(res));
10621
10622
10623
10624 if(myrpt->lasttv.tv_sec == myrpt->curtv.tv_sec)
10625 return;
10626
10627 rpt_localtime(&myrpt->curtv.tv_sec, &tmnow);
10628
10629
10630
10631 if((tmnow.tm_hour == 0)&&(tmnow.tm_min == 0)&&(tmnow.tm_sec == 0)){
10632 myrpt->dailykeyups = 0;
10633 myrpt->dailytxtime = 0;
10634 myrpt->dailykerchunks = 0;
10635 myrpt->dailyexecdcommands = 0;
10636 }
10637
10638 if(tmnow.tm_sec != 0)
10639 return;
10640
10641
10642
10643
10644
10645
10646 if (myrpt->remote)
10647 return;
10648
10649
10650
10651 if(myrpt->p.s[myrpt->p.sysstate_cur].schedulerdisable){
10652 if(debug > 6)
10653 ast_log(LOG_NOTICE, "Scheduler disabled\n");
10654 return;
10655 }
10656
10657 if(!myrpt->p.skedstanzaname){
10658 if(debug > 6)
10659 ast_log(LOG_NOTICE,"No stanza for scheduler in rpt.conf\n");
10660 return;
10661 }
10662
10663
10664 skedlist = ast_variable_browse(myrpt->cfg, myrpt->p.skedstanzaname);
10665
10666 if(debug > 6){
10667 ast_log(LOG_NOTICE, "Time now: %02d:%02d %02d %02d %02d\n",
10668 tmnow.tm_hour,tmnow.tm_min,tmnow.tm_mday,tmnow.tm_mon + 1, tmnow.tm_wday);
10669 }
10670
10671 for(; skedlist; skedlist = skedlist->next){
10672 if(debug > 6)
10673 ast_log(LOG_NOTICE, "Scheduler entry %s = %s being considered\n",skedlist->name, skedlist->value);
10674 strncpy(value,skedlist->value,99);
10675 value[99] = 0;
10676
10677 for( i = 0, vp = value ; i < 5; i++){
10678 if(!*vp)
10679 break;
10680 while((*vp == ' ') || (*vp == 0x09))
10681 vp++;
10682 strs[i] = vp;
10683 while((*vp != ' ') && (*vp != 0x09) && (*vp != 0))
10684 vp++;
10685 if(*vp)
10686 *vp++ = 0;
10687 }
10688 if(debug > 6)
10689 ast_log(LOG_NOTICE, "i = %d, min = %s, hour = %s, mday=%s, mon=%s, wday=%s\n",i,
10690 strs[0], strs[1], strs[2], strs[3], strs[4]);
10691 if(i == 5){
10692 if((*strs[0] != '*')&&(atoi(strs[0]) != tmnow.tm_min))
10693 continue;
10694 if((*strs[1] != '*')&&(atoi(strs[1]) != tmnow.tm_hour))
10695 continue;
10696 if((*strs[2] != '*')&&(atoi(strs[2]) != tmnow.tm_mday))
10697 continue;
10698 if((*strs[3] != '*')&&(atoi(strs[3]) != tmnow.tm_mon + 1))
10699 continue;
10700 if(atoi(strs[4]) == 7)
10701 strs[4] = "0";
10702 if((*strs[4] != '*')&&(atoi(strs[4]) != tmnow.tm_wday))
10703 continue;
10704 if(debug)
10705 ast_log(LOG_NOTICE, "Executing scheduler entry %s = %s\n", skedlist->name, skedlist->value);
10706 if(atoi(skedlist->name) == 0)
10707 return;
10708 val = (char *) ast_variable_retrieve(myrpt->cfg, myrpt->p.macro, skedlist->name);
10709 if (!val){
10710 ast_log(LOG_WARNING,"Scheduler could not find macro %s\n",skedlist->name);
10711 return;
10712 }
10713 if ((MAXMACRO - strlen(myrpt->macrobuf)) < strlen(val)){
10714 ast_log(LOG_WARNING, "Scheduler could not execute macro %s: Macro buffer full\n",
10715 skedlist->name);
10716 return;
10717 }
10718 myrpt->macrotimer = MACROTIME;
10719 strncat(myrpt->macrobuf,val,MAXMACRO - 1);
10720 }
10721 else{
10722 ast_log(LOG_WARNING,"Malformed scheduler entry in rpt.conf: %s = %s\n",
10723 skedlist->name, skedlist->value);
10724 }
10725 }
10726
10727 }
10728
10729
10730 static void *rpt(void *this)
10731 {
10732 struct rpt *myrpt = (struct rpt *)this;
10733 char *tele,*idtalkover,c,myfirst,*p;
10734 int ms = MSWAIT,i,lasttx=0,val,remrx=0,identqueued,othertelemqueued;
10735 int tailmessagequeued,ctqueued,dtmfed,lastmyrx,localmsgqueued;
10736 struct ast_channel *who;
10737 struct dahdi_confinfo ci;
10738 time_t t;
10739 struct rpt_link *l,*m;
10740 struct rpt_tele *telem;
10741 char tmpstr[300],lstr[MAXLINKLIST];
10742
10743
10744 if (myrpt->p.archivedir) mkdir(myrpt->p.archivedir,0600);
10745 sprintf(tmpstr,"%s/%s",myrpt->p.archivedir,myrpt->name);
10746 mkdir(tmpstr,0600);
10747 rpt_mutex_lock(&myrpt->lock);
10748
10749 telem = myrpt->tele.next;
10750 while(telem != &myrpt->tele)
10751 {
10752 ast_softhangup(telem->chan,AST_SOFTHANGUP_DEV);
10753 telem = telem->next;
10754 }
10755 rpt_mutex_unlock(&myrpt->lock);
10756
10757 for(i = 0; i < nrpts; i++)
10758 {
10759 if (&rpt_vars[i] == myrpt)
10760 {
10761 load_rpt_vars(i,0);
10762 break;
10763 }
10764 }
10765
10766 rpt_mutex_lock(&myrpt->lock);
10767 while(myrpt->xlink)
10768 {
10769 myrpt->xlink = 3;
10770 rpt_mutex_unlock(&myrpt->lock);
10771 usleep(100000);
10772 rpt_mutex_lock(&myrpt->lock);
10773 }
10774 #ifdef HAVE_IOPERM
10775 if ((!strcmp(myrpt->remoterig, remote_rig_rbi)) &&
10776 (ioperm(myrpt->p.iobase,1,1) == -1))
10777 {
10778 rpt_mutex_unlock(&myrpt->lock);
10779 ast_log(LOG_WARNING, "Cant get io permission on IO port %x hex\n",myrpt->p.iobase);
10780 myrpt->rpt_thread = AST_PTHREADT_STOP;
10781 pthread_exit(NULL);
10782 }
10783 #endif
10784 strncpy(tmpstr,myrpt->rxchanname,sizeof(tmpstr) - 1);
10785 tele = strchr(tmpstr,'/');
10786 if (!tele)
10787 {
10788 fprintf(stderr,"rpt:Rxchannel Dial number (%s) must be in format tech/number\n",myrpt->rxchanname);
10789 rpt_mutex_unlock(&myrpt->lock);
10790 myrpt->rpt_thread = AST_PTHREADT_STOP;
10791 pthread_exit(NULL);
10792 }
10793 *tele++ = 0;
10794 myrpt->rxchannel = ast_request(tmpstr,AST_FORMAT_SLINEAR,tele,NULL);
10795 myrpt->dahdirxchannel = NULL;
10796 if (!strcasecmp(tmpstr,"DAHDI"))
10797 myrpt->dahdirxchannel = myrpt->rxchannel;
10798 if (myrpt->rxchannel)
10799 {
10800 if (myrpt->rxchannel->_state == AST_STATE_BUSY)
10801 {
10802 fprintf(stderr,"rpt:Sorry unable to obtain Rx channel\n");
10803 rpt_mutex_unlock(&myrpt->lock);
10804 ast_hangup(myrpt->rxchannel);
10805 myrpt->rpt_thread = AST_PTHREADT_STOP;
10806 pthread_exit(NULL);
10807 }
10808 ast_set_read_format(myrpt->rxchannel,AST_FORMAT_SLINEAR);
10809 ast_set_write_format(myrpt->rxchannel,AST_FORMAT_SLINEAR);
10810 #ifdef AST_CDR_FLAG_POST_DISABLED
10811 if (myrpt->rxchannel->cdr)
10812 ast_set_flag(myrpt->rxchannel->cdr,AST_CDR_FLAG_POST_DISABLED);
10813 #endif
10814 #ifndef NEW_ASTERISK
10815 myrpt->rxchannel->whentohangup = 0;
10816 #endif
10817 myrpt->rxchannel->appl = "Apprpt";
10818 myrpt->rxchannel->data = "(Repeater Rx)";
10819 if (option_verbose > 2)
10820 ast_verbose(VERBOSE_PREFIX_3 "rpt (Rx) initiating call to %s/%s on %s\n",
10821 tmpstr,tele,myrpt->rxchannel->name);
10822 ast_call(myrpt->rxchannel,tele,999);
10823 if (myrpt->rxchannel->_state != AST_STATE_UP)
10824 {
10825 rpt_mutex_unlock(&myrpt->lock);
10826 ast_hangup(myrpt->rxchannel);
10827 myrpt->rpt_thread = AST_PTHREADT_STOP;
10828 pthread_exit(NULL);
10829 }
10830 }
10831 else
10832 {
10833 fprintf(stderr,"rpt:Sorry unable to obtain Rx channel\n");
10834 rpt_mutex_unlock(&myrpt->lock);
10835 myrpt->rpt_thread = AST_PTHREADT_STOP;
10836 pthread_exit(NULL);
10837 }
10838 myrpt->dahditxchannel = NULL;
10839 if (myrpt->txchanname)
10840 {
10841 strncpy(tmpstr,myrpt->txchanname,sizeof(tmpstr) - 1);
10842 tele = strchr(tmpstr,'/');
10843 if (!tele)
10844 {
10845 fprintf(stderr,"rpt:Txchannel Dial number (%s) must be in format tech/number\n",myrpt->txchanname);
10846 rpt_mutex_unlock(&myrpt->lock);
10847 ast_hangup(myrpt->rxchannel);
10848 myrpt->rpt_thread = AST_PTHREADT_STOP;
10849 pthread_exit(NULL);
10850 }
10851 *tele++ = 0;
10852 myrpt->txchannel = ast_request(tmpstr,AST_FORMAT_SLINEAR,tele,NULL);
10853 if (!strcasecmp(tmpstr,"DAHDI"))
10854 myrpt->dahditxchannel = myrpt->txchannel;
10855 if (myrpt->txchannel)
10856 {
10857 if (myrpt->txchannel->_state == AST_STATE_BUSY)
10858 {
10859 fprintf(stderr,"rpt:Sorry unable to obtain Tx channel\n");
10860 rpt_mutex_unlock(&myrpt->lock);
10861 ast_hangup(myrpt->txchannel);
10862 ast_hangup(myrpt->rxchannel);
10863 myrpt->rpt_thread = AST_PTHREADT_STOP;
10864 pthread_exit(NULL);
10865 }
10866 ast_set_read_format(myrpt->txchannel,AST_FORMAT_SLINEAR);
10867 ast_set_write_format(myrpt->txchannel,AST_FORMAT_SLINEAR);
10868 #ifdef AST_CDR_FLAG_POST_DISABLED
10869 if (myrpt->txchannel->cdr)
10870 ast_set_flag(myrpt->txchannel->cdr,AST_CDR_FLAG_POST_DISABLED);
10871 #endif
10872 #ifndef NEW_ASTERISK
10873 myrpt->txchannel->whentohangup = 0;
10874 #endif
10875 myrpt->txchannel->appl = "Apprpt";
10876 myrpt->txchannel->data = "(Repeater Tx)";
10877 if (option_verbose > 2)
10878 ast_verbose(VERBOSE_PREFIX_3 "rpt (Tx) initiating call to %s/%s on %s\n",
10879 tmpstr,tele,myrpt->txchannel->name);
10880 ast_call(myrpt->txchannel,tele,999);
10881 if (myrpt->rxchannel->_state != AST_STATE_UP)
10882 {
10883 rpt_mutex_unlock(&myrpt->lock);
10884 ast_hangup(myrpt->rxchannel);
10885 ast_hangup(myrpt->txchannel);
10886 myrpt->rpt_thread = AST_PTHREADT_STOP;
10887 pthread_exit(NULL);
10888 }
10889 }
10890 else
10891 {
10892 fprintf(stderr,"rpt:Sorry unable to obtain Tx channel\n");
10893 rpt_mutex_unlock(&myrpt->lock);
10894 ast_hangup(myrpt->rxchannel);
10895 myrpt->rpt_thread = AST_PTHREADT_STOP;
10896 pthread_exit(NULL);
10897 }
10898 }
10899 else
10900 {
10901 myrpt->txchannel = myrpt->rxchannel;
10902 if (!strncasecmp(myrpt->rxchanname,"DAHDI",3))
10903 myrpt->dahditxchannel = myrpt->txchannel;
10904 }
10905 ast_indicate(myrpt->txchannel,AST_CONTROL_RADIO_KEY);
10906 ast_indicate(myrpt->txchannel,AST_CONTROL_RADIO_UNKEY);
10907
10908 myrpt->pchannel = ast_request("DAHDI",AST_FORMAT_SLINEAR,"pseudo",NULL);
10909 if (!myrpt->pchannel)
10910 {
10911 fprintf(stderr,"rpt:Sorry unable to obtain pseudo channel\n");
10912 rpt_mutex_unlock(&myrpt->lock);
10913 if (myrpt->txchannel != myrpt->rxchannel)
10914 ast_hangup(myrpt->txchannel);
10915 ast_hangup(myrpt->rxchannel);
10916 myrpt->rpt_thread = AST_PTHREADT_STOP;
10917 pthread_exit(NULL);
10918 }
10919 #ifdef AST_CDR_FLAG_POST_DISABLED
10920 if (myrpt->pchannel->cdr)
10921 ast_set_flag(myrpt->pchannel->cdr,AST_CDR_FLAG_POST_DISABLED);
10922 #endif
10923 if (!myrpt->dahdirxchannel) myrpt->dahdirxchannel = myrpt->pchannel;
10924 if (!myrpt->dahditxchannel)
10925 {
10926
10927 myrpt->dahditxchannel = ast_request("DAHDI",AST_FORMAT_SLINEAR,"pseudo",NULL);
10928 if (!myrpt->dahditxchannel)
10929 {
10930 fprintf(stderr,"rpt:Sorry unable to obtain pseudo channel\n");
10931 rpt_mutex_unlock(&myrpt->lock);
10932 if (myrpt->txchannel != myrpt->rxchannel)
10933 ast_hangup(myrpt->txchannel);
10934 ast_hangup(myrpt->rxchannel);
10935 myrpt->rpt_thread = AST_PTHREADT_STOP;
10936 pthread_exit(NULL);
10937 }
10938 ast_set_read_format(myrpt->dahditxchannel,AST_FORMAT_SLINEAR);
10939 ast_set_write_format(myrpt->dahditxchannel,AST_FORMAT_SLINEAR);
10940 #ifdef AST_CDR_FLAG_POST_DISABLED
10941 if (myrpt->dahditxchannel->cdr)
10942 ast_set_flag(myrpt->dahditxchannel->cdr,AST_CDR_FLAG_POST_DISABLED);
10943 #endif
10944 }
10945
10946 myrpt->monchannel = ast_request("DAHDI",AST_FORMAT_SLINEAR,"pseudo",NULL);
10947 if (!myrpt->monchannel)
10948 {
10949 fprintf(stderr,"rpt:Sorry unable to obtain pseudo channel\n");
10950 rpt_mutex_unlock(&myrpt->lock);
10951 if (myrpt->txchannel != myrpt->rxchannel)
10952 ast_hangup(myrpt->txchannel);
10953 ast_hangup(myrpt->rxchannel);
10954 myrpt->rpt_thread = AST_PTHREADT_STOP;
10955 pthread_exit(NULL);
10956 }
10957 ast_set_read_format(myrpt->monchannel,AST_FORMAT_SLINEAR);
10958 ast_set_write_format(myrpt->monchannel,AST_FORMAT_SLINEAR);
10959 #ifdef AST_CDR_FLAG_POST_DISABLED
10960 if (myrpt->monchannel->cdr)
10961 ast_set_flag(myrpt->monchannel->cdr,AST_CDR_FLAG_POST_DISABLED);
10962 #endif
10963
10964 ci.chan = 0;
10965 ci.confno = -1;
10966 ci.confmode = DAHDI_CONF_CONF | DAHDI_CONF_LISTENER;
10967
10968 if (ioctl(myrpt->dahditxchannel->fds[0],DAHDI_SETCONF,&ci) == -1)
10969 {
10970 ast_log(LOG_WARNING, "Unable to set conference mode to Announce\n");
10971 rpt_mutex_unlock(&myrpt->lock);
10972 ast_hangup(myrpt->pchannel);
10973 ast_hangup(myrpt->monchannel);
10974 if (myrpt->txchannel != myrpt->rxchannel)
10975 ast_hangup(myrpt->txchannel);
10976 ast_hangup(myrpt->rxchannel);
10977 myrpt->rpt_thread = AST_PTHREADT_STOP;
10978 pthread_exit(NULL);
10979 }
10980
10981 myrpt->txconf = ci.confno;
10982
10983 ci.chan = 0;
10984 ci.confno = -1;
10985 ci.confmode = ((myrpt->p.duplex == 2) || (myrpt->p.duplex == 4)) ? DAHDI_CONF_CONFANNMON :
10986 (DAHDI_CONF_CONF | DAHDI_CONF_LISTENER | DAHDI_CONF_TALKER);
10987
10988 if (ioctl(myrpt->pchannel->fds[0],DAHDI_SETCONF,&ci) == -1)
10989 {
10990 ast_log(LOG_WARNING, "Unable to set conference mode to Announce\n");
10991 rpt_mutex_unlock(&myrpt->lock);
10992 ast_hangup(myrpt->pchannel);
10993 ast_hangup(myrpt->monchannel);
10994 if (myrpt->txchannel != myrpt->rxchannel)
10995 ast_hangup(myrpt->txchannel);
10996 ast_hangup(myrpt->rxchannel);
10997 myrpt->rpt_thread = AST_PTHREADT_STOP;
10998 pthread_exit(NULL);
10999 }
11000
11001 myrpt->conf = ci.confno;
11002
11003 ci.chan = 0;
11004 if ((strstr(myrpt->txchannel->name,"pseudo") == NULL) &&
11005 (myrpt->dahditxchannel == myrpt->txchannel))
11006 {
11007
11008 if (ioctl(myrpt->txchannel->fds[0],DAHDI_CHANNO,&ci.confno) == -1)
11009 {
11010 ast_log(LOG_WARNING, "Unable to set tx channel's chan number\n");
11011 rpt_mutex_unlock(&myrpt->lock);
11012 ast_hangup(myrpt->pchannel);
11013 ast_hangup(myrpt->monchannel);
11014 if (myrpt->txchannel != myrpt->rxchannel)
11015 ast_hangup(myrpt->txchannel);
11016 ast_hangup(myrpt->rxchannel);
11017 myrpt->rpt_thread = AST_PTHREADT_STOP;
11018 pthread_exit(NULL);
11019 }
11020 ci.confmode = DAHDI_CONF_MONITORTX;
11021 }
11022 else
11023 {
11024 ci.confno = myrpt->txconf;
11025 ci.confmode = DAHDI_CONF_CONFANNMON;
11026 }
11027
11028 if (ioctl(myrpt->monchannel->fds[0],DAHDI_SETCONF,&ci) == -1)
11029 {
11030 ast_log(LOG_WARNING, "Unable to set conference mode for monitor\n");
11031 rpt_mutex_unlock(&myrpt->lock);
11032 ast_hangup(myrpt->pchannel);
11033 ast_hangup(myrpt->monchannel);
11034 if (myrpt->txchannel != myrpt->rxchannel)
11035 ast_hangup(myrpt->txchannel);
11036 ast_hangup(myrpt->rxchannel);
11037 myrpt->rpt_thread = AST_PTHREADT_STOP;
11038 pthread_exit(NULL);
11039 }
11040
11041 myrpt->parrotchannel = ast_request("DAHDI",AST_FORMAT_SLINEAR,"pseudo",NULL);
11042 if (!myrpt->parrotchannel)
11043 {
11044 fprintf(stderr,"rpt:Sorry unable to obtain pseudo channel\n");
11045 rpt_mutex_unlock(&myrpt->lock);
11046 if (myrpt->txchannel != myrpt->rxchannel)
11047 ast_hangup(myrpt->txchannel);
11048 ast_hangup(myrpt->rxchannel);
11049 myrpt->rpt_thread = AST_PTHREADT_STOP;
11050 pthread_exit(NULL);
11051 }
11052 ast_set_read_format(myrpt->parrotchannel,AST_FORMAT_SLINEAR);
11053 ast_set_write_format(myrpt->parrotchannel,AST_FORMAT_SLINEAR);
11054 #ifdef AST_CDR_FLAG_POST_DISABLED
11055 if (myrpt->parrotchannel->cdr)
11056 ast_set_flag(myrpt->parrotchannel->cdr,AST_CDR_FLAG_POST_DISABLED);
11057 #endif
11058
11059 myrpt->voxchannel = ast_request("DAHDI",AST_FORMAT_SLINEAR,"pseudo",NULL);
11060 if (!myrpt->voxchannel)
11061 {
11062 fprintf(stderr,"rpt:Sorry unable to obtain pseudo channel\n");
11063 rpt_mutex_unlock(&myrpt->lock);
11064 if (myrpt->txchannel != myrpt->rxchannel)
11065 ast_hangup(myrpt->txchannel);
11066 ast_hangup(myrpt->rxchannel);
11067 myrpt->rpt_thread = AST_PTHREADT_STOP;
11068 pthread_exit(NULL);
11069 }
11070 ast_set_read_format(myrpt->voxchannel,AST_FORMAT_SLINEAR);
11071 ast_set_write_format(myrpt->voxchannel,AST_FORMAT_SLINEAR);
11072 #ifdef AST_CDR_FLAG_POST_DISABLED
11073 if (myrpt->voxchannel->cdr)
11074 ast_set_flag(myrpt->voxchannel->cdr,AST_CDR_FLAG_POST_DISABLED);
11075 #endif
11076
11077 myrpt->txpchannel = ast_request("DAHDI",AST_FORMAT_SLINEAR,"pseudo",NULL);
11078 if (!myrpt->txpchannel)
11079 {
11080 fprintf(stderr,"rpt:Sorry unable to obtain pseudo channel\n");
11081 rpt_mutex_unlock(&myrpt->lock);
11082 ast_hangup(myrpt->pchannel);
11083 ast_hangup(myrpt->monchannel);
11084 if (myrpt->txchannel != myrpt->rxchannel)
11085 ast_hangup(myrpt->txchannel);
11086 ast_hangup(myrpt->rxchannel);
11087 myrpt->rpt_thread = AST_PTHREADT_STOP;
11088 pthread_exit(NULL);
11089 }
11090 #ifdef AST_CDR_FLAG_POST_DISABLED
11091 if (myrpt->txpchannel->cdr)
11092 ast_set_flag(myrpt->txpchannel->cdr,AST_CDR_FLAG_POST_DISABLED);
11093 #endif
11094
11095 ci.chan = 0;
11096 ci.confno = myrpt->txconf;
11097 ci.confmode = DAHDI_CONF_CONF | DAHDI_CONF_TALKER ;
11098
11099 if (ioctl(myrpt->txpchannel->fds[0],DAHDI_SETCONF,&ci) == -1)
11100 {
11101 ast_log(LOG_WARNING, "Unable to set conference mode to Announce\n");
11102 rpt_mutex_unlock(&myrpt->lock);
11103 ast_hangup(myrpt->txpchannel);
11104 ast_hangup(myrpt->monchannel);
11105 if (myrpt->txchannel != myrpt->rxchannel)
11106 ast_hangup(myrpt->txchannel);
11107 ast_hangup(myrpt->rxchannel);
11108 myrpt->rpt_thread = AST_PTHREADT_STOP;
11109 pthread_exit(NULL);
11110 }
11111
11112 myrpt->iofd = -1;
11113 if (myrpt->p.ioport && ((myrpt->iofd = openserial(myrpt,myrpt->p.ioport)) == -1))
11114 {
11115 ast_log(LOG_ERROR, "Unable to open %s\n",myrpt->p.ioport);
11116 rpt_mutex_unlock(&myrpt->lock);
11117 ast_hangup(myrpt->pchannel);
11118 if (myrpt->txchannel != myrpt->rxchannel)
11119 ast_hangup(myrpt->txchannel);
11120 ast_hangup(myrpt->rxchannel);
11121 pthread_exit(NULL);
11122 }
11123
11124
11125
11126 myrpt->links.next = &myrpt->links;
11127 myrpt->links.prev = &myrpt->links;
11128 myrpt->tailtimer = 0;
11129 myrpt->totimer = 0;
11130 myrpt->tmsgtimer = myrpt->p.tailmessagetime;
11131 myrpt->idtimer = myrpt->p.politeid;
11132 myrpt->mustid = myrpt->tailid = 0;
11133 myrpt->callmode = 0;
11134 myrpt->tounkeyed = 0;
11135 myrpt->tonotify = 0;
11136 myrpt->retxtimer = 0;
11137 myrpt->rerxtimer = 0;
11138 myrpt->skedtimer = 0;
11139 myrpt->tailevent = 0;
11140 lasttx = 0;
11141 myrpt->keyed = 0;
11142 myrpt->txkeyed = 0;
11143 time(&myrpt->lastkeyedtime);
11144 myrpt->lastkeyedtime -= RPT_LOCKOUT_SECS;
11145 time(&myrpt->lasttxkeyedtime);
11146 myrpt->lasttxkeyedtime -= RPT_LOCKOUT_SECS;
11147 idtalkover = (char *) ast_variable_retrieve(myrpt->cfg, myrpt->name, "idtalkover");
11148 myrpt->dtmfidx = -1;
11149 myrpt->dtmfbuf[0] = 0;
11150 myrpt->rem_dtmfidx = -1;
11151 myrpt->rem_dtmfbuf[0] = 0;
11152 myrpt->dtmf_time = 0;
11153 myrpt->rem_dtmf_time = 0;
11154 myrpt->inpadtest = 0;
11155 myrpt->disgorgetime = 0;
11156 myrpt->lastnodewhichkeyedusup[0] = '\0';
11157 myrpt->dailytxtime = 0;
11158 myrpt->totaltxtime = 0;
11159 myrpt->dailykeyups = 0;
11160 myrpt->totalkeyups = 0;
11161 myrpt->dailykerchunks = 0;
11162 myrpt->totalkerchunks = 0;
11163 myrpt->dailyexecdcommands = 0;
11164 myrpt->totalexecdcommands = 0;
11165 myrpt->timeouts = 0;
11166 myrpt->exten[0] = '\0';
11167 myrpt->lastdtmfcommand[0] = '\0';
11168 voxinit_rpt(myrpt,1);
11169 myrpt->wasvox = 0;
11170 if (myrpt->p.startupmacro)
11171 {
11172 snprintf(myrpt->macrobuf,MAXMACRO - 1,"PPPP%s",myrpt->p.startupmacro);
11173 }
11174 rpt_mutex_unlock(&myrpt->lock);
11175 val = 1;
11176 ast_channel_setoption(myrpt->rxchannel,AST_OPTION_RELAXDTMF,&val,sizeof(char),0);
11177 val = 1;
11178 ast_channel_setoption(myrpt->rxchannel,AST_OPTION_TONE_VERIFY,&val,sizeof(char),0);
11179 if (myrpt->p.archivedir) donodelog(myrpt,"STARTUP");
11180 dtmfed = 0;
11181 if (myrpt->remoterig && !ISRIG_RTX(myrpt->remoterig)) setrem(myrpt);
11182 lastmyrx = 0;
11183 myfirst = 0;
11184 while (ms >= 0)
11185 {
11186 struct ast_frame *f,*f1,*f2;
11187 struct ast_channel *cs[300],*cs1[300];
11188 int totx=0,elap=0,n,x,toexit=0;
11189
11190
11191 if((myrpt->disgorgetime) && (time(NULL) >= myrpt->disgorgetime)){
11192 struct rpt_link *dl;
11193 struct rpt_tele *dt;
11194
11195 myrpt->disgorgetime = 0;
11196 ast_log(LOG_NOTICE,"********** Variable Dump Start (app_rpt) **********\n");
11197 ast_log(LOG_NOTICE,"totx = %d\n",totx);
11198 ast_log(LOG_NOTICE,"remrx = %d\n",remrx);
11199 ast_log(LOG_NOTICE,"lasttx = %d\n",lasttx);
11200 ast_log(LOG_NOTICE,"elap = %d\n",elap);
11201 ast_log(LOG_NOTICE,"toexit = %d\n",toexit);
11202
11203 ast_log(LOG_NOTICE,"myrpt->keyed = %d\n",myrpt->keyed);
11204 ast_log(LOG_NOTICE,"myrpt->localtx = %d\n",myrpt->localtx);
11205 ast_log(LOG_NOTICE,"myrpt->callmode = %d\n",myrpt->callmode);
11206 ast_log(LOG_NOTICE,"myrpt->mustid = %d\n",myrpt->mustid);
11207 ast_log(LOG_NOTICE,"myrpt->tounkeyed = %d\n",myrpt->tounkeyed);
11208 ast_log(LOG_NOTICE,"myrpt->tonotify = %d\n",myrpt->tonotify);
11209 ast_log(LOG_NOTICE,"myrpt->retxtimer = %ld\n",myrpt->retxtimer);
11210 ast_log(LOG_NOTICE,"myrpt->totimer = %d\n",myrpt->totimer);
11211 ast_log(LOG_NOTICE,"myrpt->tailtimer = %d\n",myrpt->tailtimer);
11212 ast_log(LOG_NOTICE,"myrpt->tailevent = %d\n",myrpt->tailevent);
11213
11214 dl = myrpt->links.next;
11215 while(dl != &myrpt->links){
11216 ast_log(LOG_NOTICE,"*** Link Name: %s ***\n",dl->name);
11217 ast_log(LOG_NOTICE," link->lasttx %d\n",dl->lasttx);
11218 ast_log(LOG_NOTICE," link->lastrx %d\n",dl->lastrx);
11219 ast_log(LOG_NOTICE," link->connected %d\n",dl->connected);
11220 ast_log(LOG_NOTICE," link->hasconnected %d\n",dl->hasconnected);
11221 ast_log(LOG_NOTICE," link->outbound %d\n",dl->outbound);
11222 ast_log(LOG_NOTICE," link->disced %d\n",dl->disced);
11223 ast_log(LOG_NOTICE," link->killme %d\n",dl->killme);
11224 ast_log(LOG_NOTICE," link->disctime %ld\n",dl->disctime);
11225 ast_log(LOG_NOTICE," link->retrytimer %ld\n",dl->retrytimer);
11226 ast_log(LOG_NOTICE," link->retries = %d\n",dl->retries);
11227 ast_log(LOG_NOTICE," link->reconnects = %d\n",dl->reconnects);
11228 ast_log(LOG_NOTICE," link->newkey = %d\n",dl->newkey);
11229 dl = dl->next;
11230 }
11231
11232 dt = myrpt->tele.next;
11233 if(dt != &myrpt->tele)
11234 ast_log(LOG_NOTICE,"*** Telemetry Queue ***\n");
11235 while(dt != &myrpt->tele){
11236 ast_log(LOG_NOTICE," Telemetry mode: %d\n",dt->mode);
11237 dt = dt->next;
11238 }
11239 ast_log(LOG_NOTICE,"******* Variable Dump End (app_rpt) *******\n");
11240
11241 }
11242
11243
11244 if (myrpt->reload)
11245 {
11246 struct rpt_tele *inner_telem;
11247
11248 rpt_mutex_lock(&myrpt->lock);
11249 inner_telem = myrpt->tele.next;
11250 while(inner_telem != &myrpt->tele)
11251 {
11252 ast_softhangup(inner_telem->chan,AST_SOFTHANGUP_DEV);
11253 inner_telem = inner_telem->next;
11254 }
11255 myrpt->reload = 0;
11256 rpt_mutex_unlock(&myrpt->lock);
11257 usleep(10000);
11258
11259 for(i = 0; i < nrpts; i++)
11260 {
11261 if (&rpt_vars[i] == myrpt)
11262 {
11263 load_rpt_vars(i,0);
11264 break;
11265 }
11266 }
11267 }
11268
11269 rpt_mutex_lock(&myrpt->lock);
11270 if (ast_check_hangup(myrpt->rxchannel)) break;
11271 if (ast_check_hangup(myrpt->txchannel)) break;
11272 if (ast_check_hangup(myrpt->pchannel)) break;
11273 if (ast_check_hangup(myrpt->monchannel)) break;
11274 if (myrpt->parrotchannel &&
11275 ast_check_hangup(myrpt->parrotchannel)) break;
11276 if (myrpt->voxchannel &&
11277 ast_check_hangup(myrpt->voxchannel)) break;
11278 if (ast_check_hangup(myrpt->txpchannel)) break;
11279 if (myrpt->dahditxchannel && ast_check_hangup(myrpt->dahditxchannel)) break;
11280
11281
11282 myrpt->localtx = myrpt->keyed;
11283
11284 l = myrpt->links.next;
11285 remrx = 0;
11286 while(l != &myrpt->links)
11287 {
11288 if (l->lastrx){
11289 remrx = 1;
11290 if(l->name[0] != '0')
11291 strcpy(myrpt->lastnodewhichkeyedusup, l->name);
11292 }
11293 l = l->next;
11294 }
11295
11296 if(myrpt->p.idtime)
11297 myrpt->mustid |= (myrpt->idtimer) && (myrpt->keyed || remrx) ;
11298
11299
11300 if (myrpt->p.duplex > 1)
11301 {
11302 totx = myrpt->callmode;
11303 totx = totx || myrpt->localtx;
11304 }
11305 else
11306 {
11307 int myrx = myrpt->localtx || remrx || (!myrpt->callmode);
11308
11309 if (lastmyrx != myrx)
11310 {
11311 voxinit_rpt(myrpt,!myrx);
11312 lastmyrx = myrx;
11313 }
11314 totx = 0;
11315 if (myrpt->callmode && (myrpt->voxtotimer <= 0))
11316 {
11317 if (myrpt->voxtostate)
11318 {
11319 myrpt->voxtotimer = myrpt->p.voxtimeout_ms;
11320 myrpt->voxtostate = 0;
11321 }
11322 else
11323 {
11324 myrpt->voxtotimer = myrpt->p.voxrecover_ms;
11325 myrpt->voxtostate = 1;
11326 }
11327 }
11328 if (!myrpt->voxtostate)
11329 totx = myrpt->callmode && myrpt->wasvox;
11330 }
11331
11332 identqueued = 0;
11333 localmsgqueued = 0;
11334 othertelemqueued = 0;
11335 tailmessagequeued = 0;
11336 ctqueued = 0;
11337 telem = myrpt->tele.next;
11338 while(telem != &myrpt->tele)
11339 {
11340 if((telem->mode == ID) || (telem->mode == IDTALKOVER)){
11341 identqueued = 1;
11342 }
11343 else if(telem->mode == TAILMSG)
11344 {
11345 tailmessagequeued = 1;
11346 }
11347 else if(telem->mode == STATS_TIME_LOCAL)
11348 {
11349 localmsgqueued = 1;
11350 }
11351 else
11352 {
11353 if ((telem->mode != UNKEY) && (telem->mode != LINKUNKEY))
11354 othertelemqueued = 1;
11355 else
11356 ctqueued = 1;
11357 }
11358 telem = telem->next;
11359 }
11360
11361
11362 if (!myrpt->p.notelemtx) totx = totx || othertelemqueued;
11363
11364
11365 myrpt->exttx = totx;
11366 totx = totx || myrpt->dtmf_local_timer;
11367
11368 if (myrpt->p.duplex < 2) myrpt->exttx = myrpt->exttx || myrpt->localtx;
11369
11370 totx = totx || remrx;
11371
11372 if (myrpt->p.duplex > 0)
11373 totx = totx || identqueued || ctqueued || localmsgqueued;
11374
11375 if (myrpt->p.duplex > 1)
11376 {
11377 totx = totx || (myrpt->dtmfidx > -1) ||
11378 myrpt->cmdnode[0];
11379 }
11380
11381 totx = totx || (myrpt->parrotstate > 1);
11382
11383 if (!totx)
11384 {
11385 myrpt->totimer = myrpt->p.totime;
11386 myrpt->tounkeyed = 0;
11387 myrpt->tonotify = 0;
11388 }
11389 else{
11390 myrpt->tailtimer = myrpt->p.s[myrpt->p.sysstate_cur].alternatetail ?
11391 myrpt->p.althangtime :
11392 myrpt->p.hangtime;
11393 }
11394
11395 totx = totx && myrpt->totimer;
11396
11397 if ((!myrpt->totimer) && (!myrpt->tonotify))
11398 {
11399 myrpt->tonotify = 1;
11400 myrpt->timeouts++;
11401 rpt_mutex_unlock(&myrpt->lock);
11402 rpt_telemetry(myrpt,TIMEOUT,NULL);
11403 rpt_mutex_lock(&myrpt->lock);
11404 }
11405
11406
11407 if ((!totx) && (!myrpt->totimer) && (!myrpt->tounkeyed) && (!myrpt->keyed))
11408 {
11409 myrpt->tounkeyed = 1;
11410 }
11411 if ((!totx) && (!myrpt->totimer) && myrpt->tounkeyed && myrpt->keyed)
11412 {
11413 myrpt->totimer = myrpt->p.totime;
11414 myrpt->tounkeyed = 0;
11415 myrpt->tonotify = 0;
11416 rpt_mutex_unlock(&myrpt->lock);
11417 continue;
11418 }
11419
11420 if ((!totx) && (!myrpt->totimer) && (myrpt->callmode == 4))
11421 {
11422 if(debug)
11423 ast_log(LOG_NOTICE, "timed-out and in circuit busy after call\n");
11424 myrpt->callmode = 0;
11425 myrpt->macropatch=0;
11426 channel_revert(myrpt);
11427 }
11428
11429 if (!myrpt->totimer) myrpt->tailtimer = 0;
11430
11431 if (myrpt->totimer) totx = totx || myrpt->tailtimer;
11432
11433
11434 if ((myrpt->keyed || remrx) && ((identqueued && idtalkover) || (tailmessagequeued))) {
11435 int hasid = 0,hastalkover = 0;
11436
11437 telem = myrpt->tele.next;
11438 while(telem != &myrpt->tele){
11439 if(telem->mode == ID){
11440 if (telem->chan) ast_softhangup(telem->chan, AST_SOFTHANGUP_DEV);
11441 hasid = 1;
11442 }
11443 if(telem->mode == TAILMSG){
11444 if (telem->chan) ast_softhangup(telem->chan, AST_SOFTHANGUP_DEV);
11445 }
11446 if (telem->mode == IDTALKOVER) hastalkover = 1;
11447 telem = telem->next;
11448 }
11449 rpt_mutex_unlock(&myrpt->lock);
11450 if (hasid && (!hastalkover)) rpt_telemetry(myrpt, IDTALKOVER, NULL);
11451 rpt_mutex_lock(&myrpt->lock);
11452 }
11453
11454
11455
11456
11457
11458 if(myrpt->mustid && (!myrpt->idtimer))
11459 queue_id(myrpt);
11460
11461 if ((myrpt->p.idtime && totx && (!myrpt->exttx) &&
11462 (myrpt->idtimer <= myrpt->p.politeid) && myrpt->tailtimer))
11463 {
11464 myrpt->tailid = 1;
11465 }
11466
11467
11468
11469 if(myrpt->tailevent){
11470 myrpt->tailevent = 0;
11471 if(myrpt->tailid){
11472 totx = 1;
11473 queue_id(myrpt);
11474 }
11475 else if ((myrpt->p.tailmessages[0]) &&
11476 (myrpt->p.tailmessagetime) && (myrpt->tmsgtimer == 0)){
11477 totx = 1;
11478 myrpt->tmsgtimer = myrpt->p.tailmessagetime;
11479 rpt_mutex_unlock(&myrpt->lock);
11480 rpt_telemetry(myrpt, TAILMSG, NULL);
11481 rpt_mutex_lock(&myrpt->lock);
11482 }
11483 }
11484
11485
11486
11487
11488 if (myrpt->p.duplex > 0) totx = totx || (myrpt->tele.next != &myrpt->tele);
11489 totx = totx && !myrpt->p.s[myrpt->p.sysstate_cur].txdisable;
11490 myrpt->txrealkeyed = totx;
11491 totx = totx || (!AST_LIST_EMPTY(&myrpt->txq));
11492 if (totx && (!lasttx))
11493 {
11494 char mydate[100],myfname[100];
11495 time_t myt;
11496
11497 if (myrpt->monstream) ast_closestream(myrpt->monstream);
11498 if (myrpt->p.archivedir)
11499 {
11500 long blocksleft;
11501
11502 time(&myt);
11503 strftime(mydate,sizeof(mydate) - 1,"%Y%m%d%H%M%S",
11504 localtime(&myt));
11505 sprintf(myfname,"%s/%s/%s",myrpt->p.archivedir,
11506 myrpt->name,mydate);
11507 myrpt->monstream = ast_writefile(myfname,"wav49",
11508 "app_rpt Air Archive",O_CREAT | O_APPEND,0,0600);
11509 if (myrpt->p.monminblocks)
11510 {
11511 blocksleft = diskavail(myrpt);
11512 if (blocksleft >= myrpt->p.monminblocks)
11513 donodelog(myrpt,"TXKEY,MAIN");
11514 } else donodelog(myrpt,"TXKEY,MAIN");
11515 }
11516 lasttx = 1;
11517 myrpt->txkeyed = 1;
11518 time(&myrpt->lasttxkeyedtime);
11519 myrpt->dailykeyups++;
11520 myrpt->totalkeyups++;
11521 rpt_mutex_unlock(&myrpt->lock);
11522 ast_indicate(myrpt->txchannel,AST_CONTROL_RADIO_KEY);
11523 rpt_mutex_lock(&myrpt->lock);
11524 }
11525 if ((!totx) && lasttx)
11526 {
11527 if (myrpt->monstream) ast_closestream(myrpt->monstream);
11528 myrpt->monstream = NULL;
11529
11530 lasttx = 0;
11531 myrpt->txkeyed = 0;
11532 time(&myrpt->lasttxkeyedtime);
11533 rpt_mutex_unlock(&myrpt->lock);
11534 ast_indicate(myrpt->txchannel,AST_CONTROL_RADIO_UNKEY);
11535 rpt_mutex_lock(&myrpt->lock);
11536 donodelog(myrpt,"TXUNKEY,MAIN");
11537 }
11538 time(&t);
11539
11540 if ((!myrpt->cmdnode[0]) && (myrpt->dtmfidx >= 0) && ((myrpt->dtmf_time + DTMF_TIMEOUT) < t))
11541 {
11542 myrpt->inpadtest = 0;
11543 myrpt->dtmfidx = -1;
11544 myrpt->dtmfbuf[0] = 0;
11545 }
11546
11547 if ((myrpt->rem_dtmfidx >= 0) && ((myrpt->rem_dtmf_time + DTMF_TIMEOUT) < t))
11548 {
11549 myrpt->inpadtest = 0;
11550 myrpt->rem_dtmfidx = -1;
11551 myrpt->rem_dtmfbuf[0] = 0;
11552 }
11553
11554 if (myrpt->exttx && myrpt->parrotchannel &&
11555 myrpt->p.parrotmode && (!myrpt->parrotstate))
11556 {
11557 char myfname[300];
11558
11559 ci.confno = myrpt->conf;
11560 ci.confmode = DAHDI_CONF_CONFANNMON;
11561 ci.chan = 0;
11562
11563
11564 if (ioctl(myrpt->parrotchannel->fds[0],DAHDI_SETCONF,&ci) == -1)
11565 {
11566 ast_log(LOG_WARNING, "Unable to set conference mode for parrot\n");
11567 break;
11568 }
11569
11570 sprintf(myfname,PARROTFILE,myrpt->name,myrpt->parrotcnt);
11571 strcat(myfname,".wav");
11572 unlink(myfname);
11573 sprintf(myfname,PARROTFILE,myrpt->name,myrpt->parrotcnt);
11574 myrpt->parrotstate = 1;
11575 myrpt->parrottimer = myrpt->p.parrottime;
11576 if (myrpt->parrotstream)
11577 ast_closestream(myrpt->parrotstream);
11578 myrpt->parrotstream = NULL;
11579 myrpt->parrotstream = ast_writefile(myfname,"wav",
11580 "app_rpt Parrot",O_CREAT | O_TRUNC,0,0600);
11581 }
11582
11583
11584
11585 l = myrpt->links.next;
11586 while(l != &myrpt->links)
11587 {
11588 if (l->killme)
11589 {
11590
11591 remque((struct qelem *) l);
11592 if (!strcmp(myrpt->cmdnode,l->name))
11593 myrpt->cmdnode[0] = 0;
11594 rpt_mutex_unlock(&myrpt->lock);
11595
11596 if (l->chan) ast_hangup(l->chan);
11597 ast_hangup(l->pchan);
11598 ast_free(l);
11599 rpt_mutex_lock(&myrpt->lock);
11600
11601 l = myrpt->links.next;
11602 continue;
11603 }
11604 l = l->next;
11605 }
11606 n = 0;
11607 cs[n++] = myrpt->rxchannel;
11608 cs[n++] = myrpt->pchannel;
11609 cs[n++] = myrpt->monchannel;
11610 if (myrpt->parrotchannel) cs[n++] = myrpt->parrotchannel;
11611 if (myrpt->voxchannel) cs[n++] = myrpt->voxchannel;
11612 cs[n++] = myrpt->txpchannel;
11613 if (myrpt->txchannel != myrpt->rxchannel) cs[n++] = myrpt->txchannel;
11614 if (myrpt->dahditxchannel != myrpt->txchannel)
11615 cs[n++] = myrpt->dahditxchannel;
11616 l = myrpt->links.next;
11617 while(l != &myrpt->links)
11618 {
11619 if ((!l->killme) && (!l->disctime) && l->chan)
11620 {
11621 cs[n++] = l->chan;
11622 cs[n++] = l->pchan;
11623 }
11624 l = l->next;
11625 }
11626 if ((myrpt->topkeystate == 1) &&
11627 ((t - myrpt->topkeytime) > TOPKEYWAIT))
11628 {
11629 myrpt->topkeystate = 2;
11630 qsort(myrpt->topkey,TOPKEYN,sizeof(struct rpt_topkey),
11631 topcompar);
11632 }
11633 rpt_mutex_unlock(&myrpt->lock);
11634
11635 if (myrpt->topkeystate == 2)
11636 {
11637 rpt_telemetry(myrpt,TOPKEY,NULL);
11638 myrpt->topkeystate = 3;
11639 }
11640 ms = MSWAIT;
11641 for(x = 0; x < n; x++)
11642 {
11643 int s = -(-x - myrpt->scram - 1) % n;
11644 cs1[x] = cs[s];
11645 }
11646 myrpt->scram++;
11647 who = ast_waitfor_n(cs1,n,&ms);
11648 if (who == NULL) ms = 0;
11649 elap = MSWAIT - ms;
11650 rpt_mutex_lock(&myrpt->lock);
11651 l = myrpt->links.next;
11652 while(l != &myrpt->links)
11653 {
11654 int myrx;
11655
11656 if (l->voxtotimer) l->voxtotimer -= elap;
11657 if (l->voxtotimer < 0) l->voxtotimer = 0;
11658
11659 if (l->lasttx != l->lasttx1)
11660 {
11661 voxinit_link(l,!l->lasttx);
11662 l->lasttx1 = l->lasttx;
11663 }
11664 myrx = l->lastrealrx;
11665 if ((l->phonemode) && (l->phonevox))
11666 {
11667 myrx = myrx || (!AST_LIST_EMPTY(&l->rxq));
11668 if (l->voxtotimer <= 0)
11669 {
11670 if (l->voxtostate)
11671 {
11672 l->voxtotimer = myrpt->p.voxtimeout_ms;
11673 l->voxtostate = 0;
11674 }
11675 else
11676 {
11677 l->voxtotimer = myrpt->p.voxrecover_ms;
11678 l->voxtostate = 1;
11679 }
11680 }
11681 if (!l->voxtostate)
11682 myrx = myrx || l->wasvox ;
11683 }
11684 l->lastrx = myrx;
11685 if (l->linklisttimer)
11686 {
11687 l->linklisttimer -= elap;
11688 if (l->linklisttimer < 0) l->linklisttimer = 0;
11689 }
11690 if ((!l->linklisttimer) && (l->name[0] != '0') && (!l->isremote))
11691 {
11692 struct ast_frame lf;
11693
11694 memset(&lf,0,sizeof(lf));
11695 lf.frametype = AST_FRAME_TEXT;
11696 lf.subclass = 0;
11697 lf.offset = 0;
11698 lf.mallocd = 0;
11699 lf.samples = 0;
11700 l->linklisttimer = LINKLISTTIME;
11701 strcpy(lstr,"L ");
11702 __mklinklist(myrpt,l,lstr + 2);
11703 if (l->chan)
11704 {
11705 lf.datalen = strlen(lstr) + 1;
11706 lf.data.ptr = lstr;
11707 ast_write(l->chan,&lf);
11708 if (debug > 6) ast_log(LOG_NOTICE,
11709 "@@@@ node %s sent node string %s to node %s\n",
11710 myrpt->name,lstr,l->name);
11711 }
11712 }
11713 if (l->newkey)
11714 {
11715 if ((l->retxtimer += elap) >= REDUNDANT_TX_TIME)
11716 {
11717 l->retxtimer = 0;
11718 if (l->chan && l->phonemode == 0)
11719 {
11720 if (l->lasttx)
11721 ast_indicate(l->chan,AST_CONTROL_RADIO_KEY);
11722 else
11723 ast_indicate(l->chan,AST_CONTROL_RADIO_UNKEY);
11724 }
11725 }
11726 if ((l->rerxtimer += elap) >= (REDUNDANT_TX_TIME * 5))
11727 {
11728 if (debug == 7) printf("@@@@ rx un-key\n");
11729 l->lastrealrx = 0;
11730 l->rerxtimer = 0;
11731 if (l->lastrx1)
11732 {
11733 if (myrpt->p.archivedir)
11734 {
11735 char str[100];
11736
11737 sprintf(str,"RXUNKEY(T),%s",l->name);
11738 donodelog(myrpt,str);
11739 }
11740 if(myrpt->p.duplex)
11741 rpt_telemetry(myrpt,LINKUNKEY,l);
11742 l->lastrx1 = 0;
11743 }
11744 }
11745 }
11746 if (l->disctime)
11747 {
11748 l->disctime -= elap;
11749 if (l->disctime <= 0)
11750 l->disctime = 0;
11751 }
11752
11753 if (l->retrytimer)
11754 {
11755 l->retrytimer -= elap;
11756 if (l->retrytimer < 0) l->retrytimer = 0;
11757 }
11758
11759
11760 l->connecttime += elap;
11761
11762
11763 if (l->elaptime < 0)
11764 {
11765 l = l->next;
11766 continue;
11767 }
11768 l->elaptime += elap;
11769
11770 if ((l->elaptime > MAXCONNECTTIME) &&
11771 ((!l->chan) || (l->chan->_state != AST_STATE_UP)))
11772 {
11773 l->elaptime = 0;
11774 rpt_mutex_unlock(&myrpt->lock);
11775 if (l->chan) ast_softhangup(l->chan,AST_SOFTHANGUP_DEV);
11776 rpt_mutex_lock(&myrpt->lock);
11777 break;
11778 }
11779 if ((!l->chan) && (!l->retrytimer) && l->outbound &&
11780 (l->retries++ < l->max_retries) && (l->hasconnected))
11781 {
11782 if (l->chan) ast_hangup(l->chan);
11783 l->chan = 0;
11784 rpt_mutex_unlock(&myrpt->lock);
11785 if ((l->name[0] != '0') && (!l->isremote))
11786 {
11787 if (attempt_reconnect(myrpt,l) == -1)
11788 {
11789 l->retrytimer = RETRY_TIMER_MS;
11790 }
11791 }
11792 else
11793 {
11794 l->retrytimer = l->max_retries + 1;
11795 }
11796
11797 rpt_mutex_lock(&myrpt->lock);
11798 break;
11799 }
11800 if ((!l->chan) && (!l->retrytimer) && l->outbound &&
11801 (l->retries >= l->max_retries))
11802 {
11803
11804 remque((struct qelem *) l);
11805 if (!strcmp(myrpt->cmdnode,l->name))
11806 myrpt->cmdnode[0] = 0;
11807 rpt_mutex_unlock(&myrpt->lock);
11808 if (l->name[0] != '0')
11809 {
11810 if (!l->hasconnected)
11811 rpt_telemetry(myrpt,CONNFAIL,l);
11812 else rpt_telemetry(myrpt,REMDISC,l);
11813 }
11814 if (myrpt->p.archivedir)
11815 {
11816 char str[100];
11817
11818 if (!l->hasconnected)
11819 sprintf(str,"LINKFAIL,%s",l->name);
11820 else
11821 sprintf(str,"LINKDISC,%s",l->name);
11822 donodelog(myrpt,str);
11823 }
11824
11825 ast_hangup(l->pchan);
11826 ast_free(l);
11827 rpt_mutex_lock(&myrpt->lock);
11828 break;
11829 }
11830 if ((!l->chan) && (!l->disctime) && (!l->outbound))
11831 {
11832 if(debug)ast_log(LOG_NOTICE, "LINKDISC AA\n");
11833
11834 remque((struct qelem *) l);
11835 if(myrpt->links.next==&myrpt->links)channel_revert(myrpt);
11836 if (!strcmp(myrpt->cmdnode,l->name))myrpt->cmdnode[0] = 0;
11837 rpt_mutex_unlock(&myrpt->lock);
11838 if (l->name[0] != '0')
11839 {
11840 rpt_telemetry(myrpt,REMDISC,l);
11841 }
11842 if (myrpt->p.archivedir)
11843 {
11844 char str[100];
11845 sprintf(str,"LINKDISC,%s",l->name);
11846 donodelog(myrpt,str);
11847 }
11848
11849 ast_hangup(l->pchan);
11850 ast_free(l);
11851 rpt_mutex_lock(&myrpt->lock);
11852 break;
11853 }
11854 l = l->next;
11855 }
11856 if (myrpt->linkposttimer)
11857 {
11858 myrpt->linkposttimer -= elap;
11859 if (myrpt->linkposttimer < 0) myrpt->linkposttimer = 0;
11860 }
11861 if (myrpt->linkposttimer <= 0)
11862 {
11863 int nstr;
11864 char lst,*str;
11865 time_t now;
11866
11867 myrpt->linkposttimer = LINKPOSTTIME;
11868 nstr = 0;
11869 for(l = myrpt->links.next; l != &myrpt->links; l = l->next)
11870 {
11871
11872 if (l->name[0] == '0') continue;
11873 nstr += strlen(l->name) + 1;
11874 }
11875 str = ast_malloc(nstr + 256);
11876 if (!str)
11877 {
11878 ast_log(LOG_NOTICE,"Cannot ast_malloc()\n");
11879 break;
11880 }
11881 nstr = 0;
11882 strcpy(str,"nodes=");
11883 for(l = myrpt->links.next; l != &myrpt->links; l = l->next)
11884 {
11885
11886 if (l->name[0] == '0') continue;
11887 lst = 'T';
11888 if (!l->mode) lst = 'R';
11889 if (!l->thisconnected) lst = 'C';
11890 if (nstr) strcat(str,",");
11891 sprintf(str + strlen(str),"%c%s",lst,l->name);
11892 nstr = 1;
11893 }
11894 p = strstr(tdesc, "version");
11895 if(p){
11896 int vmajor,vminor;
11897 if(sscanf(p, "version %30d.%30d", &vmajor, &vminor) == 2)
11898 sprintf(str + strlen(str),"&apprptvers=%d.%d",vmajor,vminor);
11899 }
11900 time(&now);
11901 sprintf(str + strlen(str),"&apprptuptime=%d",(int)(now-starttime));
11902 sprintf(str + strlen(str),
11903 "&totalkerchunks=%d&totalkeyups=%d&totaltxtime=%d&timeouts=%d&totalexecdcommands=%d",
11904 myrpt->totalkerchunks,myrpt->totalkeyups,(int) myrpt->totaltxtime/1000,
11905 myrpt->timeouts,myrpt->totalexecdcommands);
11906 rpt_mutex_unlock(&myrpt->lock);
11907 statpost(myrpt,str);
11908 rpt_mutex_lock(&myrpt->lock);
11909 ast_free(str);
11910 }
11911 if (myrpt->keyposttimer)
11912 {
11913 myrpt->keyposttimer -= elap;
11914 if (myrpt->keyposttimer < 0) myrpt->keyposttimer = 0;
11915 }
11916 if (myrpt->keyposttimer <= 0)
11917 {
11918 char str[100];
11919 int diff = 0;
11920 time_t now;
11921
11922 myrpt->keyposttimer = KEYPOSTTIME;
11923 time(&now);
11924 if (myrpt->lastkeyedtime)
11925 {
11926 diff = (int)(now - myrpt->lastkeyedtime);
11927 }
11928 sprintf(str,"keyed=%d&keytime=%d",myrpt->keyed,diff);
11929 rpt_mutex_unlock(&myrpt->lock);
11930 statpost(myrpt,str);
11931 rpt_mutex_lock(&myrpt->lock);
11932 }
11933 if(totx){
11934 myrpt->dailytxtime += elap;
11935 myrpt->totaltxtime += elap;
11936 }
11937 i = myrpt->tailtimer;
11938 if (myrpt->tailtimer) myrpt->tailtimer -= elap;
11939 if (myrpt->tailtimer < 0) myrpt->tailtimer = 0;
11940 if((i) && (myrpt->tailtimer == 0))
11941 myrpt->tailevent = 1;
11942 if ((!myrpt->p.s[myrpt->p.sysstate_cur].totdisable) && myrpt->totimer) myrpt->totimer -= elap;
11943 if (myrpt->totimer < 0) myrpt->totimer = 0;
11944 if (myrpt->idtimer) myrpt->idtimer -= elap;
11945 if (myrpt->idtimer < 0) myrpt->idtimer = 0;
11946 if (myrpt->tmsgtimer) myrpt->tmsgtimer -= elap;
11947 if (myrpt->tmsgtimer < 0) myrpt->tmsgtimer = 0;
11948 if (myrpt->voxtotimer) myrpt->voxtotimer -= elap;
11949 if (myrpt->voxtotimer < 0) myrpt->voxtotimer = 0;
11950 if (myrpt->exttx)
11951 {
11952 myrpt->parrottimer = myrpt->p.parrottime;
11953 }
11954 else
11955 {
11956 if (myrpt->parrottimer) myrpt->parrottimer -= elap;
11957 if (myrpt->parrottimer < 0) myrpt->parrottimer = 0;
11958 }
11959
11960 if (myrpt->macrotimer) myrpt->macrotimer -= elap;
11961 if (myrpt->macrotimer < 0) myrpt->macrotimer = 0;
11962
11963 if (myrpt->dtmf_local_timer)
11964 {
11965 if (myrpt->dtmf_local_timer > 1) myrpt->dtmf_local_timer -= elap;
11966 if (myrpt->dtmf_local_timer < 1) myrpt->dtmf_local_timer = 1;
11967 }
11968 do_dtmf_local(myrpt,0);
11969
11970 if (myrpt->skedtimer <= 0){
11971 myrpt->skedtimer = 200;
11972 do_scheduler(myrpt);
11973 }
11974 else
11975 myrpt->skedtimer -=elap;
11976 if (!ms)
11977 {
11978 rpt_mutex_unlock(&myrpt->lock);
11979 continue;
11980 }
11981 if (myrpt->p.parrotmode && (myrpt->parrotstate == 1) &&
11982 (myrpt->parrottimer <= 0))
11983 {
11984
11985 ci.confno = 0;
11986 ci.confmode = 0;
11987 ci.chan = 0;
11988
11989
11990 if (ioctl(myrpt->parrotchannel->fds[0],DAHDI_SETCONF,&ci) == -1)
11991 {
11992 ast_log(LOG_WARNING, "Unable to set conference mode for parrot\n");
11993 break;
11994 }
11995 if (myrpt->parrotstream)
11996 ast_closestream(myrpt->parrotstream);
11997 myrpt->parrotstream = NULL;
11998 myrpt->parrotstate = 2;
11999 rpt_telemetry(myrpt,PARROT,(void *) ((intptr_t)myrpt->parrotcnt++));
12000 }
12001 if (myrpt->cmdAction.state == CMD_STATE_READY)
12002 {
12003 int status;
12004 myrpt->cmdAction.state = CMD_STATE_EXECUTING;
12005
12006 rpt_mutex_unlock(&myrpt->lock);
12007
12008 status = (*function_table[myrpt->cmdAction.functionNumber].function)(myrpt,myrpt->cmdAction.param, myrpt->cmdAction.digits, myrpt->cmdAction.command_source, NULL);
12009
12010 rpt_mutex_lock(&myrpt->lock);
12011 myrpt->cmdAction.state = CMD_STATE_IDLE;
12012 }
12013
12014 c = myrpt->macrobuf[0];
12015 time(&t);
12016 if (c && (!myrpt->macrotimer) &&
12017 starttime && (t > (starttime + START_DELAY)))
12018 {
12019 char cin = c & 0x7f;
12020 myrpt->macrotimer = MACROTIME;
12021 memmove(myrpt->macrobuf,myrpt->macrobuf + 1,MAXMACRO - 1);
12022 if ((cin == 'p') || (cin == 'P'))
12023 myrpt->macrotimer = MACROPTIME;
12024 rpt_mutex_unlock(&myrpt->lock);
12025 if (myrpt->p.archivedir)
12026 {
12027 char str[100];
12028
12029 sprintf(str,"DTMF(M),MAIN,%c",cin);
12030 donodelog(myrpt,str);
12031 }
12032 local_dtmf_helper(myrpt,c);
12033 } else rpt_mutex_unlock(&myrpt->lock);
12034 if (who == myrpt->rxchannel)
12035 {
12036 int ismuted;
12037
12038 f = ast_read(myrpt->rxchannel);
12039 if (!f)
12040 {
12041 if (debug) printf("@@@@ rpt:Hung Up\n");
12042 break;
12043 }
12044 if (f->frametype == AST_FRAME_VOICE)
12045 {
12046 #ifdef _MDC_DECODE_H_
12047 unsigned char ubuf[2560];
12048 short *sp;
12049 int n;
12050 #endif
12051
12052 if ((!myrpt->localtx) && (!myrpt->p.linktolink)) {
12053 memset(f->data.ptr,0,f->datalen);
12054 }
12055
12056 #ifdef _MDC_DECODE_H_
12057 sp = (short *) f->data;
12058
12059 for(n = 0; n < f->datalen / 2; n++)
12060 {
12061 ubuf[n] = (*sp++ >> 8) + 128;
12062 }
12063 n = mdc_decoder_process_samples(myrpt->mdc,ubuf,f->datalen / 2);
12064 if (n == 1)
12065 {
12066 unsigned char op,arg;
12067 unsigned short unitID;
12068
12069 mdc_decoder_get_packet(myrpt->mdc,&op,&arg,&unitID);
12070 if (debug > 2)
12071 {
12072 ast_log(LOG_NOTICE,"Got (single-length) packet:\n");
12073 ast_log(LOG_NOTICE,"op: %02x, arg: %02x, UnitID: %04x\n",
12074 op & 255,arg & 255,unitID);
12075 }
12076 if ((op == 1) && (arg == 0))
12077 {
12078 myrpt->lastunit = unitID;
12079 mdc1200_notify(myrpt,NULL,myrpt->lastunit);
12080 mdc1200_send(myrpt,myrpt->lastunit);
12081 }
12082 }
12083 if ((debug > 2) && (i == 2))
12084 {
12085 unsigned char op,arg,ex1,ex2,ex3,ex4;
12086 unsigned short unitID;
12087
12088 mdc_decoder_get_double_packet(myrpt->mdc,&op,&arg,&unitID,
12089 &ex1,&ex2,&ex3,&ex4);
12090 ast_log(LOG_NOTICE,"Got (double-length) packet:\n");
12091 ast_log(LOG_NOTICE,"op: %02x, arg: %02x, UnitID: %04x\n",
12092 op & 255,arg & 255,unitID);
12093 ast_log(LOG_NOTICE,"ex1: %02x, ex2: %02x, ex3: %02x, ex4: %02x\n",
12094 ex1 & 255, ex2 & 255, ex3 & 255, ex4 & 255);
12095 }
12096 #endif
12097 #ifdef __RPT_NOTCH
12098
12099 rpt_filter(myrpt,f->data,f->datalen / 2);
12100 #endif
12101 if (ioctl(myrpt->dahdirxchannel->fds[0], DAHDI_GETCONFMUTE, &ismuted) == -1)
12102 {
12103 ismuted = 0;
12104 }
12105 if (dtmfed) ismuted = 1;
12106 dtmfed = 0;
12107 if (ismuted)
12108 {
12109 memset(f->data.ptr,0,f->datalen);
12110 if (myrpt->lastf1)
12111 memset(myrpt->lastf1->data.ptr,0,myrpt->lastf1->datalen);
12112 if (myrpt->lastf2)
12113 memset(myrpt->lastf2->data.ptr,0,myrpt->lastf2->datalen);
12114 }
12115 if (f) f2 = ast_frdup(f);
12116 else f2 = NULL;
12117 f1 = myrpt->lastf2;
12118 myrpt->lastf2 = myrpt->lastf1;
12119 myrpt->lastf1 = f2;
12120 if (ismuted)
12121 {
12122 if (myrpt->lastf1)
12123 memset(myrpt->lastf1->data.ptr,0,myrpt->lastf1->datalen);
12124 if (myrpt->lastf2)
12125 memset(myrpt->lastf2->data.ptr,0,myrpt->lastf2->datalen);
12126 }
12127 if (f1)
12128 {
12129 ast_write(myrpt->pchannel,f1);
12130 ast_frfree(f1);
12131 }
12132 }
12133 #ifndef OLD_ASTERISK
12134 else if (f->frametype == AST_FRAME_DTMF_BEGIN)
12135 {
12136 if (myrpt->lastf1)
12137 memset(myrpt->lastf1->data.ptr,0,myrpt->lastf1->datalen);
12138 if (myrpt->lastf2)
12139 memset(myrpt->lastf2->data.ptr,0,myrpt->lastf2->datalen);
12140 dtmfed = 1;
12141 }
12142 #endif
12143 else if (f->frametype == AST_FRAME_DTMF)
12144 {
12145 c = (char) f->subclass;
12146 ast_frfree(f);
12147 if (myrpt->lastf1)
12148 memset(myrpt->lastf1->data.ptr,0,myrpt->lastf1->datalen);
12149 if (myrpt->lastf2)
12150 memset(myrpt->lastf2->data.ptr,0,myrpt->lastf2->datalen);
12151 dtmfed = 1;
12152 if (!myrpt->keyed) continue;
12153 c = func_xlat(myrpt,c,&myrpt->p.inxlat);
12154 if (c) local_dtmf_helper(myrpt,c);
12155 continue;
12156 }
12157 else if (f->frametype == AST_FRAME_CONTROL)
12158 {
12159 if (f->subclass == AST_CONTROL_HANGUP)
12160 {
12161 if (debug) printf("@@@@ rpt:Hung Up\n");
12162 ast_frfree(f);
12163 break;
12164 }
12165
12166 if (f->subclass == AST_CONTROL_RADIO_KEY)
12167 {
12168 if ((!lasttx) || (myrpt->p.duplex > 1) || (myrpt->p.linktolink))
12169 {
12170 if (debug == 7) printf("@@@@ rx key\n");
12171 myrpt->keyed = 1;
12172 time(&myrpt->lastkeyedtime);
12173 myrpt->keyposttimer = KEYPOSTSHORTTIME;
12174 }
12175 if (myrpt->p.archivedir)
12176 {
12177 donodelog(myrpt,"RXKEY,MAIN");
12178 }
12179 if (f->datalen && f->data.ptr)
12180 {
12181 char busy = 0;
12182
12183 if (debug) ast_log(LOG_NOTICE,"Got PL %s on node %s\n",(char *)f->data.ptr,myrpt->name);
12184
12185 if (strstr((char *)f->data.ptr,"/M/")&& !myrpt->macropatch)
12186 {
12187 char value[16];
12188 strcat(value,"*6");
12189 myrpt->macropatch=1;
12190 rpt_mutex_lock(&myrpt->lock);
12191 if ((MAXMACRO - strlen(myrpt->macrobuf)) < strlen(value)){
12192 rpt_mutex_unlock(&myrpt->lock);
12193 busy=1;
12194 }
12195 if(!busy){
12196 myrpt->macrotimer = MACROTIME;
12197 strncat(myrpt->macrobuf,value,MAXMACRO - 1);
12198 if (!busy) strcpy(myrpt->lasttone,(char*)f->data.ptr);
12199 }
12200 rpt_mutex_unlock(&myrpt->lock);
12201 }
12202 else if (strcmp((char *)f->data.ptr,myrpt->lasttone))
12203 {
12204 char *value = (char *) ast_variable_retrieve(myrpt->cfg, myrpt->p.tonemacro, (char *)f->data.ptr);
12205 if (value)
12206 {
12207 if (debug) ast_log(LOG_NOTICE,"Tone %s doing %s on node %s\n",(char *) f->data.ptr,value,myrpt->name);
12208 rpt_mutex_lock(&myrpt->lock);
12209 if ((MAXMACRO - strlen(myrpt->macrobuf)) < strlen(value)){
12210 rpt_mutex_unlock(&myrpt->lock);
12211 busy=1;
12212 }
12213 if(!busy){
12214 myrpt->macrotimer = MACROTIME;
12215 strncat(myrpt->macrobuf,value,MAXMACRO - 1);
12216 }
12217 rpt_mutex_unlock(&myrpt->lock);
12218 }
12219 if (!busy) strcpy(myrpt->lasttone,(char*)f->data.ptr);
12220 }
12221 } else myrpt->lasttone[0] = 0;
12222 }
12223
12224 if (f->subclass == AST_CONTROL_RADIO_UNKEY)
12225 {
12226 if ((!lasttx) || (myrpt->p.duplex > 1) || (myrpt->p.linktolink))
12227 {
12228 if (debug == 7) printf("@@@@ rx un-key\n");
12229 if(myrpt->p.duplex && myrpt->keyed) {
12230 rpt_telemetry(myrpt,UNKEY,NULL);
12231 }
12232 }
12233 myrpt->keyed = 0;
12234 time(&myrpt->lastkeyedtime);
12235 myrpt->keyposttimer = KEYPOSTSHORTTIME;
12236 if (myrpt->p.archivedir)
12237 {
12238 donodelog(myrpt,"RXUNKEY,MAIN");
12239 }
12240 }
12241 }
12242 ast_frfree(f);
12243 continue;
12244 }
12245 if (who == myrpt->pchannel)
12246 {
12247 f = ast_read(myrpt->pchannel);
12248 if (!f)
12249 {
12250 if (debug) printf("@@@@ rpt:Hung Up\n");
12251 break;
12252 }
12253 if (f->frametype == AST_FRAME_VOICE)
12254 {
12255 ast_write(myrpt->txpchannel,f);
12256 }
12257 if (f->frametype == AST_FRAME_CONTROL)
12258 {
12259 if (f->subclass == AST_CONTROL_HANGUP)
12260 {
12261 if (debug) printf("@@@@ rpt:Hung Up\n");
12262 ast_frfree(f);
12263 break;
12264 }
12265 }
12266 ast_frfree(f);
12267 continue;
12268 }
12269 if (who == myrpt->txchannel)
12270 {
12271 f = ast_read(myrpt->txchannel);
12272 if (!f)
12273 {
12274 if (debug) printf("@@@@ rpt:Hung Up\n");
12275 break;
12276 }
12277 if (f->frametype == AST_FRAME_CONTROL)
12278 {
12279 if (f->subclass == AST_CONTROL_HANGUP)
12280 {
12281 if (debug) printf("@@@@ rpt:Hung Up\n");
12282 ast_frfree(f);
12283 break;
12284 }
12285 }
12286 ast_frfree(f);
12287 continue;
12288 }
12289 if (who == myrpt->dahditxchannel)
12290 {
12291 f = ast_read(myrpt->dahditxchannel);
12292 if (!f)
12293 {
12294 if (debug) printf("@@@@ rpt:Hung Up\n");
12295 break;
12296 }
12297 if (f->frametype == AST_FRAME_VOICE)
12298 {
12299 struct ast_frame *vframe;
12300
12301 if (myrpt->p.duplex < 2)
12302 {
12303 if (myrpt->txrealkeyed)
12304 {
12305 if ((!myfirst) && myrpt->callmode)
12306 {
12307 x = 0;
12308 AST_LIST_TRAVERSE(&myrpt->txq, vframe,
12309 frame_list) x++;
12310 for(;x < myrpt->p.simplexpatchdelay; x++)
12311 {
12312 vframe = ast_frdup(f);
12313 memset(vframe->data.ptr,0,vframe->datalen);
12314 AST_LIST_INSERT_TAIL(&myrpt->txq,vframe,frame_list);
12315 }
12316 myfirst = 1;
12317 }
12318 vframe = ast_frdup(f);
12319 AST_LIST_INSERT_TAIL(&myrpt->txq,
12320 vframe,frame_list);
12321 } else myfirst = 0;
12322 x = 0;
12323 AST_LIST_TRAVERSE(&myrpt->txq, vframe,
12324 frame_list) x++;
12325 if (!x)
12326 {
12327 memset(f->data.ptr,0,f->datalen);
12328 }
12329 else
12330 {
12331 ast_frfree(f);
12332 f = AST_LIST_REMOVE_HEAD(&myrpt->txq,
12333 frame_list);
12334 }
12335 }
12336 else
12337 {
12338 while((vframe = AST_LIST_REMOVE_HEAD(&myrpt->txq,
12339 frame_list))) ast_frfree(vframe);
12340 }
12341 ast_write(myrpt->txchannel,f);
12342 }
12343 if (f->frametype == AST_FRAME_CONTROL)
12344 {
12345 if (f->subclass == AST_CONTROL_HANGUP)
12346 {
12347 if (debug) printf("@@@@ rpt:Hung Up\n");
12348 ast_frfree(f);
12349 break;
12350 }
12351 }
12352 ast_frfree(f);
12353 continue;
12354 }
12355 toexit = 0;
12356 rpt_mutex_lock(&myrpt->lock);
12357 l = myrpt->links.next;
12358 while(l != &myrpt->links)
12359 {
12360 int remnomute;
12361 struct timeval now;
12362
12363 if (l->disctime)
12364 {
12365 l = l->next;
12366 continue;
12367 }
12368
12369 remrx = 0;
12370
12371 m = myrpt->links.next;
12372 while(m != &myrpt->links)
12373 {
12374
12375 if ((m != l) && (m->lastrx)) remrx = 1;
12376 m = m->next;
12377 }
12378 rpt_mutex_unlock(&myrpt->lock);
12379 now = ast_tvnow();
12380 if ((who == l->chan) || (!l->lastlinktv.tv_sec) ||
12381 (ast_tvdiff_ms(now,l->lastlinktv) >= 19))
12382 {
12383 l->lastlinktv = now;
12384 remnomute = myrpt->localtx &&
12385 (!(myrpt->cmdnode[0] ||
12386 (myrpt->dtmfidx > -1)));
12387 totx = (((l->isremote) ? (remnomute) :
12388 myrpt->exttx) || remrx) && l->mode;
12389 if (l->phonemode == 0 && l->chan && (l->lasttx != totx))
12390 {
12391 if (totx)
12392 {
12393 ast_indicate(l->chan,AST_CONTROL_RADIO_KEY);
12394 }
12395 else
12396 {
12397 ast_indicate(l->chan,AST_CONTROL_RADIO_UNKEY);
12398 }
12399 if (myrpt->p.archivedir)
12400 {
12401 char str[100];
12402
12403 if (totx)
12404 sprintf(str,"TXKEY,%s",l->name);
12405 else
12406 sprintf(str,"TXUNKEY,%s",l->name);
12407 donodelog(myrpt,str);
12408 }
12409 }
12410 l->lasttx = totx;
12411 }
12412 rpt_mutex_lock(&myrpt->lock);
12413 if (who == l->chan)
12414 {
12415 rpt_mutex_unlock(&myrpt->lock);
12416 f = ast_read(l->chan);
12417 if (!f)
12418 {
12419 rpt_mutex_lock(&myrpt->lock);
12420 __kickshort(myrpt);
12421 rpt_mutex_unlock(&myrpt->lock);
12422 if ((!l->disced) && (!l->outbound))
12423 {
12424 if ((l->name[0] == '0') || l->isremote)
12425 l->disctime = 1;
12426 else
12427 l->disctime = DISC_TIME;
12428 rpt_mutex_lock(&myrpt->lock);
12429 ast_hangup(l->chan);
12430 l->chan = 0;
12431 break;
12432 }
12433
12434 if (l->retrytimer)
12435 {
12436 ast_hangup(l->chan);
12437 l->chan = 0;
12438 rpt_mutex_lock(&myrpt->lock);
12439 break;
12440 }
12441 if (l->outbound && (l->retries++ < l->max_retries) && (l->hasconnected))
12442 {
12443 rpt_mutex_lock(&myrpt->lock);
12444 if (l->chan) ast_hangup(l->chan);
12445 l->chan = 0;
12446 l->hasconnected = 1;
12447 l->retrytimer = RETRY_TIMER_MS;
12448 l->elaptime = 0;
12449 l->connecttime = 0;
12450 l->thisconnected = 0;
12451 break;
12452 }
12453 rpt_mutex_lock(&myrpt->lock);
12454
12455 remque((struct qelem *) l);
12456 if (!strcmp(myrpt->cmdnode,l->name))
12457 myrpt->cmdnode[0] = 0;
12458 __kickshort(myrpt);
12459 rpt_mutex_unlock(&myrpt->lock);
12460 if (!l->hasconnected)
12461 rpt_telemetry(myrpt,CONNFAIL,l);
12462 else if (l->disced != 2) rpt_telemetry(myrpt,REMDISC,l);
12463 if (myrpt->p.archivedir)
12464 {
12465 char str[100];
12466
12467 if (!l->hasconnected)
12468 sprintf(str,"LINKFAIL,%s",l->name);
12469 else
12470 sprintf(str,"LINKDISC,%s",l->name);
12471 donodelog(myrpt,str);
12472 }
12473 if (l->lastf1) ast_frfree(l->lastf1);
12474 l->lastf1 = NULL;
12475 if (l->lastf2) ast_frfree(l->lastf2);
12476 l->lastf2 = NULL;
12477
12478 ast_hangup(l->chan);
12479 ast_hangup(l->pchan);
12480 ast_free(l);
12481 rpt_mutex_lock(&myrpt->lock);
12482 break;
12483 }
12484 if (f->frametype == AST_FRAME_VOICE)
12485 {
12486 int ismuted,n1;
12487
12488 if ((l->phonemode) && (l->phonevox))
12489 {
12490 n1 = dovox(&l->vox,
12491 f->data.ptr,f->datalen / 2);
12492 if (n1 != l->wasvox)
12493 {
12494 if (debug)ast_log(LOG_DEBUG,"Link Node %s, vox %d\n",l->name,n1);
12495 l->wasvox = n1;
12496 l->voxtostate = 0;
12497 if (n1) l->voxtotimer = myrpt->p.voxtimeout_ms;
12498 else l->voxtotimer = 0;
12499 }
12500 if (l->lastrealrx || n1)
12501 {
12502 if (!myfirst)
12503 {
12504 x = 0;
12505 AST_LIST_TRAVERSE(&l->rxq, f1,
12506 frame_list) x++;
12507 for(;x < myrpt->p.simplexphonedelay; x++)
12508 {
12509 f1 = ast_frdup(f);
12510 memset(f1->data.ptr,0,f1->datalen);
12511 AST_LIST_INSERT_TAIL(&l->rxq,
12512 f1,frame_list);
12513 }
12514 myfirst = 1;
12515 }
12516 f1 = ast_frdup(f);
12517 AST_LIST_INSERT_TAIL(&l->rxq,f1,frame_list);
12518 } else myfirst = 0;
12519 x = 0;
12520 AST_LIST_TRAVERSE(&l->rxq, f1,frame_list) x++;
12521 if (!x)
12522 {
12523 memset(f->data.ptr,0,f->datalen);
12524 }
12525 else
12526 {
12527 ast_frfree(f);
12528 f = AST_LIST_REMOVE_HEAD(&l->rxq,frame_list);
12529 }
12530 if (ioctl(l->chan->fds[0], DAHDI_GETCONFMUTE, &ismuted) == -1)
12531 {
12532 ismuted = 0;
12533 }
12534
12535 ismuted |= (!l->lastrx);
12536 if (l->dtmfed && l->phonemode) ismuted = 1;
12537 l->dtmfed = 0;
12538 if (ismuted)
12539 {
12540 memset(f->data.ptr,0,f->datalen);
12541 if (l->lastf1)
12542 memset(l->lastf1->data.ptr,0,l->lastf1->datalen);
12543 if (l->lastf2)
12544 memset(l->lastf2->data.ptr,0,l->lastf2->datalen);
12545 }
12546 if (f) f2 = ast_frdup(f);
12547 else f2 = NULL;
12548 f1 = l->lastf2;
12549 l->lastf2 = l->lastf1;
12550 l->lastf1 = f2;
12551 if (ismuted)
12552 {
12553 if (l->lastf1)
12554 memset(l->lastf1->data.ptr,0,l->lastf1->datalen);
12555 if (l->lastf2)
12556 memset(l->lastf2->data.ptr,0,l->lastf2->datalen);
12557 }
12558 if (f1)
12559 {
12560 ast_write(l->pchan,f1);
12561 ast_frfree(f1);
12562 }
12563 }
12564 else
12565 {
12566 if (!l->lastrx)
12567 memset(f->data.ptr,0,f->datalen);
12568 ast_write(l->pchan,f);
12569 }
12570 }
12571 #ifndef OLD_ASTERISK
12572 else if (f->frametype == AST_FRAME_DTMF_BEGIN)
12573 {
12574 if (l->lastf1)
12575 memset(l->lastf1->data.ptr,0,l->lastf1->datalen);
12576 if (l->lastf2)
12577 memset(l->lastf2->data.ptr,0,l->lastf2->datalen);
12578 l->dtmfed = 1;
12579 }
12580 #endif
12581 if (f->frametype == AST_FRAME_TEXT)
12582 {
12583 handle_link_data(myrpt,l,f->data.ptr);
12584 }
12585 if (f->frametype == AST_FRAME_DTMF)
12586 {
12587 if (l->lastf1)
12588 memset(l->lastf1->data.ptr,0,l->lastf1->datalen);
12589 if (l->lastf2)
12590 memset(l->lastf2->data.ptr,0,l->lastf2->datalen);
12591 l->dtmfed = 1;
12592 handle_link_phone_dtmf(myrpt,l,f->subclass);
12593 }
12594 if (f->frametype == AST_FRAME_CONTROL)
12595 {
12596 if (f->subclass == AST_CONTROL_ANSWER)
12597 {
12598 char lconnected = l->connected;
12599
12600 __kickshort(myrpt);
12601 l->connected = 1;
12602 l->hasconnected = 1;
12603 l->thisconnected = 1;
12604 l->elaptime = -1;
12605 if (!l->phonemode) send_newkey(l->chan);
12606 if (!l->isremote) l->retries = 0;
12607 if (!lconnected)
12608 {
12609 rpt_telemetry(myrpt,CONNECTED,l);
12610 if (myrpt->p.archivedir)
12611 {
12612 char str[100];
12613
12614 if (l->mode)
12615 sprintf(str,"LINKTRX,%s",l->name);
12616 else
12617 sprintf(str,"LINKMONITOR,%s",l->name);
12618 donodelog(myrpt,str);
12619 }
12620 }
12621 else
12622 l->reconnects++;
12623 }
12624
12625 if (f->subclass == AST_CONTROL_RADIO_KEY)
12626 {
12627 if (debug == 7 ) printf("@@@@ rx key\n");
12628 l->lastrealrx = 1;
12629 l->rerxtimer = 0;
12630 if (!l->lastrx1)
12631 {
12632 if (myrpt->p.archivedir)
12633 {
12634 char str[100];
12635
12636 sprintf(str,"RXKEY,%s",l->name);
12637 donodelog(myrpt,str);
12638 }
12639 l->lastrx1 = 1;
12640 }
12641 }
12642
12643 if (f->subclass == AST_CONTROL_RADIO_UNKEY)
12644 {
12645 if (debug == 7) printf("@@@@ rx un-key\n");
12646 l->lastrealrx = 0;
12647 l->rerxtimer = 0;
12648 if (l->lastrx1)
12649 {
12650 if (myrpt->p.archivedir)
12651 {
12652 char str[100];
12653
12654 sprintf(str,"RXUNKEY,%s",l->name);
12655 donodelog(myrpt,str);
12656 }
12657 l->lastrx1 = 0;
12658 if(myrpt->p.duplex)
12659 rpt_telemetry(myrpt,LINKUNKEY,l);
12660 }
12661 }
12662 if (f->subclass == AST_CONTROL_HANGUP)
12663 {
12664 ast_frfree(f);
12665 rpt_mutex_lock(&myrpt->lock);
12666 __kickshort(myrpt);
12667 rpt_mutex_unlock(&myrpt->lock);
12668 if ((!l->outbound) && (!l->disced))
12669 {
12670 if ((l->name[0] == '0') || l->isremote)
12671 l->disctime = 1;
12672 else
12673 l->disctime = DISC_TIME;
12674 rpt_mutex_lock(&myrpt->lock);
12675 ast_hangup(l->chan);
12676 l->chan = 0;
12677 break;
12678 }
12679 if (l->retrytimer)
12680 {
12681 if (l->chan) ast_hangup(l->chan);
12682 l->chan = 0;
12683 rpt_mutex_lock(&myrpt->lock);
12684 break;
12685 }
12686 if (l->outbound && (l->retries++ < l->max_retries) && (l->hasconnected))
12687 {
12688 rpt_mutex_lock(&myrpt->lock);
12689 if (l->chan) ast_hangup(l->chan);
12690 l->chan = 0;
12691 l->hasconnected = 1;
12692 l->elaptime = 0;
12693 l->retrytimer = RETRY_TIMER_MS;
12694 l->connecttime = 0;
12695 l->thisconnected = 0;
12696 break;
12697 }
12698 rpt_mutex_lock(&myrpt->lock);
12699
12700 remque((struct qelem *) l);
12701 if (!strcmp(myrpt->cmdnode,l->name))
12702 myrpt->cmdnode[0] = 0;
12703 __kickshort(myrpt);
12704 rpt_mutex_unlock(&myrpt->lock);
12705 if (!l->hasconnected)
12706 rpt_telemetry(myrpt,CONNFAIL,l);
12707 else if (l->disced != 2) rpt_telemetry(myrpt,REMDISC,l);
12708 if (myrpt->p.archivedir)
12709 {
12710 char str[100];
12711
12712 if (!l->hasconnected)
12713 sprintf(str,"LINKFAIL,%s",l->name);
12714 else
12715 sprintf(str,"LINKDISC,%s",l->name);
12716 donodelog(myrpt,str);
12717 }
12718 if (l->lastf1) ast_frfree(l->lastf1);
12719 l->lastf1 = NULL;
12720 if (l->lastf2) ast_frfree(l->lastf2);
12721 l->lastf2 = NULL;
12722
12723 ast_hangup(l->chan);
12724 ast_hangup(l->pchan);
12725 ast_free(l);
12726 rpt_mutex_lock(&myrpt->lock);
12727 break;
12728 }
12729 }
12730 ast_frfree(f);
12731 rpt_mutex_lock(&myrpt->lock);
12732 break;
12733 }
12734 if (who == l->pchan)
12735 {
12736 rpt_mutex_unlock(&myrpt->lock);
12737 f = ast_read(l->pchan);
12738 if (!f)
12739 {
12740 if (debug) printf("@@@@ rpt:Hung Up\n");
12741 toexit = 1;
12742 rpt_mutex_lock(&myrpt->lock);
12743 break;
12744 }
12745 if (f->frametype == AST_FRAME_VOICE)
12746 {
12747 if (l->chan) ast_write(l->chan,f);
12748 }
12749 if (f->frametype == AST_FRAME_CONTROL)
12750 {
12751 if (f->subclass == AST_CONTROL_HANGUP)
12752 {
12753 if (debug) printf("@@@@ rpt:Hung Up\n");
12754 ast_frfree(f);
12755 toexit = 1;
12756 rpt_mutex_lock(&myrpt->lock);
12757 break;
12758 }
12759 }
12760 ast_frfree(f);
12761 rpt_mutex_lock(&myrpt->lock);
12762 break;
12763 }
12764 l = l->next;
12765 }
12766 rpt_mutex_unlock(&myrpt->lock);
12767 if (toexit) break;
12768 if (who == myrpt->monchannel)
12769 {
12770 f = ast_read(myrpt->monchannel);
12771 if (!f)
12772 {
12773 if (debug) printf("@@@@ rpt:Hung Up\n");
12774 break;
12775 }
12776 if (f->frametype == AST_FRAME_VOICE)
12777 {
12778 if (myrpt->monstream)
12779 ast_writestream(myrpt->monstream,f);
12780 }
12781 if (f->frametype == AST_FRAME_CONTROL)
12782 {
12783 if (f->subclass == AST_CONTROL_HANGUP)
12784 {
12785 if (debug) printf("@@@@ rpt:Hung Up\n");
12786 ast_frfree(f);
12787 break;
12788 }
12789 }
12790 ast_frfree(f);
12791 continue;
12792 }
12793 if (myrpt->parrotchannel && (who == myrpt->parrotchannel))
12794 {
12795 f = ast_read(myrpt->parrotchannel);
12796 if (!f)
12797 {
12798 if (debug) printf("@@@@ rpt:Hung Up\n");
12799 break;
12800 }
12801 if (!myrpt->p.parrotmode)
12802 {
12803 char myfname[300];
12804
12805 if (myrpt->parrotstream)
12806 {
12807 ast_closestream(myrpt->parrotstream);
12808 myrpt->parrotstream = 0;
12809 }
12810 sprintf(myfname,PARROTFILE,myrpt->name,myrpt->parrotcnt);
12811 strcat(myfname,".wav");
12812 unlink(myfname);
12813 } else if (f->frametype == AST_FRAME_VOICE)
12814 {
12815 if (myrpt->parrotstream)
12816 ast_writestream(myrpt->parrotstream,f);
12817 }
12818 if (f->frametype == AST_FRAME_CONTROL)
12819 {
12820 if (f->subclass == AST_CONTROL_HANGUP)
12821 {
12822 if (debug) printf("@@@@ rpt:Hung Up\n");
12823 ast_frfree(f);
12824 break;
12825 }
12826 }
12827 ast_frfree(f);
12828 continue;
12829 }
12830 if (myrpt->voxchannel && (who == myrpt->voxchannel))
12831 {
12832 f = ast_read(myrpt->voxchannel);
12833 if (!f)
12834 {
12835 if (debug) printf("@@@@ rpt:Hung Up\n");
12836 break;
12837 }
12838 if (f->frametype == AST_FRAME_VOICE)
12839 {
12840 n = dovox(&myrpt->vox,f->data.ptr,f->datalen / 2);
12841 if (n != myrpt->wasvox)
12842 {
12843 if (debug) ast_log(LOG_DEBUG,"Node %s, vox %d\n",myrpt->name,n);
12844 myrpt->wasvox = n;
12845 myrpt->voxtostate = 0;
12846 if (n) myrpt->voxtotimer = myrpt->p.voxtimeout_ms;
12847 else myrpt->voxtotimer = 0;
12848 }
12849 }
12850 if (f->frametype == AST_FRAME_CONTROL)
12851 {
12852 if (f->subclass == AST_CONTROL_HANGUP)
12853 {
12854 if (debug) printf("@@@@ rpt:Hung Up\n");
12855 ast_frfree(f);
12856 break;
12857 }
12858 }
12859 ast_frfree(f);
12860 continue;
12861 }
12862 if (who == myrpt->txpchannel)
12863 {
12864 f = ast_read(myrpt->txpchannel);
12865 if (!f)
12866 {
12867 if (debug) printf("@@@@ rpt:Hung Up\n");
12868 break;
12869 }
12870 if (f->frametype == AST_FRAME_CONTROL)
12871 {
12872 if (f->subclass == AST_CONTROL_HANGUP)
12873 {
12874 if (debug) printf("@@@@ rpt:Hung Up\n");
12875 ast_frfree(f);
12876 break;
12877 }
12878 }
12879 ast_frfree(f);
12880 continue;
12881 }
12882 }
12883 usleep(100000);
12884 ast_hangup(myrpt->pchannel);
12885 ast_hangup(myrpt->monchannel);
12886 if (myrpt->parrotchannel) ast_hangup(myrpt->parrotchannel);
12887 myrpt->parrotstate = 0;
12888 if (myrpt->voxchannel) ast_hangup(myrpt->voxchannel);
12889 ast_hangup(myrpt->txpchannel);
12890 if (myrpt->txchannel != myrpt->rxchannel) ast_hangup(myrpt->txchannel);
12891 if (myrpt->dahditxchannel != myrpt->txchannel) ast_hangup(myrpt->dahditxchannel);
12892 if (myrpt->lastf1) ast_frfree(myrpt->lastf1);
12893 myrpt->lastf1 = NULL;
12894 if (myrpt->lastf2) ast_frfree(myrpt->lastf2);
12895 myrpt->lastf2 = NULL;
12896 ast_hangup(myrpt->rxchannel);
12897 rpt_mutex_lock(&myrpt->lock);
12898 l = myrpt->links.next;
12899 while(l != &myrpt->links)
12900 {
12901 struct rpt_link *ll = l;
12902
12903 remque((struct qelem *) l);
12904
12905 if (l->chan) ast_hangup(l->chan);
12906 ast_hangup(l->pchan);
12907 l = l->next;
12908 ast_free(ll);
12909 }
12910 if (myrpt->xlink == 1) myrpt->xlink = 2;
12911 rpt_mutex_unlock(&myrpt->lock);
12912 if (debug) printf("@@@@ rpt:Hung up channel\n");
12913 myrpt->rpt_thread = AST_PTHREADT_STOP;
12914 pthread_exit(NULL);
12915 return NULL;
12916 }
12917
12918
12919 static void *rpt_master(void *ignore)
12920 {
12921 int i,n;
12922 pthread_attr_t attr;
12923 struct ast_config *cfg;
12924 char *this,*val;
12925
12926
12927 nodelog.next = nodelog.prev = &nodelog;
12928
12929 this = NULL;
12930 n = 0;
12931 #ifndef OLD_ASTERISK
12932
12933 while(!ast_test_flag(&ast_options,AST_OPT_FLAG_FULLY_BOOTED))
12934 usleep(250000);
12935 #endif
12936 #ifdef NEW_ASTERISK
12937 rpt_vars[n].cfg = ast_config_load("rpt.conf",config_flags);
12938 #else
12939 rpt_vars[n].cfg = ast_config_load("rpt.conf");
12940 #endif
12941 cfg = rpt_vars[n].cfg;
12942 if (!cfg || cfg == CONFIG_STATUS_FILEINVALID) {
12943 ast_log(LOG_NOTICE, "Unable to open radio repeater configuration rpt.conf. Radio Repeater disabled.\n");
12944 pthread_exit(NULL);
12945 }
12946 while((this = ast_category_browse(cfg,this)) != NULL)
12947 {
12948 for(i = 0 ; i < strlen(this) ; i++){
12949 if((this[i] < '0') || (this[i] > '9'))
12950 break;
12951 }
12952 if(i != strlen(this)) continue;
12953 memset(&rpt_vars[n],0,sizeof(rpt_vars[n]));
12954 rpt_vars[n].name = ast_strdup(this);
12955 val = (char *) ast_variable_retrieve(cfg,this,"rxchannel");
12956 if (val) rpt_vars[n].rxchanname = ast_strdup(val);
12957 val = (char *) ast_variable_retrieve(cfg,this,"txchannel");
12958 if (val) rpt_vars[n].txchanname = ast_strdup(val);
12959 rpt_vars[n].remote = 0;
12960 rpt_vars[n].remoterig = "";
12961 val = (char *) ast_variable_retrieve(cfg,this,"remote");
12962 if (val)
12963 {
12964 rpt_vars[n].remoterig = ast_strdup(val);
12965 rpt_vars[n].remote = 1;
12966 }
12967 val = (char *) ast_variable_retrieve(cfg,this,"radiotype");
12968 if (val) rpt_vars[n].remoterig = ast_strdup(val);
12969 ast_mutex_init(&rpt_vars[n].lock);
12970 ast_mutex_init(&rpt_vars[n].remlock);
12971 ast_mutex_init(&rpt_vars[n].statpost_lock);
12972 rpt_vars[n].tele.next = &rpt_vars[n].tele;
12973 rpt_vars[n].tele.prev = &rpt_vars[n].tele;
12974 rpt_vars[n].rpt_thread = AST_PTHREADT_NULL;
12975 rpt_vars[n].tailmessagen = 0;
12976 #ifdef _MDC_DECODE_H_
12977 rpt_vars[n].mdc = mdc_decoder_new(8000);
12978 #endif
12979 n++;
12980 }
12981 nrpts = n;
12982 ast_config_destroy(cfg);
12983
12984
12985 for(i = 0; i < n; i++)
12986 {
12987 load_rpt_vars(i,1);
12988
12989
12990 if (rpt_vars[i].remote)
12991 {
12992 if(retreive_memory(&rpt_vars[i],"init")){
12993 if (!strcmp(rpt_vars[i].remoterig,remote_rig_rtx450))
12994 strncpy(rpt_vars[i].freq, "446.500", sizeof(rpt_vars[i].freq) - 1);
12995 else
12996 strncpy(rpt_vars[i].freq, "146.580", sizeof(rpt_vars[i].freq) - 1);
12997 strncpy(rpt_vars[i].rxpl, "100.0", sizeof(rpt_vars[i].rxpl) - 1);
12998
12999 strncpy(rpt_vars[i].txpl, "100.0", sizeof(rpt_vars[i].txpl) - 1);
13000 rpt_vars[i].remmode = REM_MODE_FM;
13001 rpt_vars[i].offset = REM_SIMPLEX;
13002 rpt_vars[i].powerlevel = REM_LOWPWR;
13003 }
13004 continue;
13005 }
13006 else
13007 {
13008 rpt_vars[i].p.memory = rpt_vars[i].name;
13009 if(retreive_memory(&rpt_vars[i],"radiofreq")){
13010 if (!strcmp(rpt_vars[i].remoterig,remote_rig_rtx450))
13011 strncpy(rpt_vars[i].freq, "446.500", sizeof(rpt_vars[i].freq) - 1);
13012 else if (!strcmp(rpt_vars[i].remoterig,remote_rig_rtx150))
13013 strncpy(rpt_vars[i].freq, "146.580", sizeof(rpt_vars[i].freq) - 1);
13014 strncpy(rpt_vars[i].rxpl, "100.0", sizeof(rpt_vars[i].rxpl) - 1);
13015
13016 strncpy(rpt_vars[i].txpl, "100.0", sizeof(rpt_vars[i].txpl) - 1);
13017 rpt_vars[i].remmode = REM_MODE_FM;
13018 rpt_vars[i].offset = REM_SIMPLEX;
13019 rpt_vars[i].powerlevel = REM_LOWPWR;
13020 }
13021 ast_log(LOG_NOTICE,"Normal Repeater Init %s %s %s\n",rpt_vars[i].name, rpt_vars[i].remoterig, rpt_vars[i].freq);
13022 }
13023 if (!rpt_vars[i].p.ident)
13024 {
13025 ast_log(LOG_WARNING,"Did not specify ident for node %s\n",rpt_vars[i].name);
13026 ast_config_destroy(cfg);
13027 pthread_exit(NULL);
13028 }
13029 pthread_attr_init(&attr);
13030 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
13031 ast_pthread_create(&rpt_vars[i].rpt_thread,&attr,rpt,(void *) &rpt_vars[i]);
13032 }
13033 usleep(500000);
13034 time(&starttime);
13035 for(;;)
13036 {
13037
13038 for(i = 0; i < n; i++)
13039 {
13040 int rv;
13041 if (rpt_vars[i].remote) continue;
13042 if (rpt_vars[i].rpt_thread == AST_PTHREADT_STOP)
13043 rv = -1;
13044 else
13045 rv = pthread_kill(rpt_vars[i].rpt_thread,0);
13046 if (rv)
13047 {
13048 if(time(NULL) - rpt_vars[i].lastthreadrestarttime <= 15)
13049 {
13050 if(rpt_vars[i].threadrestarts >= 5)
13051 {
13052 ast_log(LOG_ERROR,"Continual RPT thread restarts, killing Asterisk\n");
13053 exit(1);
13054 }
13055 else
13056 {
13057 ast_log(LOG_NOTICE,"RPT thread restarted on %s\n",rpt_vars[i].name);
13058 rpt_vars[i].threadrestarts++;
13059 }
13060 }
13061 else
13062 rpt_vars[i].threadrestarts = 0;
13063
13064 rpt_vars[i].lastthreadrestarttime = time(NULL);
13065 pthread_attr_init(&attr);
13066 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
13067 ast_pthread_create(&rpt_vars[i].rpt_thread,&attr,rpt,(void *) &rpt_vars[i]);
13068
13069 ast_log(LOG_WARNING, "rpt_thread restarted on node %s\n", rpt_vars[i].name);
13070 }
13071
13072 }
13073 for(;;)
13074 {
13075 struct nodelog *nodep;
13076 char *space,datestr[100],fname[300];
13077 int fd;
13078
13079 ast_mutex_lock(&nodeloglock);
13080 nodep = nodelog.next;
13081 if(nodep == &nodelog)
13082 {
13083 ast_mutex_unlock(&nodeloglock);
13084 break;
13085 }
13086 remque((struct qelem *)nodep);
13087 ast_mutex_unlock(&nodeloglock);
13088 space = strchr(nodep->str,' ');
13089 if (!space)
13090 {
13091 ast_free(nodep);
13092 continue;
13093 }
13094 *space = 0;
13095 strftime(datestr,sizeof(datestr) - 1,"%Y%m%d",
13096 localtime(&nodep->timestamp));
13097 sprintf(fname,"%s/%s/%s.txt",nodep->archivedir,
13098 nodep->str,datestr);
13099 fd = open(fname,O_WRONLY | O_CREAT | O_APPEND,0600);
13100 if (fd == -1)
13101 {
13102 ast_log(LOG_ERROR,"Cannot open node log file %s for write",space + 1);
13103 ast_free(nodep);
13104 continue;
13105 }
13106 if (write(fd,space + 1,strlen(space + 1)) !=
13107 strlen(space + 1))
13108 {
13109 ast_log(LOG_ERROR,"Cannot write node log file %s for write",space + 1);
13110 ast_free(nodep);
13111 continue;
13112 }
13113 close(fd);
13114 ast_free(nodep);
13115 }
13116 sleep(2);
13117 }
13118 ast_config_destroy(cfg);
13119 pthread_exit(NULL);
13120 }
13121
13122 static int rpt_exec(struct ast_channel *chan, void *data)
13123 {
13124 int res=-1,i,rem_totx,rem_rx,remkeyed,n,phone_mode = 0;
13125 int iskenwood_pci4,authtold,authreq,setting,notremming,reming;
13126 int ismuted,dtmfed,phone_vox = 0;
13127 #ifdef OLD_ASTERISK
13128 struct localuser *u;
13129 #endif
13130 char tmp[256], keyed = 0,keyed1 = 0;
13131 char *options,*stringp,*tele,c,*altp,*memp;
13132 char sx[320],*sy;
13133 struct rpt *myrpt;
13134 struct ast_frame *f,*f1,*f2;
13135 struct ast_channel *who;
13136 struct ast_channel *cs[20];
13137 struct rpt_link *l;
13138 struct dahdi_confinfo ci;
13139 struct dahdi_params par;
13140 int ms,elap,nullfd;
13141 time_t t,last_timeout_warning;
13142 struct dahdi_radio_param z;
13143 struct rpt_tele *telem;
13144 int numlinks;
13145
13146 nullfd = open("/dev/null",O_RDWR);
13147 if (ast_strlen_zero(data)) {
13148 ast_log(LOG_WARNING, "Rpt requires an argument (system node)\n");
13149 return -1;
13150 }
13151
13152 strncpy(tmp, (char *)data, sizeof(tmp)-1);
13153 time(&t);
13154
13155 if (t < starttime) t = starttime + START_DELAY;
13156 if ((!starttime) || (t < (starttime + START_DELAY)))
13157 {
13158 ast_log(LOG_NOTICE,"Node %s rejecting call: too soon!\n",tmp);
13159 ast_safe_sleep(chan,3000);
13160 return -1;
13161 }
13162
13163 ast_log(LOG_NOTICE,"parsing argument=%s \n",tmp);
13164
13165 altp=strstr(tmp, "|*");
13166 if(altp){
13167 altp[0]=0;
13168 altp++;
13169 }
13170
13171 memp=strstr(tmp, "|M");
13172 if(memp){
13173 memp[0]=0;
13174 memp+=2;
13175 }
13176
13177 stringp=tmp;
13178 strsep(&stringp, "|");
13179 options = stringp;
13180
13181 ast_log(LOG_NOTICE,"options=%s \n",options);
13182 if(memp>0)ast_log(LOG_NOTICE,"memp=%s \n",memp);
13183 if(altp>0)ast_log(LOG_NOTICE,"altp=%s \n",altp);
13184
13185 myrpt = NULL;
13186
13187 for(i = 0; i < nrpts; i++)
13188 {
13189
13190 if (!strcmp(tmp,rpt_vars[i].name))
13191 {
13192 myrpt = &rpt_vars[i];
13193 break;
13194 }
13195 }
13196
13197 pbx_builtin_setvar_helper(chan, "RPT_STAT_ERR", "");
13198
13199 if (myrpt == NULL)
13200 {
13201 pbx_builtin_setvar_helper(chan, "RPT_STAT_ERR", "NODE_NOT_FOUND");
13202 ast_log(LOG_WARNING, "Cannot find specified system node %s\n",tmp);
13203 return (priority_jump(NULL,chan));
13204 }
13205
13206 numlinks=linkcount(myrpt);
13207
13208 if(options && *options == 'q')
13209 {
13210 char buf2[128];
13211
13212 if(myrpt->keyed)
13213 pbx_builtin_setvar_helper(chan, "RPT_STAT_RXKEYED", "1");
13214 else
13215 pbx_builtin_setvar_helper(chan, "RPT_STAT_RXKEYED", "0");
13216
13217 if(myrpt->txkeyed)
13218 pbx_builtin_setvar_helper(chan, "RPT_STAT_TXKEYED", "1");
13219 else
13220 pbx_builtin_setvar_helper(chan, "RPT_STAT_TXKEYED", "0");
13221
13222 snprintf(buf2,sizeof(buf2),"%s=%i", "RPT_STAT_XLINK", myrpt->xlink);
13223 pbx_builtin_setvar(chan, buf2);
13224 snprintf(buf2,sizeof(buf2),"%s=%i", "RPT_STAT_LINKS", numlinks);
13225 pbx_builtin_setvar(chan, buf2);
13226 snprintf(buf2,sizeof(buf2),"%s=%d", "RPT_STAT_WASCHAN", myrpt->waschan);
13227 pbx_builtin_setvar(chan, buf2);
13228 snprintf(buf2,sizeof(buf2),"%s=%d", "RPT_STAT_NOWCHAN", myrpt->nowchan);
13229 pbx_builtin_setvar(chan, buf2);
13230 snprintf(buf2,sizeof(buf2),"%s=%d", "RPT_STAT_DUPLEX", myrpt->p.duplex);
13231 pbx_builtin_setvar(chan, buf2);
13232 snprintf(buf2,sizeof(buf2),"%s=%d", "RPT_STAT_PARROT", myrpt->p.parrotmode);
13233 pbx_builtin_setvar(chan, buf2);
13234
13235
13236
13237
13238 snprintf(buf2,sizeof(buf2),"%s=%d", "RPT_STAT_CALLMODE", myrpt->callmode);
13239 pbx_builtin_setvar(chan, buf2);
13240 snprintf(buf2,sizeof(buf2),"%s=%s", "RPT_STAT_LASTTONE", myrpt->lasttone);
13241 pbx_builtin_setvar(chan, buf2);
13242
13243 return priority_jump(myrpt,chan);
13244 }
13245
13246 if(options && *options == 'o')
13247 {
13248 return(channel_revert(myrpt));
13249 }
13250
13251 #if 0
13252 if((altp)&&(*options == 'Z'))
13253 {
13254 rpt_push_alt_macro(myrpt,altp);
13255 return 0;
13256 }
13257 #endif
13258
13259
13260
13261 if (options && ((*options == 'P') || (*options == 'D') || (*options == 'R') || (*options == 'S')))
13262 {
13263 int val;
13264
13265 pbx_builtin_setvar_helper(chan, "RPT_STAT_BUSY", "0");
13266
13267 myrpt->bargechan=0;
13268 if(options && strstr(options, "f")>0)
13269 {
13270 myrpt->bargechan=1;
13271 }
13272
13273 if(memp>0)
13274 {
13275 char radiochan;
13276 radiochan=strtod(data,NULL);
13277
13278
13279 if(numlinks>0 && radiochan!=myrpt->nowchan && !myrpt->bargechan)
13280 {
13281 pbx_builtin_setvar_helper(chan, "RPT_STAT_BUSY", "1");
13282 ast_log(LOG_NOTICE, "Radio Channel Busy.\n");
13283 return (priority_jump(myrpt,chan));
13284 }
13285 else if(radiochan!=myrpt->nowchan || myrpt->bargechan)
13286 {
13287 channel_steer(myrpt,memp);
13288 }
13289 }
13290 if(altp)rpt_push_alt_macro(myrpt,altp);
13291 phone_mode = 1;
13292 if (*options == 'D') phone_mode = 2;
13293 if (*options == 'S') phone_mode = 3;
13294 ast_set_callerid(chan,"0","app_rpt user","0");
13295 val = 1;
13296 ast_channel_setoption(chan,AST_OPTION_TONE_VERIFY,&val,sizeof(char),0);
13297 if ((*(options + 1) == 'V') || (*(options + 1) == 'v')) phone_vox = 1;
13298 }
13299 else
13300 {
13301 #ifdef ALLOW_LOCAL_CHANNELS
13302
13303 if ( (strncmp(chan->name,"IAX2",4)) && (strncmp(chan->name,"Local",5)) ) {
13304 ast_log(LOG_WARNING, "We only accept links via IAX2 or Local!!\n");
13305 return -1;
13306 }
13307 #else
13308 if (strncmp(chan->name,"IAX2",4))
13309 {
13310 ast_log(LOG_WARNING, "We only accept links via IAX2!!\n");
13311 return -1;
13312 }
13313 #endif
13314 if(myrpt->p.s[myrpt->p.sysstate_cur].txdisable){
13315 ast_log(LOG_NOTICE, "Connect attempt to node %s with tx disabled", myrpt->name);
13316 return -1;
13317 }
13318 }
13319 if (options && (*options == 'R'))
13320 {
13321
13322 char *return_context;
13323 int length, m, lot, timeout = 0;
13324 char buffer[256],*template;
13325 char *working, *context, *exten, *priority;
13326 char *s,*orig_s;
13327
13328 rpt_mutex_lock(&myrpt->lock);
13329 m = myrpt->callmode;
13330 rpt_mutex_unlock(&myrpt->lock);
13331
13332 if ((!myrpt->p.nobusyout) && m)
13333 {
13334 if (chan->_state != AST_STATE_UP)
13335 {
13336 ast_indicate(chan,AST_CONTROL_BUSY);
13337 }
13338 while(ast_safe_sleep(chan,10000) != -1);
13339 return -1;
13340 }
13341
13342 if (chan->_state != AST_STATE_UP)
13343 {
13344 ast_answer(chan);
13345 if (!phone_mode) send_newkey(chan);
13346 }
13347
13348 length=strlen(options)+2;
13349 orig_s=ast_malloc(length);
13350 if(!orig_s) {
13351 ast_log(LOG_WARNING, "Out of memory\n");
13352 return -1;
13353 }
13354 s=orig_s;
13355 strncpy(s,options,length);
13356
13357 template=strsep(&s,"|");
13358 if(!template) {
13359 ast_log(LOG_WARNING, "An announce template must be defined\n");
13360 ast_free(orig_s);
13361 return -1;
13362 }
13363
13364 if(s) {
13365 timeout = atoi(strsep(&s, "|"));
13366 timeout *= 1000;
13367 }
13368
13369 return_context = s;
13370
13371 if(return_context != NULL) {
13372
13373
13374 working = return_context;
13375 context = strsep(&working, "|");
13376 exten = strsep(&working, "|");
13377 if(!exten) {
13378
13379 priority = context;
13380 exten = NULL;
13381 context = NULL;
13382 } else {
13383 priority = strsep(&working, "|");
13384 if(!priority) {
13385
13386 priority = exten;
13387 exten = context;
13388 context = NULL;
13389 }
13390 }
13391 if(atoi(priority) < 0) {
13392 ast_log(LOG_WARNING, "Priority '%s' must be a number > 0\n", priority);
13393 ast_free(orig_s);
13394 return -1;
13395 }
13396
13397 chan->priority = atoi(priority);
13398 #ifdef OLD_ASTERISK
13399 if(exten && strcasecmp(exten, "BYEXTENSION"))
13400 #else
13401 if(exten)
13402 #endif
13403 strncpy(chan->exten, exten, sizeof(chan->exten)-1);
13404 if(context)
13405 strncpy(chan->context, context, sizeof(chan->context)-1);
13406 } else {
13407 chan->priority++;
13408 }
13409
13410 if(option_verbose > 2) {
13411 ast_verbose( VERBOSE_PREFIX_3 "Return Context: (%s,%s,%d) ID: %s\n", chan->context,chan->exten, chan->priority, chan->cid.cid_num);
13412 if(!ast_exists_extension(chan, chan->context, chan->exten, chan->priority, chan->cid.cid_num)) {
13413 ast_verbose( VERBOSE_PREFIX_3 "Warning: Return Context Invalid, call will return to default|s\n");
13414 }
13415 }
13416
13417
13418
13419
13420 ast_masq_park_call(chan, NULL, timeout, &lot);
13421
13422 if (option_verbose > 2) ast_verbose( VERBOSE_PREFIX_3 "Call Parking Called, lot: %d, timeout: %d, context: %s\n", lot, timeout, return_context);
13423
13424 snprintf(buffer, sizeof(buffer) - 1, "%d,%s", lot, template + 1);
13425
13426 rpt_telemetry(myrpt,REV_PATCH,buffer);
13427
13428 ast_free(orig_s);
13429
13430 return 0;
13431
13432 }
13433
13434 if (!options)
13435 {
13436 struct ast_hostent ahp;
13437 struct hostent *hp;
13438 struct in_addr ia;
13439 char hisip[100],nodeip[100],*val, *s, *s1, *s2, *s3, *b,*b1;
13440
13441
13442 if (!chan->cid.cid_num)
13443 {
13444 ast_log(LOG_WARNING, "Does not have callerid on %s\n",tmp);
13445 return -1;
13446 }
13447
13448 memset(hisip,0,sizeof(hisip));
13449 #ifdef ALLOW_LOCAL_CHANNELS
13450
13451 if (strncmp(chan->name,"Local",5)==0) {
13452 strcpy(hisip,"127.0.0.1");
13453 } else {
13454 pbx_substitute_variables_helper(chan,"${IAXPEER(CURRENTCHANNEL)}",hisip,sizeof(hisip) - 1);
13455 }
13456 #else
13457 pbx_substitute_variables_helper(chan,"${IAXPEER(CURRENTCHANNEL)}",hisip,sizeof(hisip) - 1);
13458 #endif
13459
13460 if (!hisip[0])
13461 {
13462 ast_log(LOG_WARNING, "Link IP address cannot be determined!!\n");
13463 return -1;
13464 }
13465
13466 ast_callerid_parse(chan->cid.cid_num,&b,&b1);
13467 ast_shrink_phone_number(b1);
13468 if (!strcmp(myrpt->name,b1))
13469 {
13470 ast_log(LOG_WARNING, "Trying to link to self!!\n");
13471 return -1;
13472 }
13473
13474 if (*b1 < '1')
13475 {
13476 ast_log(LOG_WARNING, "Node %s Invalid for connection here!!\n",b1);
13477 return -1;
13478 }
13479
13480
13481
13482 val = node_lookup(myrpt,b1);
13483 if (!val)
13484 {
13485 ast_log(LOG_WARNING, "Reported node %s cannot be found!!\n",b1);
13486 return -1;
13487 }
13488 strncpy(tmp,val,sizeof(tmp) - 1);
13489 s = tmp;
13490 s1 = strsep(&s,",");
13491 if (!strchr(s1,':') && strchr(s1,'/') && strncasecmp(s1, "local/", 6))
13492 {
13493 sy = strchr(s1,'/');
13494 *sy = 0;
13495 sprintf(sx,"%s:4569/%s",s1,sy + 1);
13496 s1 = sx;
13497 }
13498 s2 = strsep(&s,",");
13499 if (!s2)
13500 {
13501 ast_log(LOG_WARNING, "Reported node %s not in correct format!!\n",b1);
13502 return -1;
13503 }
13504 if (strcmp(s2,"NONE")) {
13505 hp = ast_gethostbyname(s2, &ahp);
13506 if (!hp)
13507 {
13508 ast_log(LOG_WARNING, "Reported node %s, name %s cannot be found!!\n",b1,s2);
13509 return -1;
13510 }
13511 memcpy(&ia,hp->h_addr,sizeof(in_addr_t));
13512 #ifdef OLD_ASTERISK
13513 ast_inet_ntoa(nodeip,sizeof(nodeip) - 1,ia);
13514 #else
13515 strncpy(nodeip,ast_inet_ntoa(ia),sizeof(nodeip) - 1);
13516 #endif
13517 s3 = strchr(hisip,':');
13518 if (s3) *s3 = 0;
13519 if (strcmp(hisip,nodeip))
13520 {
13521 s3 = strchr(s1,'@');
13522 if (s3) s1 = s3 + 1;
13523 s3 = strchr(s1,'/');
13524 if (s3) *s3 = 0;
13525 s3 = strchr(s1,':');
13526 if (s3) *s3 = 0;
13527 hp = ast_gethostbyname(s1, &ahp);
13528 if (!hp)
13529 {
13530 ast_log(LOG_WARNING, "Reported node %s, name %s cannot be found!!\n",b1,s1);
13531 return -1;
13532 }
13533 memcpy(&ia,hp->h_addr,sizeof(in_addr_t));
13534 #ifdef OLD_ASTERISK
13535 ast_inet_ntoa(nodeip,sizeof(nodeip) - 1,ia);
13536 #else
13537 strncpy(nodeip,ast_inet_ntoa(ia),sizeof(nodeip) - 1);
13538 #endif
13539 if (strcmp(hisip,nodeip))
13540 {
13541 ast_log(LOG_WARNING, "Node %s IP %s does not match link IP %s!!\n",b1,nodeip,hisip);
13542 return -1;
13543 }
13544 }
13545 }
13546 }
13547
13548
13549 if (!myrpt->remote)
13550 {
13551 char *b,*b1;
13552 int reconnects = 0;
13553
13554 rpt_mutex_lock(&myrpt->lock);
13555 i = myrpt->xlink;
13556 rpt_mutex_unlock(&myrpt->lock);
13557 if (i)
13558 {
13559 ast_log(LOG_WARNING, "Cannot connect to node %s, system busy\n",myrpt->name);
13560 return -1;
13561 }
13562
13563 if (!chan->cid.cid_num)
13564 {
13565 ast_log(LOG_WARNING, "Doesnt have callerid on %s\n",tmp);
13566 return -1;
13567 }
13568
13569 ast_callerid_parse(chan->cid.cid_num,&b,&b1);
13570 ast_shrink_phone_number(b1);
13571 if (!strcmp(myrpt->name,b1))
13572 {
13573 ast_log(LOG_WARNING, "Trying to link to self!!\n");
13574 return -1;
13575 }
13576 rpt_mutex_lock(&myrpt->lock);
13577 l = myrpt->links.next;
13578
13579 while(l != &myrpt->links)
13580 {
13581 if (l->name[0] == '0')
13582 {
13583 l = l->next;
13584 continue;
13585 }
13586
13587 if (!strcmp(l->name,b1)) break;
13588 l = l->next;
13589 }
13590
13591 if (l != &myrpt->links)
13592 {
13593 l->killme = 1;
13594 l->retries = l->max_retries + 1;
13595 l->disced = 2;
13596 reconnects = l->reconnects;
13597 reconnects++;
13598 rpt_mutex_unlock(&myrpt->lock);
13599 usleep(500000);
13600 } else
13601 rpt_mutex_unlock(&myrpt->lock);
13602
13603 l = ast_malloc(sizeof(struct rpt_link));
13604 if (!l)
13605 {
13606 ast_log(LOG_WARNING, "Unable to malloc\n");
13607 pthread_exit(NULL);
13608 }
13609
13610 memset((char *)l,0,sizeof(struct rpt_link));
13611 l->mode = 1;
13612 strncpy(l->name,b1,MAXNODESTR - 1);
13613 l->isremote = 0;
13614 l->chan = chan;
13615 l->connected = 1;
13616 l->thisconnected = 1;
13617 l->hasconnected = 1;
13618 l->reconnects = reconnects;
13619 l->phonemode = phone_mode;
13620 l->phonevox = phone_vox;
13621 l->lastf1 = NULL;
13622 l->lastf2 = NULL;
13623 l->dtmfed = 0;
13624 voxinit_link(l,1);
13625 ast_set_read_format(l->chan,AST_FORMAT_SLINEAR);
13626 ast_set_write_format(l->chan,AST_FORMAT_SLINEAR);
13627
13628 l->pchan = ast_request("DAHDI",AST_FORMAT_SLINEAR,"pseudo",NULL);
13629 if (!l->pchan)
13630 {
13631 fprintf(stderr,"rpt:Sorry unable to obtain pseudo channel\n");
13632 pthread_exit(NULL);
13633 }
13634 ast_set_read_format(l->pchan,AST_FORMAT_SLINEAR);
13635 ast_set_write_format(l->pchan,AST_FORMAT_SLINEAR);
13636 #ifdef AST_CDR_FLAG_POST_DISABLED
13637 if (l->pchan->cdr)
13638 ast_set_flag(l->pchan->cdr,AST_CDR_FLAG_POST_DISABLED);
13639 #endif
13640
13641 ci.chan = 0;
13642 ci.confno = myrpt->conf;
13643 ci.confmode = DAHDI_CONF_CONF | DAHDI_CONF_LISTENER | DAHDI_CONF_TALKER;
13644
13645 if (ioctl(l->pchan->fds[0],DAHDI_SETCONF,&ci) == -1)
13646 {
13647 ast_log(LOG_WARNING, "Unable to set conference mode to Announce\n");
13648 pthread_exit(NULL);
13649 }
13650 rpt_mutex_lock(&myrpt->lock);
13651 if ((phone_mode == 2) && (!phone_vox)) l->lastrealrx = 1;
13652 l->max_retries = MAX_RETRIES;
13653
13654 insque((struct qelem *)l,(struct qelem *)myrpt->links.next);
13655 __kickshort(myrpt);
13656 rpt_mutex_unlock(&myrpt->lock);
13657 if (chan->_state != AST_STATE_UP) {
13658 ast_answer(chan);
13659 if (!phone_mode) send_newkey(chan);
13660 }
13661 if (myrpt->p.archivedir)
13662 {
13663 char str[100];
13664
13665 if (l->phonemode)
13666 sprintf(str,"LINK(P),%s",l->name);
13667 else
13668 sprintf(str,"LINK,%s",l->name);
13669 donodelog(myrpt,str);
13670 }
13671 if (!phone_mode) send_newkey(chan);
13672 return 0;
13673 }
13674
13675 rpt_mutex_lock(&myrpt->lock);
13676
13677 if (myrpt->remoteon)
13678 {
13679 rpt_mutex_unlock(&myrpt->lock);
13680 usleep(500000);
13681 if (myrpt->remoteon)
13682 {
13683 ast_log(LOG_WARNING, "Trying to use busy link on %s\n",tmp);
13684 #ifdef AST_CDR_FLAG_POST_DISABLED
13685 if (chan->cdr)
13686 ast_set_flag(chan->cdr,AST_CDR_FLAG_POST_DISABLED);
13687 #endif
13688 return -1;
13689 }
13690 rpt_mutex_lock(&myrpt->lock);
13691 }
13692 if (myrpt->p.rptnode)
13693 {
13694 char killedit = 0;
13695 time_t now;
13696
13697 time(&now);
13698 for(i = 0; i < nrpts; i++)
13699 {
13700 if (!strcasecmp(rpt_vars[i].name,myrpt->p.rptnode))
13701 {
13702 if ((rpt_vars[i].links.next != &rpt_vars[i].links) ||
13703 rpt_vars[i].keyed ||
13704 ((rpt_vars[i].lastkeyedtime + RPT_LOCKOUT_SECS) > now) ||
13705 rpt_vars[i].txkeyed ||
13706 ((rpt_vars[i].lasttxkeyedtime + RPT_LOCKOUT_SECS) > now))
13707 {
13708 rpt_mutex_unlock(&myrpt->lock);
13709 ast_log(LOG_WARNING, "Trying to use busy link (repeater node %s) on %s\n",rpt_vars[i].name,tmp);
13710 #ifdef AST_CDR_FLAG_POST_DISABLED
13711 if (chan->cdr)
13712 ast_set_flag(chan->cdr,AST_CDR_FLAG_POST_DISABLED);
13713 #endif
13714 return -1;
13715 }
13716 while(rpt_vars[i].xlink != 3)
13717 {
13718 if (!killedit)
13719 {
13720 ast_softhangup(rpt_vars[i].rxchannel,AST_SOFTHANGUP_DEV);
13721 rpt_vars[i].xlink = 1;
13722 killedit = 1;
13723 }
13724 rpt_mutex_unlock(&myrpt->lock);
13725 if (ast_safe_sleep(chan,500) == -1)
13726 {
13727 #ifdef AST_CDR_FLAG_POST_DISABLED
13728 if (chan->cdr)
13729 ast_set_flag(chan->cdr,AST_CDR_FLAG_POST_DISABLED);
13730 #endif
13731 return -1;
13732 }
13733 rpt_mutex_lock(&myrpt->lock);
13734 }
13735 break;
13736 }
13737 }
13738 }
13739
13740 #ifdef HAVE_IOPERM
13741 if ( (!strcmp(myrpt->remoterig, remote_rig_rbi)||!strcmp(myrpt->remoterig, remote_rig_ppp16)) &&
13742 (ioperm(myrpt->p.iobase,1,1) == -1))
13743 {
13744 rpt_mutex_unlock(&myrpt->lock);
13745 ast_log(LOG_WARNING, "Can't get io permission on IO port %x hex\n",myrpt->p.iobase);
13746 return -1;
13747 }
13748 #endif
13749 myrpt->remoteon = 1;
13750 #ifdef OLD_ASTERISK
13751 LOCAL_USER_ADD(u);
13752 #endif
13753 rpt_mutex_unlock(&myrpt->lock);
13754
13755 for(i = 0; i < nrpts; i++)
13756 {
13757 if (&rpt_vars[i] == myrpt)
13758 {
13759 load_rpt_vars(i,0);
13760 break;
13761 }
13762 }
13763 rpt_mutex_lock(&myrpt->lock);
13764 tele = strchr(myrpt->rxchanname,'/');
13765 if (!tele)
13766 {
13767 fprintf(stderr,"rpt:Dial number must be in format tech/number\n");
13768 rpt_mutex_unlock(&myrpt->lock);
13769 pthread_exit(NULL);
13770 }
13771 *tele++ = 0;
13772 myrpt->rxchannel = ast_request(myrpt->rxchanname,AST_FORMAT_SLINEAR,tele,NULL);
13773 myrpt->dahdirxchannel = NULL;
13774 if (!strcasecmp(myrpt->rxchanname,"DAHDI"))
13775 myrpt->dahdirxchannel = myrpt->rxchannel;
13776 if (myrpt->rxchannel)
13777 {
13778 ast_set_read_format(myrpt->rxchannel,AST_FORMAT_SLINEAR);
13779 ast_set_write_format(myrpt->rxchannel,AST_FORMAT_SLINEAR);
13780 #ifdef AST_CDR_FLAG_POST_DISABLED
13781 if (myrpt->rxchannel->cdr)
13782 ast_set_flag(myrpt->rxchannel->cdr,AST_CDR_FLAG_POST_DISABLED);
13783 #endif
13784 #ifndef NEW_ASTERISK
13785 myrpt->rxchannel->whentohangup = 0;
13786 #endif
13787 myrpt->rxchannel->appl = "Apprpt";
13788 myrpt->rxchannel->data = "(Link Rx)";
13789 if (option_verbose > 2)
13790 ast_verbose(VERBOSE_PREFIX_3 "rpt (Rx) initiating call to %s/%s on %s\n",
13791 myrpt->rxchanname,tele,myrpt->rxchannel->name);
13792 rpt_mutex_unlock(&myrpt->lock);
13793 ast_call(myrpt->rxchannel,tele,999);
13794 rpt_mutex_lock(&myrpt->lock);
13795 }
13796 else
13797 {
13798 fprintf(stderr,"rpt:Sorry unable to obtain Rx channel\n");
13799 rpt_mutex_unlock(&myrpt->lock);
13800 pthread_exit(NULL);
13801 }
13802 *--tele = '/';
13803 myrpt->dahditxchannel = NULL;
13804 if (myrpt->txchanname)
13805 {
13806 tele = strchr(myrpt->txchanname,'/');
13807 if (!tele)
13808 {
13809 fprintf(stderr,"rpt:Dial number must be in format tech/number\n");
13810 rpt_mutex_unlock(&myrpt->lock);
13811 ast_hangup(myrpt->rxchannel);
13812 pthread_exit(NULL);
13813 }
13814 *tele++ = 0;
13815 myrpt->txchannel = ast_request(myrpt->txchanname,AST_FORMAT_SLINEAR,tele,NULL);
13816 if (!strncasecmp(myrpt->txchanname,"DAHDI",3))
13817 myrpt->dahditxchannel = myrpt->txchannel;
13818 if (myrpt->txchannel)
13819 {
13820 ast_set_read_format(myrpt->txchannel,AST_FORMAT_SLINEAR);
13821 ast_set_write_format(myrpt->txchannel,AST_FORMAT_SLINEAR);
13822 #ifdef AST_CDR_FLAG_POST_DISABLED
13823 if (myrpt->txchannel->cdr)
13824 ast_set_flag(myrpt->txchannel->cdr,AST_CDR_FLAG_POST_DISABLED);
13825 #endif
13826 #ifndef NEW_ASTERISK
13827 myrpt->txchannel->whentohangup = 0;
13828 #endif
13829 myrpt->txchannel->appl = "Apprpt";
13830 myrpt->txchannel->data = "(Link Tx)";
13831 if (option_verbose > 2)
13832 ast_verbose(VERBOSE_PREFIX_3 "rpt (Tx) initiating call to %s/%s on %s\n",
13833 myrpt->txchanname,tele,myrpt->txchannel->name);
13834 rpt_mutex_unlock(&myrpt->lock);
13835 ast_call(myrpt->txchannel,tele,999);
13836 rpt_mutex_lock(&myrpt->lock);
13837 }
13838 else
13839 {
13840 fprintf(stderr,"rpt:Sorry unable to obtain Tx channel\n");
13841 rpt_mutex_unlock(&myrpt->lock);
13842 ast_hangup(myrpt->rxchannel);
13843 pthread_exit(NULL);
13844 }
13845 *--tele = '/';
13846 }
13847 else
13848 {
13849 myrpt->txchannel = myrpt->rxchannel;
13850 if (!strncasecmp(myrpt->rxchanname,"DAHDI",3))
13851 myrpt->dahditxchannel = myrpt->rxchannel;
13852 }
13853
13854 myrpt->pchannel = ast_request("DAHDI",AST_FORMAT_SLINEAR,"pseudo",NULL);
13855 if (!myrpt->pchannel)
13856 {
13857 fprintf(stderr,"rpt:Sorry unable to obtain pseudo channel\n");
13858 rpt_mutex_unlock(&myrpt->lock);
13859 if (myrpt->txchannel != myrpt->rxchannel)
13860 ast_hangup(myrpt->txchannel);
13861 ast_hangup(myrpt->rxchannel);
13862 pthread_exit(NULL);
13863 }
13864 ast_set_read_format(myrpt->pchannel,AST_FORMAT_SLINEAR);
13865 ast_set_write_format(myrpt->pchannel,AST_FORMAT_SLINEAR);
13866 #ifdef AST_CDR_FLAG_POST_DISABLED
13867 if (myrpt->pchannel->cdr)
13868 ast_set_flag(myrpt->pchannel->cdr,AST_CDR_FLAG_POST_DISABLED);
13869 #endif
13870 if (!myrpt->dahdirxchannel) myrpt->dahdirxchannel = myrpt->pchannel;
13871 if (!myrpt->dahditxchannel) myrpt->dahditxchannel = myrpt->pchannel;
13872
13873 ci.chan = 0;
13874 ci.confno = -1;
13875 ci.confmode = DAHDI_CONF_CONFANNMON ;
13876
13877 if (ioctl(myrpt->pchannel->fds[0],DAHDI_SETCONF,&ci) == -1)
13878 {
13879 ast_log(LOG_WARNING, "Unable to set conference mode to Announce\n");
13880 rpt_mutex_unlock(&myrpt->lock);
13881 ast_hangup(myrpt->pchannel);
13882 if (myrpt->txchannel != myrpt->rxchannel)
13883 ast_hangup(myrpt->txchannel);
13884 ast_hangup(myrpt->rxchannel);
13885 pthread_exit(NULL);
13886 }
13887
13888 myrpt->conf = myrpt->txconf = ci.confno;
13889
13890 myrpt->iofd = -1;
13891 if (myrpt->p.ioport && ((myrpt->iofd = openserial(myrpt,myrpt->p.ioport)) == -1))
13892 {
13893 rpt_mutex_unlock(&myrpt->lock);
13894 ast_hangup(myrpt->pchannel);
13895 if (myrpt->txchannel != myrpt->rxchannel)
13896 ast_hangup(myrpt->txchannel);
13897 ast_hangup(myrpt->rxchannel);
13898 pthread_exit(NULL);
13899 }
13900 iskenwood_pci4 = 0;
13901 memset(&z,0,sizeof(z));
13902 if ((myrpt->iofd < 1) && (myrpt->txchannel == myrpt->dahditxchannel))
13903 {
13904 z.radpar = DAHDI_RADPAR_REMMODE;
13905 z.data = DAHDI_RADPAR_REM_NONE;
13906 res = ioctl(myrpt->dahditxchannel->fds[0],DAHDI_RADIO_SETPARAM,&z);
13907
13908 if ((!res) && (!strcmp(myrpt->remoterig,remote_rig_kenwood)))
13909 {
13910 z.radpar = DAHDI_RADPAR_UIOMODE;
13911 z.data = 1;
13912 if (ioctl(myrpt->dahditxchannel->fds[0],DAHDI_RADIO_SETPARAM,&z) == -1)
13913 {
13914 ast_log(LOG_ERROR,"Cannot set UIOMODE\n");
13915 return -1;
13916 }
13917 z.radpar = DAHDI_RADPAR_UIODATA;
13918 z.data = 3;
13919 if (ioctl(myrpt->dahditxchannel->fds[0],DAHDI_RADIO_SETPARAM,&z) == -1)
13920 {
13921 ast_log(LOG_ERROR,"Cannot set UIODATA\n");
13922 return -1;
13923 }
13924 i = DAHDI_OFFHOOK;
13925 if (ioctl(myrpt->dahditxchannel->fds[0],DAHDI_HOOK,&i) == -1)
13926 {
13927 ast_log(LOG_ERROR,"Cannot set hook\n");
13928 return -1;
13929 }
13930 iskenwood_pci4 = 1;
13931 }
13932 }
13933 if (myrpt->txchannel == myrpt->dahditxchannel)
13934 {
13935 i = DAHDI_ONHOOK;
13936 ioctl(myrpt->dahditxchannel->fds[0],DAHDI_HOOK,&i);
13937
13938 if ((myrpt->iofd < 1) && (!res) &&
13939 ((!strcmp(myrpt->remoterig,remote_rig_ft897)) ||
13940 (!strcmp(myrpt->remoterig,remote_rig_ic706)) ||
13941 (!strcmp(myrpt->remoterig,remote_rig_tm271))))
13942 {
13943 z.radpar = DAHDI_RADPAR_UIOMODE;
13944 z.data = 1;
13945 if (ioctl(myrpt->dahditxchannel->fds[0],DAHDI_RADIO_SETPARAM,&z) == -1)
13946 {
13947 ast_log(LOG_ERROR,"Cannot set UIOMODE\n");
13948 return -1;
13949 }
13950 z.radpar = DAHDI_RADPAR_UIODATA;
13951 z.data = 3;
13952 if (ioctl(myrpt->dahditxchannel->fds[0],DAHDI_RADIO_SETPARAM,&z) == -1)
13953 {
13954 ast_log(LOG_ERROR,"Cannot set UIODATA\n");
13955 return -1;
13956 }
13957 }
13958 }
13959 myrpt->remoterx = 0;
13960 myrpt->remotetx = 0;
13961 myrpt->retxtimer = 0;
13962 myrpt->rerxtimer = 0;
13963 myrpt->remoteon = 1;
13964 myrpt->dtmfidx = -1;
13965 myrpt->dtmfbuf[0] = 0;
13966 myrpt->dtmf_time_rem = 0;
13967 myrpt->hfscanmode = 0;
13968 myrpt->hfscanstatus = 0;
13969 if (myrpt->p.startupmacro)
13970 {
13971 snprintf(myrpt->macrobuf,MAXMACRO - 1,"PPPP%s",myrpt->p.startupmacro);
13972 }
13973 time(&myrpt->start_time);
13974 myrpt->last_activity_time = myrpt->start_time;
13975 last_timeout_warning = 0;
13976 myrpt->reload = 0;
13977 myrpt->tele.next = &myrpt->tele;
13978 myrpt->tele.prev = &myrpt->tele;
13979 myrpt->newkey = 0;
13980 rpt_mutex_unlock(&myrpt->lock);
13981 ast_set_write_format(chan, AST_FORMAT_SLINEAR);
13982 ast_set_read_format(chan, AST_FORMAT_SLINEAR);
13983 rem_rx = 0;
13984 remkeyed = 0;
13985
13986 if (myrpt->remote && (myrpt->rxchannel == myrpt->txchannel))
13987 {
13988 i = 128;
13989 ioctl(myrpt->dahdirxchannel->fds[0],DAHDI_ECHOCANCEL,&i);
13990 }
13991 if (chan->_state != AST_STATE_UP) {
13992 ast_answer(chan);
13993 if (!phone_mode) send_newkey(chan);
13994 }
13995
13996 if (myrpt->rxchannel == myrpt->dahdirxchannel)
13997 {
13998 if (ioctl(myrpt->dahdirxchannel->fds[0],DAHDI_GET_PARAMS,&par) != -1)
13999 {
14000 if (par.rxisoffhook)
14001 {
14002 ast_indicate(chan,AST_CONTROL_RADIO_KEY);
14003 myrpt->remoterx = 1;
14004 remkeyed = 1;
14005 }
14006 }
14007 }
14008 if (myrpt->p.archivedir)
14009 {
14010 char mycmd[100],mydate[100],*b,*b1;
14011 time_t myt;
14012 long blocksleft;
14013
14014
14015 mkdir(myrpt->p.archivedir,0600);
14016 sprintf(mycmd,"%s/%s",myrpt->p.archivedir,myrpt->name);
14017 mkdir(mycmd,0600);
14018 time(&myt);
14019 strftime(mydate,sizeof(mydate) - 1,"%Y%m%d%H%M%S",
14020 localtime(&myt));
14021 sprintf(mycmd,"mixmonitor start %s %s/%s/%s.wav49 a",chan->name,
14022 myrpt->p.archivedir,myrpt->name,mydate);
14023 if (myrpt->p.monminblocks)
14024 {
14025 blocksleft = diskavail(myrpt);
14026 if (myrpt->p.remotetimeout)
14027 {
14028 blocksleft -= (myrpt->p.remotetimeout *
14029 MONITOR_DISK_BLOCKS_PER_MINUTE) / 60;
14030 }
14031 if (blocksleft >= myrpt->p.monminblocks)
14032 ast_cli_command(nullfd,mycmd);
14033 } else ast_cli_command(nullfd,mycmd);
14034
14035 if (!chan->cid.cid_num)
14036 {
14037 b1 = "0";
14038 } else {
14039 ast_callerid_parse(chan->cid.cid_num,&b,&b1);
14040 ast_shrink_phone_number(b1);
14041 }
14042 sprintf(mycmd,"CONNECT,%s",b1);
14043 donodelog(myrpt,mycmd);
14044 }
14045 myrpt->loginuser[0] = 0;
14046 myrpt->loginlevel[0] = 0;
14047 myrpt->authtelltimer = 0;
14048 myrpt->authtimer = 0;
14049 authtold = 0;
14050 authreq = 0;
14051 if (myrpt->p.authlevel > 1) authreq = 1;
14052 setrem(myrpt);
14053 n = 0;
14054 dtmfed = 0;
14055 cs[n++] = chan;
14056 cs[n++] = myrpt->rxchannel;
14057 cs[n++] = myrpt->pchannel;
14058 if (myrpt->rxchannel != myrpt->txchannel)
14059 cs[n++] = myrpt->txchannel;
14060 if (!phone_mode) send_newkey(chan);
14061
14062 for(;;)
14063 {
14064 if (ast_check_hangup(chan)) break;
14065 if (ast_check_hangup(myrpt->rxchannel)) break;
14066 notremming = 0;
14067 setting = 0;
14068 reming = 0;
14069 telem = myrpt->tele.next;
14070 while(telem != &myrpt->tele)
14071 {
14072 if (telem->mode == SETREMOTE) setting = 1;
14073 if ((telem->mode == SETREMOTE) ||
14074 (telem->mode == SCAN) ||
14075 (telem->mode == TUNE)) reming = 1;
14076 else notremming = 1;
14077 telem = telem->next;
14078 }
14079 if (myrpt->reload)
14080 {
14081 myrpt->reload = 0;
14082
14083 for(i = 0; i < nrpts; i++)
14084 {
14085 if (&rpt_vars[i] == myrpt)
14086 {
14087 load_rpt_vars(i,0);
14088 break;
14089 }
14090 }
14091 }
14092 time(&t);
14093 if (myrpt->p.remotetimeout)
14094 {
14095 time_t r;
14096
14097 r = (t - myrpt->start_time);
14098 if (r >= myrpt->p.remotetimeout)
14099 {
14100 saynode(myrpt,chan,myrpt->name);
14101 sayfile(chan,"rpt/timeout");
14102 ast_safe_sleep(chan,1000);
14103 break;
14104 }
14105 if ((myrpt->p.remotetimeoutwarning) &&
14106 (r >= (myrpt->p.remotetimeout -
14107 myrpt->p.remotetimeoutwarning)) &&
14108 (r <= (myrpt->p.remotetimeout -
14109 myrpt->p.remotetimeoutwarningfreq)))
14110 {
14111 if (myrpt->p.remotetimeoutwarningfreq)
14112 {
14113 if ((t - last_timeout_warning) >=
14114 myrpt->p.remotetimeoutwarningfreq)
14115 {
14116 time(&last_timeout_warning);
14117 rpt_telemetry(myrpt,TIMEOUT_WARNING,0);
14118 }
14119 }
14120 else
14121 {
14122 if (!last_timeout_warning)
14123 {
14124 time(&last_timeout_warning);
14125 rpt_telemetry(myrpt,TIMEOUT_WARNING,0);
14126 }
14127 }
14128 }
14129 }
14130 if (myrpt->p.remoteinacttimeout && myrpt->last_activity_time)
14131 {
14132 time_t r;
14133
14134 r = (t - myrpt->last_activity_time);
14135 if (r >= myrpt->p.remoteinacttimeout)
14136 {
14137 saynode(myrpt,chan,myrpt->name);
14138 ast_safe_sleep(chan,1000);
14139 break;
14140 }
14141 if ((myrpt->p.remotetimeoutwarning) &&
14142 (r >= (myrpt->p.remoteinacttimeout -
14143 myrpt->p.remotetimeoutwarning)) &&
14144 (r <= (myrpt->p.remoteinacttimeout -
14145 myrpt->p.remotetimeoutwarningfreq)))
14146 {
14147 if (myrpt->p.remotetimeoutwarningfreq)
14148 {
14149 if ((t - last_timeout_warning) >=
14150 myrpt->p.remotetimeoutwarningfreq)
14151 {
14152 time(&last_timeout_warning);
14153 rpt_telemetry(myrpt,ACT_TIMEOUT_WARNING,0);
14154 }
14155 }
14156 else
14157 {
14158 if (!last_timeout_warning)
14159 {
14160 time(&last_timeout_warning);
14161 rpt_telemetry(myrpt,ACT_TIMEOUT_WARNING,0);
14162 }
14163 }
14164 }
14165 }
14166 ms = MSWAIT;
14167 who = ast_waitfor_n(cs,n,&ms);
14168 if (who == NULL) ms = 0;
14169 elap = MSWAIT - ms;
14170 if (myrpt->macrotimer) myrpt->macrotimer -= elap;
14171 if (myrpt->macrotimer < 0) myrpt->macrotimer = 0;
14172 if (!ms) continue;
14173
14174 if (myrpt->dtmf_local_timer)
14175 {
14176 if (myrpt->dtmf_local_timer > 1) myrpt->dtmf_local_timer -= elap;
14177 if (myrpt->dtmf_local_timer < 1) myrpt->dtmf_local_timer = 1;
14178 }
14179 rpt_mutex_lock(&myrpt->lock);
14180 do_dtmf_local(myrpt,0);
14181 rpt_mutex_unlock(&myrpt->lock);
14182
14183 rem_totx = myrpt->dtmf_local_timer && (!phone_mode);
14184 rem_totx |= keyed && (!myrpt->tunerequest);
14185 rem_rx = (remkeyed && (!setting)) || (myrpt->tele.next != &myrpt->tele);
14186 if(!strcmp(myrpt->remoterig, remote_rig_ic706))
14187 rem_totx |= myrpt->tunerequest;
14188
14189 if((debug > 6) && rem_totx) {
14190 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);
14191 }
14192 if (keyed && (!keyed1))
14193 {
14194 keyed1 = 1;
14195 }
14196
14197 if (!keyed && (keyed1))
14198 {
14199 time_t myt;
14200
14201 keyed1 = 0;
14202 time(&myt);
14203
14204 if ((myrpt->p.authlevel) &&
14205 (!myrpt->loginlevel[0]) &&
14206 (myt > (t + 3)))
14207 {
14208 authreq = 1;
14209 authtold = 0;
14210 myrpt->authtelltimer = AUTHTELLTIME - AUTHTXTIME;
14211 }
14212 }
14213
14214 if (rem_rx && (!myrpt->remoterx))
14215 {
14216 myrpt->remoterx = 1;
14217 ast_indicate(chan,AST_CONTROL_RADIO_KEY);
14218 }
14219 if ((!rem_rx) && (myrpt->remoterx))
14220 {
14221 myrpt->remoterx = 0;
14222 ast_indicate(chan,AST_CONTROL_RADIO_UNKEY);
14223 }
14224
14225 if (authreq && (!myrpt->loginlevel[0]))
14226 {
14227 if ((!authtold) && ((myrpt->authtelltimer += elap)
14228 >= AUTHTELLTIME))
14229 {
14230 authtold = 1;
14231 rpt_telemetry(myrpt,LOGINREQ,NULL);
14232 }
14233 if ((myrpt->authtimer += elap) >= AUTHLOGOUTTIME)
14234 {
14235 break;
14236 }
14237 }
14238 if (myrpt->newkey)
14239 {
14240 if ((myrpt->retxtimer += elap) >= REDUNDANT_TX_TIME)
14241 {
14242 myrpt->retxtimer = 0;
14243 if ((myrpt->remoterx) && (!myrpt->remotetx))
14244 ast_indicate(chan,AST_CONTROL_RADIO_KEY);
14245 else
14246 ast_indicate(chan,AST_CONTROL_RADIO_UNKEY);
14247 }
14248
14249 if ((myrpt->rerxtimer += elap) >= (REDUNDANT_TX_TIME * 2))
14250 {
14251 keyed = 0;
14252 myrpt->rerxtimer = 0;
14253 }
14254 }
14255 if (rem_totx && (!myrpt->remotetx))
14256 {
14257
14258 if ((!myrpt->p.authlevel) || myrpt->loginlevel[0])
14259 {
14260 if(debug > 6)
14261 ast_log(LOG_NOTICE,"Handle rem_totx=%i. dtmf_local_timer=%i tunerequest=%i\n",rem_totx,myrpt->dtmf_local_timer,myrpt->tunerequest);
14262
14263 myrpt->remotetx = 1;
14264
14265 if((myrpt->remtxfreqok = check_tx_freq(myrpt)))
14266 {
14267 time(&myrpt->last_activity_time);
14268 if ((iskenwood_pci4) && (myrpt->txchannel == myrpt->dahditxchannel))
14269 {
14270 z.radpar = DAHDI_RADPAR_UIODATA;
14271 z.data = 1;
14272 if (ioctl(myrpt->dahditxchannel->fds[0],DAHDI_RADIO_SETPARAM,&z) == -1)
14273 {
14274 ast_log(LOG_ERROR,"Cannot set UIODATA\n");
14275 return -1;
14276 }
14277 }
14278 else
14279 {
14280 ast_indicate(myrpt->txchannel,AST_CONTROL_RADIO_KEY);
14281 }
14282 if (myrpt->p.archivedir) donodelog(myrpt,"TXKEY");
14283 }
14284 }
14285 }
14286 if ((!rem_totx) && myrpt->remotetx)
14287 {
14288 myrpt->remotetx = 0;
14289 if(!myrpt->remtxfreqok){
14290 rpt_telemetry(myrpt,UNAUTHTX,NULL);
14291 }
14292 if ((iskenwood_pci4) && (myrpt->txchannel == myrpt->dahditxchannel))
14293 {
14294 z.radpar = DAHDI_RADPAR_UIODATA;
14295 z.data = 3;
14296 if (ioctl(myrpt->dahditxchannel->fds[0],DAHDI_RADIO_SETPARAM,&z) == -1)
14297 {
14298 ast_log(LOG_ERROR,"Cannot set UIODATA\n");
14299 return -1;
14300 }
14301 }
14302 else
14303 {
14304 ast_indicate(myrpt->txchannel,AST_CONTROL_RADIO_UNKEY);
14305 }
14306 if (myrpt->p.archivedir) donodelog(myrpt,"TXUNKEY");
14307 }
14308 if (myrpt->hfscanmode){
14309 myrpt->scantimer -= elap;
14310 if(myrpt->scantimer <= 0){
14311 if (!reming)
14312 {
14313 myrpt->scantimer = REM_SCANTIME;
14314 rpt_telemetry(myrpt,SCAN,0);
14315 } else myrpt->scantimer = 1;
14316 }
14317 }
14318 rpt_mutex_lock(&myrpt->lock);
14319 c = myrpt->macrobuf[0];
14320 if (c && (!myrpt->macrotimer))
14321 {
14322 myrpt->macrotimer = MACROTIME;
14323 memmove(myrpt->macrobuf,myrpt->macrobuf + 1,MAXMACRO - 1);
14324 if ((c == 'p') || (c == 'P'))
14325 myrpt->macrotimer = MACROPTIME;
14326 rpt_mutex_unlock(&myrpt->lock);
14327 if (myrpt->p.archivedir)
14328 {
14329 char str[100];
14330 sprintf(str,"DTMF(M),%c",c);
14331 donodelog(myrpt,str);
14332 }
14333 if (handle_remote_dtmf_digit(myrpt,c,&keyed,0) == -1) break;
14334 continue;
14335 } else rpt_mutex_unlock(&myrpt->lock);
14336 if (who == chan)
14337 {
14338 f = ast_read(chan);
14339 if (!f)
14340 {
14341 if (debug) printf("@@@@ link:Hung Up\n");
14342 break;
14343 }
14344 if (f->frametype == AST_FRAME_VOICE)
14345 {
14346 if (ioctl(chan->fds[0], DAHDI_GETCONFMUTE, &ismuted) == -1)
14347 {
14348 ismuted = 0;
14349 }
14350
14351 ismuted |= (!myrpt->remotetx);
14352 if (dtmfed && phone_mode) ismuted = 1;
14353 dtmfed = 0;
14354 if (ismuted)
14355 {
14356 memset(f->data.ptr,0,f->datalen);
14357 if (myrpt->lastf1)
14358 memset(myrpt->lastf1->data.ptr,0,myrpt->lastf1->datalen);
14359 if (myrpt->lastf2)
14360 memset(myrpt->lastf2->data.ptr,0,myrpt->lastf2->datalen);
14361 }
14362 if (f) f2 = ast_frdup(f);
14363 else f2 = NULL;
14364 f1 = myrpt->lastf2;
14365 myrpt->lastf2 = myrpt->lastf1;
14366 myrpt->lastf1 = f2;
14367 if (ismuted)
14368 {
14369 if (myrpt->lastf1)
14370 memset(myrpt->lastf1->data.ptr,0,myrpt->lastf1->datalen);
14371 if (myrpt->lastf2)
14372 memset(myrpt->lastf2->data.ptr,0,myrpt->lastf2->datalen);
14373 }
14374 if (f1)
14375 {
14376 if (phone_mode)
14377 ast_write(myrpt->txchannel,f1);
14378 else
14379 ast_write(myrpt->txchannel,f);
14380 ast_frfree(f1);
14381 }
14382 }
14383 #ifndef OLD_ASTERISK
14384 else if (f->frametype == AST_FRAME_DTMF_BEGIN)
14385 {
14386 if (myrpt->lastf1)
14387 memset(myrpt->lastf1->data.ptr,0,myrpt->lastf1->datalen);
14388 if (myrpt->lastf2)
14389 memset(myrpt->lastf2->data.ptr,0,myrpt->lastf2->datalen);
14390 dtmfed = 1;
14391 }
14392 #endif
14393 if (f->frametype == AST_FRAME_DTMF)
14394 {
14395 if (myrpt->lastf1)
14396 memset(myrpt->lastf1->data.ptr,0,myrpt->lastf1->datalen);
14397 if (myrpt->lastf2)
14398 memset(myrpt->lastf2->data.ptr,0,myrpt->lastf2->datalen);
14399 dtmfed = 1;
14400 if (handle_remote_phone_dtmf(myrpt,f->subclass,&keyed,phone_mode) == -1)
14401 {
14402 if (debug) printf("@@@@ rpt:Hung Up\n");
14403 ast_frfree(f);
14404 break;
14405 }
14406 }
14407 if (f->frametype == AST_FRAME_TEXT)
14408 {
14409 if (handle_remote_data(myrpt,f->data.ptr) == -1)
14410 {
14411 if (debug) printf("@@@@ rpt:Hung Up\n");
14412 ast_frfree(f);
14413 break;
14414 }
14415 }
14416 if (f->frametype == AST_FRAME_CONTROL)
14417 {
14418 if (f->subclass == AST_CONTROL_HANGUP)
14419 {
14420 if (debug) printf("@@@@ rpt:Hung Up\n");
14421 ast_frfree(f);
14422 break;
14423 }
14424
14425 if (f->subclass == AST_CONTROL_RADIO_KEY)
14426 {
14427 if (debug == 7) printf("@@@@ rx key\n");
14428 keyed = 1;
14429 myrpt->rerxtimer = 0;
14430 }
14431
14432 if (f->subclass == AST_CONTROL_RADIO_UNKEY)
14433 {
14434 myrpt->rerxtimer = 0;
14435 if (debug == 7) printf("@@@@ rx un-key\n");
14436 keyed = 0;
14437 }
14438 }
14439 ast_frfree(f);
14440 continue;
14441 }
14442 if (who == myrpt->rxchannel)
14443 {
14444 f = ast_read(myrpt->rxchannel);
14445 if (!f)
14446 {
14447 if (debug) printf("@@@@ link:Hung Up\n");
14448 break;
14449 }
14450 if (f->frametype == AST_FRAME_VOICE)
14451 {
14452 int myreming = 0;
14453
14454 if(!strcmp(myrpt->remoterig, remote_rig_kenwood))
14455 myreming = reming;
14456
14457 if (myreming || (!remkeyed) ||
14458 ((myrpt->remote) && (myrpt->remotetx)) ||
14459 ((myrpt->remmode != REM_MODE_FM) &&
14460 notremming))
14461 memset(f->data.ptr,0,f->datalen);
14462 ast_write(myrpt->pchannel,f);
14463 }
14464 else if (f->frametype == AST_FRAME_CONTROL)
14465 {
14466 if (f->subclass == AST_CONTROL_HANGUP)
14467 {
14468 if (debug) printf("@@@@ rpt:Hung Up\n");
14469 ast_frfree(f);
14470 break;
14471 }
14472
14473 if (f->subclass == AST_CONTROL_RADIO_KEY)
14474 {
14475 if (debug == 7) printf("@@@@ remote rx key\n");
14476 if (!myrpt->remotetx)
14477 {
14478 remkeyed = 1;
14479 }
14480 }
14481
14482 if (f->subclass == AST_CONTROL_RADIO_UNKEY)
14483 {
14484 if (debug == 7) printf("@@@@ remote rx un-key\n");
14485 if (!myrpt->remotetx)
14486 {
14487 remkeyed = 0;
14488 }
14489 }
14490 }
14491 ast_frfree(f);
14492 continue;
14493 }
14494 if (who == myrpt->pchannel)
14495 {
14496 f = ast_read(myrpt->pchannel);
14497 if (!f)
14498 {
14499 if (debug) printf("@@@@ link:Hung Up\n");
14500 break;
14501 }
14502 if (f->frametype == AST_FRAME_VOICE)
14503 {
14504 ast_write(chan,f);
14505 }
14506 if (f->frametype == AST_FRAME_CONTROL)
14507 {
14508 if (f->subclass == AST_CONTROL_HANGUP)
14509 {
14510 if (debug) printf("@@@@ rpt:Hung Up\n");
14511 ast_frfree(f);
14512 break;
14513 }
14514 }
14515 ast_frfree(f);
14516 continue;
14517 }
14518 if ((myrpt->rxchannel != myrpt->txchannel) &&
14519 (who == myrpt->txchannel))
14520 {
14521 f = ast_read(myrpt->txchannel);
14522 if (!f)
14523 {
14524 if (debug) printf("@@@@ link:Hung Up\n");
14525 break;
14526 }
14527 if (f->frametype == AST_FRAME_CONTROL)
14528 {
14529 if (f->subclass == AST_CONTROL_HANGUP)
14530 {
14531 if (debug) printf("@@@@ rpt:Hung Up\n");
14532 ast_frfree(f);
14533 break;
14534 }
14535 }
14536 ast_frfree(f);
14537 continue;
14538 }
14539 }
14540 if (myrpt->p.archivedir)
14541 {
14542 char mycmd[100],*b,*b1;
14543
14544
14545 if (!chan->cid.cid_num)
14546 {
14547 b1 = "0";
14548 } else {
14549 ast_callerid_parse(chan->cid.cid_num,&b,&b1);
14550 ast_shrink_phone_number(b1);
14551 }
14552 sprintf(mycmd,"DISCONNECT,%s",b1);
14553 donodelog(myrpt,mycmd);
14554 }
14555
14556 while(myrpt->tele.next != &myrpt->tele) usleep(100000);
14557 sprintf(tmp,"mixmonitor stop %s",chan->name);
14558 ast_cli_command(nullfd,tmp);
14559 close(nullfd);
14560 rpt_mutex_lock(&myrpt->lock);
14561 myrpt->hfscanmode = 0;
14562 myrpt->hfscanstatus = 0;
14563 myrpt->remoteon = 0;
14564 rpt_mutex_unlock(&myrpt->lock);
14565 if (myrpt->lastf1) ast_frfree(myrpt->lastf1);
14566 myrpt->lastf1 = NULL;
14567 if (myrpt->lastf2) ast_frfree(myrpt->lastf2);
14568 myrpt->lastf2 = NULL;
14569 if ((iskenwood_pci4) && (myrpt->txchannel == myrpt->dahditxchannel))
14570 {
14571 z.radpar = DAHDI_RADPAR_UIOMODE;
14572 z.data = 3;
14573 if (ioctl(myrpt->dahditxchannel->fds[0],DAHDI_RADIO_SETPARAM,&z) == -1)
14574 {
14575 ast_log(LOG_ERROR,"Cannot set UIOMODE\n");
14576 return -1;
14577 }
14578 z.radpar = DAHDI_RADPAR_UIODATA;
14579 z.data = 3;
14580 if (ioctl(myrpt->dahditxchannel->fds[0],DAHDI_RADIO_SETPARAM,&z) == -1)
14581 {
14582 ast_log(LOG_ERROR,"Cannot set UIODATA\n");
14583 return -1;
14584 }
14585 i = DAHDI_OFFHOOK;
14586 if (ioctl(myrpt->dahditxchannel->fds[0],DAHDI_HOOK,&i) == -1)
14587 {
14588 ast_log(LOG_ERROR,"Cannot set hook\n");
14589 return -1;
14590 }
14591 }
14592 if (myrpt->iofd) close(myrpt->iofd);
14593 myrpt->iofd = -1;
14594 ast_hangup(myrpt->pchannel);
14595 if (myrpt->rxchannel != myrpt->txchannel) ast_hangup(myrpt->txchannel);
14596 ast_hangup(myrpt->rxchannel);
14597 closerem(myrpt);
14598 if (myrpt->p.rptnode)
14599 {
14600 rpt_mutex_lock(&myrpt->lock);
14601 for(i = 0; i < nrpts; i++)
14602 {
14603 if (!strcasecmp(rpt_vars[i].name,myrpt->p.rptnode))
14604 {
14605 rpt_vars[i].xlink = 0;
14606 break;
14607 }
14608 }
14609 rpt_mutex_unlock(&myrpt->lock);
14610 }
14611 #ifdef OLD_ASTERISK
14612 LOCAL_USER_REMOVE(u);
14613 #endif
14614 return res;
14615 }
14616
14617 #ifndef OLD_ASTERISK
14618
14619
14620
14621 static int manager_rpt_local_nodes(struct mansession *s, const struct message *m)
14622 {
14623 int i;
14624 astman_append(s, "<?xml version=\"1.0\"?>\r\n");
14625 astman_append(s, "<nodes>\r\n");
14626 for (i=0; i< nrpts; i++)
14627 {
14628 astman_append(s, " <node>%s</node>\r\n", rpt_vars[i].name);
14629 }
14630 astman_append(s, "</nodes>\r\n");
14631 astman_append(s, "\r\n");
14632 return RESULT_SUCCESS;
14633 }
14634
14635
14636
14637
14638
14639
14640
14641 static void rpt_manager_success(struct mansession *s, const struct message *m)
14642 {
14643 const char *id = astman_get_header(m, "ActionID");
14644 if (!ast_strlen_zero(id))
14645 astman_append(s, "ActionID: %s\r\n", id);
14646 astman_append(s, "Response: Success\r\n");
14647 }
14648
14649
14650
14651
14652
14653 static int rpt_manager_do_stats(struct mansession *s, const struct message *m, char *str)
14654 {
14655 int i,j,numoflinks;
14656 int dailytxtime, dailykerchunks;
14657 time_t now;
14658 int totalkerchunks, dailykeyups, totalkeyups, timeouts;
14659 int totalexecdcommands, dailyexecdcommands, hours, minutes, seconds;
14660 long long totaltxtime;
14661 struct rpt_link *l;
14662 char *listoflinks[MAX_STAT_LINKS];
14663 char *lastdtmfcommand,*parrot_ena;
14664 char *tot_state, *ider_state, *patch_state;
14665 char *reverse_patch_state, *sys_ena, *tot_ena, *link_ena, *patch_ena;
14666 char *sch_ena, *input_signal, *called_number, *user_funs, *tail_type;
14667 char *transmitterkeyed;
14668 const char *node = astman_get_header(m, "Node");
14669 struct rpt *myrpt;
14670
14671 static char *not_applicable = "N/A";
14672
14673 tot_state = ider_state =
14674 patch_state = reverse_patch_state =
14675 input_signal = not_applicable;
14676 called_number = lastdtmfcommand = transmitterkeyed = NULL;
14677
14678 time(&now);
14679 for(i = 0; i < nrpts; i++)
14680 {
14681 if ((node)&&(!strcmp(node,rpt_vars[i].name))){
14682 rpt_manager_success(s,m);
14683
14684 myrpt = &rpt_vars[i];
14685
14686 if(myrpt->remote){
14687 char *loginuser, *loginlevel, *freq, *rxpl, *txpl, *modestr;
14688 char offset = 0, powerlevel = 0, rxplon = 0, txplon = 0, remoteon, remmode = 0, reportfmstuff;
14689 char offsetc,powerlevelc;
14690
14691 loginuser = loginlevel = freq = rxpl = txpl = NULL;
14692
14693 rpt_mutex_lock(&myrpt->lock);
14694 if((remoteon = myrpt->remoteon)){
14695 if(!ast_strlen_zero(myrpt->loginuser))
14696 loginuser = ast_strdup(myrpt->loginuser);
14697 if(!ast_strlen_zero(myrpt->loginlevel))
14698 loginlevel = ast_strdup(myrpt->loginlevel);
14699 if(!ast_strlen_zero(myrpt->freq))
14700 freq = ast_strdup(myrpt->freq);
14701 if(!ast_strlen_zero(myrpt->rxpl))
14702 rxpl = ast_strdup(myrpt->rxpl);
14703 if(!ast_strlen_zero(myrpt->txpl))
14704 txpl = ast_strdup(myrpt->txpl);
14705 remmode = myrpt->remmode;
14706 offset = myrpt->offset;
14707 powerlevel = myrpt->powerlevel;
14708 rxplon = myrpt->rxplon;
14709 txplon = myrpt->txplon;
14710 }
14711 rpt_mutex_unlock(&myrpt->lock);
14712 astman_append(s, "IsRemoteBase: YES\r\n");
14713 astman_append(s, "RemoteOn: %s\r\n",(remoteon) ? "YES": "NO");
14714 if(remoteon){
14715 if(loginuser){
14716 astman_append(s, "LogInUser: %s\r\n", loginuser);
14717 ast_free(loginuser);
14718 }
14719 if(loginlevel){
14720 astman_append(s, "LogInLevel: %s\r\n", loginlevel);
14721 ast_free(loginlevel);
14722 }
14723 if(freq){
14724 astman_append(s, "Freq: %s\r\n", freq);
14725 ast_free(freq);
14726 }
14727 reportfmstuff = 0;
14728 switch(remmode){
14729 case REM_MODE_FM:
14730 modestr = "FM";
14731 reportfmstuff = 1;
14732 break;
14733 case REM_MODE_AM:
14734 modestr = "AM";
14735 break;
14736 case REM_MODE_USB:
14737 modestr = "USB";
14738 break;
14739 default:
14740 modestr = "LSB";
14741 break;
14742 }
14743 astman_append(s, "RemMode: %s\r\n", modestr);
14744 if(reportfmstuff){
14745 switch(offset){
14746 case REM_SIMPLEX:
14747 offsetc = 'S';
14748 break;
14749 case REM_MINUS:
14750 offsetc = '-';
14751 break;
14752 default:
14753 offsetc = '+';
14754 break;
14755 }
14756 astman_append(s, "RemOffset: %c\r\n", offsetc);
14757 if(rxplon && rxpl){
14758 astman_append(s, "RxPl: %s\r\n",rxpl);
14759 ast_free(rxpl);
14760 }
14761 if(txplon && txpl){
14762 astman_append(s, "TxPl: %s\r\n",txpl);
14763 ast_free(txpl);
14764 }
14765 }
14766 switch(powerlevel){
14767 case REM_LOWPWR:
14768 powerlevelc = 'L';
14769 break;
14770 case REM_MEDPWR:
14771 powerlevelc = 'M';
14772 break;
14773 default:
14774 powerlevelc = 'H';
14775 break;
14776 }
14777 astman_append(s,"PowerLevel: %c\r\n", powerlevelc);
14778 }
14779 astman_append(s, "\r\n");
14780 return 0;
14781 }
14782
14783
14784
14785 rpt_mutex_lock(&myrpt->lock);
14786 dailytxtime = myrpt->dailytxtime;
14787 totaltxtime = myrpt->totaltxtime;
14788 dailykeyups = myrpt->dailykeyups;
14789 totalkeyups = myrpt->totalkeyups;
14790 dailykerchunks = myrpt->dailykerchunks;
14791 totalkerchunks = myrpt->totalkerchunks;
14792 dailyexecdcommands = myrpt->dailyexecdcommands;
14793 totalexecdcommands = myrpt->totalexecdcommands;
14794 timeouts = myrpt->timeouts;
14795
14796
14797
14798 reverse_patch_state = "DOWN";
14799 numoflinks = 0;
14800 l = myrpt->links.next;
14801 while(l && (l != &myrpt->links)){
14802 if(numoflinks >= MAX_STAT_LINKS){
14803 ast_log(LOG_NOTICE,
14804 "maximum number of links exceeds %d in rpt_do_stats()!",MAX_STAT_LINKS);
14805 break;
14806 }
14807 if (l->name[0] == '0'){
14808 reverse_patch_state = "UP";
14809 l = l->next;
14810 continue;
14811 }
14812 listoflinks[numoflinks] = ast_strdup(l->name);
14813 if(listoflinks[numoflinks] == NULL){
14814 break;
14815 }
14816 else{
14817 numoflinks++;
14818 }
14819 l = l->next;
14820 }
14821
14822 if(myrpt->keyed)
14823 input_signal = "YES";
14824 else
14825 input_signal = "NO";
14826
14827 if(myrpt->txkeyed)
14828 transmitterkeyed = "YES";
14829 else
14830 transmitterkeyed = "NO";
14831
14832 if(myrpt->p.parrotmode)
14833 parrot_ena = "ENABLED";
14834 else
14835 parrot_ena = "DISABLED";
14836
14837 if(myrpt->p.s[myrpt->p.sysstate_cur].txdisable)
14838 sys_ena = "DISABLED";
14839 else
14840 sys_ena = "ENABLED";
14841
14842 if(myrpt->p.s[myrpt->p.sysstate_cur].totdisable)
14843 tot_ena = "DISABLED";
14844 else
14845 tot_ena = "ENABLED";
14846
14847 if(myrpt->p.s[myrpt->p.sysstate_cur].linkfundisable)
14848 link_ena = "DISABLED";
14849 else
14850 link_ena = "ENABLED";
14851
14852 if(myrpt->p.s[myrpt->p.sysstate_cur].autopatchdisable)
14853 patch_ena = "DISABLED";
14854 else
14855 patch_ena = "ENABLED";
14856
14857 if(myrpt->p.s[myrpt->p.sysstate_cur].schedulerdisable)
14858 sch_ena = "DISABLED";
14859 else
14860 sch_ena = "ENABLED";
14861
14862 if(myrpt->p.s[myrpt->p.sysstate_cur].userfundisable)
14863 user_funs = "DISABLED";
14864 else
14865 user_funs = "ENABLED";
14866
14867 if(myrpt->p.s[myrpt->p.sysstate_cur].alternatetail)
14868 tail_type = "ALTERNATE";
14869 else
14870 tail_type = "STANDARD";
14871
14872 if(!myrpt->totimer)
14873 tot_state = "TIMED OUT!";
14874 else if(myrpt->totimer != myrpt->p.totime)
14875 tot_state = "ARMED";
14876 else
14877 tot_state = "RESET";
14878
14879 if(myrpt->tailid)
14880 ider_state = "QUEUED IN TAIL";
14881 else if(myrpt->mustid)
14882 ider_state = "QUEUED FOR CLEANUP";
14883 else
14884 ider_state = "CLEAN";
14885
14886 switch(myrpt->callmode){
14887 case 1:
14888 patch_state = "DIALING";
14889 break;
14890 case 2:
14891 patch_state = "CONNECTING";
14892 break;
14893 case 3:
14894 patch_state = "UP";
14895 break;
14896
14897 case 4:
14898 patch_state = "CALL FAILED";
14899 break;
14900
14901 default:
14902 patch_state = "DOWN";
14903 }
14904
14905 if(strlen(myrpt->exten)){
14906 called_number = ast_strdup(myrpt->exten);
14907 }
14908
14909 if(strlen(myrpt->lastdtmfcommand)){
14910 lastdtmfcommand = ast_strdup(myrpt->lastdtmfcommand);
14911 }
14912 rpt_mutex_unlock(&myrpt->lock);
14913
14914 astman_append(s, "IsRemoteBase: NO\r\n");
14915 astman_append(s, "NodeState: %d\r\n", myrpt->p.sysstate_cur);
14916 astman_append(s, "SignalOnInput: %s\r\n", input_signal);
14917 astman_append(s, "TransmitterKeyed: %s\r\n", transmitterkeyed);
14918 astman_append(s, "Transmitter: %s\r\n", sys_ena);
14919 astman_append(s, "Parrot: %s\r\n", parrot_ena);
14920 astman_append(s, "Scheduler: %s\r\n", sch_ena);
14921 astman_append(s, "TailLength: %s\r\n", tail_type);
14922 astman_append(s, "TimeOutTimer: %s\r\n", tot_ena);
14923 astman_append(s, "TimeOutTimerState: %s\r\n", tot_state);
14924 astman_append(s, "TimeOutsSinceSystemInitialization: %d\r\n", timeouts);
14925 astman_append(s, "IdentifierState: %s\r\n", ider_state);
14926 astman_append(s, "KerchunksToday: %d\r\n", dailykerchunks);
14927 astman_append(s, "KerchunksSinceSystemInitialization: %d\r\n", totalkerchunks);
14928 astman_append(s, "KeyupsToday: %d\r\n", dailykeyups);
14929 astman_append(s, "KeyupsSinceSystemInitialization: %d\r\n", totalkeyups);
14930 astman_append(s, "DtmfCommandsToday: %d\r\n", dailyexecdcommands);
14931 astman_append(s, "DtmfCommandsSinceSystemInitialization: %d\r\n", totalexecdcommands);
14932 astman_append(s, "LastDtmfCommandExecuted: %s\r\n",
14933 (lastdtmfcommand && strlen(lastdtmfcommand)) ? lastdtmfcommand : not_applicable);
14934 hours = dailytxtime/3600000;
14935 dailytxtime %= 3600000;
14936 minutes = dailytxtime/60000;
14937 dailytxtime %= 60000;
14938 seconds = dailytxtime/1000;
14939 dailytxtime %= 1000;
14940
14941 astman_append(s, "TxTimeToday: %02d:%02d:%02d.%d\r\n",
14942 hours, minutes, seconds, dailytxtime);
14943
14944 hours = (int) totaltxtime/3600000;
14945 totaltxtime %= 3600000;
14946 minutes = (int) totaltxtime/60000;
14947 totaltxtime %= 60000;
14948 seconds = (int) totaltxtime/1000;
14949 totaltxtime %= 1000;
14950
14951 astman_append(s, "TxTimeSinceSystemInitialization: %02d:%02d:%02d.%d\r\n",
14952 hours, minutes, seconds, (int) totaltxtime);
14953
14954 sprintf(str, "NodesCurrentlyConnectedToUs: ");
14955 if(!numoflinks){
14956 strcat(str,"<NONE>");
14957 }
14958 else{
14959 for(j = 0 ;j < numoflinks; j++){
14960 sprintf(str+strlen(str), "%s", listoflinks[j]);
14961 if(j < numoflinks - 1)
14962 strcat(str,",");
14963 }
14964 }
14965 astman_append(s,"%s\r\n", str);
14966
14967 astman_append(s, "Autopatch: %s\r\n", patch_ena);
14968 astman_append(s, "AutopatchState: %s\r\n", patch_state);
14969 astman_append(s, "AutopatchCalledNumber: %s\r\n",
14970 (called_number && strlen(called_number)) ? called_number : not_applicable);
14971 astman_append(s, "ReversePatchIaxrptConnected: %s\r\n", reverse_patch_state);
14972 astman_append(s, "UserLinkingCommands: %s\r\n", link_ena);
14973 astman_append(s, "UserFunctions: %s\r\n", user_funs);
14974
14975 for(j = 0; j < numoflinks; j++){
14976 ast_free(listoflinks[j]);
14977 }
14978 if(called_number){
14979 ast_free(called_number);
14980 }
14981 if(lastdtmfcommand){
14982 ast_free(lastdtmfcommand);
14983 }
14984 astman_append(s, "\r\n");
14985 return 0;
14986 }
14987 }
14988 astman_send_error(s, m, "RptStatus unknown or missing node");
14989 return -1;
14990 }
14991
14992
14993
14994
14995
14996
14997
14998 static int manager_rpt_status(struct mansession *s, const struct message *m)
14999 {
15000 int i,res,len,idx;
15001 int uptime,hours,minutes;
15002 time_t now;
15003 const char *cmd = astman_get_header(m, "Command");
15004 char *str;
15005 enum {MGRCMD_RPTSTAT,MGRCMD_NODESTAT};
15006 struct mgrcmdtbl{
15007 const char *cmd;
15008 int index;
15009 };
15010 static struct mgrcmdtbl mct[] = {
15011 {"RptStat",MGRCMD_RPTSTAT},
15012 {"NodeStat",MGRCMD_NODESTAT},
15013 {NULL,0}
15014 };
15015
15016 time(&now);
15017
15018 len = 1024;
15019 if(!(str = ast_malloc(len)))
15020 return -1;
15021
15022
15023 if(ast_strlen_zero(cmd)){
15024 astman_send_error(s, m, "RptStatus missing command");
15025 ast_free(str);
15026 return 0;
15027 }
15028
15029 for(i = 0 ; mct[i].cmd ; i++){
15030 if(!strcmp(mct[i].cmd, cmd))
15031 break;
15032 }
15033
15034 if(!mct[i].cmd){
15035 astman_send_error(s, m, "RptStatus unknown command");
15036 ast_free(str);
15037 return 0;
15038 }
15039 else
15040 idx = mct[i].index;
15041
15042 switch(idx){
15043
15044 case MGRCMD_RPTSTAT:
15045
15046 if((res = snprintf(str, len, "Nodes: ")) > -1)
15047 len -= res;
15048 else{
15049 ast_free(str);
15050 return 0;
15051 }
15052 for(i = 0; i < nrpts; i++){
15053 if(i < nrpts - 1){
15054 if((res = snprintf(str+strlen(str), len, "%s,",rpt_vars[i].name)) < 0){
15055 ast_free(str);
15056 return 0;
15057 }
15058 }
15059 else{
15060 if((res = snprintf(str+strlen(str), len, "%s",rpt_vars[i].name)) < 0){
15061 ast_free(str);
15062 return 0;
15063 }
15064 }
15065 len -= res;
15066 }
15067
15068 rpt_manager_success(s,m);
15069
15070 if(!nrpts)
15071 astman_append(s, "<NONE>\r\n");
15072 else
15073 astman_append(s, "%s\r\n", str);
15074
15075 uptime = (int)(now - starttime);
15076 hours = uptime/3600;
15077 uptime %= 3600;
15078 minutes = uptime/60;
15079 uptime %= 60;
15080
15081 astman_append(s, "RptUptime: %02d:%02d:%02d\r\n",
15082 hours, minutes, uptime);
15083
15084 astman_append(s, "\r\n");
15085 break;
15086
15087 case MGRCMD_NODESTAT:
15088 res = rpt_manager_do_stats(s,m,str);
15089 ast_free(str);
15090 return res;
15091
15092 default:
15093 astman_send_error(s, m, "RptStatus invalid command");
15094 break;
15095 }
15096 ast_free(str);
15097 return 0;
15098 }
15099
15100 #endif
15101
15102 #ifdef OLD_ASTERISK
15103 int unload_module()
15104 #else
15105 static int unload_module(void)
15106 #endif
15107 {
15108 int i, res;
15109
15110 #ifdef OLD_ASTERISK
15111 STANDARD_HANGUP_LOCALUSERS;
15112 #endif
15113 for(i = 0; i < nrpts; i++) {
15114 if (!strcmp(rpt_vars[i].name,rpt_vars[i].p.nodes)) continue;
15115 ast_mutex_destroy(&rpt_vars[i].lock);
15116 ast_mutex_destroy(&rpt_vars[i].remlock);
15117 }
15118 res = ast_unregister_application(app);
15119
15120 #ifdef NEW_ASTERISK
15121 ast_cli_unregister_multiple(rpt_cli, ARRAY_LEN(rpt_cli));
15122 #else
15123
15124 ast_cli_unregister(&cli_debug);
15125 ast_cli_unregister(&cli_dump);
15126 ast_cli_unregister(&cli_stats);
15127 ast_cli_unregister(&cli_lstats);
15128 ast_cli_unregister(&cli_nodes);
15129 ast_cli_unregister(&cli_local_nodes);
15130 ast_cli_unregister(&cli_reload);
15131 ast_cli_unregister(&cli_restart);
15132 ast_cli_unregister(&cli_fun);
15133 ast_cli_unregister(&cli_fun1);
15134 res |= ast_cli_unregister(&cli_cmd);
15135 #endif
15136 #ifndef OLD_ASTERISK
15137 res |= ast_manager_unregister("RptLocalNodes");
15138 res |= ast_manager_unregister("RptStatus");
15139 #endif
15140 return res;
15141 }
15142
15143 #ifdef OLD_ASTERISK
15144 int load_module()
15145 #else
15146 static int load_module(void)
15147 #endif
15148 {
15149 int res;
15150 ast_pthread_create(&rpt_master_thread,NULL,rpt_master,NULL);
15151
15152 #ifdef NEW_ASTERISK
15153 ast_cli_register_multiple(rpt_cli, ARRAY_LEN(rpt_cli));
15154 res = 0;
15155 #else
15156
15157 ast_cli_register(&cli_debug);
15158 ast_cli_register(&cli_dump);
15159 ast_cli_register(&cli_stats);
15160 ast_cli_register(&cli_lstats);
15161 ast_cli_register(&cli_nodes);
15162 ast_cli_register(&cli_local_nodes);
15163 ast_cli_register(&cli_reload);
15164 ast_cli_register(&cli_restart);
15165 ast_cli_register(&cli_fun);
15166 ast_cli_register(&cli_fun1);
15167 res = ast_cli_register(&cli_cmd);
15168 #endif
15169 #ifndef OLD_ASTERISK
15170 res |= ast_manager_register("RptLocalNodes", 0, manager_rpt_local_nodes, "List local node numbers");
15171 res |= ast_manager_register("RptStatus", 0, manager_rpt_status, "Return Rpt Status for CGI");
15172
15173 #endif
15174 res |= ast_register_application(app, rpt_exec, synopsis, descrip);
15175 return res;
15176 }
15177
15178 #ifdef OLD_ASTERISK
15179 char *description()
15180 {
15181 return tdesc;
15182 }
15183 int usecount(void)
15184 {
15185 int res;
15186 STANDARD_USECOUNT(res);
15187 return res;
15188 }
15189
15190 char *key()
15191 {
15192 return ASTERISK_GPL_KEY;
15193 }
15194 #endif
15195
15196 #ifdef OLD_ASTERISK
15197 int reload()
15198 #else
15199 static int reload(void)
15200 #endif
15201 {
15202 int n;
15203
15204 for(n = 0; n < nrpts; n++) rpt_vars[n].reload = 1;
15205 return(0);
15206 }
15207
15208
15209 #ifndef OLD_ASTERISK
15210
15211 AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_DEFAULT, "Radio Repeater/Remote Base Application",
15212 .load = load_module,
15213 .unload = unload_module,
15214 .reload = reload,
15215 );
15216 #endif
15217