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: 276347 $")
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 const 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, const char * const *argv);
01175 static int rpt_do_dump(int fd, int argc, const char * const *argv);
01176 static int rpt_do_stats(int fd, int argc, const char * const *argv);
01177 static int rpt_do_lstats(int fd, int argc, const char * const *argv);
01178 static int rpt_do_nodes(int fd, int argc, const char * const *argv);
01179 static int rpt_do_local_nodes(int fd, int argc, const char * const *argv);
01180 static int rpt_do_reload(int fd, int argc, const char * const *argv);
01181 static int rpt_do_restart(int fd, int argc, const char * const *argv);
01182 static int rpt_do_fun(int fd, int argc, const char * const *argv);
01183 static int rpt_do_fun1(int fd, int argc, const char * const *argv);
01184 static int rpt_do_cmd(int fd, int argc, const char * const *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.integer = 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.integer = 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)) {
01961 ast_free(str);
01962 ast_free(astr);
01963 return;
01964 }
01965 n = finddelim(astr,astrs,100);
01966 if (n < 1) return;
01967 ast_mutex_lock(&myrpt->statpost_lock);
01968 seq = ++myrpt->statpost_seqno;
01969 ast_mutex_unlock(&myrpt->statpost_lock);
01970 astrs[n++] = str;
01971 astrs[n] = NULL;
01972 time(&now);
01973 sprintf(str,"%s?node=%s&time=%u&seqno=%u",myrpt->p.statpost_url,
01974 myrpt->name,(unsigned int) now,seq);
01975 if (pairs) sprintf(str + strlen(str),"&%s",pairs);
01976 if (!(pid = ast_safe_fork(0)))
01977 {
01978 execv(astrs[0],astrs);
01979 ast_log(LOG_ERROR, "exec of %s failed.\n", astrs[0]);
01980 perror("asterisk");
01981 exit(0);
01982 }
01983 ast_free(astr);
01984 ast_free(str);
01985 return;
01986 }
01987
01988 static char *node_lookup(struct rpt *myrpt,char *digitbuf)
01989 {
01990
01991 char *val;
01992 int longestnode,j;
01993 struct stat mystat;
01994 static time_t last = 0;
01995 static struct ast_config *ourcfg = NULL;
01996 struct ast_variable *vp;
01997
01998
01999 val = (char *) ast_variable_retrieve(myrpt->cfg, myrpt->p.nodes, digitbuf);
02000 if (val) return(val);
02001 ast_mutex_lock(&nodelookuplock);
02002
02003 if (stat(myrpt->p.extnodefile,&mystat) == -1)
02004 {
02005 if (ourcfg) ast_config_destroy(ourcfg);
02006 ourcfg = NULL;
02007 ast_mutex_unlock(&nodelookuplock);
02008 return(NULL);
02009 }
02010
02011 if (mystat.st_mtime > last)
02012 {
02013 if (ourcfg) ast_config_destroy(ourcfg);
02014 #ifdef NEW_ASTERISK
02015 ourcfg = ast_config_load(myrpt->p.extnodefile,config_flags);
02016 #else
02017 ourcfg = ast_config_load(myrpt->p.extnodefile);
02018 #endif
02019
02020 if (!ourcfg || ourcfg == CONFIG_STATUS_FILEINVALID)
02021 {
02022 ast_mutex_unlock(&nodelookuplock);
02023 return(NULL);
02024 }
02025
02026 last = mystat.st_mtime;
02027
02028
02029 longestnode = 0;
02030 vp = ast_variable_browse(myrpt->cfg, myrpt->p.nodes);
02031 while(vp){
02032 j = strlen(vp->name);
02033 if (j > longestnode)
02034 longestnode = j;
02035 vp = vp->next;
02036 }
02037
02038 vp = ast_variable_browse(ourcfg, myrpt->p.extnodes);
02039 while(vp){
02040 j = strlen(vp->name);
02041 if (j > longestnode)
02042 longestnode = j;
02043 vp = vp->next;
02044 }
02045
02046 myrpt->longestnode = longestnode;
02047 }
02048 val = NULL;
02049 if (ourcfg)
02050 val = (char *) ast_variable_retrieve(ourcfg, myrpt->p.extnodes, digitbuf);
02051 ast_mutex_unlock(&nodelookuplock);
02052 return(val);
02053 }
02054
02055
02056
02057
02058
02059
02060 static int matchkeyword(char *string, char **param, char *keywords[])
02061 {
02062 int i,ls;
02063 for( i = 0 ; keywords[i] ; i++){
02064 ls = strlen(keywords[i]);
02065 if(!ls){
02066 *param = NULL;
02067 return 0;
02068 }
02069 if(!strncmp(string, keywords[i], ls)){
02070 if(param)
02071 *param = string + ls;
02072 return i + 1;
02073 }
02074 }
02075 *param = NULL;
02076 return 0;
02077 }
02078
02079
02080
02081
02082
02083
02084 static char *skipchars(char *string, char *charlist)
02085 {
02086 int i;
02087 while(*string){
02088 for(i = 0; charlist[i] ; i++){
02089 if(*string == charlist[i]){
02090 string++;
02091 break;
02092 }
02093 }
02094 if(!charlist[i])
02095 return string;
02096 }
02097 return string;
02098 }
02099
02100 static int myatoi(const char *str)
02101 {
02102 int ret;
02103
02104 if (!str) {
02105 return -1;
02106 }
02107
02108
02109 if (sscanf(str, "%30i", &ret) != 1) {
02110 return -1;
02111 }
02112
02113 return ret;
02114 }
02115
02116 static int mycompar(const void *a, const void *b)
02117 {
02118 char **x = (char **) a;
02119 char **y = (char **) b;
02120 int xoff,yoff;
02121
02122 if ((**x < '0') || (**x > '9')) xoff = 1; else xoff = 0;
02123 if ((**y < '0') || (**y > '9')) yoff = 1; else yoff = 0;
02124 return(strcmp((*x) + xoff,(*y) + yoff));
02125 }
02126
02127 static int topcompar(const void *a, const void *b)
02128 {
02129 struct rpt_topkey *x = (struct rpt_topkey *) a;
02130 struct rpt_topkey *y = (struct rpt_topkey *) b;
02131
02132 return(x->timesince - y->timesince);
02133 }
02134
02135 #ifdef __RPT_NOTCH
02136
02137
02138 static void rpt_filter(struct rpt *myrpt, volatile short *buf, int len)
02139 {
02140 int i,j;
02141 struct rptfilter *f;
02142
02143 for(i = 0; i < len; i++)
02144 {
02145 for(j = 0; j < MAXFILTERS; j++)
02146 {
02147 f = &myrpt->filters[j];
02148 if (!*f->desc) continue;
02149 f->x0 = f->x1; f->x1 = f->x2;
02150 f->x2 = ((float)buf[i]) / f->gain;
02151 f->y0 = f->y1; f->y1 = f->y2;
02152 f->y2 = (f->x0 + f->x2) + f->const0 * f->x1
02153 + (f->const1 * f->y0) + (f->const2 * f->y1);
02154 buf[i] = (short)f->y2;
02155 }
02156 }
02157 }
02158
02159 #endif
02160
02161
02162
02163
02164
02165
02166
02167
02168
02169
02170
02171
02172
02173
02174
02175
02176
02177
02178 #ifdef NEW_ASTERISK
02179 static void rpt_localtime( time_t * t, struct ast_tm *lt)
02180 {
02181 struct timeval when;
02182
02183 when.tv_sec = *t;
02184 when.tv_usec = 0;
02185 ast_localtime(&when, lt, NULL);
02186 }
02187
02188 #else
02189 static void rpt_localtime( time_t * t, struct tm *lt)
02190 {
02191 #ifdef OLD_ASTERISK
02192 localtime_r(t, lt);
02193 #else
02194 ast_localtime(t, lt, NULL);
02195 #endif
02196 }
02197 #endif
02198
02199
02200
02201
02202 static int retrieve_astcfgint(struct rpt *myrpt,char *category, char *name, int min, int max, int defl)
02203 {
02204 char *var;
02205 int ret;
02206 char include_zero = 0;
02207
02208 if(min < 0){
02209 min = -min;
02210 include_zero = 1;
02211 }
02212
02213 var = (char *) ast_variable_retrieve(myrpt->cfg, category, name);
02214 if(var){
02215 ret = myatoi(var);
02216 if(include_zero && !ret)
02217 return 0;
02218 if(ret < min)
02219 ret = min;
02220 if(ret > max)
02221 ret = max;
02222 }
02223 else
02224 ret = defl;
02225 return ret;
02226 }
02227
02228
02229 static void load_rpt_vars(int n,int init)
02230 {
02231 char *this,*val;
02232 int i,j,longestnode;
02233 struct ast_variable *vp;
02234 struct ast_config *cfg;
02235 char *strs[100];
02236 char s1[256];
02237 static char *cs_keywords[] = {"rptena","rptdis","apena","apdis","lnkena","lnkdis","totena","totdis","skena","skdis",
02238 "ufena","ufdis","atena","atdis",NULL};
02239
02240 if (option_verbose > 2)
02241 ast_verbose(VERBOSE_PREFIX_3 "%s config for repeater %s\n",
02242 (init) ? "Loading initial" : "Re-Loading",rpt_vars[n].name);
02243 ast_mutex_lock(&rpt_vars[n].lock);
02244 if (rpt_vars[n].cfg) ast_config_destroy(rpt_vars[n].cfg);
02245 #ifdef NEW_ASTERISK
02246 cfg = ast_config_load("rpt.conf",config_flags);
02247 #else
02248 cfg = ast_config_load("rpt.conf");
02249 #endif
02250 if (!cfg || cfg == CONFIG_STATUS_FILEINVALID) {
02251 ast_mutex_unlock(&rpt_vars[n].lock);
02252 ast_log(LOG_NOTICE, "Unable to open radio repeater configuration rpt.conf. Radio Repeater disabled.\n");
02253 pthread_exit(NULL);
02254 }
02255 rpt_vars[n].cfg = cfg;
02256 this = rpt_vars[n].name;
02257 memset(&rpt_vars[n].p,0,sizeof(rpt_vars[n].p));
02258 if (init)
02259 {
02260 char *cp;
02261 int savearea = (char *)&rpt_vars[n].p - (char *)&rpt_vars[n];
02262
02263 cp = (char *) &rpt_vars[n].p;
02264 memset(cp + sizeof(rpt_vars[n].p),0,
02265 sizeof(rpt_vars[n]) - (sizeof(rpt_vars[n].p) + savearea));
02266 rpt_vars[n].tele.next = &rpt_vars[n].tele;
02267 rpt_vars[n].tele.prev = &rpt_vars[n].tele;
02268 rpt_vars[n].rpt_thread = AST_PTHREADT_NULL;
02269 rpt_vars[n].tailmessagen = 0;
02270 }
02271 #ifdef __RPT_NOTCH
02272
02273 memset(&rpt_vars[n].filters,0,sizeof(rpt_vars[n].filters));
02274 #endif
02275 val = (char *) ast_variable_retrieve(cfg,this,"context");
02276 if (val) rpt_vars[n].p.ourcontext = val;
02277 else rpt_vars[n].p.ourcontext = this;
02278 val = (char *) ast_variable_retrieve(cfg,this,"callerid");
02279 if (val) rpt_vars[n].p.ourcallerid = val;
02280 val = (char *) ast_variable_retrieve(cfg,this,"accountcode");
02281 if (val) rpt_vars[n].p.acctcode = val;
02282 val = (char *) ast_variable_retrieve(cfg,this,"idrecording");
02283 if (val) rpt_vars[n].p.ident = val;
02284 val = (char *) ast_variable_retrieve(cfg,this,"hangtime");
02285 if (val) rpt_vars[n].p.hangtime = atoi(val);
02286 else rpt_vars[n].p.hangtime = HANGTIME;
02287 val = (char *) ast_variable_retrieve(cfg,this,"althangtime");
02288 if (val) rpt_vars[n].p.althangtime = atoi(val);
02289 else rpt_vars[n].p.althangtime = HANGTIME;
02290 val = (char *) ast_variable_retrieve(cfg,this,"totime");
02291 if (val) rpt_vars[n].p.totime = atoi(val);
02292 else rpt_vars[n].p.totime = TOTIME;
02293 val = (char *) ast_variable_retrieve(cfg,this,"voxtimeout");
02294 if (val) rpt_vars[n].p.voxtimeout_ms = atoi(val);
02295 else rpt_vars[n].p.voxtimeout_ms = VOX_TIMEOUT_MS;
02296 val = (char *) ast_variable_retrieve(cfg,this,"voxrecover");
02297 if (val) rpt_vars[n].p.voxrecover_ms = atoi(val);
02298 else rpt_vars[n].p.voxrecover_ms = VOX_RECOVER_MS;
02299 val = (char *) ast_variable_retrieve(cfg,this,"simplexpatchdelay");
02300 if (val) rpt_vars[n].p.simplexpatchdelay = atoi(val);
02301 else rpt_vars[n].p.simplexpatchdelay = SIMPLEX_PATCH_DELAY;
02302 val = (char *) ast_variable_retrieve(cfg,this,"simplexphonedelay");
02303 if (val) rpt_vars[n].p.simplexphonedelay = atoi(val);
02304 else rpt_vars[n].p.simplexphonedelay = SIMPLEX_PHONE_DELAY;
02305 val = (char *) ast_variable_retrieve(cfg,this,"statpost_program");
02306 if (val) rpt_vars[n].p.statpost_program = val;
02307 else rpt_vars[n].p.statpost_program = STATPOST_PROGRAM;
02308 rpt_vars[n].p.statpost_url =
02309 (char *) ast_variable_retrieve(cfg,this,"statpost_url");
02310 rpt_vars[n].p.tailmessagetime = retrieve_astcfgint(&rpt_vars[n],this, "tailmessagetime", 0, 2400000, 0);
02311 rpt_vars[n].p.tailsquashedtime = retrieve_astcfgint(&rpt_vars[n],this, "tailsquashedtime", 0, 2400000, 0);
02312 rpt_vars[n].p.duplex = retrieve_astcfgint(&rpt_vars[n],this,"duplex",0,4,2);
02313 rpt_vars[n].p.idtime = retrieve_astcfgint(&rpt_vars[n],this, "idtime", -60000, 2400000, IDTIME);
02314 rpt_vars[n].p.politeid = retrieve_astcfgint(&rpt_vars[n],this, "politeid", 30000, 300000, POLITEID);
02315 val = (char *) ast_variable_retrieve(cfg,this,"tonezone");
02316 if (val) rpt_vars[n].p.tonezone = val;
02317 rpt_vars[n].p.tailmessages[0] = 0;
02318 rpt_vars[n].p.tailmessagemax = 0;
02319 val = (char *) ast_variable_retrieve(cfg,this,"tailmessagelist");
02320 if (val) rpt_vars[n].p.tailmessagemax = finddelim(val, rpt_vars[n].p.tailmessages, 500);
02321 val = (char *) ast_variable_retrieve(cfg,this,"memory");
02322 if (!val) val = MEMORY;
02323 rpt_vars[n].p.memory = val;
02324 val = (char *) ast_variable_retrieve(cfg,this,"macro");
02325 if (!val) val = MACRO;
02326 rpt_vars[n].p.macro = val;
02327 val = (char *) ast_variable_retrieve(cfg,this,"tonemacro");
02328 if (!val) val = TONEMACRO;
02329 rpt_vars[n].p.tonemacro = val;
02330 val = (char *) ast_variable_retrieve(cfg,this,"startup_macro");
02331 if (val) rpt_vars[n].p.startupmacro = val;
02332 val = (char *) ast_variable_retrieve(cfg,this,"iobase");
02333
02334
02335
02336 if ((!val) || (sscanf(val,"%30i",&rpt_vars[n].p.iobase) != 1))
02337 rpt_vars[n].p.iobase = DEFAULT_IOBASE;
02338 val = (char *) ast_variable_retrieve(cfg,this,"ioport");
02339 rpt_vars[n].p.ioport = val;
02340 val = (char *) ast_variable_retrieve(cfg,this,"functions");
02341 if (!val)
02342 {
02343 val = FUNCTIONS;
02344 rpt_vars[n].p.simple = 1;
02345 }
02346 rpt_vars[n].p.functions = val;
02347 val = (char *) ast_variable_retrieve(cfg,this,"link_functions");
02348 if (val) rpt_vars[n].p.link_functions = val;
02349 else
02350 rpt_vars[n].p.link_functions = rpt_vars[n].p.functions;
02351 val = (char *) ast_variable_retrieve(cfg,this,"phone_functions");
02352 if (val) rpt_vars[n].p.phone_functions = val;
02353 val = (char *) ast_variable_retrieve(cfg,this,"dphone_functions");
02354 if (val) rpt_vars[n].p.dphone_functions = val;
02355 val = (char *) ast_variable_retrieve(cfg,this,"alt_functions");
02356 if (val) rpt_vars[n].p.alt_functions = val;
02357 val = (char *) ast_variable_retrieve(cfg,this,"funcchar");
02358 if (!val) rpt_vars[n].p.funcchar = FUNCCHAR; else
02359 rpt_vars[n].p.funcchar = *val;
02360 val = (char *) ast_variable_retrieve(cfg,this,"endchar");
02361 if (!val) rpt_vars[n].p.endchar = ENDCHAR; else
02362 rpt_vars[n].p.endchar = *val;
02363 val = (char *) ast_variable_retrieve(cfg,this,"nobusyout");
02364 if (val) rpt_vars[n].p.nobusyout = ast_true(val);
02365 val = (char *) ast_variable_retrieve(cfg,this,"notelemtx");
02366 if (val) rpt_vars[n].p.notelemtx = ast_true(val);
02367 val = (char *) ast_variable_retrieve(cfg,this,"propagate_dtmf");
02368 if (val) rpt_vars[n].p.propagate_dtmf = ast_true(val);
02369 val = (char *) ast_variable_retrieve(cfg,this,"propagate_phonedtmf");
02370 if (val) rpt_vars[n].p.propagate_phonedtmf = ast_true(val);
02371 val = (char *) ast_variable_retrieve(cfg,this,"linktolink");
02372 if (val) rpt_vars[n].p.linktolink = ast_true(val);
02373 val = (char *) ast_variable_retrieve(cfg,this,"nodes");
02374 if (!val) val = NODES;
02375 rpt_vars[n].p.nodes = val;
02376 val = (char *) ast_variable_retrieve(cfg,this,"extnodes");
02377 if (!val) val = EXTNODES;
02378 rpt_vars[n].p.extnodes = val;
02379 val = (char *) ast_variable_retrieve(cfg,this,"extnodefile");
02380 if (!val) val = EXTNODEFILE;
02381 rpt_vars[n].p.extnodefile = val;
02382 val = (char *) ast_variable_retrieve(cfg,this,"archivedir");
02383 if (val) rpt_vars[n].p.archivedir = val;
02384 val = (char *) ast_variable_retrieve(cfg,this,"authlevel");
02385 if (val) rpt_vars[n].p.authlevel = atoi(val);
02386 else rpt_vars[n].p.authlevel = 0;
02387 val = (char *) ast_variable_retrieve(cfg,this,"parrot");
02388 if (val) rpt_vars[n].p.parrotmode = ast_true(val) * 2;
02389 else rpt_vars[n].p.parrotmode = 0;
02390 val = (char *) ast_variable_retrieve(cfg,this,"parrottime");
02391 if (val) rpt_vars[n].p.parrottime = atoi(val);
02392 else rpt_vars[n].p.parrottime = PARROTTIME;
02393 val = (char *) ast_variable_retrieve(cfg,this,"rptnode");
02394 rpt_vars[n].p.rptnode = val;
02395 val = (char *) ast_variable_retrieve(cfg,this,"mars");
02396 if (val) rpt_vars[n].p.remote_mars = atoi(val);
02397 else rpt_vars[n].p.remote_mars = 0;
02398 val = (char *) ast_variable_retrieve(cfg,this,"monminblocks");
02399 if (val) rpt_vars[n].p.monminblocks = atol(val);
02400 else rpt_vars[n].p.monminblocks = DEFAULT_MONITOR_MIN_DISK_BLOCKS;
02401 val = (char *) ast_variable_retrieve(cfg,this,"remote_inact_timeout");
02402 if (val) rpt_vars[n].p.remoteinacttimeout = atoi(val);
02403 else rpt_vars[n].p.remoteinacttimeout = DEFAULT_REMOTE_INACT_TIMEOUT;
02404 val = (char *) ast_variable_retrieve(cfg,this,"civaddr");
02405 if (val) rpt_vars[n].p.civaddr = atoi(val);
02406 else rpt_vars[n].p.civaddr = DEFAULT_CIV_ADDR;
02407 val = (char *) ast_variable_retrieve(cfg,this,"remote_timeout");
02408 if (val) rpt_vars[n].p.remotetimeout = atoi(val);
02409 else rpt_vars[n].p.remotetimeout = DEFAULT_REMOTE_TIMEOUT;
02410 val = (char *) ast_variable_retrieve(cfg,this,"remote_timeout_warning");
02411 if (val) rpt_vars[n].p.remotetimeoutwarning = atoi(val);
02412 else rpt_vars[n].p.remotetimeoutwarning = DEFAULT_REMOTE_TIMEOUT_WARNING;
02413 val = (char *) ast_variable_retrieve(cfg,this,"remote_timeout_warning_freq");
02414 if (val) rpt_vars[n].p.remotetimeoutwarningfreq = atoi(val);
02415 else rpt_vars[n].p.remotetimeoutwarningfreq = DEFAULT_REMOTE_TIMEOUT_WARNING_FREQ;
02416 #ifdef __RPT_NOTCH
02417 val = (char *) ast_variable_retrieve(cfg,this,"rxnotch");
02418 if (val) {
02419 i = finddelim(val,strs,MAXFILTERS * 2);
02420 i &= ~1;
02421 if (i >= 2) for(j = 0; j < i; j += 2)
02422 {
02423 rpt_mknotch(atof(strs[j]),atof(strs[j + 1]),
02424 &rpt_vars[n].filters[j >> 1].gain,
02425 &rpt_vars[n].filters[j >> 1].const0,
02426 &rpt_vars[n].filters[j >> 1].const1,
02427 &rpt_vars[n].filters[j >> 1].const2);
02428 sprintf(rpt_vars[n].filters[j >> 1].desc,"%s Hz, BW = %s",
02429 strs[j],strs[j + 1]);
02430 }
02431
02432 }
02433 #endif
02434 val = (char *) ast_variable_retrieve(cfg,this,"inxlat");
02435 if (val) {
02436 memset(&rpt_vars[n].p.inxlat,0,sizeof(struct rpt_xlat));
02437 i = finddelim(val,strs,3);
02438 if (i) strncpy(rpt_vars[n].p.inxlat.funccharseq,strs[0],MAXXLAT - 1);
02439 if (i > 1) strncpy(rpt_vars[n].p.inxlat.endcharseq,strs[1],MAXXLAT - 1);
02440 if (i > 2) strncpy(rpt_vars[n].p.inxlat.passchars,strs[2],MAXXLAT - 1);
02441 }
02442 val = (char *) ast_variable_retrieve(cfg,this,"outxlat");
02443 if (val) {
02444 memset(&rpt_vars[n].p.outxlat,0,sizeof(struct rpt_xlat));
02445 i = finddelim(val,strs,3);
02446 if (i) strncpy(rpt_vars[n].p.outxlat.funccharseq,strs[0],MAXXLAT - 1);
02447 if (i > 1) strncpy(rpt_vars[n].p.outxlat.endcharseq,strs[1],MAXXLAT - 1);
02448 if (i > 2) strncpy(rpt_vars[n].p.outxlat.passchars,strs[2],MAXXLAT - 1);
02449 }
02450
02451 val = (char *) ast_variable_retrieve(cfg,this,"controlstates");
02452 rpt_vars[n].p.csstanzaname = val;
02453
02454
02455 val = (char *) ast_variable_retrieve(cfg,this,"scheduler");
02456 rpt_vars[n].p.skedstanzaname = val;
02457
02458
02459 val = (char *) ast_variable_retrieve(cfg,this,"txlimits");
02460 rpt_vars[n].p.txlimitsstanzaname = val;
02461
02462 longestnode = 0;
02463
02464 vp = ast_variable_browse(cfg, rpt_vars[n].p.nodes);
02465
02466 while(vp){
02467 j = strlen(vp->name);
02468 if (j > longestnode)
02469 longestnode = j;
02470 vp = vp->next;
02471 }
02472
02473 rpt_vars[n].longestnode = longestnode;
02474
02475
02476
02477
02478 rpt_vars[n].longestfunc = 0;
02479 vp = ast_variable_browse(cfg, rpt_vars[n].p.functions);
02480 while(vp){
02481 j = strlen(vp->name);
02482 if (j > rpt_vars[n].longestfunc)
02483 rpt_vars[n].longestfunc = j;
02484 vp = vp->next;
02485 }
02486
02487
02488
02489 rpt_vars[n].link_longestfunc = 0;
02490 vp = ast_variable_browse(cfg, rpt_vars[n].p.link_functions);
02491 while(vp){
02492 j = strlen(vp->name);
02493 if (j > rpt_vars[n].link_longestfunc)
02494 rpt_vars[n].link_longestfunc = j;
02495 vp = vp->next;
02496 }
02497 rpt_vars[n].phone_longestfunc = 0;
02498 if (rpt_vars[n].p.phone_functions)
02499 {
02500 vp = ast_variable_browse(cfg, rpt_vars[n].p.phone_functions);
02501 while(vp){
02502 j = strlen(vp->name);
02503 if (j > rpt_vars[n].phone_longestfunc)
02504 rpt_vars[n].phone_longestfunc = j;
02505 vp = vp->next;
02506 }
02507 }
02508 rpt_vars[n].dphone_longestfunc = 0;
02509 if (rpt_vars[n].p.dphone_functions)
02510 {
02511 vp = ast_variable_browse(cfg, rpt_vars[n].p.dphone_functions);
02512 while(vp){
02513 j = strlen(vp->name);
02514 if (j > rpt_vars[n].dphone_longestfunc)
02515 rpt_vars[n].dphone_longestfunc = j;
02516 vp = vp->next;
02517 }
02518 }
02519 rpt_vars[n].alt_longestfunc = 0;
02520 if (rpt_vars[n].p.alt_functions)
02521 {
02522 vp = ast_variable_browse(cfg, rpt_vars[n].p.alt_functions);
02523 while(vp){
02524 j = strlen(vp->name);
02525 if (j > rpt_vars[n].alt_longestfunc)
02526 rpt_vars[n].alt_longestfunc = j;
02527 vp = vp->next;
02528 }
02529 }
02530 rpt_vars[n].macro_longest = 1;
02531 vp = ast_variable_browse(cfg, rpt_vars[n].p.macro);
02532 while(vp){
02533 j = strlen(vp->name);
02534 if (j > rpt_vars[n].macro_longest)
02535 rpt_vars[n].macro_longest = j;
02536 vp = vp->next;
02537 }
02538
02539
02540 if(rpt_vars[n].p.csstanzaname)
02541 vp = ast_variable_browse(cfg, rpt_vars[n].p.csstanzaname);
02542 else
02543 vp = NULL;
02544 for( i = 0 ; vp && (i < MAX_SYSSTATES) ; i++){
02545 int k,nukw,statenum;
02546 statenum=atoi(vp->name);
02547 strncpy(s1, vp->value, 255);
02548 s1[255] = 0;
02549 nukw = finddelim(s1,strs,32);
02550
02551 for (k = 0 ; k < nukw ; k++){
02552 for(j = 0 ; cs_keywords[j] != NULL ; j++){
02553 if(!strcmp(strs[k],cs_keywords[j])){
02554 switch(j){
02555 case 0:
02556 rpt_vars[n].p.s[statenum].txdisable = 0;
02557 break;
02558 case 1:
02559 rpt_vars[n].p.s[statenum].txdisable = 1;
02560 break;
02561
02562 case 2:
02563 rpt_vars[n].p.s[statenum].autopatchdisable = 0;
02564 break;
02565
02566 case 3:
02567 rpt_vars[n].p.s[statenum].autopatchdisable = 1;
02568 break;
02569
02570 case 4:
02571 rpt_vars[n].p.s[statenum].linkfundisable = 0;
02572 break;
02573
02574 case 5:
02575 rpt_vars[n].p.s[statenum].linkfundisable = 1;
02576 break;
02577
02578 case 6:
02579 rpt_vars[n].p.s[statenum].totdisable = 0;
02580 break;
02581
02582 case 7:
02583 rpt_vars[n].p.s[statenum].totdisable = 1;
02584 break;
02585
02586 case 8:
02587 rpt_vars[n].p.s[statenum].schedulerdisable = 0;
02588 break;
02589
02590 case 9:
02591 rpt_vars[n].p.s[statenum].schedulerdisable = 1;
02592 break;
02593
02594 case 10:
02595 rpt_vars[n].p.s[statenum].userfundisable = 0;
02596 break;
02597
02598 case 11:
02599 rpt_vars[n].p.s[statenum].userfundisable = 1;
02600 break;
02601
02602 case 12:
02603 rpt_vars[n].p.s[statenum].alternatetail = 1;
02604 break;
02605
02606 case 13:
02607 rpt_vars[n].p.s[statenum].alternatetail = 0;
02608 break;
02609
02610 default:
02611 ast_log(LOG_WARNING,
02612 "Unhandled control state keyword %s", cs_keywords[i]);
02613 break;
02614 }
02615 }
02616 }
02617 }
02618 vp = vp->next;
02619 }
02620 ast_mutex_unlock(&rpt_vars[n].lock);
02621 }
02622
02623
02624
02625
02626 static int rpt_do_debug(int fd, int argc, const char * const *argv)
02627 {
02628 int newlevel;
02629
02630 if (argc != 4) {
02631 return RESULT_SHOWUSAGE;
02632 }
02633
02634 newlevel = myatoi(argv[3]);
02635
02636 if (newlevel < 0 || newlevel > 7) {
02637 return RESULT_SHOWUSAGE;
02638 }
02639
02640 if (newlevel) {
02641 ast_cli(fd, "app_rpt Debugging enabled, previous level: %d, new level: %d\n", debug, newlevel);
02642 } else {
02643 ast_cli(fd, "app_rpt Debugging disabled\n");
02644 }
02645
02646 debug = newlevel;
02647
02648 return RESULT_SUCCESS;
02649 }
02650
02651
02652
02653
02654
02655 static int rpt_do_dump(int fd, int argc, const char * const *argv)
02656 {
02657 int i;
02658
02659 if (argc != 3)
02660 return RESULT_SHOWUSAGE;
02661
02662 for(i = 0; i < nrpts; i++)
02663 {
02664 if (!strcmp(argv[2],rpt_vars[i].name))
02665 {
02666 rpt_vars[i].disgorgetime = time(NULL) + 10;
02667 ast_cli(fd, "app_rpt struct dump requested for node %s\n",argv[2]);
02668 return RESULT_SUCCESS;
02669 }
02670 }
02671 return RESULT_FAILURE;
02672 }
02673
02674
02675
02676
02677
02678 static int rpt_do_stats(int fd, int argc, const char * const *argv)
02679 {
02680 int i,j,numoflinks;
02681 int dailytxtime, dailykerchunks;
02682 time_t now;
02683 int totalkerchunks, dailykeyups, totalkeyups, timeouts;
02684 int totalexecdcommands, dailyexecdcommands, hours, minutes, seconds;
02685 int uptime;
02686 long long totaltxtime;
02687 struct rpt_link *l;
02688 char *listoflinks[MAX_STAT_LINKS];
02689 char *lastdtmfcommand,*parrot_ena;
02690 char *tot_state, *ider_state, *patch_state;
02691 char *reverse_patch_state, *sys_ena, *tot_ena, *link_ena, *patch_ena;
02692 char *sch_ena, *input_signal, *called_number, *user_funs, *tail_type;
02693 struct rpt *myrpt;
02694
02695 static char *not_applicable = "N/A";
02696
02697 if(argc != 3)
02698 return RESULT_SHOWUSAGE;
02699
02700 tot_state = ider_state =
02701 patch_state = reverse_patch_state =
02702 input_signal = not_applicable;
02703 called_number = lastdtmfcommand = NULL;
02704
02705 time(&now);
02706 for(i = 0; i < nrpts; i++)
02707 {
02708 if (!strcmp(argv[2],rpt_vars[i].name)){
02709
02710 myrpt = &rpt_vars[i];
02711 rpt_mutex_lock(&myrpt->lock);
02712 uptime = (int)(now - starttime);
02713 dailytxtime = myrpt->dailytxtime;
02714 totaltxtime = myrpt->totaltxtime;
02715 dailykeyups = myrpt->dailykeyups;
02716 totalkeyups = myrpt->totalkeyups;
02717 dailykerchunks = myrpt->dailykerchunks;
02718 totalkerchunks = myrpt->totalkerchunks;
02719 dailyexecdcommands = myrpt->dailyexecdcommands;
02720 totalexecdcommands = myrpt->totalexecdcommands;
02721 timeouts = myrpt->timeouts;
02722
02723
02724 reverse_patch_state = "DOWN";
02725 numoflinks = 0;
02726 l = myrpt->links.next;
02727 while(l && (l != &myrpt->links)){
02728 if(numoflinks >= MAX_STAT_LINKS){
02729 ast_log(LOG_NOTICE,
02730 "maximum number of links exceeds %d in rpt_do_stats()!",MAX_STAT_LINKS);
02731 break;
02732 }
02733 if (l->name[0] == '0'){
02734 reverse_patch_state = "UP";
02735 l = l->next;
02736 continue;
02737 }
02738 listoflinks[numoflinks] = ast_strdup(l->name);
02739 if(listoflinks[numoflinks] == NULL){
02740 break;
02741 }
02742 else{
02743 numoflinks++;
02744 }
02745 l = l->next;
02746 }
02747
02748 if(myrpt->keyed)
02749 input_signal = "YES";
02750 else
02751 input_signal = "NO";
02752
02753 if(myrpt->p.parrotmode)
02754 parrot_ena = "ENABLED";
02755 else
02756 parrot_ena = "DISABLED";
02757
02758 if(myrpt->p.s[myrpt->p.sysstate_cur].txdisable)
02759 sys_ena = "DISABLED";
02760 else
02761 sys_ena = "ENABLED";
02762
02763 if(myrpt->p.s[myrpt->p.sysstate_cur].totdisable)
02764 tot_ena = "DISABLED";
02765 else
02766 tot_ena = "ENABLED";
02767
02768 if(myrpt->p.s[myrpt->p.sysstate_cur].linkfundisable)
02769 link_ena = "DISABLED";
02770 else
02771 link_ena = "ENABLED";
02772
02773 if(myrpt->p.s[myrpt->p.sysstate_cur].autopatchdisable)
02774 patch_ena = "DISABLED";
02775 else
02776 patch_ena = "ENABLED";
02777
02778 if(myrpt->p.s[myrpt->p.sysstate_cur].schedulerdisable)
02779 sch_ena = "DISABLED";
02780 else
02781 sch_ena = "ENABLED";
02782
02783 if(myrpt->p.s[myrpt->p.sysstate_cur].userfundisable)
02784 user_funs = "DISABLED";
02785 else
02786 user_funs = "ENABLED";
02787
02788 if(myrpt->p.s[myrpt->p.sysstate_cur].alternatetail)
02789 tail_type = "ALTERNATE";
02790 else
02791 tail_type = "STANDARD";
02792
02793 if(!myrpt->totimer)
02794 tot_state = "TIMED OUT!";
02795 else if(myrpt->totimer != myrpt->p.totime)
02796 tot_state = "ARMED";
02797 else
02798 tot_state = "RESET";
02799
02800 if(myrpt->tailid)
02801 ider_state = "QUEUED IN TAIL";
02802 else if(myrpt->mustid)
02803 ider_state = "QUEUED FOR CLEANUP";
02804 else
02805 ider_state = "CLEAN";
02806
02807 switch(myrpt->callmode){
02808 case 1:
02809 patch_state = "DIALING";
02810 break;
02811 case 2:
02812 patch_state = "CONNECTING";
02813 break;
02814 case 3:
02815 patch_state = "UP";
02816 break;
02817
02818 case 4:
02819 patch_state = "CALL FAILED";
02820 break;
02821
02822 default:
02823 patch_state = "DOWN";
02824 }
02825
02826 if(strlen(myrpt->exten)){
02827 called_number = ast_strdup(myrpt->exten);
02828 }
02829
02830 if(strlen(myrpt->lastdtmfcommand)){
02831 lastdtmfcommand = ast_strdup(myrpt->lastdtmfcommand);
02832 }
02833 rpt_mutex_unlock(&myrpt->lock);
02834
02835 ast_cli(fd, "************************ NODE %s STATISTICS *************************\n\n", myrpt->name);
02836 ast_cli(fd, "Selected system state............................: %d\n", myrpt->p.sysstate_cur);
02837 ast_cli(fd, "Signal on input..................................: %s\n", input_signal);
02838 ast_cli(fd, "System...........................................: %s\n", sys_ena);
02839 ast_cli(fd, "Parrot Mode......................................: %s\n", parrot_ena);
02840 ast_cli(fd, "Scheduler........................................: %s\n", sch_ena);
02841 ast_cli(fd, "Tail Time........................................: %s\n", tail_type);
02842 ast_cli(fd, "Time out timer...................................: %s\n", tot_ena);
02843 ast_cli(fd, "Time out timer state.............................: %s\n", tot_state);
02844 ast_cli(fd, "Time outs since system initialization............: %d\n", timeouts);
02845 ast_cli(fd, "Identifier state.................................: %s\n", ider_state);
02846 ast_cli(fd, "Kerchunks today..................................: %d\n", dailykerchunks);
02847 ast_cli(fd, "Kerchunks since system initialization............: %d\n", totalkerchunks);
02848 ast_cli(fd, "Keyups today.....................................: %d\n", dailykeyups);
02849 ast_cli(fd, "Keyups since system initialization...............: %d\n", totalkeyups);
02850 ast_cli(fd, "DTMF commands today..............................: %d\n", dailyexecdcommands);
02851 ast_cli(fd, "DTMF commands since system initialization........: %d\n", totalexecdcommands);
02852 ast_cli(fd, "Last DTMF command executed.......................: %s\n",
02853 (lastdtmfcommand && strlen(lastdtmfcommand)) ? lastdtmfcommand : not_applicable);
02854 hours = dailytxtime/3600000;
02855 dailytxtime %= 3600000;
02856 minutes = dailytxtime/60000;
02857 dailytxtime %= 60000;
02858 seconds = dailytxtime/1000;
02859 dailytxtime %= 1000;
02860
02861 ast_cli(fd, "TX time today....................................: %02d:%02d:%02d.%d\n",
02862 hours, minutes, seconds, dailytxtime);
02863
02864 hours = (int) totaltxtime/3600000;
02865 totaltxtime %= 3600000;
02866 minutes = (int) totaltxtime/60000;
02867 totaltxtime %= 60000;
02868 seconds = (int) totaltxtime/1000;
02869 totaltxtime %= 1000;
02870
02871 ast_cli(fd, "TX time since system initialization..............: %02d:%02d:%02d.%d\n",
02872 hours, minutes, seconds, (int) totaltxtime);
02873
02874 hours = uptime/3600;
02875 uptime %= 3600;
02876 minutes = uptime/60;
02877 uptime %= 60;
02878
02879 ast_cli(fd, "Uptime...........................................: %02d:%02d:%02d\n",
02880 hours, minutes, uptime);
02881
02882 ast_cli(fd, "Nodes currently connected to us..................: ");
02883 if(!numoflinks){
02884 ast_cli(fd,"<NONE>");
02885 }
02886 else{
02887 for(j = 0 ;j < numoflinks; j++){
02888 ast_cli(fd, "%s", listoflinks[j]);
02889 if(j % 4 == 3){
02890 ast_cli(fd, "\n");
02891 ast_cli(fd, " : ");
02892 }
02893 else{
02894 if((numoflinks - 1) - j > 0)
02895 ast_cli(fd, ", ");
02896 }
02897 }
02898 }
02899 ast_cli(fd,"\n");
02900
02901 ast_cli(fd, "Autopatch........................................: %s\n", patch_ena);
02902 ast_cli(fd, "Autopatch state..................................: %s\n", patch_state);
02903 ast_cli(fd, "Autopatch called number..........................: %s\n",
02904 (called_number && strlen(called_number)) ? called_number : not_applicable);
02905 ast_cli(fd, "Reverse patch/IAXRPT connected...................: %s\n", reverse_patch_state);
02906 ast_cli(fd, "User linking commands............................: %s\n", link_ena);
02907 ast_cli(fd, "User functions...................................: %s\n\n", user_funs);
02908
02909 for(j = 0; j < numoflinks; j++){
02910 ast_free(listoflinks[j]);
02911 }
02912 ast_free(called_number);
02913 ast_free(lastdtmfcommand);
02914 return RESULT_SUCCESS;
02915 }
02916 }
02917 return RESULT_FAILURE;
02918 }
02919
02920
02921
02922
02923
02924 static int rpt_do_lstats(int fd, int argc, const char * const *argv)
02925 {
02926 int i,j;
02927 char *connstate;
02928 struct rpt *myrpt;
02929 struct rpt_link *l;
02930 struct rpt_lstat *s,*t;
02931 struct rpt_lstat s_head;
02932 if(argc != 3)
02933 return RESULT_SHOWUSAGE;
02934
02935 s = NULL;
02936 s_head.next = &s_head;
02937 s_head.prev = &s_head;
02938
02939 for(i = 0; i < nrpts; i++)
02940 {
02941 if (!strcmp(argv[2],rpt_vars[i].name)){
02942
02943 myrpt = &rpt_vars[i];
02944 rpt_mutex_lock(&myrpt->lock);
02945
02946 j = 0;
02947 l = myrpt->links.next;
02948 while(l && (l != &myrpt->links)){
02949 if (l->name[0] == '0'){
02950 l = l->next;
02951 continue;
02952 }
02953 if((s = (struct rpt_lstat *) ast_malloc(sizeof(struct rpt_lstat))) == NULL){
02954 ast_log(LOG_ERROR, "Malloc failed in rpt_do_lstats\n");
02955 rpt_mutex_unlock(&myrpt->lock);
02956 return RESULT_FAILURE;
02957 }
02958 memset(s, 0, sizeof(struct rpt_lstat));
02959 strncpy(s->name, l->name, MAXREMSTR - 1);
02960 if (l->chan) pbx_substitute_variables_helper(l->chan, "${IAXPEER(CURRENTCHANNEL)}", s->peer, MAXPEERSTR - 1);
02961 else strcpy(s->peer,"(none)");
02962 s->mode = l->mode;
02963 s->outbound = l->outbound;
02964 s->reconnects = l->reconnects;
02965 s->connecttime = l->connecttime;
02966 s->thisconnected = l->thisconnected;
02967 memcpy(s->chan_stat,l->chan_stat,NRPTSTAT * sizeof(struct rpt_chan_stat));
02968 insque((struct qelem *) s, (struct qelem *) s_head.next);
02969 memset(l->chan_stat,0,NRPTSTAT * sizeof(struct rpt_chan_stat));
02970 l = l->next;
02971 }
02972 rpt_mutex_unlock(&myrpt->lock);
02973 ast_cli(fd, "NODE PEER RECONNECTS DIRECTION CONNECT TIME CONNECT STATE\n");
02974 ast_cli(fd, "---- ---- ---------- --------- ------------ -------------\n");
02975
02976 for(s = s_head.next; s != &s_head; s = s->next){
02977 int hours, minutes, seconds;
02978 long long connecttime = s->connecttime;
02979 char conntime[21];
02980 hours = (int) connecttime/3600000;
02981 connecttime %= 3600000;
02982 minutes = (int) connecttime/60000;
02983 connecttime %= 60000;
02984 seconds = (int) connecttime/1000;
02985 connecttime %= 1000;
02986 snprintf(conntime, 20, "%02d:%02d:%02d.%d",
02987 hours, minutes, seconds, (int) connecttime);
02988 conntime[20] = 0;
02989 if(s->thisconnected)
02990 connstate = "ESTABLISHED";
02991 else
02992 connstate = "CONNECTING";
02993 ast_cli(fd, "%-10s%-20s%-12d%-11s%-20s%-20s\n",
02994 s->name, s->peer, s->reconnects, (s->outbound)? "OUT":"IN", conntime, connstate);
02995 }
02996
02997 s = s_head.next;
02998 while(s != &s_head){
02999 t = s;
03000 s = s->next;
03001 remque((struct qelem *)t);
03002 ast_free(t);
03003 }
03004 return RESULT_SUCCESS;
03005 }
03006 }
03007 return RESULT_FAILURE;
03008 }
03009
03010
03011
03012
03013
03014 static int rpt_do_nodes(int fd, int argc, const char * const *argv)
03015 {
03016 int i,j;
03017 char ns;
03018 char lbuf[MAXLINKLIST],*strs[MAXLINKLIST];
03019 struct rpt *myrpt;
03020 if(argc != 3)
03021 return RESULT_SHOWUSAGE;
03022
03023 for(i = 0; i < nrpts; i++)
03024 {
03025 if (!strcmp(argv[2],rpt_vars[i].name)){
03026
03027 myrpt = &rpt_vars[i];
03028 rpt_mutex_lock(&myrpt->lock);
03029 __mklinklist(myrpt,NULL,lbuf);
03030 rpt_mutex_unlock(&myrpt->lock);
03031
03032 ns = finddelim(lbuf,strs,MAXLINKLIST);
03033
03034 if (ns) qsort((void *)strs,ns,sizeof(char *),mycompar);
03035 ast_cli(fd,"\n");
03036 ast_cli(fd, "************************* CONNECTED NODES *************************\n\n");
03037 for(j = 0 ;; j++){
03038 if(!strs[j]){
03039 if(!j){
03040 ast_cli(fd,"<NONE>");
03041 }
03042 break;
03043 }
03044 ast_cli(fd, "%s", strs[j]);
03045 if(j % 8 == 7){
03046 ast_cli(fd, "\n");
03047 }
03048 else{
03049 if(strs[j + 1])
03050 ast_cli(fd, ", ");
03051 }
03052 }
03053 ast_cli(fd,"\n\n");
03054 return RESULT_SUCCESS;
03055 }
03056 }
03057 return RESULT_FAILURE;
03058 }
03059
03060
03061
03062
03063
03064 static int rpt_do_local_nodes(int fd, int argc, const char * const *argv)
03065 {
03066
03067 int i;
03068 ast_cli(fd, "\nNode\n----\n");
03069 for (i=0; i< nrpts; i++)
03070 {
03071 ast_cli(fd, "%s\n", rpt_vars[i].name);
03072 }
03073 ast_cli(fd,"\n");
03074 return RESULT_SUCCESS;
03075 }
03076
03077
03078
03079
03080
03081
03082 static int rpt_do_reload(int fd, int argc, const char * const *argv)
03083 {
03084 int n;
03085
03086 if (argc > 2) return RESULT_SHOWUSAGE;
03087
03088 for(n = 0; n < nrpts; n++) rpt_vars[n].reload = 1;
03089
03090 return RESULT_FAILURE;
03091 }
03092
03093
03094
03095
03096
03097 static int rpt_do_restart(int fd, int argc, const char * const *argv)
03098 {
03099 int i;
03100
03101 if (argc > 2) return RESULT_SHOWUSAGE;
03102 for(i = 0; i < nrpts; i++)
03103 {
03104 if (rpt_vars[i].rxchannel) ast_softhangup(rpt_vars[i].rxchannel,AST_SOFTHANGUP_DEV);
03105 }
03106 return RESULT_FAILURE;
03107 }
03108
03109
03110
03111
03112
03113
03114 static int rpt_do_fun(int fd, int argc, const char * const *argv)
03115 {
03116 int i,busy=0;
03117
03118 if (argc != 4) return RESULT_SHOWUSAGE;
03119
03120 for(i = 0; i < nrpts; i++){
03121 if(!strcmp(argv[2], rpt_vars[i].name)){
03122 struct rpt *myrpt = &rpt_vars[i];
03123 rpt_mutex_lock(&myrpt->lock);
03124 if ((MAXMACRO - strlen(myrpt->macrobuf)) < strlen(argv[3])){
03125 rpt_mutex_unlock(&myrpt->lock);
03126 busy=1;
03127 }
03128 if(!busy){
03129 myrpt->macrotimer = MACROTIME;
03130 strncat(myrpt->macrobuf,argv[3],MAXMACRO - 1);
03131 }
03132 rpt_mutex_unlock(&myrpt->lock);
03133 }
03134 }
03135 if(busy){
03136 ast_cli(fd, "Function decoder busy");
03137 }
03138 return RESULT_FAILURE;
03139 }
03140
03141
03142
03143
03144
03145
03146
03147
03148 static int rpt_push_alt_macro(struct rpt *myrpt, char *sptr)
03149 {
03150 int busy=0;
03151
03152 rpt_mutex_lock(&myrpt->lock);
03153 if ((MAXMACRO - strlen(myrpt->macrobuf)) < strlen(sptr)){
03154 rpt_mutex_unlock(&myrpt->lock);
03155 busy=1;
03156 }
03157 if(!busy){
03158 int x;
03159 if (debug)ast_log(LOG_NOTICE, "rpt_push_alt_macro %s\n",sptr);
03160 myrpt->macrotimer = MACROTIME;
03161 for(x = 0; *(sptr + x); x++)
03162 myrpt->macrobuf[x] = *(sptr + x) | 0x80;
03163 *(sptr + x) = 0;
03164 }
03165 rpt_mutex_unlock(&myrpt->lock);
03166
03167 if(busy)ast_log(LOG_WARNING, "Function decoder busy on app_rpt command macro.\n");
03168
03169 return busy;
03170 }
03171
03172
03173
03174 static int rpt_do_fun1(int fd, int argc, const char * const *argv)
03175 {
03176 int i;
03177
03178 if (argc != 4) return RESULT_SHOWUSAGE;
03179
03180 for(i = 0; i < nrpts; i++){
03181 if(!strcmp(argv[2], rpt_vars[i].name)){
03182 struct rpt *myrpt = &rpt_vars[i];
03183 rpt_push_alt_macro(myrpt, (char *) argv[3]);
03184 }
03185 }
03186 return RESULT_FAILURE;
03187 }
03188
03189
03190
03191
03192 static int rpt_do_cmd(int fd, int argc, const char * const *argv)
03193 {
03194 int i, l;
03195 int busy=0;
03196 int maxActions = sizeof(function_table)/sizeof(struct function_table_tag);
03197
03198 int thisRpt = -1;
03199 int thisAction = -1;
03200 struct rpt *myrpt = NULL;
03201 if (argc != 6) return RESULT_SHOWUSAGE;
03202
03203 for(i = 0; i < nrpts; i++)
03204 {
03205 if(!strcmp(argv[2], rpt_vars[i].name))
03206 {
03207 thisRpt = i;
03208 myrpt = &rpt_vars[i];
03209 break;
03210 }
03211 }
03212
03213 if (thisRpt < 0)
03214 {
03215 ast_cli(fd, "Unknown node number %s.\n", argv[2]);
03216 return RESULT_FAILURE;
03217 }
03218
03219
03220 l = strlen(argv[3]);
03221 for(i = 0 ; i < maxActions; i++)
03222 {
03223 if(!strncasecmp(argv[3], function_table[i].action, l))
03224 {
03225 thisAction = i;
03226 break;
03227 }
03228 }
03229
03230 if (thisAction < 0)
03231 {
03232 ast_cli(fd, "Unknown action name %s.\n", argv[3]);
03233 return RESULT_FAILURE;
03234 }
03235
03236
03237
03238 rpt_mutex_lock(&myrpt->lock);
03239
03240 if (rpt_vars[thisRpt].cmdAction.state == CMD_STATE_IDLE)
03241 {
03242 rpt_vars[thisRpt].cmdAction.state = CMD_STATE_BUSY;
03243 rpt_vars[thisRpt].cmdAction.functionNumber = thisAction;
03244 strncpy(rpt_vars[thisRpt].cmdAction.param, argv[4], MAXDTMF);
03245 strncpy(rpt_vars[thisRpt].cmdAction.digits, argv[5], MAXDTMF);
03246 rpt_vars[thisRpt].cmdAction.command_source = SOURCE_RPT;
03247 rpt_vars[thisRpt].cmdAction.state = CMD_STATE_READY;
03248 }
03249 else
03250 {
03251 busy = 1;
03252 }
03253 rpt_mutex_unlock(&myrpt->lock);
03254
03255 return (busy ? RESULT_FAILURE : RESULT_SUCCESS);
03256 }
03257
03258 static int play_tone_pair(struct ast_channel *chan, int f1, int f2, int duration, int amplitude)
03259 {
03260 int res;
03261
03262 if ((res = ast_tonepair_start(chan, f1, f2, duration, amplitude)))
03263 return res;
03264
03265 while(chan->generatordata) {
03266 if (ast_safe_sleep(chan,1)) return -1;
03267 }
03268
03269 return 0;
03270 }
03271
03272 static int play_tone(struct ast_channel *chan, int freq, int duration, int amplitude)
03273 {
03274 return play_tone_pair(chan, freq, 0, duration, amplitude);
03275 }
03276
03277 static int play_silence(struct ast_channel *chan, int duration)
03278 {
03279 return play_tone_pair(chan, 0, 0, duration, 0);
03280 }
03281
03282 #ifdef NEW_ASTERISK
03283
03284 static char *res2cli(int r)
03285
03286 {
03287 switch (r)
03288 {
03289 case RESULT_SUCCESS:
03290 return(CLI_SUCCESS);
03291 case RESULT_SHOWUSAGE:
03292 return(CLI_SHOWUSAGE);
03293 default:
03294 return(CLI_FAILURE);
03295 }
03296 }
03297
03298 static char *handle_cli_debug(struct ast_cli_entry *e,
03299 int cmd, struct ast_cli_args *a)
03300 {
03301 switch (cmd) {
03302 case CLI_INIT:
03303 e->command = "rpt debug level";
03304 e->usage = debug_usage;
03305 return NULL;
03306 case CLI_GENERATE:
03307 return NULL;
03308 }
03309 return res2cli(rpt_do_debug(a->fd, a->argc, a->argv));
03310 }
03311
03312 static char *handle_cli_dump(struct ast_cli_entry *e,
03313 int cmd, struct ast_cli_args *a)
03314 {
03315 switch (cmd) {
03316 case CLI_INIT:
03317 e->command = "rpt dump level";
03318 e->usage = dump_usage;
03319 return NULL;
03320 case CLI_GENERATE:
03321 return NULL;
03322 }
03323 return res2cli(rpt_do_dump(a->fd,a->argc,a->argv));
03324 }
03325
03326
03327 static char *handle_cli_stats(struct ast_cli_entry *e,
03328 int cmd, struct ast_cli_args *a)
03329 {
03330 switch (cmd) {
03331 case CLI_INIT:
03332 e->command = "rpt stats";
03333 e->usage = dump_stats;
03334 return NULL;
03335 case CLI_GENERATE:
03336 return NULL;
03337 }
03338 return res2cli(rpt_do_stats(a->fd,a->argc,a->argv));
03339 }
03340
03341 static char *handle_cli_nodes(struct ast_cli_entry *e,
03342 int cmd, struct ast_cli_args *a)
03343 {
03344 switch (cmd) {
03345 case CLI_INIT:
03346 e->command = "rpt nodes";
03347 e->usage = dump_nodes;
03348 return NULL;
03349 case CLI_GENERATE:
03350 return NULL;
03351 }
03352 return res2cli(rpt_do_nodes(a->fd,a->argc,a->argv));
03353 }
03354
03355 static char *handle_cli_local_nodes(struct ast_cli_entry *e,
03356 int cmd, struct ast_cli_args *a)
03357 {
03358 switch (cmd) {
03359 case CLI_INIT:
03360 e->command = "rpt localnodes";
03361 e->usage = usage_local_nodes;
03362 return NULL;
03363 case CLI_GENERATE:
03364 return NULL;
03365 }
03366 return res2cli(rpt_do_local_nodes(a->fd,a->argc,a->argv));
03367 }
03368
03369 static char *handle_cli_lstats(struct ast_cli_entry *e,
03370 int cmd, struct ast_cli_args *a)
03371 {
03372 switch (cmd) {
03373 case CLI_INIT:
03374 e->command = "rpt lstats";
03375 e->usage = dump_lstats;
03376 return NULL;
03377 case CLI_GENERATE:
03378 return NULL;
03379 }
03380 return res2cli(rpt_do_lstats(a->fd,a->argc,a->argv));
03381 }
03382
03383 static char *handle_cli_reload(struct ast_cli_entry *e,
03384 int cmd, struct ast_cli_args *a)
03385 {
03386 switch (cmd) {
03387 case CLI_INIT:
03388 e->command = "rpt reload";
03389 e->usage = reload_usage;
03390 return NULL;
03391 case CLI_GENERATE:
03392 return NULL;
03393 }
03394 return res2cli(rpt_do_reload(a->fd,a->argc,a->argv));
03395 }
03396
03397 static char *handle_cli_restart(struct ast_cli_entry *e,
03398 int cmd, struct ast_cli_args *a)
03399 {
03400 switch (cmd) {
03401 case CLI_INIT:
03402 e->command = "rpt restart";
03403 e->usage = restart_usage;
03404 return NULL;
03405 case CLI_GENERATE:
03406 return NULL;
03407 }
03408 return res2cli(rpt_do_restart(a->fd,a->argc,a->argv));
03409 }
03410
03411 static char *handle_cli_fun(struct ast_cli_entry *e,
03412 int cmd, struct ast_cli_args *a)
03413 {
03414 switch (cmd) {
03415 case CLI_INIT:
03416 e->command = "rpt fun";
03417 e->usage = fun_usage;
03418 return NULL;
03419 case CLI_GENERATE:
03420 return NULL;
03421 }
03422 return res2cli(rpt_do_fun(a->fd,a->argc,a->argv));
03423 }
03424
03425 static char *handle_cli_fun1(struct ast_cli_entry *e,
03426 int cmd, struct ast_cli_args *a)
03427 {
03428 switch (cmd) {
03429 case CLI_INIT:
03430 e->command = "rpt fun1";
03431 e->usage = fun_usage;
03432 return NULL;
03433 case CLI_GENERATE:
03434 return NULL;
03435 }
03436 return res2cli(rpt_do_fun1(a->fd,a->argc,a->argv));
03437 }
03438
03439 static char *handle_cli_cmd(struct ast_cli_entry *e,
03440 int cmd, struct ast_cli_args *a)
03441 {
03442 switch (cmd) {
03443 case CLI_INIT:
03444 e->command = "rpt cmd";
03445 e->usage = cmd_usage;
03446 return NULL;
03447 case CLI_GENERATE:
03448 return NULL;
03449 }
03450 return res2cli(rpt_do_cmd(a->fd,a->argc,a->argv));
03451 }
03452
03453 static struct ast_cli_entry rpt_cli[] = {
03454 AST_CLI_DEFINE(handle_cli_debug,"Enable app_rpt debugging"),
03455 AST_CLI_DEFINE(handle_cli_dump,"Dump app_rpt structs for debugging"),
03456 AST_CLI_DEFINE(handle_cli_stats,"Dump node statistics"),
03457 AST_CLI_DEFINE(handle_cli_nodes,"Dump node list"),
03458 AST_CLI_DEFINE(handle_cli_local_nodes, "Dump list of local node numbers"),
03459 AST_CLI_DEFINE(handle_cli_lstats,"Dump link statistics"),
03460 AST_CLI_DEFINE(handle_cli_reload,"Reload app_rpt config"),
03461 AST_CLI_DEFINE(handle_cli_restart,"Restart app_rpt"),
03462 AST_CLI_DEFINE(handle_cli_fun,"Execute a DTMF function"),
03463 AST_CLI_DEFINE(handle_cli_fun1,"Execute a DTMF function"),
03464 AST_CLI_DEFINE(handle_cli_cmd,"Execute a DTMF function")
03465 };
03466
03467 #endif
03468
03469 static int send_morse(struct ast_channel *chan, char *string, int speed, int freq, int amplitude)
03470 {
03471
03472 static struct morse_bits mbits[] = {
03473 {0, 0},
03474 {0, 0},
03475 {6, 18},
03476 {0, 0},
03477 {7, 72},
03478 {0, 0},
03479 {0, 0},
03480 {6, 30},
03481 {5, 13},
03482 {6, 29},
03483 {0, 0},
03484 {5, 10},
03485 {6, 51},
03486 {6, 33},
03487 {6, 42},
03488 {5, 9},
03489 {5, 31},
03490 {5, 30},
03491 {5, 28},
03492 {5, 24},
03493 {5, 16},
03494 {5, 0},
03495 {5, 1},
03496 {5, 3},
03497 {5, 7},
03498 {5, 15},
03499 {6, 7},
03500 {6, 21},
03501 {0, 0},
03502 {5, 33},
03503 {0, 0},
03504 {6, 12},
03505 {0, 0},
03506 {2, 2},
03507 {4, 1},
03508 {4, 5},
03509 {3, 1},
03510 {1, 0},
03511 {4, 4},
03512 {3, 3},
03513 {4, 0},
03514 {2, 0},
03515 {4, 14},
03516 {3, 5},
03517 {4, 2},
03518 {2, 3},
03519 {2, 1},
03520 {3, 7},
03521 {4, 6},
03522 {4, 11},
03523 {3, 2},
03524 {3, 0},
03525 {1, 1},
03526 {3, 4},
03527 {4, 8},
03528 {3, 6},
03529 {4, 9},
03530 {4, 13},
03531 {4, 3}
03532 };
03533
03534
03535 int dottime;
03536 int dashtime;
03537 int intralettertime;
03538 int interlettertime;
03539 int interwordtime;
03540 int len, ddcomb;
03541 int res;
03542 int c;
03543 int i;
03544 int flags;
03545
03546 res = 0;
03547
03548
03549
03550 dottime = 900/speed;
03551
03552
03553
03554 dashtime = 3 * dottime;
03555 intralettertime = dottime;
03556 interlettertime = dottime * 4 ;
03557 interwordtime = dottime * 7;
03558
03559 for(;(*string) && (!res); string++){
03560
03561 c = *string;
03562
03563
03564
03565 if((c >= 'a') && (c <= 'z'))
03566 c -= 0x20;
03567
03568
03569
03570 if(c > 'Z')
03571 continue;
03572
03573
03574
03575 if(c == ' '){
03576 if(!res)
03577 res = play_silence(chan, interwordtime);
03578 continue;
03579 }
03580
03581
03582
03583 c -= 0x20;
03584
03585
03586
03587 len = mbits[c].len;
03588 ddcomb = mbits[c].ddcomb;
03589
03590
03591
03592 for(; len ; len--){
03593 if(!res)
03594 res = play_tone(chan, freq, (ddcomb & 1) ? dashtime : dottime, amplitude);
03595 if(!res)
03596 res = play_silence(chan, intralettertime);
03597 ddcomb >>= 1;
03598 }
03599
03600
03601
03602 if(!res)
03603 res = play_silence(chan, interlettertime - intralettertime);
03604 }
03605
03606
03607
03608 if (!res)
03609 res = ast_waitstream(chan, "");
03610 ast_stopstream(chan);
03611
03612
03613
03614
03615
03616 for(i = 0; i < 20 ; i++){
03617 flags = DAHDI_IOMUX_WRITEEMPTY | DAHDI_IOMUX_NOWAIT;
03618 res = ioctl(chan->fds[0], DAHDI_IOMUX, &flags);
03619 if(flags & DAHDI_IOMUX_WRITEEMPTY)
03620 break;
03621 if( ast_safe_sleep(chan, 50)){
03622 res = -1;
03623 break;
03624 }
03625 }
03626
03627
03628 return res;
03629 }
03630
03631 static int send_tone_telemetry(struct ast_channel *chan, char *tonestring)
03632 {
03633 char *p,*stringp;
03634 char *tonesubset;
03635 int f1,f2;
03636 int duration;
03637 int amplitude;
03638 int res;
03639 int i;
03640 int flags;
03641
03642 res = 0;
03643
03644 if(!tonestring)
03645 return res;
03646
03647 p = stringp = ast_strdup(tonestring);
03648
03649 for(;tonestring;){
03650 tonesubset = strsep(&stringp,")");
03651 if(!tonesubset)
03652 break;
03653 if(sscanf(tonesubset,"(%30d,%30d,%30d,%30d", &f1, &f2, &duration, &litude) != 4)
03654 break;
03655 res = play_tone_pair(chan, f1, f2, duration, amplitude);
03656 if(res)
03657 break;
03658 }
03659 ast_free(p);
03660 if(!res)
03661 res = play_tone_pair(chan, 0, 0, 100, 0);
03662
03663 if (!res)
03664 res = ast_waitstream(chan, "");
03665
03666 ast_stopstream(chan);
03667
03668
03669
03670
03671
03672 for(i = 0; i < 20 ; i++){
03673 flags = DAHDI_IOMUX_WRITEEMPTY | DAHDI_IOMUX_NOWAIT;
03674 res = ioctl(chan->fds[0], DAHDI_IOMUX, &flags);
03675 if(flags & DAHDI_IOMUX_WRITEEMPTY)
03676 break;
03677 if( ast_safe_sleep(chan, 50)){
03678 res = -1;
03679 break;
03680 }
03681 }
03682
03683 return res;
03684
03685 }
03686
03687 static int sayfile(struct ast_channel *mychannel,char *fname)
03688 {
03689 int res;
03690
03691 res = ast_streamfile(mychannel, fname, mychannel->language);
03692 if (!res)
03693 res = ast_waitstream(mychannel, "");
03694 else
03695 ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", mychannel->name);
03696 ast_stopstream(mychannel);
03697 return res;
03698 }
03699
03700 static int saycharstr(struct ast_channel *mychannel,char *str)
03701 {
03702 int res;
03703
03704 res = ast_say_character_str(mychannel,str,NULL,mychannel->language);
03705 if (!res)
03706 res = ast_waitstream(mychannel, "");
03707 else
03708 ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", mychannel->name);
03709 ast_stopstream(mychannel);
03710 return res;
03711 }
03712
03713 static int saynum(struct ast_channel *mychannel, int num)
03714 {
03715 int res;
03716 res = ast_say_number(mychannel, num, NULL, mychannel->language, NULL);
03717 if(!res)
03718 res = ast_waitstream(mychannel, "");
03719 else
03720 ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", mychannel->name);
03721 ast_stopstream(mychannel);
03722 return res;
03723 }
03724
03725
03726
03727
03728 static int saynode(struct rpt *myrpt, struct ast_channel *mychannel, char *name)
03729 {
03730 int res;
03731 char *val,fname[300];
03732
03733 val = (char *) ast_variable_retrieve(myrpt->cfg, myrpt->name, "nodenames");
03734 if (!val) val = NODENAMES;
03735 snprintf(fname,sizeof(fname) - 1,"%s/%s",val,name);
03736 if (ast_fileexists(fname,NULL,mychannel->language) > 0)
03737 return(sayfile(mychannel,fname));
03738 res = sayfile(mychannel,"rpt/node");
03739 if (!res)
03740 res = ast_say_character_str(mychannel,name,NULL,mychannel->language);
03741 return res;
03742 }
03743
03744 static int telem_any(struct rpt *myrpt,struct ast_channel *chan, char *entry)
03745 {
03746 int res;
03747 char c;
03748
03749 static int morsespeed;
03750 static int morsefreq;
03751 static int morseampl;
03752 static int morseidfreq = 0;
03753 static int morseidampl;
03754 static char mcat[] = MORSE;
03755
03756 res = 0;
03757
03758 if(!morseidfreq){
03759 morsespeed = retrieve_astcfgint(myrpt, mcat, "speed", 5, 20, 20);
03760 morsefreq = retrieve_astcfgint(myrpt, mcat, "frequency", 300, 3000, 800);
03761 morseampl = retrieve_astcfgint(myrpt, mcat, "amplitude", 200, 8192, 4096);
03762 morseidampl = retrieve_astcfgint(myrpt, mcat, "idamplitude", 200, 8192, 2048);
03763 morseidfreq = retrieve_astcfgint(myrpt, mcat, "idfrequency", 300, 3000, 330);
03764 }
03765
03766
03767
03768 if(entry[0] == '|'){
03769 c = entry[1];
03770 if((c >= 'a')&&(c <= 'z'))
03771 c -= 0x20;
03772
03773 switch(c){
03774 case 'I':
03775 res = send_morse(chan, entry + 2, morsespeed, morseidfreq, morseidampl);
03776 break;
03777
03778 case 'M':
03779 res = send_morse(chan, entry + 2, morsespeed, morsefreq, morseampl);
03780 break;
03781
03782 case 'T':
03783 res = send_tone_telemetry(chan, entry + 2);
03784 break;
03785 default:
03786 res = -1;
03787 }
03788 }
03789 else
03790 res = sayfile(chan, entry);
03791 return res;
03792 }
03793
03794
03795
03796
03797
03798
03799
03800 static int telem_lookup(struct rpt *myrpt,struct ast_channel *chan, char *node, char *name)
03801 {
03802
03803 int res;
03804 int i;
03805 char *entry;
03806 char *telemetry;
03807 char *telemetry_save;
03808
03809 res = 0;
03810 telemetry_save = NULL;
03811 entry = NULL;
03812
03813
03814 telemetry = (char *) ast_variable_retrieve(myrpt->cfg, node, TELEMETRY);
03815 if(telemetry ){
03816 telemetry_save = ast_strdup(telemetry);
03817 if(!telemetry_save){
03818 ast_log(LOG_WARNING,"ast_strdup() failed in telem_lookup()\n");
03819 return res;
03820 }
03821 entry = (char *) ast_variable_retrieve(myrpt->cfg, telemetry_save, name);
03822 }
03823
03824
03825
03826 if(!entry){
03827
03828 for(i = 0; i < sizeof(tele_defs)/sizeof(struct telem_defaults) ; i++){
03829 if(!strcasecmp(tele_defs[i].name, name))
03830 entry = tele_defs[i].value;
03831 }
03832 }
03833 if(entry){
03834 if(strlen(entry))
03835 if (chan) telem_any(myrpt,chan, entry);
03836 }
03837 else{
03838 res = -1;
03839 }
03840 ast_free(telemetry_save);
03841 return res;
03842 }
03843
03844
03845
03846
03847
03848 static int get_wait_interval(struct rpt *myrpt, int type)
03849 {
03850 int interval;
03851 char *wait_times;
03852 char *wait_times_save;
03853
03854 wait_times_save = NULL;
03855 wait_times = (char *) ast_variable_retrieve(myrpt->cfg, myrpt->name, "wait_times");
03856
03857 if(wait_times){
03858 wait_times_save = ast_strdup(wait_times);
03859 if(!wait_times_save)
03860 return 0;
03861
03862 }
03863
03864 switch(type){
03865 case DLY_TELEM:
03866 if(wait_times)
03867 interval = retrieve_astcfgint(myrpt,wait_times_save, "telemwait", 500, 5000, 1000);
03868 else
03869 interval = 1000;
03870 break;
03871
03872 case DLY_ID:
03873 if(wait_times)
03874 interval = retrieve_astcfgint(myrpt,wait_times_save, "idwait",250,5000,500);
03875 else
03876 interval = 500;
03877 break;
03878
03879 case DLY_UNKEY:
03880 if(wait_times)
03881 interval = retrieve_astcfgint(myrpt,wait_times_save, "unkeywait",50,5000,1000);
03882 else
03883 interval = 1000;
03884 break;
03885
03886 case DLY_LINKUNKEY:
03887 if(wait_times)
03888 interval = retrieve_astcfgint(myrpt,wait_times_save, "linkunkeywait",500,5000,1000);
03889 else
03890 interval = 1000;
03891 break;
03892
03893 case DLY_CALLTERM:
03894 if(wait_times)
03895 interval = retrieve_astcfgint(myrpt,wait_times_save, "calltermwait",500,5000,1500);
03896 else
03897 interval = 1500;
03898 break;
03899
03900 case DLY_COMP:
03901 if(wait_times)
03902 interval = retrieve_astcfgint(myrpt,wait_times_save, "compwait",500,5000,200);
03903 else
03904 interval = 200;
03905 break;
03906
03907 case DLY_PARROT:
03908 if(wait_times)
03909 interval = retrieve_astcfgint(myrpt,wait_times_save, "parrotwait",500,5000,200);
03910 else
03911 interval = 200;
03912 break;
03913
03914 default:
03915 interval = 0;
03916 break;
03917 }
03918 ast_free(wait_times_save);
03919 return interval;
03920 }
03921
03922
03923
03924
03925
03926 static void wait_interval(struct rpt *myrpt, int type, struct ast_channel *chan)
03927 {
03928 int interval;
03929 interval = get_wait_interval(myrpt, type);
03930 if(debug)
03931 ast_log(LOG_NOTICE,"Delay interval = %d\n", interval);
03932 if(interval)
03933 ast_safe_sleep(chan,interval);
03934 if(debug)
03935 ast_log(LOG_NOTICE,"Delay complete\n");
03936 return;
03937 }
03938
03939 static int split_freq(char *mhz, char *decimals, char *freq);
03940
03941 static void *rpt_tele_thread(void *this)
03942 {
03943 struct dahdi_confinfo ci;
03944 int res = 0,haslink,hastx,hasremote,imdone = 0, unkeys_queued, x;
03945 struct rpt_tele *mytele = (struct rpt_tele *)this;
03946 struct rpt_tele *tlist;
03947 struct rpt *myrpt;
03948 struct rpt_link *l,*l1,linkbase;
03949 struct ast_channel *mychannel;
03950 int vmajor, vminor, m;
03951 char *p,*ct,*ct_copy,*ident, *nodename,*cp;
03952 time_t t;
03953 #ifdef NEW_ASTERISK
03954 struct ast_tm localtm;
03955 #else
03956 struct tm localtm;
03957 #endif
03958 char lbuf[MAXLINKLIST],*strs[MAXLINKLIST];
03959 int i,ns,rbimode;
03960 char mhz[MAXREMSTR];
03961 char decimals[MAXREMSTR];
03962 char mystr[200];
03963 struct dahdi_params par;
03964
03965
03966
03967 myrpt = mytele->rpt;
03968
03969
03970 rpt_mutex_lock(&myrpt->lock);
03971 nodename = ast_strdup(myrpt->name);
03972 if(!nodename)
03973 {
03974 fprintf(stderr,"rpt:Sorry unable strdup nodename\n");
03975 rpt_mutex_lock(&myrpt->lock);
03976 remque((struct qelem *)mytele);
03977 ast_log(LOG_NOTICE,"Telemetry thread aborted at line %d, mode: %d\n",__LINE__, mytele->mode);
03978 rpt_mutex_unlock(&myrpt->lock);
03979 ast_free(mytele);
03980 pthread_exit(NULL);
03981 }
03982
03983 if (myrpt->p.ident){
03984 ident = ast_strdup(myrpt->p.ident);
03985 if(!ident)
03986 {
03987 fprintf(stderr,"rpt:Sorry unable strdup ident\n");
03988 rpt_mutex_lock(&myrpt->lock);
03989 remque((struct qelem *)mytele);
03990 ast_log(LOG_NOTICE,"Telemetry thread aborted at line %d, mode: %d\n",
03991 __LINE__, mytele->mode);
03992 rpt_mutex_unlock(&myrpt->lock);
03993 ast_free(nodename);
03994 ast_free(mytele);
03995 pthread_exit(NULL);
03996 }
03997 }
03998 else
03999 {
04000 ident = "";
04001 }
04002 rpt_mutex_unlock(&myrpt->lock);
04003
04004
04005
04006
04007 mychannel = ast_request("DAHDI", AST_FORMAT_SLINEAR, NULL, "pseudo", NULL);
04008 if (!mychannel)
04009 {
04010 fprintf(stderr,"rpt:Sorry unable to obtain pseudo channel\n");
04011 rpt_mutex_lock(&myrpt->lock);
04012 remque((struct qelem *)mytele);
04013 ast_log(LOG_NOTICE,"Telemetry thread aborted at line %d, mode: %d\n",__LINE__, mytele->mode);
04014 rpt_mutex_unlock(&myrpt->lock);
04015 ast_free(nodename);
04016 ast_free(ident);
04017 ast_free(mytele);
04018 pthread_exit(NULL);
04019 }
04020 #ifdef AST_CDR_FLAG_POST_DISABLED
04021 if (mychannel->cdr)
04022 ast_set_flag(mychannel->cdr,AST_CDR_FLAG_POST_DISABLED);
04023 #endif
04024 rpt_mutex_lock(&myrpt->lock);
04025 mytele->chan = mychannel;
04026 rpt_mutex_unlock(&myrpt->lock);
04027
04028 while((mytele->mode != SETREMOTE) && (mytele->mode != UNKEY) &&
04029 (mytele->mode != LINKUNKEY))
04030 {
04031 rpt_mutex_lock(&myrpt->lock);
04032 if (!myrpt->active_telem)
04033 {
04034 myrpt->active_telem = mytele;
04035 rpt_mutex_unlock(&myrpt->lock);
04036 break;
04037 }
04038 rpt_mutex_unlock(&myrpt->lock);
04039 usleep(100000);
04040 }
04041
04042
04043 ci.chan = 0;
04044
04045
04046
04047 ci.confno = (((mytele->mode == ID) || (mytele->mode == IDTALKOVER) || (mytele->mode == UNKEY) ||
04048 (mytele->mode == TAILMSG) || (mytele->mode == LINKUNKEY) || (mytele->mode == TIMEOUT) ||
04049 (mytele->mode == PARROT) || (mytele->mode == STATS_TIME_LOCAL)) ?
04050 myrpt->txconf : myrpt->conf);
04051 ci.confmode = DAHDI_CONF_CONFANN;
04052
04053 if (ioctl(mychannel->fds[0],DAHDI_SETCONF,&ci) == -1)
04054 {
04055 ast_log(LOG_WARNING, "Unable to set conference mode to Announce\n");
04056 rpt_mutex_lock(&myrpt->lock);
04057 myrpt->active_telem = NULL;
04058 remque((struct qelem *)mytele);
04059 rpt_mutex_unlock(&myrpt->lock);
04060 ast_log(LOG_NOTICE,"Telemetry thread aborted at line %d, mode: %d\n",__LINE__, mytele->mode);
04061 ast_free(nodename);
04062 ast_free(ident);
04063 ast_free(mytele);
04064 ast_hangup(mychannel);
04065 pthread_exit(NULL);
04066 }
04067 ast_stopstream(mychannel);
04068 switch(mytele->mode)
04069 {
04070 case ID:
04071 case ID1:
04072
04073 wait_interval(myrpt, (mytele->mode == ID) ? DLY_ID : DLY_TELEM,mychannel);
04074 res = telem_any(myrpt,mychannel, ident);
04075 imdone=1;
04076 break;
04077
04078 case TAILMSG:
04079 res = ast_streamfile(mychannel, myrpt->p.tailmessages[myrpt->tailmessagen], mychannel->language);
04080 break;
04081
04082 case IDTALKOVER:
04083 p = (char *) ast_variable_retrieve(myrpt->cfg, nodename, "idtalkover");
04084 if(p)
04085 res = telem_any(myrpt,mychannel, p);
04086 imdone=1;
04087 break;
04088
04089 case PROC:
04090
04091 wait_interval(myrpt, DLY_TELEM, mychannel);
04092 res = telem_lookup(myrpt, mychannel, myrpt->name, "patchup");
04093 if(res < 0){
04094 res = ast_streamfile(mychannel, "rpt/callproceeding", mychannel->language);
04095 }
04096 break;
04097 case TERM:
04098
04099 wait_interval(myrpt, DLY_CALLTERM, mychannel);
04100 res = telem_lookup(myrpt, mychannel, myrpt->name, "patchdown");
04101 if(res < 0){
04102 res = ast_streamfile(mychannel, "rpt/callterminated", mychannel->language);
04103 }
04104 break;
04105 case COMPLETE:
04106
04107 wait_interval(myrpt, DLY_TELEM, mychannel);
04108 res = telem_lookup(myrpt,mychannel, myrpt->name, "functcomplete");
04109 break;
04110 case MACRO_NOTFOUND:
04111
04112 wait_interval(myrpt, DLY_TELEM, mychannel);
04113 res = ast_streamfile(mychannel, "rpt/macro_notfound", mychannel->language);
04114 break;
04115 case MACRO_BUSY:
04116
04117 wait_interval(myrpt, DLY_TELEM, mychannel);
04118 res = ast_streamfile(mychannel, "rpt/macro_busy", mychannel->language);
04119 break;
04120 case UNKEY:
04121 if(myrpt->patchnoct && myrpt->callmode){
04122 imdone = 1;
04123 break;
04124 }
04125
04126
04127
04128
04129
04130 x = get_wait_interval(myrpt, DLY_UNKEY);
04131 rpt_mutex_lock(&myrpt->lock);
04132 myrpt->unkeytocttimer = x;
04133 rpt_mutex_unlock(&myrpt->lock);
04134
04135
04136
04137
04138
04139 tlist = myrpt->tele.next;
04140 unkeys_queued = 0;
04141 if (tlist != &myrpt->tele)
04142 {
04143 rpt_mutex_lock(&myrpt->lock);
04144 while(tlist != &myrpt->tele){
04145 if (tlist->mode == UNKEY) unkeys_queued++;
04146 tlist = tlist->next;
04147 }
04148 rpt_mutex_unlock(&myrpt->lock);
04149 }
04150 if( unkeys_queued > 1){
04151 imdone = 1;
04152 break;
04153 }
04154
04155
04156
04157 while(myrpt->unkeytocttimer)
04158 {
04159 int ctint;
04160 if(myrpt->unkeytocttimer > 100)
04161 ctint = 100;
04162 else
04163 ctint = myrpt->unkeytocttimer;
04164 ast_safe_sleep(mychannel, ctint);
04165 rpt_mutex_lock(&myrpt->lock);
04166 if(myrpt->unkeytocttimer < ctint)
04167 myrpt->unkeytocttimer = 0;
04168 else
04169 myrpt->unkeytocttimer -= ctint;
04170 rpt_mutex_unlock(&myrpt->lock);
04171 }
04172
04173
04174
04175
04176
04177 if(myrpt->keyed){
04178 imdone = 1;
04179 break;
04180 }
04181
04182 rpt_mutex_lock(&myrpt->lock);
04183 myrpt->dailykerchunks++;
04184 myrpt->totalkerchunks++;
04185 rpt_mutex_unlock(&myrpt->lock);
04186
04187 haslink = 0;
04188 hastx = 0;
04189 hasremote = 0;
04190 l = myrpt->links.next;
04191 if (l != &myrpt->links)
04192 {
04193 rpt_mutex_lock(&myrpt->lock);
04194 while(l != &myrpt->links)
04195 {
04196 if (l->name[0] == '0')
04197 {
04198 l = l->next;
04199 continue;
04200 }
04201 haslink = 1;
04202 if (l->mode) {
04203 hastx++;
04204 if (l->isremote) hasremote++;
04205 }
04206 l = l->next;
04207 }
04208 rpt_mutex_unlock(&myrpt->lock);
04209 }
04210 if (haslink)
04211 {
04212
04213 res = telem_lookup(myrpt,mychannel, myrpt->name, (!hastx) ? "remotemon" : "remotetx");
04214 if(res)
04215 ast_log(LOG_WARNING, "telem_lookup:remotexx failed on %s\n", mychannel->name);
04216
04217
04218
04219 if (myrpt->cmdnode[0])
04220 {
04221 ast_safe_sleep(mychannel,200);
04222 res = telem_lookup(myrpt,mychannel, myrpt->name, "cmdmode");
04223 if(res)
04224 ast_log(LOG_WARNING, "telem_lookup:cmdmode failed on %s\n", mychannel->name);
04225 ast_stopstream(mychannel);
04226 }
04227 }
04228 else if((ct = (char *) ast_variable_retrieve(myrpt->cfg, nodename, "unlinkedct"))){
04229 ct_copy = ast_strdup(ct);
04230 if(ct_copy)
04231 {
04232 res = telem_lookup(myrpt,mychannel, myrpt->name, ct_copy);
04233 ast_free(ct_copy);
04234 }
04235 else
04236 res = -1;
04237 if(res)
04238 ast_log(LOG_WARNING, "telem_lookup:ctx failed on %s\n", mychannel->name);
04239 }
04240 if (hasremote && (!myrpt->cmdnode[0]))
04241 {
04242
04243 ci.chan = 0;
04244 ci.confno = myrpt->conf;
04245 ci.confmode = DAHDI_CONF_CONFANN;
04246
04247 if (ioctl(mychannel->fds[0],DAHDI_SETCONF,&ci) == -1)
04248 {
04249 ast_log(LOG_WARNING, "Unable to set conference mode to Announce\n");
04250 rpt_mutex_lock(&myrpt->lock);
04251 myrpt->active_telem = NULL;
04252 remque((struct qelem *)mytele);
04253 rpt_mutex_unlock(&myrpt->lock);
04254 ast_log(LOG_NOTICE,"Telemetry thread aborted at line %d, mode: %d\n",__LINE__, mytele->mode);
04255 ast_free(nodename);
04256 ast_free(ident);
04257 ast_free(mytele);
04258 ast_hangup(mychannel);
04259 pthread_exit(NULL);
04260 }
04261 if((ct = (char *) ast_variable_retrieve(myrpt->cfg, nodename, "remotect"))){
04262 ast_safe_sleep(mychannel,200);
04263 ct_copy = ast_strdup(ct);
04264 if(ct_copy)
04265 {
04266 res = telem_lookup(myrpt,mychannel, myrpt->name, ct_copy);
04267 ast_free(ct_copy);
04268 }
04269 else
04270 res = -1;
04271
04272 if(res)
04273 ast_log(LOG_WARNING, "telem_lookup:ctx failed on %s\n", mychannel->name);
04274 }
04275 }
04276 #if defined(_MDC_DECODE_H_) && defined(MDC_SAY_WHEN_DOING_CT)
04277 if (myrpt->lastunit)
04278 {
04279 char mystr[10];
04280
04281 ast_safe_sleep(mychannel,200);
04282
04283 ci.chan = 0;
04284 ci.confno = myrpt->txconf;
04285 ci.confmode = DAHDI_CONF_CONFANN;
04286
04287 if (ioctl(mychannel->fds[0],DAHDI_SETCONF,&ci) == -1)
04288 {
04289 ast_log(LOG_WARNING, "Unable to set conference mode to Announce\n");
04290 rpt_mutex_lock(&myrpt->lock);
04291 myrpt->active_telem = NULL;
04292 remque((struct qelem *)mytele);
04293 rpt_mutex_unlock(&myrpt->lock);
04294 ast_log(LOG_NOTICE,"Telemetry thread aborted at line %d, mode: %d\n",__LINE__, mytele->mode);
04295 ast_free(nodename);
04296 ast_free(ident);
04297 ast_free(mytele);
04298 ast_hangup(mychannel);
04299 pthread_exit(NULL);
04300 }
04301 sprintf(mystr,"%04x",myrpt->lastunit);
04302 myrpt->lastunit = 0;
04303 ast_say_character_str(mychannel,mystr,NULL,mychannel->language);
04304 break;
04305 }
04306 #endif
04307 imdone = 1;
04308 break;
04309 case LINKUNKEY:
04310 if(myrpt->patchnoct && myrpt->callmode){
04311 imdone = 1;
04312 break;
04313 }
04314
04315
04316
04317
04318
04319 x = get_wait_interval(myrpt, DLY_LINKUNKEY);
04320 mytele->mylink.linkunkeytocttimer = x;
04321
04322
04323
04324
04325
04326 tlist = myrpt->tele.next;
04327 unkeys_queued = 0;
04328 if (tlist != &myrpt->tele)
04329 {
04330 rpt_mutex_lock(&myrpt->lock);
04331 while(tlist != &myrpt->tele){
04332 if (tlist->mode == LINKUNKEY) unkeys_queued++;
04333 tlist = tlist->next;
04334 }
04335 rpt_mutex_unlock(&myrpt->lock);
04336 }
04337 if( unkeys_queued > 1){
04338 imdone = 1;
04339 break;
04340 }
04341
04342
04343
04344 while(mytele->mylink.linkunkeytocttimer)
04345 {
04346 int ctint;
04347 if(mytele->mylink.linkunkeytocttimer > 100)
04348 ctint = 100;
04349 else
04350 ctint = mytele->mylink.linkunkeytocttimer;
04351 ast_safe_sleep(mychannel, ctint);
04352 rpt_mutex_lock(&myrpt->lock);
04353 if(mytele->mylink.linkunkeytocttimer < ctint)
04354 mytele->mylink.linkunkeytocttimer = 0;
04355 else
04356 mytele->mylink.linkunkeytocttimer -= ctint;
04357 rpt_mutex_unlock(&myrpt->lock);
04358 }
04359
04360 if((ct = (char *) ast_variable_retrieve(myrpt->cfg, nodename, "linkunkeyct"))){
04361 ct_copy = ast_strdup(ct);
04362 if(ct_copy){
04363 res = telem_lookup(myrpt,mychannel, myrpt->name, ct_copy);
04364 ast_free(ct_copy);
04365 }
04366 else
04367 res = -1;
04368 if(res)
04369 ast_log(LOG_WARNING, "telem_lookup:ctx failed on %s\n", mychannel->name);
04370 }
04371 imdone = 1;
04372 break;
04373 case REMDISC:
04374
04375 wait_interval(myrpt, DLY_TELEM, mychannel);
04376 l = myrpt->links.next;
04377 haslink = 0;
04378
04379 if (l != &myrpt->links)
04380 {
04381 rpt_mutex_lock(&myrpt->lock);
04382 while(l != &myrpt->links)
04383 {
04384 if (l->name[0] == '0')
04385 {
04386 l = l->next;
04387 continue;
04388 }
04389 if (!strcmp(l->name,mytele->mylink.name))
04390 {
04391 haslink = 1;
04392 break;
04393 }
04394 l = l->next;
04395 }
04396 rpt_mutex_unlock(&myrpt->lock);
04397 }
04398 if (haslink)
04399 {
04400 imdone = 1;
04401 break;
04402 }
04403 res = saynode(myrpt,mychannel,mytele->mylink.name);
04404 if (!res)
04405 res = ast_streamfile(mychannel, ((mytele->mylink.hasconnected) ?
04406 "rpt/remote_disc" : "rpt/remote_busy"), mychannel->language);
04407 break;
04408 case REMALREADY:
04409
04410 wait_interval(myrpt, DLY_TELEM, mychannel);
04411 res = ast_streamfile(mychannel, "rpt/remote_already", mychannel->language);
04412 break;
04413 case REMNOTFOUND:
04414
04415 wait_interval(myrpt, DLY_TELEM, mychannel);
04416 res = ast_streamfile(mychannel, "rpt/remote_notfound", mychannel->language);
04417 break;
04418 case REMGO:
04419
04420 wait_interval(myrpt, DLY_TELEM, mychannel);
04421 res = ast_streamfile(mychannel, "rpt/remote_go", mychannel->language);
04422 break;
04423 case CONNECTED:
04424
04425 wait_interval(myrpt, DLY_TELEM, mychannel);
04426 res = saynode(myrpt,mychannel,mytele->mylink.name);
04427 if (!res)
04428 res = ast_streamfile(mychannel, "rpt/connected", mychannel->language);
04429 if (!res)
04430 res = ast_waitstream(mychannel, "");
04431 else
04432 ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", mychannel->name);
04433 ast_stopstream(mychannel);
04434 res = ast_streamfile(mychannel, "digits/2", mychannel->language);
04435 if (!res)
04436 res = ast_waitstream(mychannel, "");
04437 else
04438 ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", mychannel->name);
04439 ast_stopstream(mychannel);
04440 res = saynode(myrpt,mychannel,myrpt->name);
04441 imdone = 1;
04442 break;
04443 case CONNFAIL:
04444 res = saynode(myrpt,mychannel,mytele->mylink.name);
04445 if (!res)
04446 res = ast_streamfile(mychannel, "rpt/connection_failed", mychannel->language);
04447 break;
04448 case MEMNOTFOUND:
04449
04450 wait_interval(myrpt, DLY_TELEM, mychannel);
04451 res = ast_streamfile(mychannel, "rpt/memory_notfound", mychannel->language);
04452 break;
04453 case PLAYBACK:
04454
04455 wait_interval(myrpt, DLY_TELEM, mychannel);
04456 res = ast_streamfile(mychannel, mytele->param, mychannel->language);
04457 break;
04458 case TOPKEY:
04459
04460 wait_interval(myrpt, DLY_TELEM, mychannel);
04461 for(i = 0; i < TOPKEYN; i++)
04462 {
04463 if (!myrpt->topkey[i].node[0]) continue;
04464 if ((!myrpt->topkeylong) && (myrpt->topkey[i].keyed)) continue;
04465 res = saynode(myrpt, mychannel, myrpt->topkey[i].node);
04466 if (!res) res = sayfile(mychannel,(myrpt->topkey[i].keyed) ?
04467 "rpt/keyedfor" : "rpt/unkeyedfor");
04468 if (!res) res = saynum(mychannel,
04469 myrpt->topkey[i].timesince);
04470 if (!res) res = sayfile(mychannel,"rpt/seconds");
04471 if (!myrpt->topkeylong) break;
04472 }
04473 imdone = 1;
04474 break;
04475 case SETREMOTE:
04476 ast_mutex_lock(&myrpt->remlock);
04477 res = 0;
04478 if(!strcmp(myrpt->remoterig, remote_rig_ft897))
04479 {
04480 res = set_ft897(myrpt);
04481 }
04482 else if(!strcmp(myrpt->remoterig, remote_rig_tm271))
04483 {
04484 res = set_tm271(myrpt);
04485 }
04486 else if(!strcmp(myrpt->remoterig, remote_rig_ic706))
04487 {
04488 res = set_ic706(myrpt);
04489 }
04490 #ifdef HAVE_IOPERM
04491 else if(!strcmp(myrpt->remoterig, remote_rig_rbi)||!strcmp(myrpt->remoterig, remote_rig_ppp16))
04492 {
04493 if (ioperm(myrpt->p.iobase,1,1) == -1)
04494 {
04495 rpt_mutex_unlock(&myrpt->lock);
04496 ast_log(LOG_WARNING, "Cant get io permission on IO port %x hex\n",myrpt->p.iobase);
04497 res = -1;
04498 }
04499 else res = setrbi(myrpt);
04500 }
04501 #endif
04502 else if(!strcmp(myrpt->remoterig, remote_rig_kenwood))
04503 {
04504 if (myrpt->iofd >= 0) setdtr(myrpt->iofd,1);
04505 res = setkenwood(myrpt);
04506 if (myrpt->iofd >= 0) setdtr(myrpt->iofd,0);
04507 if (ast_safe_sleep(mychannel,200) == -1)
04508 {
04509 ast_mutex_unlock(&myrpt->remlock);
04510 res = -1;
04511 break;
04512 }
04513 if (myrpt->iofd < 0)
04514 {
04515 i = DAHDI_FLUSH_EVENT;
04516 if (ioctl(myrpt->dahditxchannel->fds[0],DAHDI_FLUSH,&i) == -1)
04517 {
04518 ast_mutex_unlock(&myrpt->remlock);
04519 ast_log(LOG_ERROR,"Cant flush events");
04520 res = -1;
04521 break;
04522 }
04523 if (ioctl(myrpt->dahdirxchannel->fds[0],DAHDI_GET_PARAMS,&par) == -1)
04524 {
04525 ast_mutex_unlock(&myrpt->remlock);
04526 ast_log(LOG_ERROR,"Cant get params");
04527 res = -1;
04528 break;
04529 }
04530 myrpt->remoterx =
04531 (par.rxisoffhook || (myrpt->tele.next != &myrpt->tele));
04532 }
04533 }
04534
04535 ast_mutex_unlock(&myrpt->remlock);
04536 if (!res)
04537 {
04538 imdone = 1;
04539 break;
04540 }
04541
04542 case INVFREQ:
04543
04544 wait_interval(myrpt, DLY_TELEM, mychannel);
04545 res = ast_streamfile(mychannel, "rpt/invalid-freq", mychannel->language);
04546 break;
04547 case REMMODE:
04548 cp = 0;
04549 wait_interval(myrpt, DLY_TELEM, mychannel);
04550 switch(myrpt->remmode)
04551 {
04552 case REM_MODE_FM:
04553 saycharstr(mychannel,"FM");
04554 break;
04555 case REM_MODE_USB:
04556 saycharstr(mychannel,"USB");
04557 break;
04558 case REM_MODE_LSB:
04559 saycharstr(mychannel,"LSB");
04560 break;
04561 case REM_MODE_AM:
04562 saycharstr(mychannel,"AM");
04563 break;
04564 }
04565 wait_interval(myrpt, DLY_COMP, mychannel);
04566 if (!res) res = telem_lookup(myrpt,mychannel, myrpt->name, "functcomplete");
04567 break;
04568 case LOGINREQ:
04569 wait_interval(myrpt, DLY_TELEM, mychannel);
04570 sayfile(mychannel,"rpt/login");
04571 saycharstr(mychannel,myrpt->name);
04572 break;
04573 case REMLOGIN:
04574 wait_interval(myrpt, DLY_TELEM, mychannel);
04575 saycharstr(mychannel,myrpt->loginuser);
04576 saynode(myrpt,mychannel,myrpt->name);
04577 wait_interval(myrpt, DLY_COMP, mychannel);
04578 if (!res) res = telem_lookup(myrpt,mychannel, myrpt->name, "functcomplete");
04579 break;
04580 case REMXXX:
04581 wait_interval(myrpt, DLY_TELEM, mychannel);
04582 res = 0;
04583 switch(mytele->submode)
04584 {
04585 case 100:
04586 sayfile(mychannel, "rpt/rxpl");
04587 sayfile(mychannel, "rpt/off");
04588 break;
04589 case 101:
04590 sayfile(mychannel, "rpt/rxpl");
04591 sayfile(mychannel, "rpt/on");
04592 break;
04593 case 102:
04594 sayfile(mychannel, "rpt/txpl");
04595 sayfile(mychannel, "rpt/off");
04596 break;
04597 case 103:
04598 sayfile(mychannel, "rpt/txpl");
04599 sayfile(mychannel, "rpt/on");
04600 break;
04601 case 104:
04602 sayfile(mychannel, "rpt/lopwr");
04603 break;
04604 case 105:
04605 sayfile(mychannel, "rpt/medpwr");
04606 break;
04607 case 106:
04608 sayfile(mychannel, "rpt/hipwr");
04609 break;
04610 case 113:
04611 sayfile(mychannel,"rpt/down");
04612 sayfile(mychannel, "rpt/slow");
04613 break;
04614 case 114:
04615 sayfile(mychannel,"rpt/down");
04616 sayfile(mychannel, "rpt/quick");
04617 break;
04618 case 115:
04619 sayfile(mychannel,"rpt/down");
04620 sayfile(mychannel, "rpt/fast");
04621 break;
04622 case 116:
04623 sayfile(mychannel,"rpt/up");
04624 sayfile(mychannel, "rpt/slow");
04625 break;
04626 case 117:
04627 sayfile(mychannel,"rpt/up");
04628 sayfile(mychannel, "rpt/quick");
04629 break;
04630 case 118:
04631 sayfile(mychannel,"rpt/up");
04632 sayfile(mychannel, "rpt/fast");
04633 break;
04634 default:
04635 res = -1;
04636 }
04637 wait_interval(myrpt, DLY_COMP, mychannel);
04638 if (!res) res = telem_lookup(myrpt,mychannel, myrpt->name, "functcomplete");
04639 break;
04640 case SCAN:
04641 ast_mutex_lock(&myrpt->remlock);
04642 if (myrpt->hfscanstop)
04643 {
04644 myrpt->hfscanstatus = 0;
04645 myrpt->hfscanmode = 0;
04646 myrpt->hfscanstop = 0;
04647 mytele->mode = SCANSTAT;
04648 ast_mutex_unlock(&myrpt->remlock);
04649 if (ast_safe_sleep(mychannel,1000) == -1) break;
04650 sayfile(mychannel, "rpt/stop");
04651 imdone = 1;
04652 break;
04653 }
04654 if (myrpt->hfscanstatus > -2) service_scan(myrpt);
04655 i = myrpt->hfscanstatus;
04656 myrpt->hfscanstatus = 0;
04657 if (i) mytele->mode = SCANSTAT;
04658 ast_mutex_unlock(&myrpt->remlock);
04659 if (i < 0) sayfile(mychannel, "rpt/stop");
04660 else if (i > 0) saynum(mychannel,i);
04661 imdone = 1;
04662 break;
04663 case TUNE:
04664 ast_mutex_lock(&myrpt->remlock);
04665 if (!strcmp(myrpt->remoterig,remote_rig_ic706))
04666 {
04667 set_mode_ic706(myrpt, REM_MODE_AM);
04668 if(play_tone(mychannel, 800, 6000, 8192) == -1) break;
04669 ast_safe_sleep(mychannel,500);
04670 set_mode_ic706(myrpt, myrpt->remmode);
04671 myrpt->tunerequest = 0;
04672 ast_mutex_unlock(&myrpt->remlock);
04673 imdone = 1;
04674 break;
04675 }
04676 set_mode_ft897(myrpt, REM_MODE_AM);
04677 simple_command_ft897(myrpt, 8);
04678 if(play_tone(mychannel, 800, 6000, 8192) == -1) break;
04679 simple_command_ft897(myrpt, 0x88);
04680 ast_safe_sleep(mychannel,500);
04681 set_mode_ft897(myrpt, myrpt->remmode);
04682 myrpt->tunerequest = 0;
04683 ast_mutex_unlock(&myrpt->remlock);
04684 imdone = 1;
04685 break;
04686 case REMSHORTSTATUS:
04687 case REMLONGSTATUS:
04688 wait_interval(myrpt, DLY_TELEM, mychannel);
04689 res = saynode(myrpt,mychannel,myrpt->name);
04690 if(!res)
04691 res = sayfile(mychannel,"rpt/frequency");
04692 if(!res)
04693 res = split_freq(mhz, decimals, myrpt->freq);
04694 if (!multimode_capable(myrpt)) decimals[3] = 0;
04695 if(!res){
04696 m = atoi(mhz);
04697 if(m < 100)
04698 res = saynum(mychannel, m);
04699 else
04700 res = saycharstr(mychannel, mhz);
04701 }
04702 if(!res)
04703 res = sayfile(mychannel, "letters/dot");
04704 if(!res)
04705 res = saycharstr(mychannel, decimals);
04706
04707 if(res) break;
04708 if(myrpt->remmode == REM_MODE_FM){
04709 switch(myrpt->offset){
04710
04711 case REM_MINUS:
04712 res = sayfile(mychannel,"rpt/minus");
04713 break;
04714
04715 case REM_SIMPLEX:
04716 res = sayfile(mychannel,"rpt/simplex");
04717 break;
04718
04719 case REM_PLUS:
04720 res = sayfile(mychannel,"rpt/plus");
04721 break;
04722
04723 default:
04724 break;
04725 }
04726 }
04727 else{
04728 switch(myrpt->remmode){
04729
04730 case REM_MODE_USB:
04731 res = saycharstr(mychannel, "USB");
04732 break;
04733
04734 case REM_MODE_LSB:
04735 res = saycharstr(mychannel, "LSB");
04736 break;
04737
04738 case REM_MODE_AM:
04739 res = saycharstr(mychannel, "AM");
04740 break;
04741
04742
04743 default:
04744 break;
04745 }
04746 }
04747
04748 if (res == -1) break;
04749
04750 if(mytele->mode == REMSHORTSTATUS){
04751 wait_interval(myrpt, DLY_COMP, mychannel);
04752 if (!res) res = telem_lookup(myrpt,mychannel, myrpt->name, "functcomplete");
04753 break;
04754 }
04755
04756 if (strcmp(myrpt->remoterig,remote_rig_ic706))
04757 {
04758 switch(myrpt->powerlevel){
04759
04760 case REM_LOWPWR:
04761 res = sayfile(mychannel,"rpt/lopwr") ;
04762 break;
04763 case REM_MEDPWR:
04764 res = sayfile(mychannel,"rpt/medpwr");
04765 break;
04766 case REM_HIPWR:
04767 res = sayfile(mychannel,"rpt/hipwr");
04768 break;
04769 }
04770 }
04771
04772 rbimode = ((!strncmp(myrpt->remoterig,remote_rig_rbi,3))
04773 || (!strncmp(myrpt->remoterig,remote_rig_ic706,3)));
04774 if (res || (sayfile(mychannel,"rpt/rxpl") == -1)) break;
04775 if (rbimode && (sayfile(mychannel,"rpt/txpl") == -1)) break;
04776 if ((sayfile(mychannel,"rpt/frequency") == -1) ||
04777 (saycharstr(mychannel,myrpt->rxpl) == -1)) break;
04778 if ((!rbimode) && ((sayfile(mychannel,"rpt/txpl") == -1) ||
04779 (sayfile(mychannel,"rpt/frequency") == -1) ||
04780 (saycharstr(mychannel,myrpt->txpl) == -1))) break;
04781 if(myrpt->remmode == REM_MODE_FM){
04782 if ((sayfile(mychannel,"rpt/rxpl") == -1) ||
04783 (sayfile(mychannel,((myrpt->rxplon) ? "rpt/on" : "rpt/off")) == -1) ||
04784 (sayfile(mychannel,"rpt/txpl") == -1) ||
04785 (sayfile(mychannel,((myrpt->txplon) ? "rpt/on" : "rpt/off")) == -1))
04786 {
04787 break;
04788 }
04789 }
04790 wait_interval(myrpt, DLY_COMP, mychannel);
04791 if (!res) res = telem_lookup(myrpt,mychannel, myrpt->name, "functcomplete");
04792 break;
04793 case STATUS:
04794
04795 wait_interval(myrpt, DLY_TELEM, mychannel);
04796 hastx = 0;
04797 linkbase.next = &linkbase;
04798 linkbase.prev = &linkbase;
04799 rpt_mutex_lock(&myrpt->lock);
04800
04801 l = myrpt->links.next;
04802 while(l != &myrpt->links)
04803 {
04804 if (l->name[0] == '0')
04805 {
04806 l = l->next;
04807 continue;
04808 }
04809 l1 = ast_malloc(sizeof(struct rpt_link));
04810 if (!l1)
04811 {
04812 ast_log(LOG_WARNING, "Cannot alloc memory on %s\n", mychannel->name);
04813 remque((struct qelem *)mytele);
04814 myrpt->active_telem = NULL;
04815 rpt_mutex_unlock(&myrpt->lock);
04816 ast_log(LOG_NOTICE,"Telemetry thread aborted at line %d, mode: %d\n",__LINE__, mytele->mode);
04817 ast_free(nodename);
04818 ast_free(ident);
04819 ast_free(mytele);
04820 ast_hangup(mychannel);
04821 pthread_exit(NULL);
04822 }
04823 memcpy(l1,l,sizeof(struct rpt_link));
04824 l1->next = l1->prev = NULL;
04825 insque((struct qelem *)l1,(struct qelem *)linkbase.next);
04826 l = l->next;
04827 }
04828 rpt_mutex_unlock(&myrpt->lock);
04829 res = saynode(myrpt,mychannel,myrpt->name);
04830 if (myrpt->callmode)
04831 {
04832 hastx = 1;
04833 res = ast_streamfile(mychannel, "rpt/autopatch_on", mychannel->language);
04834 if (!res)
04835 res = ast_waitstream(mychannel, "");
04836 else
04837 ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", mychannel->name);
04838 ast_stopstream(mychannel);
04839 }
04840 l = linkbase.next;
04841 while(l != &linkbase)
04842 {
04843 char *s;
04844
04845 hastx = 1;
04846 res = saynode(myrpt,mychannel,l->name);
04847 s = "rpt/tranceive";
04848 if (!l->mode) s = "rpt/monitor";
04849 if (!l->thisconnected) s = "rpt/connecting";
04850 res = ast_streamfile(mychannel, s, mychannel->language);
04851 if (!res)
04852 res = ast_waitstream(mychannel, "");
04853 else
04854 ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", mychannel->name);
04855 ast_stopstream(mychannel);
04856 l = l->next;
04857 }
04858 if (!hastx)
04859 {
04860 res = ast_streamfile(mychannel, "rpt/repeat_only", mychannel->language);
04861 if (!res)
04862 res = ast_waitstream(mychannel, "");
04863 else
04864 ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", mychannel->name);
04865 ast_stopstream(mychannel);
04866 }
04867
04868 l = linkbase.next;
04869 while(l != &linkbase)
04870 {
04871 l1 = l;
04872 l = l->next;
04873 remque((struct qelem *)l1);
04874 ast_free(l1);
04875 }
04876 imdone = 1;
04877 break;
04878 case FULLSTATUS:
04879 rpt_mutex_lock(&myrpt->lock);
04880
04881 __mklinklist(myrpt,NULL,lbuf);
04882 rpt_mutex_unlock(&myrpt->lock);
04883
04884 ns = finddelim(lbuf,strs,MAXLINKLIST);
04885
04886 if (ns) qsort((void *)strs,ns,sizeof(char *),mycompar);
04887
04888 wait_interval(myrpt, DLY_TELEM, mychannel);
04889 hastx = 0;
04890 res = saynode(myrpt,mychannel,myrpt->name);
04891 if (myrpt->callmode)
04892 {
04893 hastx = 1;
04894 res = ast_streamfile(mychannel, "rpt/autopatch_on", mychannel->language);
04895 if (!res)
04896 res = ast_waitstream(mychannel, "");
04897 else
04898 ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", mychannel->name);
04899 ast_stopstream(mychannel);
04900 }
04901
04902 for(i = 0; i < ns; i++)
04903 {
04904 char *s,mode = 'T';
04905
04906
04907 if ((*strs[i] < '0') || (*strs[i] > '9'))
04908 {
04909 mode = *strs[i];
04910 strs[i]++;
04911 }
04912
04913 hastx = 1;
04914 res = saynode(myrpt,mychannel,strs[i]);
04915 s = "rpt/tranceive";
04916 if (mode == 'R') s = "rpt/monitor";
04917 if (mode == 'C') s = "rpt/connecting";
04918 res = ast_streamfile(mychannel, s, mychannel->language);
04919 if (!res)
04920 res = ast_waitstream(mychannel, "");
04921 else
04922 ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", mychannel->name);
04923 ast_stopstream(mychannel);
04924 }
04925 if (!hastx)
04926 {
04927 res = ast_streamfile(mychannel, "rpt/repeat_only", mychannel->language);
04928 if (!res)
04929 res = ast_waitstream(mychannel, "");
04930 else
04931 ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", mychannel->name);
04932 ast_stopstream(mychannel);
04933 }
04934 imdone = 1;
04935 break;
04936
04937 case LASTNODEKEY:
04938 rpt_mutex_lock(&myrpt->lock);
04939 if(myrpt->lastnodewhichkeyedusup){
04940 p = ast_strdup(myrpt->lastnodewhichkeyedusup);
04941 if(!p){
04942 ast_log(LOG_WARNING, "ast_strdup failed in telemetery LASTNODEKEY");
04943 imdone = 1;
04944 break;
04945 }
04946 }
04947 else
04948 p = NULL;
04949 rpt_mutex_unlock(&myrpt->lock);
04950 if(!p){
04951 imdone = 1;
04952 break;
04953 }
04954 wait_interval(myrpt, DLY_TELEM, mychannel);
04955 res = saynode(myrpt,mychannel,p);
04956 ast_free(p);
04957 imdone = 1;
04958 break;
04959
04960 case UNAUTHTX:
04961 wait_interval(myrpt, DLY_TELEM, mychannel);
04962 res = ast_streamfile(mychannel, "rpt/unauthtx", mychannel->language);
04963 if (!res)
04964 res = ast_waitstream(mychannel, "");
04965 else
04966 ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", mychannel->name);
04967 ast_stopstream(mychannel);
04968 imdone = 1;
04969 break;
04970
04971 case PARROT:
04972
04973 sprintf(mystr,PARROTFILE,myrpt->name,(unsigned int)mytele->parrot);
04974 if (ast_fileexists(mystr,NULL,mychannel->language) <= 0)
04975 {
04976 imdone = 1;
04977 myrpt->parrotstate = 0;
04978 break;
04979 }
04980 wait_interval(myrpt, DLY_PARROT, mychannel);
04981 sprintf(mystr,PARROTFILE,myrpt->name,(unsigned int)mytele->parrot);
04982 res = ast_streamfile(mychannel, mystr, mychannel->language);
04983 if (!res)
04984 res = ast_waitstream(mychannel, "");
04985 else
04986 ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", mychannel->name);
04987 ast_stopstream(mychannel);
04988 sprintf(mystr,PARROTFILE,myrpt->name,(unsigned int)mytele->parrot);
04989 strcat(mystr,".wav");
04990 unlink(mystr);
04991 imdone = 1;
04992 myrpt->parrotstate = 0;
04993 break;
04994
04995 case TIMEOUT:
04996 res = saynode(myrpt,mychannel,myrpt->name);
04997 if (!res)
04998 res = ast_streamfile(mychannel, "rpt/timeout", mychannel->language);
04999 break;
05000
05001 case TIMEOUT_WARNING:
05002 time(&t);
05003 res = saynode(myrpt,mychannel,myrpt->name);
05004 if (!res)
05005 res = ast_streamfile(mychannel, "rpt/timeout-warning", mychannel->language);
05006 if (!res)
05007 res = ast_waitstream(mychannel, "");
05008 else
05009 ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", mychannel->name);
05010 ast_stopstream(mychannel);
05011 if(!res)
05012 ast_say_number(mychannel, myrpt->p.remotetimeout -
05013 (t - myrpt->last_activity_time),
05014 "", mychannel->language, (char *) NULL);
05015 if (!res)
05016 res = ast_waitstream(mychannel, "");
05017 ast_stopstream(mychannel);
05018 res = ast_streamfile(mychannel, "queue-seconds", mychannel->language);
05019 break;
05020
05021 case ACT_TIMEOUT_WARNING:
05022 time(&t);
05023 res = saynode(myrpt,mychannel,myrpt->name);
05024 if (!res)
05025 res = ast_streamfile(mychannel, "rpt/act-timeout-warning", mychannel->language);
05026 if (!res)
05027 res = ast_waitstream(mychannel, "");
05028 else
05029 ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", mychannel->name);
05030 ast_stopstream(mychannel);
05031 if(!res)
05032 ast_say_number(mychannel, myrpt->p.remoteinacttimeout -
05033 (t - myrpt->last_activity_time),
05034 "", mychannel->language, (char *) NULL);
05035 if (!res)
05036 res = ast_waitstream(mychannel, "");
05037 ast_stopstream(mychannel);
05038 res = ast_streamfile(mychannel, "queue-seconds", mychannel->language);
05039 break;
05040
05041 case STATS_TIME:
05042 case STATS_TIME_LOCAL:
05043 wait_interval(myrpt, DLY_TELEM, mychannel);
05044 t = time(NULL);
05045 rpt_localtime(&t, &localtm);
05046
05047 if((localtm.tm_hour >= 0) && (localtm.tm_hour < 12))
05048 p = "rpt/goodmorning";
05049 else if((localtm.tm_hour >= 12) && (localtm.tm_hour < 18))
05050 p = "rpt/goodafternoon";
05051 else
05052 p = "rpt/goodevening";
05053 if (sayfile(mychannel,p) == -1)
05054 {
05055 imdone = 1;
05056 break;
05057 }
05058
05059 if (sayfile(mychannel,"rpt/thetimeis") == -1)
05060 {
05061 imdone = 1;
05062 break;
05063 }
05064
05065 res = ast_say_time(mychannel, t, "", mychannel->language);
05066 if (!res)
05067 res = ast_waitstream(mychannel, "");
05068 ast_stopstream(mychannel);
05069 imdone = 1;
05070 break;
05071 case STATS_VERSION:
05072 p = strstr(tdesc, "version");
05073 if(!p)
05074 break;
05075 if(sscanf(p, "version %30d.%30d", &vmajor, &vminor) != 2)
05076 break;
05077 wait_interval(myrpt, DLY_TELEM, mychannel);
05078
05079 if (sayfile(mychannel,"rpt/version") == -1)
05080 {
05081 imdone = 1;
05082 break;
05083 }
05084 if(!res)
05085 ast_say_number(mychannel, vmajor, "", mychannel->language, (char *) NULL);
05086 if (!res)
05087 res = ast_waitstream(mychannel, "");
05088 ast_stopstream(mychannel);
05089 if (saycharstr(mychannel,".") == -1)
05090 {
05091 imdone = 1;
05092 break;
05093 }
05094 if(!res)
05095 ast_say_number(mychannel, vminor, "", mychannel->language, (char *) NULL);
05096 if (!res){
05097 res = ast_waitstream(mychannel, "");
05098 ast_stopstream(mychannel);
05099 }
05100 else
05101 ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", mychannel->name);
05102 imdone = 1;
05103 break;
05104 case ARB_ALPHA:
05105 wait_interval(myrpt, DLY_TELEM, mychannel);
05106 if(mytele->param)
05107 saycharstr(mychannel, mytele->param);
05108 imdone = 1;
05109 break;
05110 case REV_PATCH:
05111 wait_interval(myrpt, DLY_TELEM, mychannel);
05112 if(mytele->param) {
05113
05114
05115 char *tpl_working, *tpl_current;
05116 char *tmp[100], *myparm;
05117 int looptemp=0,idx=0, dres = 0;
05118
05119
05120 tpl_working = ast_strdup(mytele->param);
05121 myparm = strsep(&tpl_working,",");
05122 tpl_current=strsep(&tpl_working, ":");
05123
05124 while(tpl_current && looptemp < sizeof(tmp)) {
05125 tmp[looptemp]=tpl_current;
05126 looptemp++;
05127 tpl_current=strsep(&tpl_working,":");
05128 }
05129
05130 for(idx=0; idx<looptemp; idx++) {
05131 if(!strcmp(tmp[idx], "PARKED")) {
05132 ast_say_digits(mychannel, atoi(myparm), "", mychannel->language);
05133 } else if(!strcmp(tmp[idx], "NODE")) {
05134 ast_say_digits(mychannel, atoi(myrpt->name), "", mychannel->language);
05135 } else {
05136 dres = ast_streamfile(mychannel, tmp[idx], mychannel->language);
05137 if(!dres) {
05138 dres = ast_waitstream(mychannel, "");
05139 } else {
05140 ast_log(LOG_WARNING, "ast_streamfile of %s failed on %s\n", tmp[idx], mychannel->name);
05141 dres = 0;
05142 }
05143 }
05144 }
05145 ast_free(tpl_working);
05146 }
05147 imdone = 1;
05148 break;
05149 case TEST_TONE:
05150 imdone = 1;
05151 if (myrpt->stopgen) break;
05152 myrpt->stopgen = -1;
05153 if ((res = ast_tonepair_start(mychannel, 1004.0, 0, 99999999, 7200.0)))
05154 {
05155 myrpt->stopgen = 0;
05156 break;
05157 }
05158 while(mychannel->generatordata && (myrpt->stopgen <= 0)) {
05159 if (ast_safe_sleep(mychannel,1)) break;
05160 imdone = 1;
05161 }
05162 myrpt->stopgen = 0;
05163 break;
05164 default:
05165 break;
05166 }
05167 if (!imdone)
05168 {
05169 if (!res)
05170 res = ast_waitstream(mychannel, "");
05171 else {
05172 ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", mychannel->name);
05173 res = 0;
05174 }
05175 }
05176 ast_stopstream(mychannel);
05177 rpt_mutex_lock(&myrpt->lock);
05178 if (mytele->mode == TAILMSG)
05179 {
05180 if (!res)
05181 {
05182 myrpt->tailmessagen++;
05183 if(myrpt->tailmessagen >= myrpt->p.tailmessagemax) myrpt->tailmessagen = 0;
05184 }
05185 else
05186 {
05187 myrpt->tmsgtimer = myrpt->p.tailsquashedtime;
05188 }
05189 }
05190 remque((struct qelem *)mytele);
05191 myrpt->active_telem = NULL;
05192 rpt_mutex_unlock(&myrpt->lock);
05193 ast_free(nodename);
05194 ast_free(ident);
05195 ast_free(mytele);
05196 ast_hangup(mychannel);
05197 #ifdef APP_RPT_LOCK_DEBUG
05198 {
05199 struct lockthread *t;
05200
05201 sleep(5);
05202 ast_mutex_lock(&locklock);
05203 t = get_lockthread(pthread_self());
05204 if (t) memset(t,0,sizeof(struct lockthread));
05205 ast_mutex_unlock(&locklock);
05206 }
05207 #endif
05208 pthread_exit(NULL);
05209 }
05210
05211 static void rpt_telemetry(struct rpt *myrpt,int mode, void *data)
05212 {
05213 struct rpt_tele *tele;
05214 struct rpt_link *mylink = NULL;
05215 int res;
05216 pthread_attr_t attr;
05217 char *v1, *v2;
05218
05219 if(debug > 6)
05220 ast_log(LOG_NOTICE,"mode=%i data=%s\n",mode, (char *)data);
05221
05222 switch(mode)
05223 {
05224 case UNKEY:
05225
05226
05227 v1 = (char *) ast_variable_retrieve(myrpt->cfg, myrpt->name,
05228 "unlinkedct");
05229 v2 = (char *) ast_variable_retrieve(myrpt->cfg, myrpt->name,
05230 "remotect");
05231 if (telem_lookup(myrpt,NULL, myrpt->name, "remotemon") &&
05232 telem_lookup(myrpt,NULL, myrpt->name, "remotetx") &&
05233 telem_lookup(myrpt,NULL, myrpt->name, "cmdmode") &&
05234 (!(v1 && telem_lookup(myrpt,NULL, myrpt->name, v1))) &&
05235 (!(v2 && telem_lookup(myrpt,NULL, myrpt->name, v2)))) return;
05236 break;
05237 case LINKUNKEY:
05238 if (!ast_variable_retrieve(myrpt->cfg, myrpt->name, "linkunkeyct"))
05239 return;
05240 break;
05241 default:
05242 break;
05243 }
05244 tele = ast_malloc(sizeof(struct rpt_tele));
05245 if (!tele)
05246 {
05247 ast_log(LOG_WARNING, "Unable to allocate memory\n");
05248 pthread_exit(NULL);
05249 return;
05250 }
05251
05252 memset((char *)tele,0,sizeof(struct rpt_tele));
05253 tele->rpt = myrpt;
05254 tele->mode = mode;
05255 if (mode == PARROT) tele->parrot = (uintptr_t) data;
05256 else mylink = (struct rpt_link *) data;
05257 rpt_mutex_lock(&myrpt->lock);
05258 if((mode == CONNFAIL) || (mode == REMDISC) || (mode == CONNECTED) ||
05259 (mode == LINKUNKEY)){
05260 memset(&tele->mylink,0,sizeof(struct rpt_link));
05261 if (mylink){
05262 memcpy(&tele->mylink,mylink,sizeof(struct rpt_link));
05263 }
05264 }
05265 else if ((mode == ARB_ALPHA) || (mode == REV_PATCH) || (mode == PLAYBACK)) {
05266 strncpy(tele->param, (char *) data, TELEPARAMSIZE - 1);
05267 tele->param[TELEPARAMSIZE - 1] = 0;
05268 }
05269 if (mode == REMXXX) tele->submode = (intptr_t) data;
05270 insque((struct qelem *)tele, (struct qelem *)myrpt->tele.next);
05271 rpt_mutex_unlock(&myrpt->lock);
05272 pthread_attr_init(&attr);
05273 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
05274 res = ast_pthread_create(&tele->threadid,&attr,rpt_tele_thread,(void *) tele);
05275 if(res < 0){
05276 rpt_mutex_lock(&myrpt->lock);
05277 remque((struct qlem *) tele);
05278 rpt_mutex_unlock(&myrpt->lock);
05279 ast_log(LOG_WARNING, "Could not create telemetry thread: %s",strerror(res));
05280 }
05281 return;
05282 }
05283
05284 static void *rpt_call(void *this)
05285 {
05286 struct dahdi_confinfo ci;
05287 struct rpt *myrpt = (struct rpt *)this;
05288 int res;
05289 int stopped,congstarted,dialtimer,lastcidx,aborted;
05290 struct ast_channel *mychannel,*genchannel;
05291
05292 myrpt->mydtmf = 0;
05293
05294 mychannel = ast_request("DAHDI", AST_FORMAT_SLINEAR, NULL, "pseudo", NULL);
05295 if (!mychannel)
05296 {
05297 fprintf(stderr,"rpt:Sorry unable to obtain pseudo channel\n");
05298 pthread_exit(NULL);
05299 }
05300 #ifdef AST_CDR_FLAG_POST_DISABLED
05301 if (mychannel->cdr)
05302 ast_set_flag(mychannel->cdr,AST_CDR_FLAG_POST_DISABLED);
05303 #endif
05304 ci.chan = 0;
05305 ci.confno = myrpt->conf;
05306 #if 0
05307 ci.confmode = DAHDI_CONF_REALANDPSEUDO | DAHDI_CONF_TALKER | DAHDI_CONF_LISTENER
05308 | DAHDI_CONF_PSEUDO_TALKER | DAHDI_CONF_PSEUDO_LISTENER;
05309 #endif
05310 ci.confmode = DAHDI_CONF_CONF | DAHDI_CONF_TALKER | DAHDI_CONF_LISTENER;
05311
05312 if (ioctl(mychannel->fds[0],DAHDI_SETCONF,&ci) == -1)
05313 {
05314 ast_log(LOG_WARNING, "Unable to set conference mode to Announce\n");
05315 ast_hangup(mychannel);
05316 myrpt->callmode = 0;
05317 pthread_exit(NULL);
05318 }
05319
05320 genchannel = ast_request("DAHDI", AST_FORMAT_SLINEAR, NULL, "pseudo", NULL);
05321 if (!genchannel)
05322 {
05323 fprintf(stderr,"rpt:Sorry unable to obtain pseudo channel\n");
05324 ast_hangup(mychannel);
05325 pthread_exit(NULL);
05326 }
05327 #ifdef AST_CDR_FLAG_POST_DISABLED
05328 if (genchannel->cdr)
05329 ast_set_flag(genchannel->cdr,AST_CDR_FLAG_POST_DISABLED);
05330 #endif
05331 ci.chan = 0;
05332 ci.confno = myrpt->conf;
05333 ci.confmode = DAHDI_CONF_REALANDPSEUDO | DAHDI_CONF_TALKER | DAHDI_CONF_LISTENER
05334 | DAHDI_CONF_PSEUDO_TALKER | DAHDI_CONF_PSEUDO_LISTENER;
05335
05336 if (ioctl(genchannel->fds[0],DAHDI_SETCONF,&ci) == -1)
05337 {
05338 ast_log(LOG_WARNING, "Unable to set conference mode to Announce\n");
05339 ast_hangup(mychannel);
05340 ast_hangup(genchannel);
05341 myrpt->callmode = 0;
05342 pthread_exit(NULL);
05343 }
05344 if (myrpt->p.tonezone && (tone_zone_set_zone(mychannel->fds[0],myrpt->p.tonezone) == -1))
05345 {
05346 ast_log(LOG_WARNING, "Unable to set tone zone %s\n",myrpt->p.tonezone);
05347 ast_hangup(mychannel);
05348 ast_hangup(genchannel);
05349 myrpt->callmode = 0;
05350 pthread_exit(NULL);
05351 }
05352 if (myrpt->p.tonezone && (tone_zone_set_zone(genchannel->fds[0],myrpt->p.tonezone) == -1))
05353 {
05354 ast_log(LOG_WARNING, "Unable to set tone zone %s\n",myrpt->p.tonezone);
05355 ast_hangup(mychannel);
05356 ast_hangup(genchannel);
05357 myrpt->callmode = 0;
05358 pthread_exit(NULL);
05359 }
05360
05361 if ((!myrpt->patchquiet) && (tone_zone_play_tone(genchannel->fds[0],DAHDI_TONE_DIALTONE) < 0))
05362 {
05363 ast_log(LOG_WARNING, "Cannot start dialtone\n");
05364 ast_hangup(mychannel);
05365 ast_hangup(genchannel);
05366 myrpt->callmode = 0;
05367 pthread_exit(NULL);
05368 }
05369 stopped = 0;
05370 congstarted = 0;
05371 dialtimer = 0;
05372 lastcidx = 0;
05373 myrpt->calldigittimer = 0;
05374 aborted = 0;
05375
05376 while ((myrpt->callmode == 1) || (myrpt->callmode == 4))
05377 {
05378 if((myrpt->patchdialtime)&&(myrpt->callmode == 1)&&(myrpt->cidx != lastcidx)){
05379 dialtimer = 0;
05380 lastcidx = myrpt->cidx;
05381 }
05382
05383 if((myrpt->patchdialtime)&&(dialtimer >= myrpt->patchdialtime)){
05384 if(debug)
05385 ast_log(LOG_NOTICE, "dialtimer %i > patchdialtime %i\n", dialtimer,myrpt->patchdialtime);
05386 rpt_mutex_lock(&myrpt->lock);
05387 aborted = 1;
05388 myrpt->callmode = 0;
05389 rpt_mutex_unlock(&myrpt->lock);
05390 break;
05391 }
05392
05393 if ((!myrpt->patchquiet) && (!stopped) && (myrpt->callmode == 1) && (myrpt->cidx > 0))
05394 {
05395 stopped = 1;
05396
05397 tone_zone_play_tone(genchannel->fds[0],-1);
05398 }
05399 if (myrpt->callmode == 1)
05400 {
05401 if(myrpt->calldigittimer > PATCH_DIALPLAN_TIMEOUT)
05402 {
05403 myrpt->callmode = 2;
05404 break;
05405 }
05406
05407 if (myrpt->calldigittimer)
05408 myrpt->calldigittimer += MSWAIT;
05409 }
05410 if (myrpt->callmode == 4)
05411 {
05412 if(!congstarted){
05413 congstarted = 1;
05414
05415 tone_zone_play_tone(genchannel->fds[0],DAHDI_TONE_CONGESTION);
05416 }
05417 }
05418 res = ast_safe_sleep(mychannel, MSWAIT);
05419 if (res < 0)
05420 {
05421 if(debug)
05422 ast_log(LOG_NOTICE, "ast_safe_sleep=%i\n", res);
05423 ast_hangup(mychannel);
05424 ast_hangup(genchannel);
05425 rpt_mutex_lock(&myrpt->lock);
05426 myrpt->callmode = 0;
05427 rpt_mutex_unlock(&myrpt->lock);
05428 pthread_exit(NULL);
05429 }
05430 dialtimer += MSWAIT;
05431 }
05432
05433 tone_zone_play_tone(genchannel->fds[0],-1);
05434
05435 if (!myrpt->callmode)
05436 {
05437 if(debug)
05438 ast_log(LOG_NOTICE, "callmode==0\n");
05439 ast_hangup(mychannel);
05440 ast_hangup(genchannel);
05441 rpt_mutex_lock(&myrpt->lock);
05442 myrpt->callmode = 0;
05443 myrpt->macropatch=0;
05444 channel_revert(myrpt);
05445 rpt_mutex_unlock(&myrpt->lock);
05446 if((!myrpt->patchquiet) && aborted)
05447 rpt_telemetry(myrpt, TERM, NULL);
05448 pthread_exit(NULL);
05449 }
05450
05451 if (myrpt->p.ourcallerid && *myrpt->p.ourcallerid){
05452 char *name, *loc, *instr;
05453 instr = ast_strdup(myrpt->p.ourcallerid);
05454 if(instr){
05455 ast_callerid_parse(instr, &name, &loc);
05456 if(loc){
05457 mychannel->caller.id.number.valid = 1;
05458 ast_free(mychannel->caller.id.number.str);
05459 mychannel->caller.id.number.str = ast_strdup(loc);
05460 }
05461 if(name){
05462 mychannel->caller.id.name.valid = 1;
05463 ast_free(mychannel->caller.id.name.str);
05464 mychannel->caller.id.name.str = ast_strdup(name);
05465 }
05466 ast_free(instr);
05467 }
05468 }
05469
05470 ast_copy_string(mychannel->exten, myrpt->exten, sizeof(mychannel->exten) - 1);
05471 ast_copy_string(mychannel->context, myrpt->patchcontext, sizeof(mychannel->context) - 1);
05472
05473 if (myrpt->p.acctcode)
05474 ast_cdr_setaccount(mychannel,myrpt->p.acctcode);
05475 mychannel->priority = 1;
05476 ast_channel_undefer_dtmf(mychannel);
05477 if (ast_pbx_start(mychannel) < 0)
05478 {
05479 ast_log(LOG_WARNING, "Unable to start PBX!!\n");
05480 ast_hangup(mychannel);
05481 ast_hangup(genchannel);
05482 rpt_mutex_lock(&myrpt->lock);
05483 myrpt->callmode = 0;
05484 rpt_mutex_unlock(&myrpt->lock);
05485 pthread_exit(NULL);
05486 }
05487 usleep(10000);
05488 rpt_mutex_lock(&myrpt->lock);
05489 myrpt->callmode = 3;
05490
05491 ci.chan = 0;
05492 ci.confno = myrpt->conf;
05493 ci.confmode = (myrpt->p.duplex == 2) ? DAHDI_CONF_CONFANNMON :
05494 (DAHDI_CONF_CONF | DAHDI_CONF_LISTENER | DAHDI_CONF_TALKER);
05495
05496 if (ioctl(myrpt->pchannel->fds[0],DAHDI_SETCONF,&ci) == -1)
05497 {
05498 ast_log(LOG_WARNING, "Unable to set conference mode to Announce\n");
05499 ast_hangup(mychannel);
05500 ast_hangup(genchannel);
05501 myrpt->callmode = 0;
05502 pthread_exit(NULL);
05503 }
05504
05505 if (ioctl(mychannel->fds[0],DAHDI_CHANNO,&res) == -1)
05506 {
05507 ast_log(LOG_WARNING, "Unable to get autopatch channel number\n");
05508 ast_hangup(mychannel);
05509 myrpt->callmode = 0;
05510 pthread_exit(NULL);
05511 }
05512 ci.chan = 0;
05513 ci.confno = res;
05514 ci.confmode = DAHDI_CONF_MONITOR;
05515
05516 if (ioctl(myrpt->voxchannel->fds[0],DAHDI_SETCONF,&ci) == -1)
05517 {
05518 ast_log(LOG_WARNING, "Unable to set conference mode to Announce\n");
05519 ast_hangup(mychannel);
05520 myrpt->callmode = 0;
05521 pthread_exit(NULL);
05522 }
05523 while(myrpt->callmode)
05524 {
05525 if ((!mychannel->pbx) && (myrpt->callmode != 4))
05526 {
05527
05528 if(myrpt->patchfarenddisconnect || (myrpt->p.duplex < 2)){
05529 if(debug)ast_log(LOG_NOTICE,"callmode=%i, patchfarenddisconnect=%i, duplex=%i\n",\
05530 myrpt->callmode,myrpt->patchfarenddisconnect,myrpt->p.duplex);
05531 myrpt->callmode = 0;
05532 myrpt->macropatch=0;
05533 if(!myrpt->patchquiet){
05534 rpt_mutex_unlock(&myrpt->lock);
05535 rpt_telemetry(myrpt, TERM, NULL);
05536 rpt_mutex_lock(&myrpt->lock);
05537 }
05538 }
05539 else{
05540 myrpt->callmode = 4;
05541 rpt_mutex_unlock(&myrpt->lock);
05542
05543 tone_zone_play_tone(genchannel->fds[0],DAHDI_TONE_CONGESTION);
05544 rpt_mutex_lock(&myrpt->lock);
05545 }
05546 }
05547 if (myrpt->mydtmf)
05548 {
05549 struct ast_frame wf = {AST_FRAME_DTMF, } ;
05550 wf.subclass.integer = myrpt->mydtmf;
05551 rpt_mutex_unlock(&myrpt->lock);
05552 ast_queue_frame(mychannel,&wf);
05553 #ifdef NEW_ASTERISK
05554 ast_senddigit(genchannel,myrpt->mydtmf,0);
05555 #else
05556 ast_senddigit(genchannel,myrpt->mydtmf);
05557 #endif
05558 rpt_mutex_lock(&myrpt->lock);
05559 myrpt->mydtmf = 0;
05560 }
05561 rpt_mutex_unlock(&myrpt->lock);
05562 usleep(MSWAIT * 1000);
05563 rpt_mutex_lock(&myrpt->lock);
05564 }
05565 if(debug)
05566 ast_log(LOG_NOTICE, "exit channel loop\n");
05567 rpt_mutex_unlock(&myrpt->lock);
05568 tone_zone_play_tone(genchannel->fds[0],-1);
05569 if (mychannel->pbx) ast_softhangup(mychannel,AST_SOFTHANGUP_DEV);
05570 ast_hangup(genchannel);
05571 rpt_mutex_lock(&myrpt->lock);
05572 myrpt->callmode = 0;
05573 myrpt->macropatch=0;
05574 channel_revert(myrpt);
05575 rpt_mutex_unlock(&myrpt->lock);
05576
05577 ci.chan = 0;
05578 ci.confno = myrpt->conf;
05579 ci.confmode = ((myrpt->p.duplex == 2) || (myrpt->p.duplex == 4)) ? DAHDI_CONF_CONFANNMON :
05580 (DAHDI_CONF_CONF | DAHDI_CONF_LISTENER | DAHDI_CONF_TALKER);
05581
05582 if (ioctl(myrpt->pchannel->fds[0],DAHDI_SETCONF,&ci) == -1)
05583 {
05584 ast_log(LOG_WARNING, "Unable to set conference mode to Announce\n");
05585 }
05586 pthread_exit(NULL);
05587 }
05588
05589 static void send_link_dtmf(struct rpt *myrpt,char c)
05590 {
05591 char str[300];
05592 struct ast_frame wf;
05593 struct rpt_link *l;
05594
05595 snprintf(str, sizeof(str), "D %s %s %d %c", myrpt->cmdnode, myrpt->name, ++(myrpt->dtmfidx), c);
05596 wf.frametype = AST_FRAME_TEXT;
05597 wf.subclass.integer = 0;
05598 wf.offset = 0;
05599 wf.mallocd = 0;
05600 wf.datalen = strlen(str) + 1;
05601 wf.samples = 0;
05602 l = myrpt->links.next;
05603
05604 while(l != &myrpt->links)
05605 {
05606 if (l->name[0] == '0')
05607 {
05608 l = l->next;
05609 continue;
05610 }
05611
05612 if (!strcmp(l->name,myrpt->cmdnode))
05613 {
05614 wf.data.ptr = str;
05615 if (l->chan) ast_write(l->chan,&wf);
05616 return;
05617 }
05618 l = l->next;
05619 }
05620 l = myrpt->links.next;
05621
05622 while(l != &myrpt->links)
05623 {
05624 wf.data.ptr = str;
05625 if (l->chan) ast_write(l->chan,&wf);
05626 l = l->next;
05627 }
05628 return;
05629 }
05630
05631 static void send_link_keyquery(struct rpt *myrpt)
05632 {
05633 char str[300];
05634 struct ast_frame wf;
05635 struct rpt_link *l;
05636
05637 rpt_mutex_lock(&myrpt->lock);
05638 memset(myrpt->topkey,0,sizeof(myrpt->topkey));
05639 myrpt->topkeystate = 1;
05640 time(&myrpt->topkeytime);
05641 rpt_mutex_unlock(&myrpt->lock);
05642 snprintf(str, sizeof(str), "K? * %s 0 0", myrpt->name);
05643 wf.frametype = AST_FRAME_TEXT;
05644 wf.subclass.integer = 0;
05645 wf.offset = 0;
05646 wf.mallocd = 0;
05647 wf.datalen = strlen(str) + 1;
05648 wf.samples = 0;
05649 l = myrpt->links.next;
05650
05651 while(l != &myrpt->links)
05652 {
05653 wf.data.ptr = str;
05654 if (l->chan) ast_write(l->chan,&wf);
05655 l = l->next;
05656 }
05657 return;
05658 }
05659
05660
05661
05662 static void send_newkey(struct ast_channel *chan)
05663 {
05664
05665
05666 ast_sendtext(chan,newkeystr);
05667 return;
05668 }
05669
05670
05671
05672
05673
05674
05675
05676
05677
05678
05679
05680
05681
05682 static int connect_link(struct rpt *myrpt, char* node, int mode, int perma)
05683 {
05684 char *val, *s, *s1, *s2, *tele;
05685 char lstr[MAXLINKLIST],*strs[MAXLINKLIST];
05686 char tmp[300], deststr[300] = "",modechange = 0;
05687 char sx[320],*sy;
05688 struct rpt_link *l;
05689 int reconnects = 0;
05690 int i,n;
05691 struct dahdi_confinfo ci;
05692
05693 val = node_lookup(myrpt,node);
05694 if (!val){
05695 if(strlen(node) >= myrpt->longestnode)
05696 return -1;
05697 return 1;
05698 }
05699
05700 if(!strcmp(myrpt->name,node))
05701 return -2;
05702
05703 if(debug > 3){
05704 ast_log(LOG_NOTICE,"Connect attempt to node %s\n", node);
05705 ast_log(LOG_NOTICE,"Mode: %s\n",(mode)?"Transceive":"Monitor");
05706 ast_log(LOG_NOTICE,"Connection type: %s\n",(perma)?"Permalink":"Normal");
05707 }
05708
05709 strncpy(tmp,val,sizeof(tmp) - 1);
05710 s = tmp;
05711 s1 = strsep(&s,",");
05712 if (!strchr(s1,':') && strchr(s1,'/') && strncasecmp(s1, "local/", 6))
05713 {
05714 sy = strchr(s1,'/');
05715 *sy = 0;
05716 sprintf(sx,"%s:4569/%s",s1,sy + 1);
05717 s1 = sx;
05718 }
05719 s2 = strsep(&s,",");
05720 rpt_mutex_lock(&myrpt->lock);
05721 l = myrpt->links.next;
05722
05723 while(l != &myrpt->links){
05724 if (l->name[0] == '0')
05725 {
05726 l = l->next;
05727 continue;
05728 }
05729
05730 if (!strcmp(l->name, node))
05731 break;
05732 l = l->next;
05733 }
05734
05735 if (l != &myrpt->links){
05736
05737 if ((l->mode) || (!l->chan)) {
05738 rpt_mutex_unlock(&myrpt->lock);
05739 return 2;
05740 }
05741 reconnects = l->reconnects;
05742 rpt_mutex_unlock(&myrpt->lock);
05743 if (l->chan) ast_softhangup(l->chan, AST_SOFTHANGUP_DEV);
05744 l->retries = l->max_retries + 1;
05745 l->disced = 2;
05746 modechange = 1;
05747 } else
05748 {
05749 __mklinklist(myrpt,NULL,lstr);
05750 rpt_mutex_unlock(&myrpt->lock);
05751 n = finddelim(lstr,strs,MAXLINKLIST);
05752 for(i = 0; i < n; i++)
05753 {
05754 if ((*strs[i] < '0') ||
05755 (*strs[i] > '9')) strs[i]++;
05756 if (!strcmp(strs[i],node))
05757 {
05758 return 2;
05759 }
05760 }
05761 }
05762 strncpy(myrpt->lastlinknode,node,MAXNODESTR - 1);
05763
05764 l = ast_malloc(sizeof(struct rpt_link));
05765 if (!l)
05766 {
05767 ast_log(LOG_WARNING, "Unable to malloc\n");
05768 return -1;
05769 }
05770
05771 memset((char *)l,0,sizeof(struct rpt_link));
05772 l->mode = mode;
05773 l->outbound = 1;
05774 l->thisconnected = 0;
05775 voxinit_link(l,1);
05776 strncpy(l->name, node, MAXNODESTR - 1);
05777 l->isremote = (s && ast_true(s));
05778 if (modechange) l->connected = 1;
05779 l->hasconnected = l->perma = perma;
05780 #ifdef ALLOW_LOCAL_CHANNELS
05781 if ((strncasecmp(s1,"iax2/", 5) == 0) || (strncasecmp(s1, "local/", 6) == 0))
05782 strncpy(deststr, s1, sizeof(deststr));
05783 else
05784 snprintf(deststr, sizeof(deststr), "IAX2/%s", s1);
05785 #else
05786 snprintf(deststr, sizeof(deststr), "IAX2/%s", s1);
05787 #endif
05788 tele = strchr(deststr, '/');
05789 if (!tele){
05790 ast_log(LOG_WARNING,"link3:Dial number (%s) must be in format tech/number\n",deststr);
05791 ast_free(l);
05792 return -1;
05793 }
05794 *tele++ = 0;
05795 l->chan = ast_request(deststr, AST_FORMAT_SLINEAR, NULL, tele, NULL);
05796 if (l->chan){
05797 ast_set_read_format(l->chan, AST_FORMAT_SLINEAR);
05798 ast_set_write_format(l->chan, AST_FORMAT_SLINEAR);
05799 #ifdef AST_CDR_FLAG_POST_DISABLED
05800 if (l->chan->cdr)
05801 ast_set_flag(l->chan->cdr,AST_CDR_FLAG_POST_DISABLED);
05802 #endif
05803 #ifndef NEW_ASTERISK
05804 l->chan->whentohangup = 0;
05805 #endif
05806 l->chan->appl = "Apprpt";
05807 l->chan->data = "(Remote Rx)";
05808 if (debug > 3)
05809 ast_log(LOG_NOTICE, "rpt (remote) initiating call to %s/%s on %s\n",
05810 deststr, tele, l->chan->name);
05811 l->chan->caller.id.number.valid = 1;
05812 ast_free(l->chan->caller.id.number.str);
05813 l->chan->caller.id.number.str = ast_strdup(myrpt->name);
05814 ast_call(l->chan,tele,999);
05815 }
05816 else {
05817 if(debug > 3)
05818 ast_log(LOG_NOTICE, "Unable to place call to %s/%s on %s\n",
05819 deststr,tele,l->chan->name);
05820 if (myrpt->p.archivedir)
05821 {
05822 char str[100];
05823 sprintf(str,"LINKFAIL,%s",l->name);
05824 donodelog(myrpt,str);
05825 }
05826 ast_free(l);
05827 return -1;
05828 }
05829
05830 l->pchan = ast_request("DAHDI", AST_FORMAT_SLINEAR, NULL, "pseudo", NULL);
05831 if (!l->pchan){
05832 ast_log(LOG_WARNING,"rpt connect: Sorry unable to obtain pseudo channel\n");
05833 ast_hangup(l->chan);
05834 ast_free(l);
05835 return -1;
05836 }
05837 ast_set_read_format(l->pchan, AST_FORMAT_SLINEAR);
05838 ast_set_write_format(l->pchan, AST_FORMAT_SLINEAR);
05839 #ifdef AST_CDR_FLAG_POST_DISABLED
05840 if (l->pchan->cdr)
05841 ast_set_flag(l->pchan->cdr,AST_CDR_FLAG_POST_DISABLED);
05842 #endif
05843
05844 ci.chan = 0;
05845 ci.confno = myrpt->conf;
05846 ci.confmode = DAHDI_CONF_CONF | DAHDI_CONF_LISTENER | DAHDI_CONF_TALKER;
05847
05848 if (ioctl(l->pchan->fds[0], DAHDI_SETCONF, &ci) == -1)
05849 {
05850 ast_log(LOG_WARNING, "Unable to set conference mode to Announce\n");
05851 ast_hangup(l->chan);
05852 ast_hangup(l->pchan);
05853 ast_free(l);
05854 return -1;
05855 }
05856 rpt_mutex_lock(&myrpt->lock);
05857 l->reconnects = reconnects;
05858
05859 l->max_retries = MAX_RETRIES;
05860 if (perma)
05861 l->max_retries = MAX_RETRIES_PERM;
05862 if (l->isremote) l->retries = l->max_retries + 1;
05863 insque((struct qelem *)l,(struct qelem *)myrpt->links.next);
05864 __kickshort(myrpt);
05865 rpt_mutex_unlock(&myrpt->lock);
05866 if (!l->phonemode) send_newkey(l->chan);
05867 return 0;
05868 }
05869
05870
05871
05872
05873
05874
05875
05876 static int function_ilink(struct rpt *myrpt, char *param, char *digits, int command_source, struct rpt_link *mylink)
05877 {
05878
05879 char *val, *s, *s1, *s2;
05880 char tmp[300];
05881 char digitbuf[MAXNODESTR],*strs[MAXLINKLIST];
05882 char mode,perma;
05883 char sx[320],*sy;
05884 struct rpt_link *l;
05885 int i,r;
05886
05887 if(!param)
05888 return DC_ERROR;
05889
05890
05891 if (myrpt->p.s[myrpt->p.sysstate_cur].txdisable || myrpt->p.s[myrpt->p.sysstate_cur].linkfundisable )
05892 return DC_ERROR;
05893
05894 strncpy(digitbuf,digits,MAXNODESTR - 1);
05895
05896 if(debug > 6)
05897 printf("@@@@ ilink param = %s, digitbuf = %s\n", (param)? param : "(null)", digitbuf);
05898
05899 switch(myatoi(param)){
05900 case 11:
05901 case 1:
05902 if ((digitbuf[0] == '0') && (myrpt->lastlinknode[0]))
05903 strcpy(digitbuf,myrpt->lastlinknode);
05904 val = node_lookup(myrpt,digitbuf);
05905 if (!val){
05906 if(strlen(digitbuf) >= myrpt->longestnode)
05907 return DC_ERROR;
05908 break;
05909 }
05910 strncpy(tmp,val,sizeof(tmp) - 1);
05911 s = tmp;
05912 s1 = strsep(&s,",");
05913 if (!strchr(s1,':') && strchr(s1,'/') && strncasecmp(s1, "local/", 6))
05914 {
05915 sy = strchr(s1,'/');
05916 *sy = 0;
05917 sprintf(sx,"%s:4569/%s",s1,sy + 1);
05918 s1 = sx;
05919 }
05920 s2 = strsep(&s,",");
05921 rpt_mutex_lock(&myrpt->lock);
05922 l = myrpt->links.next;
05923
05924 while(l != &myrpt->links){
05925 if (l->name[0] == '0')
05926 {
05927 l = l->next;
05928 continue;
05929 }
05930
05931 if (!strcmp(l->name, digitbuf))
05932 break;
05933 l = l->next;
05934 }
05935 if (l != &myrpt->links){
05936 struct ast_frame wf;
05937
05938
05939 if ((myatoi(param) < 10) &&
05940 (l->max_retries > MAX_RETRIES))
05941 {
05942 rpt_mutex_unlock(&myrpt->lock);
05943 return DC_COMPLETE;
05944 }
05945 strncpy(myrpt->lastlinknode,digitbuf,MAXNODESTR - 1);
05946 l->retries = l->max_retries + 1;
05947 l->disced = 1;
05948 rpt_mutex_unlock(&myrpt->lock);
05949 wf.frametype = AST_FRAME_TEXT;
05950 wf.subclass.integer = 0;
05951 wf.offset = 0;
05952 wf.mallocd = 0;
05953 wf.datalen = strlen(discstr) + 1;
05954 wf.samples = 0;
05955 wf.data.ptr = discstr;
05956 if (l->chan)
05957 {
05958 ast_write(l->chan,&wf);
05959 if (ast_safe_sleep(l->chan,250) == -1) return DC_ERROR;
05960 ast_softhangup(l->chan,AST_SOFTHANGUP_DEV);
05961 }
05962 rpt_telemetry(myrpt, COMPLETE, NULL);
05963 return DC_COMPLETE;
05964 }
05965 rpt_mutex_unlock(&myrpt->lock);
05966 return DC_COMPLETE;
05967 case 2:
05968 case 3:
05969 case 12:
05970 case 13:
05971 if ((digitbuf[0] == '0') && (myrpt->lastlinknode[0]))
05972 strcpy(digitbuf,myrpt->lastlinknode);
05973
05974 perma = (atoi(param) > 10) ? 1 : 0;
05975 mode = (atoi(param) & 1) ? 1 : 0;
05976 r = connect_link(myrpt, digitbuf, mode, perma);
05977 switch(r){
05978 case -2:
05979 return DC_COMPLETE;
05980
05981 case 0:
05982 rpt_telemetry(myrpt, COMPLETE, NULL);
05983 return DC_COMPLETE;
05984
05985 case 1:
05986 break;
05987
05988 case 2:
05989 rpt_telemetry(myrpt, REMALREADY, NULL);
05990 return DC_COMPLETE;
05991
05992 default:
05993 rpt_telemetry(myrpt, CONNFAIL, NULL);
05994 return DC_COMPLETE;
05995 }
05996 break;
05997
05998 case 4:
05999
06000
06001 if (((command_source != SOURCE_RPT) &&
06002 (command_source != SOURCE_PHONE) &&
06003 (command_source != SOURCE_ALT) &&
06004 (command_source != SOURCE_DPHONE)) ||
06005 (myrpt->links.next == &myrpt->links))
06006 return DC_COMPLETE;
06007
06008
06009 if ((myrpt->cmdnode[0]) || (!strcmp(myrpt->name, digitbuf))){
06010
06011 rpt_telemetry(myrpt, REMALREADY, NULL);
06012 return DC_COMPLETE;
06013 }
06014 if ((digitbuf[0] == '0') && (myrpt->lastlinknode[0]))
06015 strcpy(digitbuf,myrpt->lastlinknode);
06016
06017 val = node_lookup(myrpt,digitbuf);
06018 if (!val){
06019 if(strlen(digitbuf) >= myrpt->longestnode)
06020 return DC_ERROR;
06021 break;
06022
06023 }
06024 rpt_mutex_lock(&myrpt->lock);
06025 strcpy(myrpt->lastlinknode,digitbuf);
06026 strncpy(myrpt->cmdnode, digitbuf, sizeof(myrpt->cmdnode) - 1);
06027 rpt_mutex_unlock(&myrpt->lock);
06028 rpt_telemetry(myrpt, REMGO, NULL);
06029 return DC_COMPLETE;
06030
06031 case 5:
06032 rpt_telemetry(myrpt, STATUS, NULL);
06033 return DC_COMPLETE;
06034
06035 case 15:
06036 rpt_telemetry(myrpt, FULLSTATUS, NULL);
06037 return DC_COMPLETE;
06038
06039
06040 case 6:
06041 rpt_mutex_lock(&myrpt->lock);
06042 myrpt->savednodes[0] = 0;
06043 l = myrpt->links.next;
06044
06045 while(l != &myrpt->links){
06046 struct ast_frame wf;
06047 if (l->name[0] == '0')
06048 {
06049 l = l->next;
06050 continue;
06051 }
06052
06053 sprintf(tmp,"%c%c%s",(l->mode) ? 'X' : 'M',(l->perma) ? 'P':'T',l->name);
06054 if(strlen(tmp) + strlen(myrpt->savednodes) + 1 < MAXNODESTR){
06055 if(myrpt->savednodes[0])
06056 strcat(myrpt->savednodes, ",");
06057 strcat(myrpt->savednodes, tmp);
06058 }
06059 l->retries = l->max_retries + 1;
06060 l->disced = 2;
06061 rpt_mutex_unlock(&myrpt->lock);
06062
06063
06064 wf.frametype = AST_FRAME_TEXT;
06065 wf.subclass.integer = 0;
06066 wf.offset = 0;
06067 wf.mallocd = 0;
06068 wf.datalen = strlen(discstr) + 1;
06069 wf.samples = 0;
06070 wf.data.ptr = discstr;
06071 if (l->chan)
06072 {
06073 ast_write(l->chan,&wf);
06074 ast_safe_sleep(l->chan,250);
06075 ast_softhangup(l->chan,AST_SOFTHANGUP_DEV);
06076 }
06077 rpt_mutex_lock(&myrpt->lock);
06078 l = l->next;
06079 }
06080 rpt_mutex_unlock(&myrpt->lock);
06081 if(debug > 3)
06082 ast_log(LOG_NOTICE,"Nodes disconnected: %s\n",myrpt->savednodes);
06083 rpt_telemetry(myrpt, COMPLETE, NULL);
06084 return DC_COMPLETE;
06085
06086 case 7:
06087 rpt_telemetry(myrpt, LASTNODEKEY, NULL);
06088 break;
06089
06090
06091 #ifdef _MDC_DECODE_H_
06092 case 8:
06093 myrpt->lastunit = 0xd00d;
06094 mdc1200_notify(myrpt,NULL,myrpt->lastunit);
06095 mdc1200_send(myrpt,myrpt->lastunit);
06096 break;
06097 #endif
06098
06099 case 16:
06100 strcpy(tmp, myrpt->savednodes);
06101 finddelim(tmp, strs, MAXLINKLIST);
06102 for(i = 0; tmp[0] && strs[i] != NULL && i < MAXLINKLIST; i++){
06103 s1 = strs[i];
06104 mode = (s1[0] == 'X') ? 1 : 0;
06105 perma = (s1[1] == 'P') ? 1 : 0;
06106 connect_link(myrpt, s1 + 2, mode, perma);
06107 }
06108 rpt_telemetry(myrpt, COMPLETE, NULL);
06109 break;
06110
06111 case 200:
06112 case 201:
06113 case 202:
06114 case 203:
06115 case 204:
06116 case 205:
06117 case 206:
06118 case 207:
06119 case 208:
06120 case 209:
06121 case 210:
06122 case 211:
06123 case 212:
06124 case 213:
06125 case 214:
06126 case 215:
06127 if (((myrpt->p.propagate_dtmf) &&
06128 (command_source == SOURCE_LNK)) ||
06129 ((myrpt->p.propagate_phonedtmf) &&
06130 ((command_source == SOURCE_PHONE) ||
06131 (command_source == SOURCE_ALT) ||
06132 (command_source == SOURCE_DPHONE))))
06133 do_dtmf_local(myrpt,
06134 remdtmfstr[myatoi(param) - 200]);
06135 default:
06136 return DC_ERROR;
06137
06138 }
06139
06140 return DC_INDETERMINATE;
06141 }
06142
06143
06144
06145
06146
06147 static int function_autopatchup(struct rpt *myrpt, char *param, char *digitbuf, int command_source, struct rpt_link *mylink)
06148 {
06149 pthread_attr_t attr;
06150 int i, idx, paramlength;
06151 char *lparam;
06152 char *value = NULL;
06153 char *paramlist[20];
06154
06155 static char *keywords[] = {
06156 "context",
06157 "dialtime",
06158 "farenddisconnect",
06159 "noct",
06160 "quiet",
06161 NULL
06162 };
06163
06164 if (myrpt->p.s[myrpt->p.sysstate_cur].txdisable || myrpt->p.s[myrpt->p.sysstate_cur].autopatchdisable)
06165 return DC_ERROR;
06166
06167 if(debug)
06168 printf("@@@@ Autopatch up\n");
06169
06170 if(!myrpt->callmode){
06171
06172 myrpt->patchnoct = 0;
06173 myrpt->patchdialtime = 0;
06174 myrpt->patchfarenddisconnect = 0;
06175 myrpt->patchquiet = 0;
06176 strncpy(myrpt->patchcontext, myrpt->p.ourcontext, MAXPATCHCONTEXT);
06177
06178 if(param){
06179
06180 lparam = ast_strdup(param);
06181 if(!lparam){
06182 ast_log(LOG_ERROR,"App_rpt out of memory on line %d\n",__LINE__);
06183 return DC_ERROR;
06184 }
06185 paramlength = finddelim(lparam, paramlist, 20);
06186 for(i = 0; i < paramlength; i++){
06187 idx = matchkeyword(paramlist[i], &value, keywords);
06188 if(value)
06189 value = skipchars(value, "= ");
06190 switch(idx){
06191
06192 case 1:
06193 strncpy(myrpt->patchcontext, value, MAXPATCHCONTEXT - 1) ;
06194 break;
06195
06196 case 2:
06197 myrpt->patchdialtime = atoi(value);
06198 break;
06199
06200 case 3:
06201 myrpt->patchfarenddisconnect = atoi(value);
06202 break;
06203
06204 case 4:
06205 myrpt->patchnoct = atoi(value);
06206 break;
06207
06208 case 5:
06209 myrpt->patchquiet = atoi(value);
06210 break;
06211
06212 default:
06213 break;
06214 }
06215 }
06216 ast_free(lparam);
06217 }
06218 }
06219
06220 rpt_mutex_lock(&myrpt->lock);
06221
06222
06223
06224 if ((myrpt->callmode == 2) || (myrpt->callmode == 3)){
06225 myrpt->mydtmf = myrpt->p.endchar;
06226 }
06227 if (myrpt->callmode){
06228 rpt_mutex_unlock(&myrpt->lock);
06229 return DC_COMPLETE;
06230 }
06231 myrpt->callmode = 1;
06232 myrpt->cidx = 0;
06233 myrpt->exten[myrpt->cidx] = 0;
06234 rpt_mutex_unlock(&myrpt->lock);
06235 pthread_attr_init(&attr);
06236 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
06237 ast_pthread_create(&myrpt->rpt_call_thread,&attr,rpt_call,(void *) myrpt);
06238 return DC_COMPLETE;
06239 }
06240
06241
06242
06243
06244
06245 static int function_autopatchdn(struct rpt *myrpt, char *param, char *digitbuf, int command_source, struct rpt_link *mylink)
06246 {
06247 if (myrpt->p.s[myrpt->p.sysstate_cur].txdisable || myrpt->p.s[myrpt->p.sysstate_cur].autopatchdisable)
06248 return DC_ERROR;
06249
06250 if(debug)
06251 printf("@@@@ Autopatch down\n");
06252
06253 rpt_mutex_lock(&myrpt->lock);
06254
06255 myrpt->macropatch=0;
06256
06257 if (!myrpt->callmode){
06258 rpt_mutex_unlock(&myrpt->lock);
06259 return DC_COMPLETE;
06260 }
06261
06262 myrpt->callmode = 0;
06263 channel_revert(myrpt);
06264 rpt_mutex_unlock(&myrpt->lock);
06265 rpt_telemetry(myrpt, TERM, NULL);
06266 return DC_COMPLETE;
06267 }
06268
06269
06270
06271
06272
06273 static int function_status(struct rpt *myrpt, char *param, char *digitbuf, int command_source, struct rpt_link *mylink)
06274 {
06275
06276 if (!param)
06277 return DC_ERROR;
06278
06279 if ((myrpt->p.s[myrpt->p.sysstate_cur].txdisable) || (myrpt->p.s[myrpt->p.sysstate_cur].userfundisable))
06280 return DC_ERROR;
06281
06282 if(debug)
06283 printf("@@@@ status param = %s, digitbuf = %s\n", (param)? param : "(null)", digitbuf);
06284
06285 switch(myatoi(param)){
06286 case 1:
06287 rpt_telemetry(myrpt, ID1, NULL);
06288 return DC_COMPLETE;
06289 case 2:
06290 rpt_telemetry(myrpt, STATS_TIME, NULL);
06291 return DC_COMPLETE;
06292 case 3:
06293 rpt_telemetry(myrpt, STATS_VERSION, NULL);
06294 return DC_COMPLETE;
06295 case 11:
06296 rpt_telemetry(myrpt, ID , NULL);
06297 return DC_COMPLETE;
06298 case 12:
06299 rpt_telemetry(myrpt, STATS_TIME_LOCAL, NULL);
06300 return DC_COMPLETE;
06301 default:
06302 return DC_ERROR;
06303 }
06304 return DC_INDETERMINATE;
06305 }
06306
06307
06308
06309 static int function_macro(struct rpt *myrpt, char *param, char *digitbuf, int command_source, struct rpt_link *mylink)
06310 {
06311 char *val;
06312 int i;
06313 if (myrpt->remote)
06314 return DC_ERROR;
06315
06316 if(debug)
06317 printf("@@@@ macro-oni param = %s, digitbuf = %s\n", (param)? param : "(null)", digitbuf);
06318
06319 if(strlen(digitbuf) < 1)
06320 return DC_INDETERMINATE;
06321
06322 for(i = 0 ; i < digitbuf[i] ; i++) {
06323 if((digitbuf[i] < '0') || (digitbuf[i] > '9'))
06324 return DC_ERROR;
06325 }
06326
06327 if (*digitbuf == '0') val = myrpt->p.startupmacro;
06328 else val = (char *) ast_variable_retrieve(myrpt->cfg, myrpt->p.macro, digitbuf);
06329
06330 if (!val){
06331 if (strlen(digitbuf) < myrpt->macro_longest)
06332 return DC_INDETERMINATE;
06333 rpt_telemetry(myrpt, MACRO_NOTFOUND, NULL);
06334 return DC_COMPLETE;
06335 }
06336 rpt_mutex_lock(&myrpt->lock);
06337 if ((MAXMACRO - strlen(myrpt->macrobuf)) < strlen(val))
06338 {
06339 rpt_mutex_unlock(&myrpt->lock);
06340 rpt_telemetry(myrpt, MACRO_BUSY, NULL);
06341 return DC_ERROR;
06342 }
06343 myrpt->macrotimer = MACROTIME;
06344 strncat(myrpt->macrobuf,val,MAXMACRO - 1);
06345 rpt_mutex_unlock(&myrpt->lock);
06346 return DC_COMPLETE;
06347 }
06348
06349
06350
06351
06352
06353 static int function_playback(struct rpt *myrpt, char *param, char *digitbuf, int command_source, struct rpt_link *mylink)
06354 {
06355
06356 if (myrpt->remote)
06357 return DC_ERROR;
06358
06359 if(debug)
06360 printf("@@@@ playback param = %s, digitbuf = %s\n", (param)? param : "(null)", digitbuf);
06361
06362 if (ast_fileexists(param,NULL,myrpt->rxchannel->language) <= 0)
06363 return DC_ERROR;
06364
06365 rpt_telemetry(myrpt,PLAYBACK,param);
06366 return DC_COMPLETE;
06367 }
06368
06369
06370
06371
06372
06373 static int function_cop(struct rpt *myrpt, char *param, char *digitbuf, int command_source, struct rpt_link *mylink)
06374 {
06375 char string[16];
06376 int res;
06377
06378 int i, r;
06379
06380 if(!param)
06381 return DC_ERROR;
06382
06383 switch(myatoi(param)){
06384 case 1:
06385 res = system("killall -9 asterisk");
06386 return DC_COMPLETE;
06387
06388 case 2:
06389 myrpt->p.s[myrpt->p.sysstate_cur].txdisable = 0;
06390 rpt_telemetry(myrpt, ARB_ALPHA, (void *) "RPTENA");
06391 return DC_COMPLETE;
06392
06393 case 3:
06394 myrpt->p.s[myrpt->p.sysstate_cur].txdisable = 1;
06395 return DC_COMPLETE;
06396
06397 case 4:
06398 if (myrpt->stopgen < 0)
06399 {
06400 myrpt->stopgen = 1;
06401 }
06402 else
06403 {
06404 myrpt->stopgen = 0;
06405 rpt_telemetry(myrpt, TEST_TONE, NULL);
06406 }
06407 return DC_COMPLETE;
06408
06409 case 5:
06410 myrpt->disgorgetime = time(NULL) + 10;
06411 return DC_COMPLETE;
06412
06413 case 6:
06414 if (command_source != SOURCE_PHONE) return DC_INDETERMINATE;
06415 return DC_DOKEY;
06416
06417
06418 case 7:
06419 myrpt->p.s[myrpt->p.sysstate_cur].totdisable = 0;
06420 rpt_telemetry(myrpt, ARB_ALPHA, (void *) "TOTENA");
06421 return DC_COMPLETE;
06422
06423 case 8:
06424 myrpt->p.s[myrpt->p.sysstate_cur].totdisable = 1;
06425 rpt_telemetry(myrpt, ARB_ALPHA, (void *) "TOTDIS");
06426 return DC_COMPLETE;
06427
06428 case 9:
06429 myrpt->p.s[myrpt->p.sysstate_cur].autopatchdisable = 0;
06430 rpt_telemetry(myrpt, ARB_ALPHA, (void *) "APENA");
06431 return DC_COMPLETE;
06432
06433 case 10:
06434 myrpt->p.s[myrpt->p.sysstate_cur].autopatchdisable = 1;
06435 rpt_telemetry(myrpt, ARB_ALPHA, (void *) "APDIS");
06436 return DC_COMPLETE;
06437
06438 case 11:
06439 myrpt->p.s[myrpt->p.sysstate_cur].linkfundisable = 0;
06440 rpt_telemetry(myrpt, ARB_ALPHA, (void *) "LNKENA");
06441 return DC_COMPLETE;
06442
06443 case 12:
06444 myrpt->p.s[myrpt->p.sysstate_cur].linkfundisable = 1;
06445 rpt_telemetry(myrpt, ARB_ALPHA, (void *) "LNKDIS");
06446 return DC_COMPLETE;
06447
06448 case 13:
06449 string[0] = string[1] = 'S';
06450 string[2] = myrpt->p.sysstate_cur + '0';
06451 string[3] = '\0';
06452 rpt_telemetry(myrpt, ARB_ALPHA, (void *) string);
06453 return DC_COMPLETE;
06454
06455 case 14:
06456 if(strlen(digitbuf) == 0)
06457 break;
06458 if((digitbuf[0] < '0') || (digitbuf[0] > '9'))
06459 return DC_ERROR;
06460 myrpt->p.sysstate_cur = digitbuf[0] - '0';
06461 string[0] = string[1] = 'S';
06462 string[2] = myrpt->p.sysstate_cur + '0';
06463 string[3] = '\0';
06464 rpt_telemetry(myrpt, ARB_ALPHA, (void *) string);
06465 return DC_COMPLETE;
06466
06467 case 15:
06468 myrpt->p.s[myrpt->p.sysstate_cur].schedulerdisable = 0;
06469 rpt_telemetry(myrpt, ARB_ALPHA, (void *) "SKENA");
06470 return DC_COMPLETE;
06471
06472 case 16:
06473 myrpt->p.s[myrpt->p.sysstate_cur].schedulerdisable = 1;
06474 rpt_telemetry(myrpt, ARB_ALPHA, (void *) "SKDIS");
06475 return DC_COMPLETE;
06476
06477 case 17:
06478 myrpt->p.s[myrpt->p.sysstate_cur].userfundisable = 0;
06479 rpt_telemetry(myrpt, ARB_ALPHA, (void *) "UFENA");
06480 return DC_COMPLETE;
06481
06482 case 18:
06483 myrpt->p.s[myrpt->p.sysstate_cur].userfundisable = 1;
06484 rpt_telemetry(myrpt, ARB_ALPHA, (void *) "UFDIS");
06485 return DC_COMPLETE;
06486
06487 case 19:
06488 myrpt->p.s[myrpt->p.sysstate_cur].alternatetail = 1;
06489 rpt_telemetry(myrpt, ARB_ALPHA, (void *) "ATENA");
06490 return DC_COMPLETE;
06491
06492 case 20:
06493 myrpt->p.s[myrpt->p.sysstate_cur].alternatetail = 0;
06494 rpt_telemetry(myrpt, ARB_ALPHA, (void *) "ATDIS");
06495 return DC_COMPLETE;
06496
06497 case 21:
06498 birdbath(myrpt);
06499 if (myrpt->p.parrotmode < 2)
06500 {
06501 myrpt->p.parrotmode = 0;
06502 rpt_telemetry(myrpt,COMPLETE,NULL);
06503 return DC_COMPLETE;
06504 }
06505 break;
06506
06507 case 22:
06508 birdbath(myrpt);
06509 if (myrpt->p.parrotmode < 2)
06510 {
06511 myrpt->p.parrotmode = 1;
06512 rpt_telemetry(myrpt,COMPLETE,NULL);
06513 return DC_COMPLETE;
06514 }
06515 break;
06516 case 23:
06517 birdbath(myrpt);
06518 rpt_telemetry(myrpt,COMPLETE,NULL);
06519 return DC_COMPLETE;
06520 case 24:
06521 flush_telem(myrpt);
06522 rpt_telemetry(myrpt,COMPLETE,NULL);
06523 return DC_COMPLETE;
06524 case 25:
06525 send_link_keyquery(myrpt);
06526 myrpt->topkeylong = 0;
06527 rpt_telemetry(myrpt,COMPLETE,NULL);
06528 return DC_COMPLETE;
06529 case 26:
06530 send_link_keyquery(myrpt);
06531 myrpt->topkeylong = 1;
06532 rpt_telemetry(myrpt,COMPLETE,NULL);
06533 return DC_COMPLETE;
06534
06535 case 30:
06536
06537 if(strlen(digitbuf) < 2)
06538 break;
06539
06540 for(i = 0 ; i < 2 ; i++){
06541 if((digitbuf[i] < '0') || (digitbuf[i] > '9'))
06542 return DC_ERROR;
06543 }
06544
06545 r = retreive_memory(myrpt, digitbuf);
06546 if (r < 0){
06547 rpt_telemetry(myrpt,MEMNOTFOUND,NULL);
06548 return DC_COMPLETE;
06549 }
06550 if (r > 0){
06551 return DC_ERROR;
06552 }
06553 if (setrem(myrpt) == -1) return DC_ERROR;
06554 return DC_COMPLETE;
06555
06556 case 31:
06557
06558
06559 if(strlen(digitbuf) < 2)
06560 break;
06561
06562 for(i = 0 ; i < 2 ; i++){
06563 if((digitbuf[i] < '0') || (digitbuf[i] > '9'))
06564 return DC_ERROR;
06565 }
06566 channel_steer(myrpt,digitbuf);
06567 return DC_COMPLETE;
06568
06569 case 32:
06570 i = strlen(digitbuf);
06571 if(!i){
06572 if(debug > 3)
06573 ast_log(LOG_NOTICE,"Padtest entered");
06574 myrpt->inpadtest = 1;
06575 }
06576 else{
06577 if(debug > 3)
06578 ast_log(LOG_NOTICE,"Padtest len= %d digits=%s",i,digitbuf);
06579 if(digitbuf[i-1] != myrpt->p.endchar)
06580 break;
06581 rpt_telemetry(myrpt, ARB_ALPHA, digitbuf);
06582 myrpt->inpadtest = 0;
06583 if(debug > 3)
06584 ast_log(LOG_NOTICE,"Padtest exited");
06585 return DC_COMPLETE;
06586 }
06587 }
06588 return DC_INDETERMINATE;
06589 }
06590
06591
06592
06593 static int collect_function_digits(struct rpt *myrpt, char *digits,
06594 int command_source, struct rpt_link *mylink)
06595 {
06596 int i,rv;
06597 char *stringp,*action,*param,*functiondigits;
06598 char function_table_name[30] = "";
06599 char workstring[200];
06600
06601 struct ast_variable *vp;
06602
06603 if (debug > 6) ast_log(LOG_NOTICE,"digits=%s source=%d\n",digits, command_source);
06604
06605
06606
06607
06608 if (command_source == SOURCE_DPHONE) {
06609 if (!myrpt->p.dphone_functions) return DC_INDETERMINATE;
06610 strncpy(function_table_name, myrpt->p.dphone_functions, sizeof(function_table_name) - 1);
06611 }
06612 else if (command_source == SOURCE_ALT) {
06613 if (!myrpt->p.alt_functions) return DC_INDETERMINATE;
06614 strncpy(function_table_name, myrpt->p.alt_functions, sizeof(function_table_name) - 1);
06615 }
06616 else if (command_source == SOURCE_PHONE) {
06617 if (!myrpt->p.phone_functions) return DC_INDETERMINATE;
06618 strncpy(function_table_name, myrpt->p.phone_functions, sizeof(function_table_name) - 1);
06619 }
06620 else if (command_source == SOURCE_LNK)
06621 strncpy(function_table_name, myrpt->p.link_functions, sizeof(function_table_name) - 1);
06622 else
06623 strncpy(function_table_name, myrpt->p.functions, sizeof(function_table_name) - 1);
06624
06625 vp = ast_variable_browse(myrpt->cfg, function_table_name);
06626 while(vp) {
06627 if(!strncasecmp(vp->name, digits, strlen(vp->name)))
06628 break;
06629 vp = vp->next;
06630 }
06631
06632 if(!vp) {
06633 int n;
06634
06635 n = myrpt->longestfunc;
06636 if (command_source == SOURCE_LNK) n = myrpt->link_longestfunc;
06637 else
06638 if (command_source == SOURCE_PHONE) n = myrpt->phone_longestfunc;
06639 else
06640 if (command_source == SOURCE_ALT) n = myrpt->alt_longestfunc;
06641 else
06642 if (command_source == SOURCE_DPHONE) n = myrpt->dphone_longestfunc;
06643
06644 if(strlen(digits) >= n)
06645 return DC_ERROR;
06646 else
06647 return DC_INDETERMINATE;
06648 }
06649
06650 strncpy(workstring, vp->value, sizeof(workstring) - 1 );
06651 stringp = workstring;
06652 action = strsep(&stringp, ",");
06653 param = stringp;
06654 if(debug)
06655 printf("@@@@ action: %s, param = %s\n",action, (param) ? param : "(null)");
06656
06657 for(i = 0 ; i < (sizeof(function_table)/sizeof(struct function_table_tag)); i++){
06658 if(!strncasecmp(action, function_table[i].action, strlen(action)))
06659 break;
06660 }
06661 if(debug)
06662 printf("@@@@ table index i = %d\n",i);
06663 if(i == (sizeof(function_table)/sizeof(struct function_table_tag))){
06664
06665 return DC_ERROR;
06666 }
06667 if(function_table[i].function == NULL){
06668
06669 if(debug)
06670 printf("@@@@ NULL for action: %s\n",action);
06671 return DC_ERROR;
06672 }
06673 functiondigits = digits + strlen(vp->name);
06674 rv=(*function_table[i].function)(myrpt, param, functiondigits, command_source, mylink);
06675 if (debug > 6) ast_log(LOG_NOTICE,"rv=%i\n",rv);
06676 return(rv);
06677 }
06678
06679
06680 static void handle_link_data(struct rpt *myrpt, struct rpt_link *mylink,
06681 char *str)
06682 {
06683
06684
06685 char tmp[512],tmp1[512],cmd[300] = "",dest[300],src[300],c;
06686 int i,seq, res, ts;
06687 struct rpt_link *l;
06688 struct ast_frame wf;
06689
06690 wf.frametype = AST_FRAME_TEXT;
06691 wf.subclass.integer = 0;
06692 wf.offset = 0;
06693 wf.mallocd = 0;
06694 wf.datalen = strlen(str) + 1;
06695 wf.samples = 0;
06696
06697 strncpy(tmp,str,sizeof(tmp) - 1);
06698
06699 if (!strcmp(tmp,discstr))
06700 {
06701 mylink->disced = 1;
06702 mylink->retries = mylink->max_retries + 1;
06703 ast_softhangup(mylink->chan,AST_SOFTHANGUP_DEV);
06704 return;
06705 }
06706 if (!strcmp(tmp,newkeystr))
06707 {
06708 mylink->newkey = 1;
06709 return;
06710 }
06711 if (tmp[0] == 'L')
06712 {
06713 rpt_mutex_lock(&myrpt->lock);
06714 strcpy(mylink->linklist,tmp + 2);
06715 time(&mylink->linklistreceived);
06716 rpt_mutex_unlock(&myrpt->lock);
06717 if (debug > 6) ast_log(LOG_NOTICE,"@@@@ node %s received node list %s from node %s\n",
06718 myrpt->name,tmp,mylink->name);
06719 return;
06720 }
06721 if (tmp[0] == 'K')
06722 {
06723 if (sscanf(tmp, "%299s %299s %299s %30d %30d", cmd, dest, src, &seq, &ts) != 5)
06724 {
06725 ast_log(LOG_WARNING, "Unable to parse keying string %s\n",str);
06726 return;
06727 }
06728 if (dest[0] == '0')
06729 {
06730 strcpy(dest,myrpt->name);
06731 }
06732
06733 if (strcmp(dest,myrpt->name))
06734 {
06735 l = myrpt->links.next;
06736
06737 while(l != &myrpt->links)
06738 {
06739 if (l->name[0] == '0')
06740 {
06741 l = l->next;
06742 continue;
06743 }
06744
06745 if ((l == mylink) || (!strcmp(l->name,mylink->name)))
06746 {
06747 l = l->next;
06748 continue;
06749 }
06750
06751 if (!strcmp(l->name,dest))
06752 {
06753
06754 if (strcmp(l->name,src)) {
06755 wf.data.ptr = str;
06756 if (l->chan) ast_write(l->chan,&wf);
06757 }
06758 return;
06759 }
06760 l = l->next;
06761 }
06762 }
06763
06764 if ((strcmp(dest,myrpt->name)) || (dest[0] == '*'))
06765 {
06766 l = myrpt->links.next;
06767
06768 while(l != &myrpt->links)
06769 {
06770 if (l->name[0] == '0')
06771 {
06772 l = l->next;
06773 continue;
06774 }
06775
06776 if ((l == mylink) || (!strcmp(l->name,mylink->name)))
06777 {
06778 l = l->next;
06779 continue;
06780 }
06781
06782 if (strcmp(l->name,src)) {
06783 wf.data.ptr = str;
06784 if (l->chan) ast_write(l->chan,&wf);
06785 }
06786 l = l->next;
06787 }
06788 }
06789
06790 if (strcmp(dest,myrpt->name) && (dest[0] != '*')) return;
06791 if (cmd[1] == '?')
06792 {
06793 time_t now;
06794 int n = 0;
06795
06796 time(&now);
06797 if (myrpt->lastkeyedtime)
06798 {
06799 n = (int)(now - myrpt->lastkeyedtime);
06800 }
06801 sprintf(tmp1,"K %s %s %d %d",src,myrpt->name,myrpt->keyed,n);
06802 wf.data.ptr = tmp1;
06803 wf.datalen = strlen(tmp1) + 1;
06804 if (mylink->chan) ast_write(mylink->chan,&wf);
06805 return;
06806 }
06807 if (myrpt->topkeystate != 1) return;
06808 rpt_mutex_lock(&myrpt->lock);
06809 for(i = 0; i < TOPKEYN; i++)
06810 {
06811 if (!strcmp(myrpt->topkey[i].node,src)) break;
06812 }
06813 if (i >= TOPKEYN)
06814 {
06815 for(i = 0; i < TOPKEYN; i++)
06816 {
06817 if (!myrpt->topkey[i].node[0]) break;
06818 }
06819 }
06820 if (i < TOPKEYN)
06821 {
06822 strncpy(myrpt->topkey[i].node,src,TOPKEYMAXSTR - 1);
06823 myrpt->topkey[i].timesince = ts;
06824 myrpt->topkey[i].keyed = seq;
06825 }
06826 rpt_mutex_unlock(&myrpt->lock);
06827 return;
06828 }
06829 if (tmp[0] == 'I')
06830 {
06831
06832
06833 if (sscanf(tmp,"%299s %299s %30x",cmd,src,&seq) != 3)
06834 {
06835 ast_log(LOG_WARNING, "Unable to parse ident string %s\n",str);
06836 return;
06837 }
06838 mdc1200_notify(myrpt,src,seq);
06839 strcpy(dest,"*");
06840 }
06841 else
06842 {
06843
06844
06845 if (sscanf(tmp,"%299s %299s %299s %30d %1c",cmd,dest,src,&seq,&c) != 5)
06846 {
06847 ast_log(LOG_WARNING, "Unable to parse link string %s\n",str);
06848 return;
06849 }
06850 if (strcmp(cmd,"D"))
06851 {
06852 ast_log(LOG_WARNING, "Unable to parse link string %s\n",str);
06853 return;
06854 }
06855 }
06856 if (dest[0] == '0')
06857 {
06858 strcpy(dest,myrpt->name);
06859 }
06860
06861
06862 if (strcmp(dest,myrpt->name))
06863 {
06864 l = myrpt->links.next;
06865
06866 while(l != &myrpt->links)
06867 {
06868 if (l->name[0] == '0')
06869 {
06870 l = l->next;
06871 continue;
06872 }
06873
06874 if ((l == mylink) || (!strcmp(l->name,mylink->name)))
06875 {
06876 l = l->next;
06877 continue;
06878 }
06879
06880 if (!strcmp(l->name,dest))
06881 {
06882
06883 if (strcmp(l->name,src)) {
06884 wf.data.ptr = str;
06885 if (l->chan) ast_write(l->chan,&wf);
06886 }
06887 return;
06888 }
06889 l = l->next;
06890 }
06891 l = myrpt->links.next;
06892
06893 while(l != &myrpt->links)
06894 {
06895 if (l->name[0] == '0')
06896 {
06897 l = l->next;
06898 continue;
06899 }
06900
06901 if ((l == mylink) || (!strcmp(l->name,mylink->name)))
06902 {
06903 l = l->next;
06904 continue;
06905 }
06906
06907 if (strcmp(l->name,src)) {
06908 wf.data.ptr = str;
06909 if (l->chan) ast_write(l->chan,&wf);
06910 }
06911 l = l->next;
06912 }
06913 return;
06914 }
06915 if (myrpt->p.archivedir)
06916 {
06917 char dtmfstr[100];
06918
06919 sprintf(dtmfstr,"DTMF,%s,%c",mylink->name,c);
06920 donodelog(myrpt,dtmfstr);
06921 }
06922 c = func_xlat(myrpt,c,&myrpt->p.outxlat);
06923 if (!c) return;
06924 rpt_mutex_lock(&myrpt->lock);
06925 if (c == myrpt->p.endchar) myrpt->stopgen = 1;
06926 if (myrpt->callmode == 1)
06927 {
06928 myrpt->exten[myrpt->cidx++] = c;
06929 myrpt->exten[myrpt->cidx] = 0;
06930
06931 if (ast_exists_extension(myrpt->pchannel,myrpt->patchcontext,myrpt->exten,1,NULL))
06932 {
06933
06934 if (!ast_matchmore_extension(myrpt->pchannel,myrpt->patchcontext,
06935 myrpt->exten,1,NULL))
06936 {
06937 myrpt->callmode = 2;
06938 if(!myrpt->patchquiet)
06939 {
06940 rpt_mutex_unlock(&myrpt->lock);
06941 rpt_telemetry(myrpt,PROC,NULL);
06942 rpt_mutex_lock(&myrpt->lock);
06943 }
06944 }
06945 else
06946 {
06947 myrpt->calldigittimer = 1;
06948 }
06949 }
06950
06951 if (!ast_canmatch_extension(myrpt->pchannel,myrpt->patchcontext,myrpt->exten,1,NULL))
06952 {
06953
06954 myrpt->callmode = 4;
06955 }
06956 }
06957 if ((!myrpt->inpadtest) &&(c == myrpt->p.funcchar))
06958 {
06959 myrpt->rem_dtmfidx = 0;
06960 myrpt->rem_dtmfbuf[myrpt->rem_dtmfidx] = 0;
06961 time(&myrpt->rem_dtmf_time);
06962 rpt_mutex_unlock(&myrpt->lock);
06963 return;
06964 }
06965 else if (myrpt->rem_dtmfidx < 0)
06966 {
06967 if ((myrpt->callmode == 2) || (myrpt->callmode == 3))
06968 {
06969 myrpt->mydtmf = c;
06970 }
06971 if (myrpt->p.propagate_dtmf) do_dtmf_local(myrpt,c);
06972 if (myrpt->p.propagate_phonedtmf) do_dtmf_phone(myrpt,mylink,c);
06973 rpt_mutex_unlock(&myrpt->lock);
06974 return;
06975 }
06976 else if (((myrpt->inpadtest) || (c != myrpt->p.endchar)) && (myrpt->rem_dtmfidx >= 0))
06977 {
06978 time(&myrpt->rem_dtmf_time);
06979 if (myrpt->rem_dtmfidx < MAXDTMF)
06980 {
06981 myrpt->rem_dtmfbuf[myrpt->rem_dtmfidx++] = c;
06982 myrpt->rem_dtmfbuf[myrpt->rem_dtmfidx] = 0;
06983
06984 rpt_mutex_unlock(&myrpt->lock);
06985 strncpy(cmd, myrpt->rem_dtmfbuf, sizeof(cmd) - 1);
06986 res = collect_function_digits(myrpt, cmd, SOURCE_LNK, mylink);
06987 rpt_mutex_lock(&myrpt->lock);
06988
06989 switch(res){
06990
06991 case DC_INDETERMINATE:
06992 break;
06993
06994 case DC_REQ_FLUSH:
06995 myrpt->rem_dtmfidx = 0;
06996 myrpt->rem_dtmfbuf[0] = 0;
06997 break;
06998
06999
07000 case DC_COMPLETE:
07001 case DC_COMPLETEQUIET:
07002 myrpt->totalexecdcommands++;
07003 myrpt->dailyexecdcommands++;
07004 strncpy(myrpt->lastdtmfcommand, cmd, MAXDTMF-1);
07005 myrpt->lastdtmfcommand[MAXDTMF-1] = '\0';
07006 myrpt->rem_dtmfbuf[0] = 0;
07007 myrpt->rem_dtmfidx = -1;
07008 myrpt->rem_dtmf_time = 0;
07009 break;
07010
07011 case DC_ERROR:
07012 default:
07013 myrpt->rem_dtmfbuf[0] = 0;
07014 myrpt->rem_dtmfidx = -1;
07015 myrpt->rem_dtmf_time = 0;
07016 break;
07017 }
07018 }
07019
07020 }
07021 rpt_mutex_unlock(&myrpt->lock);
07022 return;
07023 }
07024
07025 static void handle_link_phone_dtmf(struct rpt *myrpt, struct rpt_link *mylink,
07026 char c)
07027 {
07028
07029 char cmd[300];
07030 int res;
07031
07032 if (myrpt->p.archivedir)
07033 {
07034 char str[100];
07035
07036 sprintf(str,"DTMF(P),%s,%c",mylink->name,c);
07037 donodelog(myrpt,str);
07038 }
07039 rpt_mutex_lock(&myrpt->lock);
07040
07041 if (mylink->phonemode == 3)
07042 {
07043 if(c == myrpt->p.endchar)
07044 {
07045 mylink->lastrealrx = 0;
07046 rpt_mutex_unlock(&myrpt->lock);
07047 return;
07048 }
07049
07050 if(c == myrpt->p.funcchar)
07051 {
07052 mylink->lastrealrx = !mylink->lastrealrx;
07053 rpt_mutex_unlock(&myrpt->lock);
07054 return;
07055 }
07056 }
07057 else
07058 {
07059 if (c == myrpt->p.endchar)
07060 {
07061 if (mylink->lastrx)
07062 {
07063 mylink->lastrealrx = 0;
07064 rpt_mutex_unlock(&myrpt->lock);
07065 return;
07066 }
07067 myrpt->stopgen = 1;
07068 if (myrpt->cmdnode[0])
07069 {
07070 myrpt->cmdnode[0] = 0;
07071 myrpt->dtmfidx = -1;
07072 myrpt->dtmfbuf[0] = 0;
07073 rpt_mutex_unlock(&myrpt->lock);
07074 rpt_telemetry(myrpt,COMPLETE,NULL);
07075 return;
07076 }
07077 }
07078 }
07079 if (myrpt->cmdnode[0])
07080 {
07081 rpt_mutex_unlock(&myrpt->lock);
07082 send_link_dtmf(myrpt,c);
07083 return;
07084 }
07085 if (myrpt->callmode == 1)
07086 {
07087 myrpt->exten[myrpt->cidx++] = c;
07088 myrpt->exten[myrpt->cidx] = 0;
07089
07090 if (ast_exists_extension(myrpt->pchannel,myrpt->patchcontext,myrpt->exten,1,NULL))
07091 {
07092
07093 if (!ast_matchmore_extension(myrpt->pchannel,myrpt->patchcontext,
07094 myrpt->exten,1,NULL))
07095 {
07096 myrpt->callmode = 2;
07097 if(!myrpt->patchquiet)
07098 {
07099 rpt_mutex_unlock(&myrpt->lock);
07100 rpt_telemetry(myrpt,PROC,NULL);
07101 rpt_mutex_lock(&myrpt->lock);
07102 }
07103 }
07104 else
07105 {
07106 myrpt->calldigittimer = 1;
07107 }
07108 }
07109
07110 if (!ast_canmatch_extension(myrpt->pchannel,myrpt->patchcontext,myrpt->exten,1,NULL))
07111 {
07112
07113 myrpt->callmode = 4;
07114 }
07115 }
07116 if ((myrpt->callmode == 2) || (myrpt->callmode == 3))
07117 {
07118 myrpt->mydtmf = c;
07119 }
07120 if ((!myrpt->inpadtest) && (c == myrpt->p.funcchar))
07121 {
07122 myrpt->rem_dtmfidx = 0;
07123 myrpt->rem_dtmfbuf[myrpt->rem_dtmfidx] = 0;
07124 time(&myrpt->rem_dtmf_time);
07125 rpt_mutex_unlock(&myrpt->lock);
07126 return;
07127 }
07128 else if (((myrpt->inpadtest) || (c != myrpt->p.endchar)) && (myrpt->rem_dtmfidx >= 0))
07129 {
07130 time(&myrpt->rem_dtmf_time);
07131 if (myrpt->rem_dtmfidx < MAXDTMF)
07132 {
07133 myrpt->rem_dtmfbuf[myrpt->rem_dtmfidx++] = c;
07134 myrpt->rem_dtmfbuf[myrpt->rem_dtmfidx] = 0;
07135
07136 rpt_mutex_unlock(&myrpt->lock);
07137 strncpy(cmd, myrpt->rem_dtmfbuf, sizeof(cmd) - 1);
07138 switch(mylink->phonemode)
07139 {
07140 case 1:
07141 res = collect_function_digits(myrpt, cmd,
07142 SOURCE_PHONE, mylink);
07143 break;
07144 case 2:
07145 res = collect_function_digits(myrpt, cmd,
07146 SOURCE_DPHONE,mylink);
07147 break;
07148 case 4:
07149 res = collect_function_digits(myrpt, cmd,
07150 SOURCE_ALT,mylink);
07151 break;
07152 default:
07153 res = collect_function_digits(myrpt, cmd,
07154 SOURCE_LNK, mylink);
07155 break;
07156 }
07157
07158 rpt_mutex_lock(&myrpt->lock);
07159
07160 switch(res){
07161
07162 case DC_INDETERMINATE:
07163 break;
07164
07165 case DC_DOKEY:
07166 mylink->lastrealrx = 1;
07167 break;
07168
07169 case DC_REQ_FLUSH:
07170 myrpt->rem_dtmfidx = 0;
07171 myrpt->rem_dtmfbuf[0] = 0;
07172 break;
07173
07174
07175 case DC_COMPLETE:
07176 case DC_COMPLETEQUIET:
07177 myrpt->totalexecdcommands++;
07178 myrpt->dailyexecdcommands++;
07179 strncpy(myrpt->lastdtmfcommand, cmd, MAXDTMF-1);
07180 myrpt->lastdtmfcommand[MAXDTMF-1] = '\0';
07181 myrpt->rem_dtmfbuf[0] = 0;
07182 myrpt->rem_dtmfidx = -1;
07183 myrpt->rem_dtmf_time = 0;
07184 break;
07185
07186 case DC_ERROR:
07187 default:
07188 myrpt->rem_dtmfbuf[0] = 0;
07189 myrpt->rem_dtmfidx = -1;
07190 myrpt->rem_dtmf_time = 0;
07191 break;
07192 }
07193 }
07194
07195 }
07196 rpt_mutex_unlock(&myrpt->lock);
07197 return;
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
07228
07229
07230
07231 static int rbi_mhztoband(char *str)
07232 {
07233 int i;
07234
07235 i = atoi(str) / 10;
07236 switch(i)
07237 {
07238 case 2:
07239 return 10;
07240 case 5:
07241 return 11;
07242 case 14:
07243 return 2;
07244 case 22:
07245 return 3;
07246 case 44:
07247 return 4;
07248 case 124:
07249 return 0;
07250 case 125:
07251 return 1;
07252 case 126:
07253 return 8;
07254 case 127:
07255 return 5;
07256 case 128:
07257 return 6;
07258 case 129:
07259 return 7;
07260 default:
07261 break;
07262 }
07263 return -1;
07264 }
07265
07266
07267 static int rbi_pltocode(char *str)
07268 {
07269 int i;
07270 char *s;
07271
07272 s = strchr(str,'.');
07273 i = 0;
07274 if (s) i = atoi(s + 1);
07275 i += atoi(str) * 10;
07276 switch(i)
07277 {
07278 case 670:
07279 return 0;
07280 case 719:
07281 return 1;
07282 case 744:
07283 return 2;
07284 case 770:
07285 return 3;
07286 case 797:
07287 return 4;
07288 case 825:
07289 return 5;
07290 case 854:
07291 return 6;
07292 case 885:
07293 return 7;
07294 case 915:
07295 return 8;
07296 case 948:
07297 return 9;
07298 case 974:
07299 return 10;
07300 case 1000:
07301 return 11;
07302 case 1035:
07303 return 12;
07304 case 1072:
07305 return 13;
07306 case 1109:
07307 return 14;
07308 case 1148:
07309 return 15;
07310 case 1188:
07311 return 16;
07312 case 1230:
07313 return 17;
07314 case 1273:
07315 return 18;
07316 case 1318:
07317 return 19;
07318 case 1365:
07319 return 20;
07320 case 1413:
07321 return 21;
07322 case 1462:
07323 return 22;
07324 case 1514:
07325 return 23;
07326 case 1567:
07327 return 24;
07328 case 1622:
07329 return 25;
07330 case 1679:
07331 return 26;
07332 case 1738:
07333 return 27;
07334 case 1799:
07335 return 28;
07336 case 1862:
07337 return 29;
07338 case 1928:
07339 return 30;
07340 case 2035:
07341 return 31;
07342 case 2107:
07343 return 32;
07344 case 2181:
07345 return 33;
07346 case 2257:
07347 return 34;
07348 case 2336:
07349 return 35;
07350 case 2418:
07351 return 36;
07352 case 2503:
07353 return 37;
07354 }
07355 return -1;
07356 }
07357
07358
07359
07360
07361
07362 static void rbi_out_parallel(struct rpt *myrpt,unsigned char *data)
07363 {
07364 #ifdef __i386__
07365 int i,j;
07366 unsigned char od,d;
07367 static volatile long long delayvar;
07368
07369 for(i = 0 ; i < 5 ; i++){
07370 od = *data++;
07371 for(j = 0 ; j < 8 ; j++){
07372 d = od & 1;
07373 outb(d,myrpt->p.iobase);
07374
07375 for(delayvar = 1; delayvar < 15000; delayvar++);
07376 od >>= 1;
07377 outb(d | 2,myrpt->p.iobase);
07378
07379 for(delayvar = 1; delayvar < 30000; delayvar++);
07380 outb(d,myrpt->p.iobase);
07381
07382 for(delayvar = 1; delayvar < 10000; delayvar++);
07383 }
07384 }
07385
07386 for(delayvar = 1; delayvar < 50000; delayvar++);
07387 #endif
07388 }
07389
07390 static void rbi_out(struct rpt *myrpt,unsigned char *data)
07391 {
07392 struct dahdi_radio_param r;
07393
07394 memset(&r,0,sizeof(struct dahdi_radio_param));
07395 r.radpar = DAHDI_RADPAR_REMMODE;
07396 r.data = DAHDI_RADPAR_REM_RBI1;
07397
07398 if (ioctl(myrpt->dahdirxchannel->fds[0],DAHDI_RADIO_SETPARAM,&r) == -1)
07399 {
07400 rbi_out_parallel(myrpt,data);
07401 return;
07402 }
07403 r.radpar = DAHDI_RADPAR_REMCOMMAND;
07404 memcpy(&r.data,data,5);
07405 if (ioctl(myrpt->dahdirxchannel->fds[0],DAHDI_RADIO_SETPARAM,&r) == -1)
07406 {
07407 ast_log(LOG_WARNING,"Cannot send RBI command for channel %s\n",myrpt->dahdirxchannel->name);
07408 return;
07409 }
07410 }
07411
07412 static int serial_remote_io(struct rpt *myrpt, unsigned char *txbuf, int txbytes,
07413 unsigned char *rxbuf, int rxmaxbytes, int asciiflag)
07414 {
07415 int i,j,idx,oldmode,olddata;
07416 struct dahdi_radio_param prm;
07417 char c;
07418
07419 if(debug) {
07420 ast_log(LOG_NOTICE, "ioport=%s iofd=0x%x\n",myrpt->p.ioport,myrpt->iofd);
07421 printf("String output was:\n");
07422 for(i = 0; i < txbytes; i++)
07423 printf("%02X ", (unsigned char ) txbuf[i]);
07424 printf("\n");
07425 }
07426
07427 if (myrpt->iofd >= 0)
07428 {
07429 if (write(myrpt->iofd,txbuf,txbytes) != txbytes)
07430 {
07431 return -1;
07432 }
07433 if ((!rxmaxbytes) || (rxbuf == NULL))
07434 {
07435 return(0);
07436 }
07437 memset(rxbuf,0,rxmaxbytes);
07438 for(i = 0; i < rxmaxbytes; i++)
07439 {
07440 j = read(myrpt->iofd,&c,1);
07441 if (j < 1)
07442 {
07443 return(i);
07444 }
07445 rxbuf[i] = c;
07446 if (asciiflag & 1)
07447 {
07448 rxbuf[i + 1] = 0;
07449 if (c == '\r') break;
07450 }
07451 }
07452 if(debug) {
07453 printf("String returned was:\n");
07454 for(j = 0; j < i; j++)
07455 printf("%02X ", (unsigned char ) rxbuf[j]);
07456 printf("\n");
07457 }
07458 return(i);
07459 }
07460
07461
07462 if (myrpt->rxchannel != myrpt->dahdirxchannel) return -1;
07463
07464 prm.radpar = DAHDI_RADPAR_UIOMODE;
07465 if (ioctl(myrpt->dahdirxchannel->fds[0],DAHDI_RADIO_GETPARAM,&prm) == -1) return -1;
07466 oldmode = prm.data;
07467 prm.radpar = DAHDI_RADPAR_UIODATA;
07468 if (ioctl(myrpt->dahdirxchannel->fds[0],DAHDI_RADIO_GETPARAM,&prm) == -1) return -1;
07469 olddata = prm.data;
07470 prm.radpar = DAHDI_RADPAR_REMMODE;
07471 if (asciiflag & 1) prm.data = DAHDI_RADPAR_REM_SERIAL_ASCII;
07472 else prm.data = DAHDI_RADPAR_REM_SERIAL;
07473 if (ioctl(myrpt->dahdirxchannel->fds[0],DAHDI_RADIO_SETPARAM,&prm) == -1) return -1;
07474 if (asciiflag & 2)
07475 {
07476 i = DAHDI_ONHOOK;
07477 if (ioctl(myrpt->dahdirxchannel->fds[0],DAHDI_HOOK,&i) == -1) return -1;
07478 usleep(100000);
07479 }
07480 prm.radpar = DAHDI_RADPAR_REMCOMMAND;
07481 prm.data = rxmaxbytes;
07482 memcpy(prm.buf,txbuf,txbytes);
07483 prm.index = txbytes;
07484 if (ioctl(myrpt->dahdirxchannel->fds[0],DAHDI_RADIO_SETPARAM,&prm) == -1) return -1;
07485 if (rxbuf)
07486 {
07487 *rxbuf = 0;
07488 memcpy(rxbuf,prm.buf,prm.index);
07489 }
07490 idx = prm.index;
07491 prm.radpar = DAHDI_RADPAR_REMMODE;
07492 prm.data = DAHDI_RADPAR_REM_NONE;
07493 if (ioctl(myrpt->dahdirxchannel->fds[0],DAHDI_RADIO_SETPARAM,&prm) == -1) return -1;
07494 if (asciiflag & 2)
07495 {
07496 i = DAHDI_OFFHOOK;
07497 if (ioctl(myrpt->dahdirxchannel->fds[0],DAHDI_HOOK,&i) == -1) return -1;
07498 }
07499 prm.radpar = DAHDI_RADPAR_UIOMODE;
07500 prm.data = oldmode;
07501 if (ioctl(myrpt->dahdirxchannel->fds[0],DAHDI_RADIO_SETPARAM,&prm) == -1) return -1;
07502 prm.radpar = DAHDI_RADPAR_UIODATA;
07503 prm.data = olddata;
07504 if (ioctl(myrpt->dahdirxchannel->fds[0],DAHDI_RADIO_SETPARAM,&prm) == -1) return -1;
07505 return(idx);
07506 }
07507
07508 static int civ_cmd(struct rpt *myrpt,unsigned char *cmd, int cmdlen)
07509 {
07510 unsigned char rxbuf[100];
07511 int i,rv ;
07512
07513 rv = serial_remote_io(myrpt,cmd,cmdlen,rxbuf,cmdlen + 6,0);
07514 if (rv == -1) return(-1);
07515 if (rv != (cmdlen + 6)) return(1);
07516 for(i = 0; i < 6; i++)
07517 if (rxbuf[i] != cmd[i]) return(1);
07518 if (rxbuf[cmdlen] != 0xfe) return(1);
07519 if (rxbuf[cmdlen + 1] != 0xfe) return(1);
07520 if (rxbuf[cmdlen + 4] != 0xfb) return(1);
07521 if (rxbuf[cmdlen + 5] != 0xfd) return(1);
07522 return(0);
07523 }
07524
07525 static int sendkenwood(struct rpt *myrpt,char *txstr, char *rxstr)
07526 {
07527 int i;
07528
07529 ast_log(LOG_NOTICE,"Sent to kenwood: %s\n",txstr);
07530 if (debug) printf("Send to kenwood: %s\n",txstr);
07531 i = serial_remote_io(myrpt, (unsigned char *)txstr, strlen(txstr),
07532 (unsigned char *)rxstr,RAD_SERIAL_BUFLEN - 1,3);
07533 if (i < 0) return -1;
07534 if ((i > 0) && (rxstr[i - 1] == '\r'))
07535 rxstr[i-- - 1] = 0;
07536 if (debug) printf("Got from kenwood: %s\n",rxstr);
07537 ast_log(LOG_NOTICE,"Got from kenwood: %s\n",rxstr);
07538 return(i);
07539 }
07540
07541
07542 static int kenwood_pltocode(char *str)
07543 {
07544 int i;
07545 char *s;
07546
07547 s = strchr(str,'.');
07548 i = 0;
07549 if (s) i = atoi(s + 1);
07550 i += atoi(str) * 10;
07551 switch(i)
07552 {
07553 case 670:
07554 return 1;
07555 case 719:
07556 return 3;
07557 case 744:
07558 return 4;
07559 case 770:
07560 return 5;
07561 case 797:
07562 return 6;
07563 case 825:
07564 return 7;
07565 case 854:
07566 return 8;
07567 case 885:
07568 return 9;
07569 case 915:
07570 return 10;
07571 case 948:
07572 return 11;
07573 case 974:
07574 return 12;
07575 case 1000:
07576 return 13;
07577 case 1035:
07578 return 14;
07579 case 1072:
07580 return 15;
07581 case 1109:
07582 return 16;
07583 case 1148:
07584 return 17;
07585 case 1188:
07586 return 18;
07587 case 1230:
07588 return 19;
07589 case 1273:
07590 return 20;
07591 case 1318:
07592 return 21;
07593 case 1365:
07594 return 22;
07595 case 1413:
07596 return 23;
07597 case 1462:
07598 return 24;
07599 case 1514:
07600 return 25;
07601 case 1567:
07602 return 26;
07603 case 1622:
07604 return 27;
07605 case 1679:
07606 return 28;
07607 case 1738:
07608 return 29;
07609 case 1799:
07610 return 30;
07611 case 1862:
07612 return 31;
07613 case 1928:
07614 return 32;
07615 case 2035:
07616 return 33;
07617 case 2107:
07618 return 34;
07619 case 2181:
07620 return 35;
07621 case 2257:
07622 return 36;
07623 case 2336:
07624 return 37;
07625 case 2418:
07626 return 38;
07627 case 2503:
07628 return 39;
07629 }
07630 return -1;
07631 }
07632
07633 static int sendrxkenwood(struct rpt *myrpt, char *txstr, char *rxstr,
07634 char *cmpstr)
07635 {
07636 int i,j;
07637
07638 for(i = 0;i < KENWOOD_RETRIES;i++)
07639 {
07640 j = sendkenwood(myrpt,txstr,rxstr);
07641 if (j < 0) return(j);
07642 if (j == 0) continue;
07643 if (!strncmp(rxstr,cmpstr,strlen(cmpstr))) return(0);
07644 }
07645 return(-1);
07646 }
07647
07648 static int setkenwood(struct rpt *myrpt)
07649 {
07650 char rxstr[RAD_SERIAL_BUFLEN],txstr[RAD_SERIAL_BUFLEN],freq[20];
07651 char mhz[MAXREMSTR],offset[20],band,decimals[MAXREMSTR],band1,band2;
07652 int myrxpl;
07653
07654 int offsets[] = {0,2,1};
07655 int powers[] = {2,1,0};
07656
07657 if (sendrxkenwood(myrpt,"VMC 0,0\r",rxstr,"VMC") < 0) return -1;
07658 split_freq(mhz, decimals, myrpt->freq);
07659 if (atoi(mhz) > 400)
07660 {
07661 band = '6';
07662 band1 = '1';
07663 band2 = '5';
07664 strcpy(offset,"005000000");
07665 }
07666 else
07667 {
07668 band = '2';
07669 band1 = '0';
07670 band2 = '2';
07671 strcpy(offset,"000600000");
07672 }
07673 strcpy(freq,"000000");
07674 strncpy(freq,decimals,strlen(decimals));
07675 myrxpl = myrpt->rxplon;
07676 if (IS_XPMR(myrpt)) myrxpl = 0;
07677 sprintf(txstr,"VW %c,%05d%s,0,%d,0,%d,%d,,%02d,,%02d,%s\r",
07678 band,atoi(mhz),freq,offsets[(int)myrpt->offset],
07679 (myrpt->txplon != 0),myrxpl,
07680 kenwood_pltocode(myrpt->txpl),kenwood_pltocode(myrpt->rxpl),
07681 offset);
07682 if (sendrxkenwood(myrpt,txstr,rxstr,"VW") < 0) return -1;
07683 sprintf(txstr,"RBN %c\r",band2);
07684 if (sendrxkenwood(myrpt,txstr,rxstr,"RBN") < 0) return -1;
07685 sprintf(txstr,"PC %c,%d\r",band1,powers[(int)myrpt->powerlevel]);
07686 if (sendrxkenwood(myrpt,txstr,rxstr,"PC") < 0) return -1;
07687 return 0;
07688 }
07689
07690 static int set_tm271(struct rpt *myrpt)
07691 {
07692 char rxstr[RAD_SERIAL_BUFLEN],txstr[RAD_SERIAL_BUFLEN],freq[20];
07693 char mhz[MAXREMSTR],decimals[MAXREMSTR];
07694
07695 int offsets[] = {0,2,1};
07696 int powers[] = {2,1,0};
07697
07698 split_freq(mhz, decimals, myrpt->freq);
07699 strcpy(freq,"000000");
07700 strncpy(freq,decimals,strlen(decimals));
07701
07702 sprintf(txstr,"VF %04d%s,4,%d,0,%d,0,0,%d,%d,000,00600000,0,0\r",
07703 atoi(mhz),freq,offsets[(int)myrpt->offset],
07704 (myrpt->txplon != 0),kenwood_pltocode(myrpt->txpl),
07705 kenwood_pltocode(myrpt->rxpl));
07706
07707 if (sendrxkenwood(myrpt,txstr,rxstr,"VF") < 0) return -1;
07708 if (sendrxkenwood(myrpt,"VM 0\r",rxstr,"VM") < 0) return -1;
07709 sprintf(txstr,"PC %d\r",powers[(int)myrpt->powerlevel]);
07710 if (sendrxkenwood(myrpt,txstr,rxstr,"PC") < 0) return -1;
07711 return 0;
07712 }
07713
07714 static int setrbi(struct rpt *myrpt)
07715 {
07716 char tmp[MAXREMSTR] = "",*s;
07717 unsigned char rbicmd[5];
07718 int band,txoffset = 0,txpower = 0,rxpl;
07719
07720
07721 if (!myrpt->remoterig) return(0);
07722 if (!myrpt->remoterig[0]) return(0);
07723
07724 if (strncmp(myrpt->remoterig,remote_rig_rbi,3)) return(0);
07725 if (setrbi_check(myrpt) == -1) return(-1);
07726 strncpy(tmp, myrpt->freq, sizeof(tmp) - 1);
07727 s = strchr(tmp,'.');
07728
07729
07730 if (s == NULL){
07731 if(debug)
07732 printf("@@@@ Frequency needs a decimal\n");
07733 return -1;
07734 }
07735
07736 *s++ = 0;
07737 if (strlen(tmp) < 2){
07738 if(debug)
07739 printf("@@@@ Bad MHz digits: %s\n", tmp);
07740 return -1;
07741 }
07742
07743 if (strlen(s) < 3){
07744 if(debug)
07745 printf("@@@@ Bad KHz digits: %s\n", s);
07746 return -1;
07747 }
07748
07749 if ((s[2] != '0') && (s[2] != '5')){
07750 if(debug)
07751 printf("@@@@ KHz must end in 0 or 5: %c\n", s[2]);
07752 return -1;
07753 }
07754
07755 band = rbi_mhztoband(tmp);
07756 if (band == -1){
07757 if(debug)
07758 printf("@@@@ Bad Band: %s\n", tmp);
07759 return -1;
07760 }
07761
07762 rxpl = rbi_pltocode(myrpt->rxpl);
07763
07764 if (rxpl == -1){
07765 if(debug)
07766 printf("@@@@ Bad TX PL: %s\n", myrpt->rxpl);
07767 return -1;
07768 }
07769
07770
07771 switch(myrpt->offset)
07772 {
07773 case REM_MINUS:
07774 txoffset = 0;
07775 break;
07776 case REM_PLUS:
07777 txoffset = 0x10;
07778 break;
07779 case REM_SIMPLEX:
07780 txoffset = 0x20;
07781 break;
07782 }
07783 switch(myrpt->powerlevel)
07784 {
07785 case REM_LOWPWR:
07786 txpower = 0;
07787 break;
07788 case REM_MEDPWR:
07789 txpower = 0x20;
07790 break;
07791 case REM_HIPWR:
07792 txpower = 0x10;
07793 break;
07794 }
07795 rbicmd[0] = 0;
07796 rbicmd[1] = band | txpower | 0xc0;
07797 rbicmd[2] = (*(s - 2) - '0') | txoffset | 0x80;
07798 if (s[2] == '5') rbicmd[2] |= 0x40;
07799 rbicmd[3] = ((*s - '0') << 4) + (s[1] - '0');
07800 rbicmd[4] = rxpl;
07801 if (myrpt->txplon) rbicmd[4] |= 0x40;
07802 if (myrpt->rxplon) rbicmd[4] |= 0x80;
07803 rbi_out(myrpt,rbicmd);
07804 return 0;
07805 }
07806
07807 static int setrtx(struct rpt *myrpt)
07808 {
07809 char tmp[MAXREMSTR] = "",*s,rigstr[200],pwr,res = 0;
07810 int band,txoffset = 0,txpower = 0,rxpl,txpl;
07811 float ofac;
07812 double txfreq;
07813
07814
07815 if (!myrpt->remoterig) return(0);
07816 if (!myrpt->remoterig[0]) return(0);
07817
07818 if (!ISRIG_RTX(myrpt->remoterig)) return(0);
07819
07820 if (!IS_XPMR(myrpt)) return(0);
07821 strncpy(tmp, myrpt->freq, sizeof(tmp) - 1);
07822 s = strchr(tmp,'.');
07823
07824
07825 if(debug)printf("setrtx() %s %s\n",myrpt->name,myrpt->remoterig);
07826
07827 if (s == NULL){
07828 if(debug)
07829 printf("@@@@ Frequency needs a decimal\n");
07830 return -1;
07831 }
07832 *s++ = 0;
07833 if (strlen(tmp) < 2){
07834 if(debug)
07835 printf("@@@@ Bad MHz digits: %s\n", tmp);
07836 return -1;
07837 }
07838
07839 if (strlen(s) < 3){
07840 if(debug)
07841 printf("@@@@ Bad KHz digits: %s\n", s);
07842 return -1;
07843 }
07844
07845 if ((s[2] != '0') && (s[2] != '5')){
07846 if(debug)
07847 printf("@@@@ KHz must end in 0 or 5: %c\n", s[2]);
07848 return -1;
07849 }
07850
07851 band = rbi_mhztoband(tmp);
07852 if (band == -1){
07853 if(debug)
07854 printf("@@@@ Bad Band: %s\n", tmp);
07855 return -1;
07856 }
07857
07858 rxpl = rbi_pltocode(myrpt->rxpl);
07859
07860 if (rxpl == -1){
07861 if(debug)
07862 printf("@@@@ Bad RX PL: %s\n", myrpt->rxpl);
07863 return -1;
07864 }
07865
07866 txpl = rbi_pltocode(myrpt->txpl);
07867
07868 if (txpl == -1){
07869 if(debug)
07870 printf("@@@@ Bad TX PL: %s\n", myrpt->txpl);
07871 return -1;
07872 }
07873
07874 switch(myrpt->offset)
07875 {
07876 case REM_MINUS:
07877 txoffset = 0;
07878 break;
07879 case REM_PLUS:
07880 txoffset = 0x10;
07881 break;
07882 case REM_SIMPLEX:
07883 txoffset = 0x20;
07884 break;
07885 }
07886 switch(myrpt->powerlevel)
07887 {
07888 case REM_LOWPWR:
07889 txpower = 0;
07890 break;
07891 case REM_MEDPWR:
07892 txpower = 0x20;
07893 break;
07894 case REM_HIPWR:
07895 txpower = 0x10;
07896 break;
07897 }
07898
07899 res = setrtx_check(myrpt);
07900 if (res < 0) return res;
07901 ofac = 0.0;
07902 if (myrpt->offset == REM_MINUS) ofac = -1.0;
07903 if (myrpt->offset == REM_PLUS) ofac = 1.0;
07904
07905 if (!strcmp(myrpt->remoterig,remote_rig_rtx450))
07906 txfreq = atof(myrpt->freq) + (ofac * 5.0);
07907 else
07908 txfreq = atof(myrpt->freq) + (ofac * 0.6);
07909
07910 pwr = 'L';
07911 if (myrpt->powerlevel == REM_HIPWR) pwr = 'H';
07912 if (!res)
07913 {
07914 sprintf(rigstr,"SETFREQ %s %f %s %s %c",myrpt->freq,txfreq,
07915 (myrpt->rxplon) ? myrpt->rxpl : "0.0",
07916 (myrpt->txplon) ? myrpt->txpl : "0.0",pwr);
07917 send_usb_txt(myrpt,rigstr);
07918 rpt_telemetry(myrpt,COMPLETE,NULL);
07919 res = 0;
07920 }
07921 return 0;
07922 }
07923 #if 0
07924
07925
07926
07927
07928 static int setxpmr(struct rpt *myrpt)
07929 {
07930 char rigstr[200];
07931 int rxpl,txpl;
07932
07933
07934 if (!myrpt->remoterig) return(0);
07935 if (!myrpt->remoterig[0]) return(0);
07936
07937 if (ISRIG_RTX(myrpt->remoterig)) return(0);
07938
07939 if (!IS_XPMR(myrpt)) return(0);
07940
07941 if(debug)printf("setxpmr() %s %s\n",myrpt->name,myrpt->remoterig );
07942
07943 rxpl = rbi_pltocode(myrpt->rxpl);
07944
07945 if (rxpl == -1){
07946 if(debug)
07947 printf("@@@@ Bad RX PL: %s\n", myrpt->rxpl);
07948 return -1;
07949 }
07950
07951 txpl = rbi_pltocode(myrpt->txpl);
07952 if (txpl == -1){
07953 if(debug)
07954 printf("@@@@ Bad TX PL: %s\n", myrpt->txpl);
07955 return -1;
07956 }
07957 sprintf(rigstr,"SETFREQ 0.0 0.0 %s %s L",
07958 (myrpt->rxplon) ? myrpt->rxpl : "0.0",
07959 (myrpt->txplon) ? myrpt->txpl : "0.0");
07960 send_usb_txt(myrpt,rigstr);
07961 return 0;
07962 }
07963 #endif
07964
07965 static int setrbi_check(struct rpt *myrpt)
07966 {
07967 char tmp[MAXREMSTR] = "",*s;
07968 int band,txpl;
07969
07970
07971 if (!myrpt->remote) return(0);
07972
07973 if (strncmp(myrpt->remoterig,remote_rig_rbi,3)) return(0);
07974 strncpy(tmp, myrpt->freq, sizeof(tmp) - 1);
07975 s = strchr(tmp,'.');
07976
07977
07978 if (s == NULL){
07979 if(debug)
07980 printf("@@@@ Frequency needs a decimal\n");
07981 return -1;
07982 }
07983
07984 *s++ = 0;
07985 if (strlen(tmp) < 2){
07986 if(debug)
07987 printf("@@@@ Bad MHz digits: %s\n", tmp);
07988 return -1;
07989 }
07990
07991 if (strlen(s) < 3){
07992 if(debug)
07993 printf("@@@@ Bad KHz digits: %s\n", s);
07994 return -1;
07995 }
07996
07997 if ((s[2] != '0') && (s[2] != '5')){
07998 if(debug)
07999 printf("@@@@ KHz must end in 0 or 5: %c\n", s[2]);
08000 return -1;
08001 }
08002
08003 band = rbi_mhztoband(tmp);
08004 if (band == -1){
08005 if(debug)
08006 printf("@@@@ Bad Band: %s\n", tmp);
08007 return -1;
08008 }
08009
08010 txpl = rbi_pltocode(myrpt->txpl);
08011
08012 if (txpl == -1){
08013 if(debug)
08014 printf("@@@@ Bad TX PL: %s\n", myrpt->txpl);
08015 return -1;
08016 }
08017 return 0;
08018 }
08019
08020 static int setrtx_check(struct rpt *myrpt)
08021 {
08022 char tmp[MAXREMSTR] = "",*s;
08023 int band,txpl,rxpl;
08024
08025
08026 if (!myrpt->remote) return(0);
08027
08028 if (strncmp(myrpt->remoterig,remote_rig_rbi,3)) return(0);
08029 strncpy(tmp, myrpt->freq, sizeof(tmp) - 1);
08030 s = strchr(tmp,'.');
08031
08032
08033 if (s == NULL){
08034 if(debug)
08035 printf("@@@@ Frequency needs a decimal\n");
08036 return -1;
08037 }
08038
08039 *s++ = 0;
08040 if (strlen(tmp) < 2){
08041 if(debug)
08042 printf("@@@@ Bad MHz digits: %s\n", tmp);
08043 return -1;
08044 }
08045
08046 if (strlen(s) < 3){
08047 if(debug)
08048 printf("@@@@ Bad KHz digits: %s\n", s);
08049 return -1;
08050 }
08051
08052 if ((s[2] != '0') && (s[2] != '5')){
08053 if(debug)
08054 printf("@@@@ KHz must end in 0 or 5: %c\n", s[2]);
08055 return -1;
08056 }
08057
08058 band = rbi_mhztoband(tmp);
08059 if (band == -1){
08060 if(debug)
08061 printf("@@@@ Bad Band: %s\n", tmp);
08062 return -1;
08063 }
08064
08065 txpl = rbi_pltocode(myrpt->txpl);
08066
08067 if (txpl == -1){
08068 if(debug)
08069 printf("@@@@ Bad TX PL: %s\n", myrpt->txpl);
08070 return -1;
08071 }
08072
08073 rxpl = rbi_pltocode(myrpt->rxpl);
08074
08075 if (rxpl == -1){
08076 if(debug)
08077 printf("@@@@ Bad RX PL: %s\n", myrpt->rxpl);
08078 return -1;
08079 }
08080 return 0;
08081 }
08082
08083 static int check_freq_kenwood(int m, int d, int *defmode)
08084 {
08085 int dflmd = REM_MODE_FM;
08086
08087 if (m == 144){
08088 if(d < 10100)
08089 return -1;
08090 }
08091 else if((m >= 145) && (m < 148)){
08092 ;
08093 }
08094 else if((m >= 430) && (m < 450)){
08095 ;
08096 }
08097 else
08098 return -1;
08099
08100 if(defmode)
08101 *defmode = dflmd;
08102
08103
08104 return 0;
08105 }
08106
08107
08108 static int check_freq_tm271(int m, int d, int *defmode)
08109 {
08110 int dflmd = REM_MODE_FM;
08111
08112 if (m == 144){
08113 if(d < 10100)
08114 return -1;
08115 }
08116 else if((m >= 145) && (m < 148)){
08117 ;
08118 }
08119 return -1;
08120
08121 if(defmode)
08122 *defmode = dflmd;
08123
08124
08125 return 0;
08126 }
08127
08128
08129
08130
08131
08132 static int check_freq_rbi(int m, int d, int *defmode)
08133 {
08134 int dflmd = REM_MODE_FM;
08135
08136 if(m == 50){
08137 if(d < 10100)
08138 return -1;
08139 }
08140 else if((m >= 51) && ( m < 54)){
08141 ;
08142 }
08143 else if(m == 144){
08144 if(d < 10100)
08145 return -1;
08146 }
08147 else if((m >= 145) && (m < 148)){
08148 ;
08149 }
08150 else if((m >= 222) && (m < 225)){
08151 ;
08152 }
08153 else if((m >= 430) && (m < 450)){
08154 ;
08155 }
08156 else if((m >= 1240) && (m < 1300)){
08157 ;
08158 }
08159 else
08160 return -1;
08161
08162 if(defmode)
08163 *defmode = dflmd;
08164
08165
08166 return 0;
08167 }
08168
08169
08170
08171
08172 static int check_freq_rtx(int m, int d, int *defmode, struct rpt *myrpt)
08173 {
08174 int dflmd = REM_MODE_FM;
08175
08176 if (!strcmp(myrpt->remoterig,remote_rig_rtx150))
08177 {
08178
08179 if(m == 144){
08180 if(d < 10100)
08181 return -1;
08182 }
08183 else if((m >= 145) && (m < 148)){
08184 ;
08185 }
08186 else
08187 return -1;
08188 }
08189 else
08190 {
08191 if((m >= 430) && (m < 450)){
08192 ;
08193 }
08194 else
08195 return -1;
08196 }
08197 if(defmode)
08198 *defmode = dflmd;
08199
08200
08201 return 0;
08202 }
08203
08204
08205
08206
08207
08208 static int decimals2int(char *fraction)
08209 {
08210 int i;
08211 char len = strlen(fraction);
08212 int multiplier = 100000;
08213 int res = 0;
08214
08215 if(!len)
08216 return 0;
08217 for( i = 0 ; i < len ; i++, multiplier /= 10)
08218 res += (fraction[i] - '0') * multiplier;
08219 return res;
08220 }
08221
08222
08223
08224
08225
08226
08227 static int split_freq(char *mhz, char *decimals, char *freq)
08228 {
08229 char freq_copy[MAXREMSTR];
08230 char *decp;
08231
08232 decp = strchr(strncpy(freq_copy, freq, MAXREMSTR),'.');
08233 if(decp){
08234 *decp++ = 0;
08235 strncpy(mhz, freq_copy, MAXREMSTR);
08236 strcpy(decimals, "00000");
08237 strncpy(decimals, decp, strlen(decp));
08238 decimals[5] = 0;
08239 return 0;
08240 }
08241 else
08242 return -1;
08243
08244 }
08245
08246
08247
08248
08249
08250 static int split_ctcss_freq(char *hertz, char *decimal, char *freq)
08251 {
08252 char freq_copy[MAXREMSTR];
08253 char *decp;
08254
08255 decp = strchr(strncpy(freq_copy, freq, MAXREMSTR),'.');
08256 if(decp){
08257 *decp++ = 0;
08258 strncpy(hertz, freq_copy, MAXREMSTR);
08259 strncpy(decimal, decp, strlen(decp));
08260 decimal[strlen(decp)] = '\0';
08261 return 0;
08262 }
08263 else
08264 return -1;
08265 }
08266
08267
08268
08269
08270
08271
08272
08273
08274
08275
08276
08277 static int check_freq_ft897(int m, int d, int *defmode)
08278 {
08279 int dflmd = REM_MODE_FM;
08280
08281 if(m == 1){
08282 dflmd = REM_MODE_LSB;
08283 if(d < 80000)
08284 return -1;
08285 }
08286 else if(m == 3){
08287 dflmd = REM_MODE_LSB;
08288 if(d < 50000)
08289 return -1;
08290 }
08291 else if(m == 7){
08292 dflmd = REM_MODE_LSB;
08293 if(d > 30000)
08294 return -1;
08295 }
08296 else if(m == 14){
08297 dflmd = REM_MODE_USB;
08298 if(d > 35000)
08299 return -1;
08300 }
08301 else if(m == 18){
08302 dflmd = REM_MODE_USB;
08303 if((d < 6800) || (d > 16800))
08304 return -1;
08305 }
08306 else if(m == 21){
08307 dflmd = REM_MODE_USB;
08308 if((d < 20000) || (d > 45000))
08309 return -1;
08310 }
08311 else if(m == 24){
08312 dflmd = REM_MODE_USB;
08313 if((d < 89000) || (d > 99000))
08314 return -1;
08315 }
08316 else if(m == 28){
08317 dflmd = REM_MODE_USB;
08318 }
08319 else if(m == 29){
08320 if(d >= 51000)
08321 dflmd = REM_MODE_FM;
08322 else
08323 dflmd = REM_MODE_USB;
08324 if(d > 70000)
08325 return -1;
08326 }
08327 else if(m == 50){
08328 if(d >= 30000)
08329 dflmd = REM_MODE_FM;
08330 else
08331 dflmd = REM_MODE_USB;
08332
08333 }
08334 else if((m >= 51) && ( m < 54)){
08335 dflmd = REM_MODE_FM;
08336 }
08337 else if(m == 144){
08338 if(d >= 30000)
08339 dflmd = REM_MODE_FM;
08340 else
08341 dflmd = REM_MODE_USB;
08342 }
08343 else if((m >= 145) && (m < 148)){
08344 dflmd = REM_MODE_FM;
08345 }
08346 else if((m >= 430) && (m < 450)){
08347 if(m < 438)
08348 dflmd = REM_MODE_USB;
08349 else
08350 dflmd = REM_MODE_FM;
08351 ;
08352 }
08353 else
08354 return -1;
08355
08356 if(defmode)
08357 *defmode = dflmd;
08358
08359 return 0;
08360 }
08361
08362
08363
08364
08365
08366 static int set_freq_ft897(struct rpt *myrpt, char *newfreq)
08367 {
08368 unsigned char cmdstr[5];
08369 int fd,m,d;
08370 char mhz[MAXREMSTR];
08371 char decimals[MAXREMSTR];
08372
08373 fd = 0;
08374 if(debug)
08375 printf("New frequency: %s\n",newfreq);
08376
08377 if(split_freq(mhz, decimals, newfreq))
08378 return -1;
08379
08380 m = atoi(mhz);
08381 d = atoi(decimals);
08382
08383
08384
08385 cmdstr[0] = ((m / 100) << 4) + ((m % 100)/10);
08386 cmdstr[1] = ((m % 10) << 4) + (d / 10000);
08387 cmdstr[2] = (((d % 10000)/1000) << 4) + ((d % 1000)/ 100);
08388 cmdstr[3] = (((d % 100)/10) << 4) + (d % 10);
08389 cmdstr[4] = 0x01;
08390
08391 return serial_remote_io(myrpt, cmdstr, 5, NULL, 0, 0);
08392
08393 }
08394
08395
08396
08397 static int simple_command_ft897(struct rpt *myrpt, char command)
08398 {
08399 unsigned char cmdstr[5];
08400
08401 memset(cmdstr, 0, 5);
08402
08403 cmdstr[4] = command;
08404
08405 return serial_remote_io(myrpt, cmdstr, 5, NULL, 0, 0);
08406
08407 }
08408
08409
08410
08411 static int set_offset_ft897(struct rpt *myrpt, char offset)
08412 {
08413 unsigned char cmdstr[5];
08414
08415 memset(cmdstr, 0, 5);
08416
08417 switch(offset){
08418 case REM_SIMPLEX:
08419 cmdstr[0] = 0x89;
08420 break;
08421
08422 case REM_MINUS:
08423 cmdstr[0] = 0x09;
08424 break;
08425
08426 case REM_PLUS:
08427 cmdstr[0] = 0x49;
08428 break;
08429
08430 default:
08431 return -1;
08432 }
08433
08434 cmdstr[4] = 0x09;
08435
08436 return serial_remote_io(myrpt, cmdstr, 5, NULL, 0, 0);
08437 }
08438
08439
08440
08441 static int set_mode_ft897(struct rpt *myrpt, char newmode)
08442 {
08443 unsigned char cmdstr[5];
08444
08445 memset(cmdstr, 0, 5);
08446
08447 switch(newmode){
08448 case REM_MODE_FM:
08449 cmdstr[0] = 0x08;
08450 break;
08451
08452 case REM_MODE_USB:
08453 cmdstr[0] = 0x01;
08454 break;
08455
08456 case REM_MODE_LSB:
08457 cmdstr[0] = 0x00;
08458 break;
08459
08460 case REM_MODE_AM:
08461 cmdstr[0] = 0x04;
08462 break;
08463
08464 default:
08465 return -1;
08466 }
08467 cmdstr[4] = 0x07;
08468
08469 return serial_remote_io(myrpt, cmdstr, 5, NULL, 0, 0);
08470 }
08471
08472
08473
08474 static int set_ctcss_mode_ft897(struct rpt *myrpt, char txplon, char rxplon)
08475 {
08476 unsigned char cmdstr[5];
08477
08478 memset(cmdstr, 0, 5);
08479
08480 if(rxplon && txplon)
08481 cmdstr[0] = 0x2A;
08482 else if (!rxplon && txplon)
08483 cmdstr[0] = 0x4A;
08484 else if (rxplon && !txplon)
08485 cmdstr[0] = 0x3A;
08486 else
08487 cmdstr[0] = 0x8A;
08488
08489 cmdstr[4] = 0x0A;
08490
08491 return serial_remote_io(myrpt, cmdstr, 5, NULL, 0, 0);
08492 }
08493
08494
08495
08496
08497 static int set_ctcss_freq_ft897(struct rpt *myrpt, char *txtone, char *rxtone)
08498 {
08499 unsigned char cmdstr[5];
08500 char hertz[MAXREMSTR],decimal[MAXREMSTR];
08501 int h,d;
08502
08503 memset(cmdstr, 0, 5);
08504
08505 if(split_ctcss_freq(hertz, decimal, txtone))
08506 return -1;
08507
08508 h = atoi(hertz);
08509 d = atoi(decimal);
08510
08511 cmdstr[0] = ((h / 100) << 4) + (h % 100)/ 10;
08512 cmdstr[1] = ((h % 10) << 4) + (d % 10);
08513
08514 if(rxtone){
08515
08516 if(split_ctcss_freq(hertz, decimal, rxtone))
08517 return -1;
08518
08519 h = atoi(hertz);
08520 d = atoi(decimal);
08521
08522 cmdstr[2] = ((h / 100) << 4) + (h % 100)/ 10;
08523 cmdstr[3] = ((h % 10) << 4) + (d % 10);
08524 }
08525 cmdstr[4] = 0x0B;
08526
08527 return serial_remote_io(myrpt, cmdstr, 5, NULL, 0, 0);
08528 }
08529
08530
08531
08532 static int set_ft897(struct rpt *myrpt)
08533 {
08534 int res;
08535
08536 if(debug)
08537 printf("@@@@ lock on\n");
08538
08539 res = simple_command_ft897(myrpt, 0x00);
08540
08541 if(debug)
08542 printf("@@@@ ptt off\n");
08543
08544 if(!res)
08545 res = simple_command_ft897(myrpt, 0x88);
08546
08547 if(debug)
08548 printf("Modulation mode\n");
08549
08550 if(!res)
08551 res = set_mode_ft897(myrpt, myrpt->remmode);
08552
08553 if(debug)
08554 printf("Split off\n");
08555
08556 if(!res)
08557 simple_command_ft897(myrpt, 0x82);
08558
08559 if(debug)
08560 printf("Frequency\n");
08561
08562 if(!res)
08563 res = set_freq_ft897(myrpt, myrpt->freq);
08564 if((myrpt->remmode == REM_MODE_FM)){
08565 if(debug)
08566 printf("Offset\n");
08567 if(!res)
08568 res = set_offset_ft897(myrpt, myrpt->offset);
08569 if((!res)&&(myrpt->rxplon || myrpt->txplon)){
08570 if(debug)
08571 printf("CTCSS tone freqs.\n");
08572 res = set_ctcss_freq_ft897(myrpt, myrpt->txpl, myrpt->rxpl);
08573 }
08574 if(!res){
08575 if(debug)
08576 printf("CTCSS mode\n");
08577 res = set_ctcss_mode_ft897(myrpt, myrpt->txplon, myrpt->rxplon);
08578 }
08579 }
08580 if((myrpt->remmode == REM_MODE_USB)||(myrpt->remmode == REM_MODE_LSB)){
08581 if(debug)
08582 printf("Clarifier off\n");
08583 simple_command_ft897(myrpt, 0x85);
08584 }
08585 return res;
08586 }
08587
08588 static int closerem_ft897(struct rpt *myrpt)
08589 {
08590 simple_command_ft897(myrpt, 0x88);
08591 return 0;
08592 }
08593
08594
08595
08596
08597
08598
08599
08600 static int multimode_bump_freq_ft897(struct rpt *myrpt, int interval)
08601 {
08602 int m,d;
08603 char mhz[MAXREMSTR], decimals[MAXREMSTR];
08604
08605 if(debug)
08606 printf("Before bump: %s\n", myrpt->freq);
08607
08608 if(split_freq(mhz, decimals, myrpt->freq))
08609 return -1;
08610
08611 m = atoi(mhz);
08612 d = atoi(decimals);
08613
08614 d += (interval / 10);
08615 if(d < 0){
08616 m--;
08617 d += 100000;
08618 }
08619 else if(d >= 100000){
08620 m++;
08621 d -= 100000;
08622 }
08623
08624 if(check_freq_ft897(m, d, NULL)){
08625 if(debug)
08626 printf("Bump freq invalid\n");
08627 return -1;
08628 }
08629
08630 snprintf(myrpt->freq, MAXREMSTR, "%d.%05d", m, d);
08631
08632 if(debug)
08633 printf("After bump: %s\n", myrpt->freq);
08634
08635 return set_freq_ft897(myrpt, myrpt->freq);
08636 }
08637
08638
08639
08640
08641
08642
08643
08644
08645
08646
08647 static int check_freq_ic706(int m, int d, int *defmode, char mars)
08648 {
08649 int dflmd = REM_MODE_FM;
08650 int rv=0;
08651
08652 if(debug > 6)
08653 ast_log(LOG_NOTICE,"(%i,%i,%i,%i)\n",m,d,*defmode,mars);
08654
08655
08656
08657 if(m == 1){
08658 dflmd = REM_MODE_LSB;
08659 if(d < 80000)rv=-1;
08660 }
08661 else if(m == 3){
08662 dflmd = REM_MODE_LSB;
08663 if(d < 50000)rv=-1;
08664 }
08665 else if(m == 7){
08666 dflmd = REM_MODE_LSB;
08667 if(d > 30000)rv=-1;
08668 }
08669 else if(m == 14){
08670 dflmd = REM_MODE_USB;
08671 if(d > 35000)rv=-1;
08672 }
08673 else if(m == 18){
08674 dflmd = REM_MODE_USB;
08675 if((d < 6800) || (d > 16800))rv=-1;
08676 }
08677 else if(m == 21){
08678 dflmd = REM_MODE_USB;
08679 if((d < 20000) || (d > 45000))rv=-1;
08680 }
08681 else if(m == 24){
08682 dflmd = REM_MODE_USB;
08683 if((d < 89000) || (d > 99000))rv=-1;
08684 }
08685 else if(m == 28){
08686 dflmd = REM_MODE_USB;
08687 }
08688 else if(m == 29){
08689 if(d >= 51000)
08690 dflmd = REM_MODE_FM;
08691 else
08692 dflmd = REM_MODE_USB;
08693 if(d > 70000)rv=-1;
08694 }
08695 else if(m == 50){
08696 if(d >= 30000)
08697 dflmd = REM_MODE_FM;
08698 else
08699 dflmd = REM_MODE_USB;
08700 }
08701 else if((m >= 51) && ( m < 54)){
08702 dflmd = REM_MODE_FM;
08703 }
08704 else if(m == 144){
08705 if(d >= 30000)
08706 dflmd = REM_MODE_FM;
08707 else
08708 dflmd = REM_MODE_USB;
08709 }
08710 else if((m >= 145) && (m < 148)){
08711 dflmd = REM_MODE_FM;
08712 }
08713 else if((m >= 430) && (m < 450)){
08714 if(m < 438)
08715 dflmd = REM_MODE_USB;
08716 else
08717 dflmd = REM_MODE_FM;
08718 }
08719
08720
08721 if(mars && rv<0){
08722 if((m >= 450) && (m < 470)){
08723 dflmd = REM_MODE_FM;
08724 rv=0;
08725 }
08726 else if((m >= 148) && (m < 174)){
08727 dflmd = REM_MODE_FM;
08728 rv=0;
08729 }
08730 else if((m >= 138) && (m < 144)){
08731 dflmd = REM_MODE_AM;
08732 rv=0;
08733 }
08734 else if((m >= 108) && (m < 138)){
08735 dflmd = REM_MODE_AM;
08736 rv=0;
08737 }
08738 else if( (m==0 && d>=55000) || (m==1 && d<=75000) ){
08739 dflmd = REM_MODE_AM;
08740 rv=0;
08741 }
08742 else if( (m == 1 && d>75000) || (m>1 && m<30) ){
08743 dflmd = REM_MODE_AM;
08744 rv=0;
08745 }
08746 }
08747
08748 if(defmode)
08749 *defmode = dflmd;
08750
08751 if(debug > 1)
08752 ast_log(LOG_NOTICE,"(%i,%i,%i,%i) returning %i\n",m,d,*defmode,mars,rv);
08753
08754 return rv;
08755 }
08756
08757
08758 static int ic706_pltocode(char *str)
08759 {
08760 int i;
08761 char *s;
08762 int rv=-1;
08763
08764 s = strchr(str,'.');
08765 i = 0;
08766 if (s) i = atoi(s + 1);
08767 i += atoi(str) * 10;
08768 switch(i)
08769 {
08770 case 670:
08771 rv=0;
08772 case 693:
08773 rv=1;
08774 case 719:
08775 rv=2;
08776 case 744:
08777 rv=3;
08778 case 770:
08779 rv=4;
08780 case 797:
08781 rv=5;
08782 case 825:
08783 rv=6;
08784 case 854:
08785 rv=7;
08786 case 885:
08787 rv=8;
08788 case 915:
08789 rv=9;
08790 case 948:
08791 rv=10;
08792 case 974:
08793 rv=11;
08794 case 1000:
08795 rv=12;
08796 case 1035:
08797 rv=13;
08798 case 1072:
08799 rv=14;
08800 case 1109:
08801 rv=15;
08802 case 1148:
08803 rv=16;
08804 case 1188:
08805 rv=17;
08806 case 1230:
08807 rv=18;
08808 case 1273:
08809 rv=19;
08810 case 1318:
08811 rv=20;
08812 case 1365:
08813 rv=21;
08814 case 1413:
08815 rv=22;
08816 case 1462:
08817 rv=23;
08818 case 1514:
08819 rv=24;
08820 case 1567:
08821 rv=25;
08822 case 1598:
08823 rv=26;
08824 case 1622:
08825 rv=27;
08826 case 1655:
08827 rv=28;
08828 case 1679:
08829 rv=29;
08830 case 1713:
08831 rv=30;
08832 case 1738:
08833 rv=31;
08834 case 1773:
08835 rv=32;
08836 case 1799:
08837 rv=33;
08838 case 1835:
08839 rv=34;
08840 case 1862:
08841 rv=35;
08842 case 1899:
08843 rv=36;
08844 case 1928:
08845 rv=37;
08846 case 1966:
08847 rv=38;
08848 case 1995:
08849 rv=39;
08850 case 2035:
08851 rv=40;
08852 case 2065:
08853 rv=41;
08854 case 2107:
08855 rv=42;
08856 case 2181:
08857 rv=43;
08858 case 2257:
08859 rv=44;
08860 case 2291:
08861 rv=45;
08862 case 2336:
08863 rv=46;
08864 case 2418:
08865 rv=47;
08866 case 2503:
08867 rv=48;
08868 case 2541:
08869 rv=49;
08870 }
08871 if(debug > 1)
08872 ast_log(LOG_NOTICE,"%i rv=%i\n",i, rv);
08873
08874 return rv;
08875 }
08876
08877
08878
08879 static int simple_command_ic706(struct rpt *myrpt, char command, char subcommand)
08880 {
08881 unsigned char cmdstr[10];
08882
08883 cmdstr[0] = cmdstr[1] = 0xfe;
08884 cmdstr[2] = myrpt->p.civaddr;
08885 cmdstr[3] = 0xe0;
08886 cmdstr[4] = command;
08887 cmdstr[5] = subcommand;
08888 cmdstr[6] = 0xfd;
08889
08890 return(civ_cmd(myrpt,cmdstr,7));
08891 }
08892
08893
08894
08895
08896
08897 static int set_freq_ic706(struct rpt *myrpt, char *newfreq)
08898 {
08899 unsigned char cmdstr[20];
08900 char mhz[MAXREMSTR], decimals[MAXREMSTR];
08901 int fd,m,d;
08902
08903 fd = 0;
08904 if(debug)
08905 ast_log(LOG_NOTICE,"newfreq:%s\n",newfreq);
08906
08907 if(split_freq(mhz, decimals, newfreq))
08908 return -1;
08909
08910 m = atoi(mhz);
08911 d = atoi(decimals);
08912
08913
08914
08915 cmdstr[0] = cmdstr[1] = 0xfe;
08916 cmdstr[2] = myrpt->p.civaddr;
08917 cmdstr[3] = 0xe0;
08918 cmdstr[4] = 5;
08919 cmdstr[5] = ((d % 10) << 4);
08920 cmdstr[6] = (((d % 1000)/ 100) << 4) + ((d % 100)/10);
08921 cmdstr[7] = ((d / 10000) << 4) + ((d % 10000)/1000);
08922 cmdstr[8] = (((m % 100)/10) << 4) + (m % 10);
08923 cmdstr[9] = (m / 100);
08924 cmdstr[10] = 0xfd;
08925
08926 return(civ_cmd(myrpt,cmdstr,11));
08927 }
08928
08929
08930
08931 static int set_offset_ic706(struct rpt *myrpt, char offset)
08932 {
08933 unsigned char c;
08934
08935 if(debug > 6)
08936 ast_log(LOG_NOTICE,"offset=%i\n",offset);
08937
08938 switch(offset){
08939 case REM_SIMPLEX:
08940 c = 0x10;
08941 break;
08942
08943 case REM_MINUS:
08944 c = 0x11;
08945 break;
08946
08947 case REM_PLUS:
08948 c = 0x12;
08949 break;
08950
08951 default:
08952 return -1;
08953 }
08954
08955 return simple_command_ic706(myrpt,0x0f,c);
08956
08957 }
08958
08959
08960
08961 static int set_mode_ic706(struct rpt *myrpt, char newmode)
08962 {
08963 unsigned char c;
08964
08965 if(debug > 6)
08966 ast_log(LOG_NOTICE,"newmode=%i\n",newmode);
08967
08968 switch(newmode){
08969 case REM_MODE_FM:
08970 c = 5;
08971 break;
08972
08973 case REM_MODE_USB:
08974 c = 1;
08975 break;
08976
08977 case REM_MODE_LSB:
08978 c = 0;
08979 break;
08980
08981 case REM_MODE_AM:
08982 c = 2;
08983 break;
08984
08985 default:
08986 return -1;
08987 }
08988 return simple_command_ic706(myrpt,6,c);
08989 }
08990
08991
08992
08993 static int set_ctcss_mode_ic706(struct rpt *myrpt, char txplon, char rxplon)
08994 {
08995 unsigned char cmdstr[10];
08996 int rv;
08997
08998 if(debug > 6)
08999 ast_log(LOG_NOTICE,"txplon=%i rxplon=%i \n",txplon,rxplon);
09000
09001 cmdstr[0] = cmdstr[1] = 0xfe;
09002 cmdstr[2] = myrpt->p.civaddr;
09003 cmdstr[3] = 0xe0;
09004 cmdstr[4] = 0x16;
09005 cmdstr[5] = 0x42;
09006 cmdstr[6] = (txplon != 0);
09007 cmdstr[7] = 0xfd;
09008
09009 rv = civ_cmd(myrpt,cmdstr,8);
09010 if (rv) return(-1);
09011
09012 cmdstr[0] = cmdstr[1] = 0xfe;
09013 cmdstr[2] = myrpt->p.civaddr;
09014 cmdstr[3] = 0xe0;
09015 cmdstr[4] = 0x16;
09016 cmdstr[5] = 0x43;
09017 cmdstr[6] = (rxplon != 0);
09018 cmdstr[7] = 0xfd;
09019
09020 return(civ_cmd(myrpt,cmdstr,8));
09021 }
09022
09023 #if 0
09024
09025
09026 static int set_ctcss_freq_ic706(struct rpt *myrpt, char *txtone, char *rxtone)
09027 {
09028 unsigned char cmdstr[10];
09029 char hertz[MAXREMSTR],decimal[MAXREMSTR];
09030 int h,d,rv;
09031
09032 memset(cmdstr, 0, 5);
09033
09034 if(debug > 6)
09035 ast_log(LOG_NOTICE,"txtone=%s rxtone=%s \n",txtone,rxtone);
09036
09037 if(split_ctcss_freq(hertz, decimal, txtone))
09038 return -1;
09039
09040 h = atoi(hertz);
09041 d = atoi(decimal);
09042
09043 cmdstr[0] = cmdstr[1] = 0xfe;
09044 cmdstr[2] = myrpt->p.civaddr;
09045 cmdstr[3] = 0xe0;
09046 cmdstr[4] = 0x1b;
09047 cmdstr[5] = 0;
09048 cmdstr[6] = ((h / 100) << 4) + (h % 100)/ 10;
09049 cmdstr[7] = ((h % 10) << 4) + (d % 10);
09050 cmdstr[8] = 0xfd;
09051
09052 rv = civ_cmd(myrpt,cmdstr,9);
09053 if (rv) return(-1);
09054
09055 if (!rxtone) return(0);
09056
09057 if(split_ctcss_freq(hertz, decimal, rxtone))
09058 return -1;
09059
09060 h = atoi(hertz);
09061 d = atoi(decimal);
09062
09063 cmdstr[0] = cmdstr[1] = 0xfe;
09064 cmdstr[2] = myrpt->p.civaddr;
09065 cmdstr[3] = 0xe0;
09066 cmdstr[4] = 0x1b;
09067 cmdstr[5] = 1;
09068 cmdstr[6] = ((h / 100) << 4) + (h % 100)/ 10;
09069 cmdstr[7] = ((h % 10) << 4) + (d % 10);
09070 cmdstr[8] = 0xfd;
09071 return(civ_cmd(myrpt,cmdstr,9));
09072 }
09073 #endif
09074
09075 static int vfo_ic706(struct rpt *myrpt)
09076 {
09077 unsigned char cmdstr[10];
09078
09079 cmdstr[0] = cmdstr[1] = 0xfe;
09080 cmdstr[2] = myrpt->p.civaddr;
09081 cmdstr[3] = 0xe0;
09082 cmdstr[4] = 7;
09083 cmdstr[5] = 0xfd;
09084
09085 return(civ_cmd(myrpt,cmdstr,6));
09086 }
09087
09088 static int mem2vfo_ic706(struct rpt *myrpt)
09089 {
09090 unsigned char cmdstr[10];
09091
09092 cmdstr[0] = cmdstr[1] = 0xfe;
09093 cmdstr[2] = myrpt->p.civaddr;
09094 cmdstr[3] = 0xe0;
09095 cmdstr[4] = 0x0a;
09096 cmdstr[5] = 0xfd;
09097
09098 return(civ_cmd(myrpt,cmdstr,6));
09099 }
09100
09101 static int select_mem_ic706(struct rpt *myrpt, int slot)
09102 {
09103 unsigned char cmdstr[10];
09104
09105 cmdstr[0] = cmdstr[1] = 0xfe;
09106 cmdstr[2] = myrpt->p.civaddr;
09107 cmdstr[3] = 0xe0;
09108 cmdstr[4] = 8;
09109 cmdstr[5] = 0;
09110 cmdstr[6] = ((slot / 10) << 4) + (slot % 10);
09111 cmdstr[7] = 0xfd;
09112
09113 return(civ_cmd(myrpt,cmdstr,8));
09114 }
09115
09116 static int set_ic706(struct rpt *myrpt)
09117 {
09118 int res = 0,i;
09119
09120 if(debug)ast_log(LOG_NOTICE, "Set to VFO A iobase=%i\n",myrpt->p.iobase);
09121
09122 if (!res)
09123 res = simple_command_ic706(myrpt,7,0);
09124
09125 if((myrpt->remmode == REM_MODE_FM))
09126 {
09127 i = ic706_pltocode(myrpt->rxpl);
09128 if (i == -1) return -1;
09129 if(debug)
09130 printf("Select memory number\n");
09131 if (!res)
09132 res = select_mem_ic706(myrpt,i + IC706_PL_MEMORY_OFFSET);
09133 if(debug)
09134 printf("Transfer memory to VFO\n");
09135 if (!res)
09136 res = mem2vfo_ic706(myrpt);
09137 }
09138
09139 if(debug)
09140 printf("Set to VFO\n");
09141
09142 if (!res)
09143 res = vfo_ic706(myrpt);
09144
09145 if(debug)
09146 printf("Modulation mode\n");
09147
09148 if (!res)
09149 res = set_mode_ic706(myrpt, myrpt->remmode);
09150
09151 if(debug)
09152 printf("Split off\n");
09153
09154 if(!res)
09155 simple_command_ic706(myrpt, 0x82,0);
09156
09157 if(debug)
09158 printf("Frequency\n");
09159
09160 if(!res)
09161 res = set_freq_ic706(myrpt, myrpt->freq);
09162 if((myrpt->remmode == REM_MODE_FM)){
09163 if(debug)
09164 printf("Offset\n");
09165 if(!res)
09166 res = set_offset_ic706(myrpt, myrpt->offset);
09167 if(!res){
09168 if(debug)
09169 printf("CTCSS mode\n");
09170 res = set_ctcss_mode_ic706(myrpt, myrpt->txplon, myrpt->rxplon);
09171 }
09172 }
09173 return res;
09174 }
09175
09176
09177
09178
09179
09180
09181
09182 static int multimode_bump_freq_ic706(struct rpt *myrpt, int interval)
09183 {
09184 int m,d;
09185 char mhz[MAXREMSTR], decimals[MAXREMSTR];
09186 unsigned char cmdstr[20];
09187
09188 if(debug)
09189 printf("Before bump: %s\n", myrpt->freq);
09190
09191 if(split_freq(mhz, decimals, myrpt->freq))
09192 return -1;
09193
09194 m = atoi(mhz);
09195 d = atoi(decimals);
09196
09197 d += (interval / 10);
09198 if(d < 0){
09199 m--;
09200 d += 100000;
09201 }
09202 else if(d >= 100000){
09203 m++;
09204 d -= 100000;
09205 }
09206
09207 if(check_freq_ic706(m, d, NULL,myrpt->p.remote_mars)){
09208 if(debug)
09209 printf("Bump freq invalid\n");
09210 return -1;
09211 }
09212
09213 snprintf(myrpt->freq, MAXREMSTR, "%d.%05d", m, d);
09214
09215 if(debug)
09216 printf("After bump: %s\n", myrpt->freq);
09217
09218
09219
09220 cmdstr[0] = cmdstr[1] = 0xfe;
09221 cmdstr[2] = myrpt->p.civaddr;
09222 cmdstr[3] = 0xe0;
09223 cmdstr[4] = 0;
09224 cmdstr[5] = ((d % 10) << 4);
09225 cmdstr[6] = (((d % 1000)/ 100) << 4) + ((d % 100)/10);
09226 cmdstr[7] = ((d / 10000) << 4) + ((d % 10000)/1000);
09227 cmdstr[8] = (((m % 100)/10) << 4) + (m % 10);
09228 cmdstr[9] = (m / 100);
09229 cmdstr[10] = 0xfd;
09230
09231 return(serial_remote_io(myrpt,cmdstr,11,NULL,0,0));
09232 }
09233
09234
09235
09236
09237
09238
09239 static int setrem(struct rpt *myrpt)
09240 {
09241 char str[300];
09242 char *offsets[] = {"SIMPLEX","MINUS","PLUS"};
09243 char *powerlevels[] = {"LOW","MEDIUM","HIGH"};
09244 char *modes[] = {"FM","USB","LSB","AM"};
09245 int res = -1;
09246
09247 #if 0
09248 printf("FREQ,%s,%s,%s,%s,%s,%s,%d,%d\n",myrpt->freq,
09249 modes[(int)myrpt->remmode],
09250 myrpt->txpl,myrpt->rxpl,offsets[(int)myrpt->offset],
09251 powerlevels[(int)myrpt->powerlevel],myrpt->txplon,
09252 myrpt->rxplon);
09253 #endif
09254 if (myrpt->p.archivedir)
09255 {
09256 sprintf(str,"FREQ,%s,%s,%s,%s,%s,%s,%d,%d",myrpt->freq,
09257 modes[(int)myrpt->remmode],
09258 myrpt->txpl,myrpt->rxpl,offsets[(int)myrpt->offset],
09259 powerlevels[(int)myrpt->powerlevel],myrpt->txplon,
09260 myrpt->rxplon);
09261 donodelog(myrpt,str);
09262 }
09263 if(!strcmp(myrpt->remoterig, remote_rig_ft897))
09264 {
09265 rpt_telemetry(myrpt,SETREMOTE,NULL);
09266 res = 0;
09267 }
09268 if(!strcmp(myrpt->remoterig, remote_rig_ic706))
09269 {
09270 rpt_telemetry(myrpt,SETREMOTE,NULL);
09271 res = 0;
09272 }
09273 if(!strcmp(myrpt->remoterig, remote_rig_tm271))
09274 {
09275 rpt_telemetry(myrpt,SETREMOTE,NULL);
09276 res = 0;
09277 }
09278 else if(!strcmp(myrpt->remoterig, remote_rig_rbi))
09279 {
09280 res = setrbi_check(myrpt);
09281 if (!res)
09282 {
09283 rpt_telemetry(myrpt,SETREMOTE,NULL);
09284 res = 0;
09285 }
09286 }
09287 else if(ISRIG_RTX(myrpt->remoterig))
09288 {
09289 setrtx(myrpt);
09290 res = 0;
09291 }
09292 else if(!strcmp(myrpt->remoterig, remote_rig_kenwood)) {
09293 rpt_telemetry(myrpt,SETREMOTE,NULL);
09294 res = 0;
09295 }
09296 else
09297 res = 0;
09298
09299 if (res < 0) ast_log(LOG_ERROR,"Unable to send remote command on node %s\n",myrpt->name);
09300
09301 return res;
09302 }
09303
09304 static int closerem(struct rpt *myrpt)
09305 {
09306 if(!strcmp(myrpt->remoterig, remote_rig_ft897))
09307 return closerem_ft897(myrpt);
09308 else
09309 return 0;
09310 }
09311
09312
09313
09314
09315
09316 static int check_freq(struct rpt *myrpt, int m, int d, int *defmode)
09317 {
09318 if(!strcmp(myrpt->remoterig, remote_rig_ft897))
09319 return check_freq_ft897(m, d, defmode);
09320 else if(!strcmp(myrpt->remoterig, remote_rig_ic706))
09321 return check_freq_ic706(m, d, defmode,myrpt->p.remote_mars);
09322 else if(!strcmp(myrpt->remoterig, remote_rig_rbi))
09323 return check_freq_rbi(m, d, defmode);
09324 else if(!strcmp(myrpt->remoterig, remote_rig_kenwood))
09325 return check_freq_kenwood(m, d, defmode);
09326 else if(!strcmp(myrpt->remoterig, remote_rig_tm271))
09327 return check_freq_tm271(m, d, defmode);
09328 else if(ISRIG_RTX(myrpt->remoterig))
09329 return check_freq_rtx(m, d, defmode, myrpt);
09330 else
09331 return -1;
09332 }
09333
09334
09335
09336
09337
09338
09339 static char check_tx_freq(struct rpt *myrpt)
09340 {
09341 int i,rv=0;
09342 int radio_mhz, radio_decimals, ulimit_mhz, ulimit_decimals, llimit_mhz, llimit_decimals;
09343 char radio_mhz_char[MAXREMSTR];
09344 char radio_decimals_char[MAXREMSTR];
09345 char limit_mhz_char[MAXREMSTR];
09346 char limit_decimals_char[MAXREMSTR];
09347 char limits[256];
09348 char *limit_ranges[40];
09349 struct ast_variable *limitlist;
09350
09351 if(debug > 3){
09352 ast_log(LOG_NOTICE, "myrpt->freq = %s\n", myrpt->freq);
09353 }
09354
09355
09356
09357 if(!myrpt->p.txlimitsstanzaname || !myrpt->loginuser[0] || !myrpt->loginlevel[0]){
09358 if(debug > 3){
09359 ast_log(LOG_NOTICE, "No tx band table defined, or no user logged in. rv=1\n");
09360 }
09361 rv=1;
09362 return 1;
09363 }
09364
09365
09366 limitlist = ast_variable_browse(myrpt->cfg, myrpt->p.txlimitsstanzaname);
09367
09368 if(!limitlist){
09369 ast_log(LOG_WARNING, "No entries in %s band table stanza. rv=0\n", myrpt->p.txlimitsstanzaname);
09370 rv=0;
09371 return 0;
09372 }
09373
09374 split_freq(radio_mhz_char, radio_decimals_char, myrpt->freq);
09375 radio_mhz = atoi(radio_mhz_char);
09376 radio_decimals = decimals2int(radio_decimals_char);
09377
09378 if(debug > 3){
09379 ast_log(LOG_NOTICE, "Login User = %s, login level = %s\n", myrpt->loginuser, myrpt->loginlevel);
09380 }
09381
09382
09383
09384 for(;limitlist; limitlist=limitlist->next){
09385 if(!strcmp(limitlist->name, myrpt->loginlevel))
09386 break;
09387 }
09388
09389 if(!limitlist){
09390 ast_log(LOG_WARNING, "Can't find %s entry in band table stanza %s. rv=0\n", myrpt->loginlevel, myrpt->p.txlimitsstanzaname);
09391 rv=0;
09392 return 0;
09393 }
09394
09395 if(debug > 3){
09396 ast_log(LOG_NOTICE, "Auth: %s = %s\n", limitlist->name, limitlist->value);
09397 }
09398
09399
09400
09401 strncpy(limits, limitlist->value, 256);
09402 limits[255] = 0;
09403 finddelim(limits, limit_ranges, 40);
09404 for(i = 0; i < 40 && limit_ranges[i] ; i++){
09405 char range[40];
09406 char *r,*s;
09407 strncpy(range, limit_ranges[i], 40);
09408 range[39] = 0;
09409 if(debug > 3)
09410 ast_log(LOG_NOTICE, "Check %s within %s\n", myrpt->freq, range);
09411
09412 r = strchr(range, '-');
09413 if(!r){
09414 ast_log(LOG_WARNING, "Malformed range in %s tx band table entry. rv=0\n", limitlist->name);
09415 rv=0;
09416 break;
09417 }
09418 *r++ = 0;
09419 s = eatwhite(range);
09420 r = eatwhite(r);
09421 split_freq(limit_mhz_char, limit_decimals_char, s);
09422 llimit_mhz = atoi(limit_mhz_char);
09423 llimit_decimals = decimals2int(limit_decimals_char);
09424 split_freq(limit_mhz_char, limit_decimals_char, r);
09425 ulimit_mhz = atoi(limit_mhz_char);
09426 ulimit_decimals = decimals2int(limit_decimals_char);
09427
09428 if((radio_mhz >= llimit_mhz) && (radio_mhz <= ulimit_mhz)){
09429 if(radio_mhz == llimit_mhz){
09430 if(radio_decimals >= llimit_decimals){
09431 if(llimit_mhz == ulimit_mhz){
09432 if(radio_decimals <= ulimit_decimals){
09433 rv=1;
09434 break;
09435 }
09436 else{
09437 if(debug > 3)
09438 ast_log(LOG_NOTICE, "Invalid TX frequency, debug msg 1\n");
09439 rv=0;
09440 break;
09441 }
09442 }
09443 else{
09444 rv=1;
09445 break;
09446 }
09447 }
09448 else{
09449 if(debug > 3)
09450 ast_log(LOG_NOTICE, "Invalid TX frequency, debug msg 2\n");
09451 rv=0;
09452 break;
09453 }
09454 }
09455 else if(radio_mhz == ulimit_mhz){
09456 if(radio_decimals <= ulimit_decimals){
09457 if(debug > 3)
09458 ast_log(LOG_NOTICE, "radio_decimals <= ulimit_decimals\n");
09459 rv=1;
09460 break;
09461 }
09462 else{
09463 if(debug > 3)
09464 ast_log(LOG_NOTICE, "Invalid TX frequency, debug msg 3\n");
09465 rv=0;
09466 break;
09467 }
09468 }
09469 else
09470 if(debug > 3)
09471 ast_log(LOG_NOTICE, "Valid TX freq within a multi-Mhz band and ok.\n");
09472 rv=1;
09473 break;
09474 }
09475 }
09476 if(debug > 3)
09477 ast_log(LOG_NOTICE, "rv=%i\n",rv);
09478
09479 return rv;
09480 }
09481
09482
09483
09484
09485
09486
09487 static int multimode_bump_freq(struct rpt *myrpt, int interval)
09488 {
09489 if(!strcmp(myrpt->remoterig, remote_rig_ft897))
09490 return multimode_bump_freq_ft897(myrpt, interval);
09491 else if(!strcmp(myrpt->remoterig, remote_rig_ic706))
09492 return multimode_bump_freq_ic706(myrpt, interval);
09493 else
09494 return -1;
09495 }
09496
09497
09498
09499
09500
09501
09502 static void stop_scan(struct rpt *myrpt)
09503 {
09504 myrpt->hfscanstop = 1;
09505 rpt_telemetry(myrpt,SCAN,0);
09506 }
09507
09508
09509
09510
09511
09512
09513 static int service_scan(struct rpt *myrpt)
09514 {
09515 int res, interval;
09516 char mhz[MAXREMSTR], decimals[MAXREMSTR], k10=0i, k100=0;
09517
09518 switch(myrpt->hfscanmode){
09519
09520 case HF_SCAN_DOWN_SLOW:
09521 interval = -10;
09522 break;
09523
09524 case HF_SCAN_DOWN_QUICK:
09525 interval = -50;
09526 break;
09527
09528 case HF_SCAN_DOWN_FAST:
09529 interval = -200;
09530 break;
09531
09532 case HF_SCAN_UP_SLOW:
09533 interval = 10;
09534 break;
09535
09536 case HF_SCAN_UP_QUICK:
09537 interval = 50;
09538 break;
09539
09540 case HF_SCAN_UP_FAST:
09541 interval = 200;
09542 break;
09543
09544 default:
09545 myrpt->hfscanmode = 0;
09546 return -1;
09547 }
09548
09549 res = split_freq(mhz, decimals, myrpt->freq);
09550
09551 if(!res){
09552 k100 =decimals[0];
09553 k10 = decimals[1];
09554 res = multimode_bump_freq(myrpt, interval);
09555 }
09556
09557 if(!res)
09558 res = split_freq(mhz, decimals, myrpt->freq);
09559
09560
09561 if(res){
09562 myrpt->hfscanmode = 0;
09563 myrpt->hfscanstatus = -2;
09564 return -1;
09565 }
09566
09567
09568 if(k10 != decimals[1]){
09569 int myhund = (interval < 0) ? k100 : decimals[0];
09570 int myten = (interval < 0) ? k10 : decimals[1];
09571 myrpt->hfscanstatus = (myten == '0') ? (myhund - '0') * 100 : (myten - '0') * 10;
09572 } else myrpt->hfscanstatus = 0;
09573 return res;
09574
09575 }
09576
09577
09578
09579 static int get_mem_set(struct rpt *myrpt, char *digitbuf)
09580 {
09581 int res=0;
09582 if(debug)ast_log(LOG_NOTICE," digitbuf=%s\n", digitbuf);
09583 res = retreive_memory(myrpt, digitbuf);
09584 if(!res)res=setrem(myrpt);
09585 if(debug)ast_log(LOG_NOTICE," freq=%s res=%i\n", myrpt->freq, res);
09586 return res;
09587 }
09588
09589
09590
09591
09592 static int channel_steer(struct rpt *myrpt, char *data)
09593 {
09594 int res=0;
09595
09596 if(debug)ast_log(LOG_NOTICE,"remoterig=%s, data=%s\n",myrpt->remoterig,data);
09597 if (!myrpt->remoterig) return(0);
09598 if(data<=0)
09599 {
09600 res=-1;
09601 }
09602 else
09603 {
09604 myrpt->nowchan=strtod(data,NULL);
09605 if(!strcmp(myrpt->remoterig, remote_rig_ppp16))
09606 {
09607 char string[16];
09608 sprintf(string,"SETCHAN %d ",myrpt->nowchan);
09609 send_usb_txt(myrpt,string);
09610 }
09611 else
09612 {
09613 if(get_mem_set(myrpt, data))res=-1;
09614 }
09615 }
09616 if(debug)ast_log(LOG_NOTICE,"nowchan=%i res=%i\n",myrpt->nowchan, res);
09617 return res;
09618 }
09619
09620
09621 static int channel_revert(struct rpt *myrpt)
09622 {
09623 int res=0;
09624 if(debug)ast_log(LOG_NOTICE,"remoterig=%s, nowchan=%02d, waschan=%02d\n",myrpt->remoterig,myrpt->nowchan,myrpt->waschan);
09625 if (!myrpt->remoterig) return(0);
09626 if(myrpt->nowchan!=myrpt->waschan)
09627 {
09628 char data[8];
09629 if(debug)ast_log(LOG_NOTICE,"reverting.\n");
09630 sprintf(data,"%02d",myrpt->waschan);
09631 myrpt->nowchan=myrpt->waschan;
09632 channel_steer(myrpt,data);
09633 res=1;
09634 }
09635 return(res);
09636 }
09637
09638
09639
09640
09641 static int function_remote(struct rpt *myrpt, char *param, char *digitbuf, int command_source, struct rpt_link *mylink)
09642 {
09643 char *s,*s1,*s2;
09644 int i,j,r,ht,k,l,ls2,m,d,offset,offsave, modesave, defmode=0;
09645 intptr_t p;
09646 char multimode = 0;
09647 char oc,*cp,*cp1,*cp2;
09648 char tmp[20], freq[20] = "", savestr[20] = "";
09649 char mhz[MAXREMSTR], decimals[MAXREMSTR];
09650
09651 if(debug > 6) {
09652 ast_log(LOG_NOTICE,"%s param=%s digitbuf=%s source=%i\n",myrpt->name,param,digitbuf,command_source);
09653 }
09654
09655 if((!param) || (command_source == SOURCE_RPT) || (command_source == SOURCE_LNK))
09656 return DC_ERROR;
09657
09658 p = myatoi(param);
09659
09660 if ((p != 99) && (p != 5) && (p != 140) && myrpt->p.authlevel &&
09661 (!myrpt->loginlevel[0])) return DC_ERROR;
09662 multimode = multimode_capable(myrpt);
09663
09664 switch(p){
09665
09666 case 1:
09667 if(strlen(digitbuf) < 2)
09668 break;
09669
09670 for(i = 0 ; i < 2 ; i++){
09671 if((digitbuf[i] < '0') || (digitbuf[i] > '9'))
09672 return DC_ERROR;
09673 }
09674 r=get_mem_set(myrpt, digitbuf);
09675 if (r < 0){
09676 rpt_telemetry(myrpt,MEMNOTFOUND,NULL);
09677 return DC_COMPLETE;
09678 }
09679 else if (r > 0){
09680 return DC_ERROR;
09681 }
09682 return DC_COMPLETE;
09683
09684 case 2:
09685
09686
09687 for(i = 0, j = 0, k = 0, l = 0 ; digitbuf[i] ; i++){
09688 if(digitbuf[i] == '*'){
09689 j++;
09690 continue;
09691 }
09692 if((digitbuf[i] < '0') || (digitbuf[i] > '9'))
09693 goto invalid_freq;
09694 else{
09695 if(j == 0)
09696 l++;
09697 if(j == 1)
09698 k++;
09699 }
09700 }
09701
09702 i = strlen(digitbuf) - 1;
09703 if(multimode){
09704 if((j > 2) || (l > 3) || (k > 6))
09705 goto invalid_freq;
09706 }
09707 else{
09708 if((j > 2) || (l > 4) || (k > 3))
09709 goto invalid_freq;
09710 }
09711
09712
09713
09714 if(j < 2)
09715 break;
09716
09717
09718
09719 strncpy(tmp, digitbuf ,sizeof(tmp) - 1);
09720
09721 s = tmp;
09722 s1 = strsep(&s, "*");
09723 s2 = strsep(&s,"*");
09724 ls2 = strlen(s2);
09725
09726 switch(ls2){
09727 case 1:
09728 ht = 0;
09729 k = 100 * atoi(s2);
09730 break;
09731
09732 case 2:
09733 ht = 0;
09734 k = 10 * atoi(s2);
09735 break;
09736
09737 case 3:
09738 if(!multimode){
09739 if((s2[2] != '0')&&(s2[2] != '5'))
09740 goto invalid_freq;
09741 }
09742 ht = 0;
09743 k = atoi(s2);
09744 break;
09745 case 4:
09746 k = atoi(s2)/10;
09747 ht = 10 * (atoi(s2+(ls2-1)));
09748 break;
09749
09750 case 5:
09751 k = atoi(s2)/100;
09752 ht = (atoi(s2+(ls2-2)));
09753 break;
09754
09755 default:
09756 goto invalid_freq;
09757 }
09758
09759
09760
09761 snprintf(freq, sizeof(freq), "%s.%03d%02d",s1, k, ht);
09762
09763 if(debug)
09764 ast_log(LOG_NOTICE, "New frequency: %s\n", freq);
09765
09766 split_freq(mhz, decimals, freq);
09767 m = atoi(mhz);
09768 d = atoi(decimals);
09769
09770 if(check_freq(myrpt, m, d, &defmode))
09771 goto invalid_freq;
09772
09773
09774 if((defmode == REM_MODE_FM) && (digitbuf[i] == '*'))
09775 break;
09776
09777
09778 offset = REM_SIMPLEX;
09779
09780 if(defmode == REM_MODE_FM){
09781 oc = *s;
09782
09783 if (oc){
09784 switch(oc){
09785 case '1':
09786 offset = REM_MINUS;
09787 break;
09788
09789 case '2':
09790 offset = REM_SIMPLEX;
09791 break;
09792
09793 case '3':
09794 offset = REM_PLUS;
09795 break;
09796
09797 default:
09798 goto invalid_freq;
09799 }
09800 }
09801 }
09802 offsave = myrpt->offset;
09803 modesave = myrpt->remmode;
09804 strncpy(savestr, myrpt->freq, sizeof(savestr) - 1);
09805 strncpy(myrpt->freq, freq, sizeof(myrpt->freq) - 1);
09806 myrpt->offset = offset;
09807 myrpt->remmode = defmode;
09808
09809 if (setrem(myrpt) == -1){
09810 myrpt->offset = offsave;
09811 myrpt->remmode = modesave;
09812 strncpy(myrpt->freq, savestr, sizeof(myrpt->freq) - 1);
09813 goto invalid_freq;
09814 }
09815
09816 return DC_COMPLETE;
09817
09818 invalid_freq:
09819 rpt_telemetry(myrpt,INVFREQ,NULL);
09820 return DC_ERROR;
09821
09822 case 3:
09823 for(i = 0, j = 0, k = 0, l = 0 ; digitbuf[i] ; i++){
09824 if(digitbuf[i] == '*'){
09825 j++;
09826 continue;
09827 }
09828 if((digitbuf[i] < '0') || (digitbuf[i] > '9'))
09829 return DC_ERROR;
09830 else{
09831 if(j)
09832 l++;
09833 else
09834 k++;
09835 }
09836 }
09837 if((j > 1) || (k > 3) || (l > 1))
09838 return DC_ERROR;
09839 i = strlen(digitbuf) - 1;
09840 if((j != 1) || (k < 2)|| (l != 1))
09841 break;
09842 if(debug)
09843 printf("PL digits entered %s\n", digitbuf);
09844
09845 strncpy(tmp, digitbuf, sizeof(tmp) - 1);
09846
09847 s = strchr(tmp,'*');
09848 if(s)
09849 *s = '.';
09850 strncpy(savestr, myrpt->rxpl, sizeof(savestr) - 1);
09851 strncpy(myrpt->rxpl, tmp, sizeof(myrpt->rxpl) - 1);
09852 if(!strcmp(myrpt->remoterig, remote_rig_rbi))
09853 {
09854 strncpy(myrpt->txpl, tmp, sizeof(myrpt->txpl) - 1);
09855 }
09856 if (setrem(myrpt) == -1){
09857 strncpy(myrpt->rxpl, savestr, sizeof(myrpt->rxpl) - 1);
09858 return DC_ERROR;
09859 }
09860 return DC_COMPLETE;
09861
09862 case 4:
09863
09864 if(!strcmp(myrpt->remoterig, remote_rig_rbi))
09865 return DC_ERROR;
09866
09867
09868
09869
09870
09871 if(!strcmp(myrpt->remoterig, remote_rig_ic706))
09872 {
09873 if(debug)
09874 ast_log(LOG_WARNING,"Setting IC706 Tx CTCSS Code Not Supported. Set Rx Code for both.\n");
09875 return DC_ERROR;
09876 }
09877 for(i = 0, j = 0, k = 0, l = 0 ; digitbuf[i] ; i++){
09878 if(digitbuf[i] == '*'){
09879 j++;
09880 continue;
09881 }
09882 if((digitbuf[i] < '0') || (digitbuf[i] > '9'))
09883 return DC_ERROR;
09884 else{
09885 if(j)
09886 l++;
09887 else
09888 k++;
09889 }
09890 }
09891 if((j > 1) || (k > 3) || (l > 1))
09892 return DC_ERROR;
09893 i = strlen(digitbuf) - 1;
09894 if((j != 1) || (k < 2)|| (l != 1))
09895 break;
09896 if(debug)
09897 printf("PL digits entered %s\n", digitbuf);
09898
09899 strncpy(tmp, digitbuf, sizeof(tmp) - 1);
09900
09901 s = strchr(tmp,'*');
09902 if(s)
09903 *s = '.';
09904 strncpy(savestr, myrpt->txpl, sizeof(savestr) - 1);
09905 strncpy(myrpt->txpl, tmp, sizeof(myrpt->txpl) - 1);
09906
09907 if (setrem(myrpt) == -1){
09908 strncpy(myrpt->txpl, savestr, sizeof(myrpt->txpl) - 1);
09909 return DC_ERROR;
09910 }
09911 return DC_COMPLETE;
09912
09913
09914 case 6:
09915 if(strlen(digitbuf) < 1)
09916 break;
09917
09918 if(!multimode)
09919 return DC_ERROR;
09920
09921 switch(*digitbuf){
09922 case '1':
09923 split_freq(mhz, decimals, myrpt->freq);
09924 m=atoi(mhz);
09925 if(m < 29)
09926 return DC_ERROR;
09927 myrpt->remmode = REM_MODE_FM;
09928
09929 rpt_telemetry(myrpt,REMMODE,NULL);
09930 break;
09931
09932 case '2':
09933 myrpt->remmode = REM_MODE_USB;
09934 rpt_telemetry(myrpt,REMMODE,NULL);
09935 break;
09936
09937 case '3':
09938 myrpt->remmode = REM_MODE_LSB;
09939 rpt_telemetry(myrpt,REMMODE,NULL);
09940 break;
09941
09942 case '4':
09943 myrpt->remmode = REM_MODE_AM;
09944 rpt_telemetry(myrpt,REMMODE,NULL);
09945 break;
09946
09947 default:
09948 return DC_ERROR;
09949 }
09950
09951 if(setrem(myrpt))
09952 return DC_ERROR;
09953 return DC_COMPLETEQUIET;
09954 case 99:
09955
09956 if (myrpt->loginlevel[0])
09957 return DC_ERROR;
09958 *myrpt->loginuser = 0;
09959 myrpt->loginlevel[0] = 0;
09960 cp = ast_strdup(param);
09961 cp1 = strchr(cp,',');
09962 ast_mutex_lock(&myrpt->lock);
09963 if (cp1)
09964 {
09965 *cp1 = 0;
09966 cp2 = strchr(cp1 + 1,',');
09967 if (cp2)
09968 {
09969 *cp2 = 0;
09970 strncpy(myrpt->loginlevel,cp2 + 1,
09971 sizeof(myrpt->loginlevel) - 1);
09972 }
09973 strncpy(myrpt->loginuser,cp1 + 1,sizeof(myrpt->loginuser));
09974 ast_mutex_unlock(&myrpt->lock);
09975 if (myrpt->p.archivedir)
09976 {
09977 char str[100];
09978
09979 sprintf(str,"LOGIN,%s,%s",
09980 myrpt->loginuser,myrpt->loginlevel);
09981 donodelog(myrpt,str);
09982 }
09983 if (debug)
09984 printf("loginuser %s level %s\n",myrpt->loginuser,myrpt->loginlevel);
09985 rpt_telemetry(myrpt,REMLOGIN,NULL);
09986 }
09987 ast_free(cp);
09988 return DC_COMPLETEQUIET;
09989 case 100:
09990 myrpt->rxplon = 0;
09991 setrem(myrpt);
09992 rpt_telemetry(myrpt,REMXXX,(void *)p);
09993 return DC_COMPLETEQUIET;
09994 case 101:
09995 myrpt->rxplon = 1;
09996 setrem(myrpt);
09997 rpt_telemetry(myrpt,REMXXX,(void *)p);
09998 return DC_COMPLETEQUIET;
09999 case 102:
10000 myrpt->txplon = 0;
10001 setrem(myrpt);
10002 rpt_telemetry(myrpt,REMXXX,(void *)p);
10003 return DC_COMPLETEQUIET;
10004 case 103:
10005 myrpt->txplon = 1;
10006 setrem(myrpt);
10007 rpt_telemetry(myrpt,REMXXX,(void *)p);
10008 return DC_COMPLETEQUIET;
10009 case 104:
10010 if(!strcmp(myrpt->remoterig, remote_rig_ic706))
10011 return DC_ERROR;
10012 myrpt->powerlevel = REM_LOWPWR;
10013 setrem(myrpt);
10014 rpt_telemetry(myrpt,REMXXX,(void *)p);
10015 return DC_COMPLETEQUIET;
10016 case 105:
10017 if(!strcmp(myrpt->remoterig, remote_rig_ic706))
10018 return DC_ERROR;
10019 if (ISRIG_RTX(myrpt->remoterig)) return DC_ERROR;
10020 myrpt->powerlevel = REM_MEDPWR;
10021 setrem(myrpt);
10022 rpt_telemetry(myrpt,REMXXX,(void *)p);
10023 return DC_COMPLETEQUIET;
10024 case 106:
10025 if(!strcmp(myrpt->remoterig, remote_rig_ic706))
10026 return DC_ERROR;
10027 myrpt->powerlevel = REM_HIPWR;
10028 setrem(myrpt);
10029 rpt_telemetry(myrpt,REMXXX,(void *)p);
10030 return DC_COMPLETEQUIET;
10031 case 107:
10032 multimode_bump_freq(myrpt, -20);
10033 return DC_COMPLETE;
10034 case 108:
10035 multimode_bump_freq(myrpt, -100);
10036 return DC_COMPLETE;
10037 case 109:
10038 multimode_bump_freq(myrpt, -500);
10039 return DC_COMPLETE;
10040 case 110:
10041 multimode_bump_freq(myrpt, 20);
10042 return DC_COMPLETE;
10043 case 111:
10044 multimode_bump_freq(myrpt, 100);
10045 return DC_COMPLETE;
10046 case 112:
10047 multimode_bump_freq(myrpt, 500);
10048 return DC_COMPLETE;
10049 case 113:
10050 myrpt->scantimer = REM_SCANTIME;
10051 myrpt->hfscanmode = HF_SCAN_DOWN_SLOW;
10052 rpt_telemetry(myrpt,REMXXX,(void *)p);
10053 return DC_COMPLETEQUIET;
10054 case 114:
10055 myrpt->scantimer = REM_SCANTIME;
10056 myrpt->hfscanmode = HF_SCAN_DOWN_QUICK;
10057 rpt_telemetry(myrpt,REMXXX,(void *)p);
10058 return DC_COMPLETEQUIET;
10059 case 115:
10060 myrpt->scantimer = REM_SCANTIME;
10061 myrpt->hfscanmode = HF_SCAN_DOWN_FAST;
10062 rpt_telemetry(myrpt,REMXXX,(void *)p);
10063 return DC_COMPLETEQUIET;
10064 case 116:
10065 myrpt->scantimer = REM_SCANTIME;
10066 myrpt->hfscanmode = HF_SCAN_UP_SLOW;
10067 rpt_telemetry(myrpt,REMXXX,(void *)p);
10068 return DC_COMPLETEQUIET;
10069 case 117:
10070 myrpt->scantimer = REM_SCANTIME;
10071 myrpt->hfscanmode = HF_SCAN_UP_QUICK;
10072 rpt_telemetry(myrpt,REMXXX,(void *)p);
10073 return DC_COMPLETEQUIET;
10074 case 118:
10075 myrpt->scantimer = REM_SCANTIME;
10076 myrpt->hfscanmode = HF_SCAN_UP_FAST;
10077 rpt_telemetry(myrpt,REMXXX,(void *)p);
10078 return DC_COMPLETEQUIET;
10079 case 119:
10080 if(debug > 3)
10081 ast_log(LOG_NOTICE,"TUNE REQUEST\n");
10082
10083 if((!myrpt->tunerequest) &&
10084 ((!strcmp(myrpt->remoterig, remote_rig_ft897) ||
10085 !strcmp(myrpt->remoterig, remote_rig_ic706)) )) {
10086 myrpt->remotetx = 0;
10087 ast_indicate(myrpt->txchannel,AST_CONTROL_RADIO_UNKEY);
10088 myrpt->tunerequest = 1;
10089 rpt_telemetry(myrpt,TUNE,NULL);
10090 return DC_COMPLETEQUIET;
10091 }
10092 return DC_ERROR;
10093 case 5:
10094 rpt_telemetry(myrpt,REMLONGSTATUS,NULL);
10095 return DC_COMPLETEQUIET;
10096 case 140:
10097 rpt_telemetry(myrpt,REMSHORTSTATUS,NULL);
10098 return DC_COMPLETEQUIET;
10099 case 200:
10100 case 201:
10101 case 202:
10102 case 203:
10103 case 204:
10104 case 205:
10105 case 206:
10106 case 207:
10107 case 208:
10108 case 209:
10109 case 210:
10110 case 211:
10111 case 212:
10112 case 213:
10113 case 214:
10114 case 215:
10115 do_dtmf_local(myrpt,remdtmfstr[p - 200]);
10116 return DC_COMPLETEQUIET;
10117 default:
10118 break;
10119 }
10120 return DC_INDETERMINATE;
10121 }
10122
10123
10124 static int handle_remote_dtmf_digit(struct rpt *myrpt,char c, char *keyed, int phonemode)
10125 {
10126 time_t now;
10127 int ret,res = 0,src;
10128
10129 if(debug > 6)
10130 ast_log(LOG_NOTICE,"c=%c phonemode=%i dtmfidx=%i\n",c,phonemode,myrpt->dtmfidx);
10131
10132 time(&myrpt->last_activity_time);
10133
10134 if(myrpt->hfscanmode){
10135 stop_scan(myrpt);
10136 return 0;
10137 }
10138
10139 time(&now);
10140
10141 if ((myrpt->dtmf_time_rem + DTMF_TIMEOUT) < now)
10142 {
10143 myrpt->dtmfidx = -1;
10144 myrpt->dtmfbuf[0] = 0;
10145 myrpt->dtmf_time_rem = 0;
10146 }
10147
10148 if (myrpt->dtmfidx == -1)
10149 {
10150
10151 if (c != myrpt->p.funcchar)
10152 {
10153 if (!myrpt->p.propagate_dtmf)
10154 {
10155 rpt_mutex_lock(&myrpt->lock);
10156 do_dtmf_local(myrpt,c);
10157 rpt_mutex_unlock(&myrpt->lock);
10158 }
10159 return 0;
10160 }
10161 myrpt->dtmfidx = 0;
10162 myrpt->dtmfbuf[0] = 0;
10163 myrpt->dtmf_time_rem = now;
10164 return 0;
10165 }
10166
10167 if (myrpt->dtmfidx >= MAXDTMF)
10168 {
10169 myrpt->dtmfidx = 0;
10170 myrpt->dtmfbuf[0] = 0;
10171 myrpt->dtmf_time_rem = now;
10172 }
10173 if (c == myrpt->p.funcchar)
10174 {
10175
10176 if ((myrpt->dtmfidx < 1) ||
10177 (myrpt->dtmfbuf[myrpt->dtmfidx - 1] == myrpt->p.funcchar))
10178 {
10179 myrpt->dtmfidx = 0;
10180 myrpt->dtmfbuf[0] = 0;
10181 myrpt->dtmf_time_rem = now;
10182 return 0;
10183 }
10184 }
10185 myrpt->dtmfbuf[myrpt->dtmfidx++] = c;
10186 myrpt->dtmfbuf[myrpt->dtmfidx] = 0;
10187 myrpt->dtmf_time_rem = now;
10188
10189
10190 src = SOURCE_RMT;
10191 if (phonemode == 2) src = SOURCE_DPHONE;
10192 else if (phonemode) src = SOURCE_PHONE;
10193 else if (phonemode == 4) src = SOURCE_ALT;
10194 ret = collect_function_digits(myrpt, myrpt->dtmfbuf, src, NULL);
10195
10196 switch(ret){
10197
10198 case DC_INDETERMINATE:
10199 res = 0;
10200 break;
10201
10202 case DC_DOKEY:
10203 if (keyed) *keyed = 1;
10204 res = 0;
10205 break;
10206
10207 case DC_REQ_FLUSH:
10208 myrpt->dtmfidx = 0;
10209 myrpt->dtmfbuf[0] = 0;
10210 res = 0;
10211 break;
10212
10213
10214 case DC_COMPLETE:
10215 res = 1;
10216 case DC_COMPLETEQUIET:
10217 myrpt->totalexecdcommands++;
10218 myrpt->dailyexecdcommands++;
10219 strncpy(myrpt->lastdtmfcommand, myrpt->dtmfbuf, MAXDTMF-1);
10220 myrpt->lastdtmfcommand[MAXDTMF-1] = '\0';
10221 myrpt->dtmfbuf[0] = 0;
10222 myrpt->dtmfidx = -1;
10223 myrpt->dtmf_time_rem = 0;
10224 break;
10225
10226 case DC_ERROR:
10227 default:
10228 myrpt->dtmfbuf[0] = 0;
10229 myrpt->dtmfidx = -1;
10230 myrpt->dtmf_time_rem = 0;
10231 res = 0;
10232 break;
10233 }
10234
10235 return res;
10236 }
10237
10238 static int handle_remote_data(struct rpt *myrpt, char *str)
10239 {
10240
10241
10242 char tmp[300],cmd[300],dest[300],src[300],c;
10243 int seq,res;
10244
10245
10246 strncpy(tmp,str,sizeof(tmp) - 1);
10247 if (!strcmp(tmp,discstr)) return 0;
10248 if (!strcmp(tmp,newkeystr))
10249 {
10250 myrpt->newkey = 1;
10251 return 0;
10252 }
10253
10254 #ifndef DO_NOT_NOTIFY_MDC1200_ON_REMOTE_BASES
10255 if (tmp[0] == 'I')
10256 {
10257
10258
10259 if (sscanf(tmp,"%299s %299s %30x",cmd,src,&seq) != 3)
10260 {
10261 ast_log(LOG_WARNING, "Unable to parse ident string %s\n",str);
10262 return 0;
10263 }
10264 mdc1200_notify(myrpt,src,seq);
10265 return 0;
10266 }
10267 #endif
10268
10269
10270 if (sscanf(tmp,"%299s %299s %299s %30d %1c",cmd,dest,src,&seq,&c) != 5)
10271 {
10272 ast_log(LOG_WARNING, "Unable to parse link string %s\n",str);
10273 return 0;
10274 }
10275 if (strcmp(cmd,"D"))
10276 {
10277 ast_log(LOG_WARNING, "Unable to parse link string %s\n",str);
10278 return 0;
10279 }
10280
10281 if (strcmp(dest,myrpt->name)) return 0;
10282 if (myrpt->p.archivedir)
10283 {
10284 char dtmfstr[100];
10285
10286 sprintf(dtmfstr,"DTMF,%c",c);
10287 donodelog(myrpt,dtmfstr);
10288 }
10289 c = func_xlat(myrpt,c,&myrpt->p.outxlat);
10290 if (!c) return(0);
10291 res = handle_remote_dtmf_digit(myrpt,c, NULL, 0);
10292 if (res != 1)
10293 return res;
10294 rpt_telemetry(myrpt,COMPLETE,NULL);
10295 return 0;
10296 }
10297
10298 static int handle_remote_phone_dtmf(struct rpt *myrpt, char c, char *keyed, int phonemode)
10299 {
10300 int res;
10301
10302
10303 if(phonemode == 3)
10304 {
10305 if (keyed && *keyed && ((c == myrpt->p.funcchar) || (c == myrpt->p.endchar)))
10306 {
10307 *keyed = 0;
10308 return 0;
10309 }
10310 else if (keyed && !*keyed && (c = myrpt->p.funcchar))
10311 {
10312 *keyed = 1;
10313 return 0;
10314 }
10315 }
10316 else
10317 {
10318
10319 if (keyed && *keyed && (c == myrpt->p.endchar))
10320 {
10321 *keyed = 0;
10322 return DC_INDETERMINATE;
10323 }
10324 }
10325 if (myrpt->p.archivedir)
10326 {
10327 char str[100];
10328
10329 sprintf(str,"DTMF(P),%c",c);
10330 donodelog(myrpt,str);
10331 }
10332 res = handle_remote_dtmf_digit(myrpt,c,keyed, phonemode);
10333 if (res != 1)
10334 return res;
10335 rpt_telemetry(myrpt,COMPLETE,NULL);
10336 return 0;
10337 }
10338
10339 static int attempt_reconnect(struct rpt *myrpt, struct rpt_link *l)
10340 {
10341 char *val, *s, *s1, *s2, *tele;
10342 char tmp[300], deststr[300] = "";
10343 char sx[320],*sy;
10344
10345
10346 val = node_lookup(myrpt,l->name);
10347 if (!val)
10348 {
10349 fprintf(stderr,"attempt_reconnect: cannot find node %s\n",l->name);
10350 return -1;
10351 }
10352
10353 rpt_mutex_lock(&myrpt->lock);
10354
10355 remque((struct qelem *) l);
10356 rpt_mutex_unlock(&myrpt->lock);
10357 strncpy(tmp,val,sizeof(tmp) - 1);
10358 s = tmp;
10359 s1 = strsep(&s,",");
10360 if (!strchr(s1,':') && strchr(s1,'/') && strncasecmp(s1, "local/", 6))
10361 {
10362 sy = strchr(s1,'/');
10363 *sy = 0;
10364 sprintf(sx,"%s:4569/%s",s1,sy + 1);
10365 s1 = sx;
10366 }
10367 s2 = strsep(&s,",");
10368 snprintf(deststr, sizeof(deststr), "IAX2/%s", s1);
10369 tele = strchr(deststr, '/');
10370 if (!tele) {
10371 fprintf(stderr,"attempt_reconnect:Dial number (%s) must be in format tech/number\n",deststr);
10372 return -1;
10373 }
10374 *tele++ = 0;
10375 l->elaptime = 0;
10376 l->connecttime = 0;
10377 l->thisconnected = 0;
10378 l->newkey = 0;
10379 l->chan = ast_request(deststr, AST_FORMAT_SLINEAR, NULL, tele, NULL);
10380 if (l->chan){
10381 ast_set_read_format(l->chan, AST_FORMAT_SLINEAR);
10382 ast_set_write_format(l->chan, AST_FORMAT_SLINEAR);
10383 #ifndef NEW_ASTERISK
10384 l->chan->whentohangup = 0;
10385 #endif
10386 l->chan->appl = "Apprpt";
10387 l->chan->data = "(Remote Rx)";
10388 if (option_verbose > 2)
10389 ast_verbose(VERBOSE_PREFIX_3 "rpt (attempt_reconnect) initiating call to %s/%s on %s\n",
10390 deststr, tele, l->chan->name);
10391 l->chan->caller.id.number.valid = 1;
10392 ast_free(l->chan->caller.id.number.str);
10393 l->chan->caller.id.number.str = ast_strdup(myrpt->name);
10394 ast_call(l->chan,tele,999);
10395
10396 }
10397 else
10398 {
10399 if (option_verbose > 2)
10400 ast_verbose(VERBOSE_PREFIX_3 "Unable to place call to %s/%s on %s\n",
10401 deststr,tele,l->chan->name);
10402 return -1;
10403 }
10404 rpt_mutex_lock(&myrpt->lock);
10405
10406 insque((struct qelem *)l,(struct qelem *)myrpt->links.next);
10407 rpt_mutex_unlock(&myrpt->lock);
10408 ast_log(LOG_WARNING,"Reconnect Attempt to %s in process\n",l->name);
10409 if (!l->phonemode) send_newkey(l->chan);
10410 return 0;
10411 }
10412
10413
10414 static void local_dtmf_helper(struct rpt *myrpt,char c_in)
10415 {
10416 int res;
10417 pthread_attr_t attr;
10418 char cmd[MAXDTMF+1] = "",c;
10419
10420
10421 c = c_in & 0x7f;
10422 if (myrpt->p.archivedir)
10423 {
10424 char str[100];
10425
10426 sprintf(str,"DTMF,MAIN,%c",c);
10427 donodelog(myrpt,str);
10428 }
10429 if (c == myrpt->p.endchar)
10430 {
10431
10432 if (myrpt->p.simple && myrpt->callmode)
10433 {
10434 if(debug)
10435 ast_log(LOG_WARNING, "simple mode autopatch kill\n");
10436 rpt_mutex_lock(&myrpt->lock);
10437 myrpt->callmode = 0;
10438 myrpt->macropatch=0;
10439 channel_revert(myrpt);
10440 rpt_mutex_unlock(&myrpt->lock);
10441 rpt_telemetry(myrpt,TERM,NULL);
10442 return;
10443 }
10444 rpt_mutex_lock(&myrpt->lock);
10445 myrpt->stopgen = 1;
10446 if (myrpt->cmdnode[0])
10447 {
10448 myrpt->cmdnode[0] = 0;
10449 myrpt->dtmfidx = -1;
10450 myrpt->dtmfbuf[0] = 0;
10451 rpt_mutex_unlock(&myrpt->lock);
10452 rpt_telemetry(myrpt,COMPLETE,NULL);
10453 return;
10454 }
10455 else if(!myrpt->inpadtest)
10456 {
10457 rpt_mutex_unlock(&myrpt->lock);
10458 if (myrpt->p.propagate_phonedtmf)
10459 do_dtmf_phone(myrpt,NULL,c);
10460 return;
10461 }
10462 else
10463 rpt_mutex_unlock(&myrpt->lock);
10464 }
10465 rpt_mutex_lock(&myrpt->lock);
10466 if (myrpt->cmdnode[0])
10467 {
10468 rpt_mutex_unlock(&myrpt->lock);
10469 send_link_dtmf(myrpt,c);
10470 return;
10471 }
10472 if (!myrpt->p.simple)
10473 {
10474 if ((!myrpt->inpadtest)&&(c == myrpt->p.funcchar))
10475 {
10476 myrpt->dtmfidx = 0;
10477 myrpt->dtmfbuf[myrpt->dtmfidx] = 0;
10478 rpt_mutex_unlock(&myrpt->lock);
10479 time(&myrpt->dtmf_time);
10480 return;
10481 }
10482 else if (((myrpt->inpadtest)||(c != myrpt->p.endchar)) && (myrpt->dtmfidx >= 0))
10483 {
10484 time(&myrpt->dtmf_time);
10485
10486 if (myrpt->dtmfidx < MAXDTMF)
10487 {
10488 int src;
10489
10490 myrpt->dtmfbuf[myrpt->dtmfidx++] = c;
10491 myrpt->dtmfbuf[myrpt->dtmfidx] = 0;
10492
10493 strncpy(cmd, myrpt->dtmfbuf, sizeof(cmd) - 1);
10494
10495 rpt_mutex_unlock(&myrpt->lock);
10496 src = SOURCE_RPT;
10497 if (c_in & 0x80) src = SOURCE_ALT;
10498 res = collect_function_digits(myrpt, cmd, src, NULL);
10499 rpt_mutex_lock(&myrpt->lock);
10500 switch(res){
10501 case DC_INDETERMINATE:
10502 break;
10503 case DC_REQ_FLUSH:
10504 myrpt->dtmfidx = 0;
10505 myrpt->dtmfbuf[0] = 0;
10506 break;
10507 case DC_COMPLETE:
10508 case DC_COMPLETEQUIET:
10509 myrpt->totalexecdcommands++;
10510 myrpt->dailyexecdcommands++;
10511 strncpy(myrpt->lastdtmfcommand, cmd, MAXDTMF-1);
10512 myrpt->lastdtmfcommand[MAXDTMF-1] = '\0';
10513 myrpt->dtmfbuf[0] = 0;
10514 myrpt->dtmfidx = -1;
10515 myrpt->dtmf_time = 0;
10516 break;
10517
10518 case DC_ERROR:
10519 default:
10520 myrpt->dtmfbuf[0] = 0;
10521 myrpt->dtmfidx = -1;
10522 myrpt->dtmf_time = 0;
10523 break;
10524 }
10525 if(res != DC_INDETERMINATE) {
10526 rpt_mutex_unlock(&myrpt->lock);
10527 return;
10528 }
10529 }
10530 }
10531 }
10532 else
10533 {
10534 if ((!myrpt->callmode) && (c == myrpt->p.funcchar))
10535 {
10536 myrpt->callmode = 1;
10537 myrpt->patchnoct = 0;
10538 myrpt->patchquiet = 0;
10539 myrpt->patchfarenddisconnect = 0;
10540 myrpt->patchdialtime = 0;
10541 strncpy(myrpt->patchcontext, myrpt->p.ourcontext, MAXPATCHCONTEXT);
10542 myrpt->cidx = 0;
10543 myrpt->exten[myrpt->cidx] = 0;
10544 rpt_mutex_unlock(&myrpt->lock);
10545 pthread_attr_init(&attr);
10546 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
10547 ast_pthread_create(&myrpt->rpt_call_thread,&attr,rpt_call,(void *)myrpt);
10548 return;
10549 }
10550 }
10551 if (myrpt->callmode == 1)
10552 {
10553 myrpt->exten[myrpt->cidx++] = c;
10554 myrpt->exten[myrpt->cidx] = 0;
10555
10556 if (ast_exists_extension(myrpt->pchannel,myrpt->patchcontext,myrpt->exten,1,NULL))
10557 {
10558
10559 if (!ast_matchmore_extension(myrpt->pchannel,myrpt->patchcontext,
10560 myrpt->exten,1,NULL))
10561 {
10562 myrpt->callmode = 2;
10563 rpt_mutex_unlock(&myrpt->lock);
10564 if(!myrpt->patchquiet)
10565 rpt_telemetry(myrpt,PROC,NULL);
10566 return;
10567 }
10568 else
10569 {
10570 myrpt->calldigittimer = 1;
10571 }
10572 }
10573
10574 if (!ast_canmatch_extension(myrpt->pchannel,myrpt->patchcontext,myrpt->exten,1,NULL))
10575 {
10576
10577 myrpt->callmode = 4;
10578 }
10579 rpt_mutex_unlock(&myrpt->lock);
10580 return;
10581 }
10582 if ((myrpt->callmode == 2) || (myrpt->callmode == 3))
10583 {
10584 myrpt->mydtmf = c;
10585 }
10586 rpt_mutex_unlock(&myrpt->lock);
10587 if ((myrpt->dtmfidx < 0) && myrpt->p.propagate_phonedtmf)
10588 do_dtmf_phone(myrpt,NULL,c);
10589 return;
10590 }
10591
10592
10593
10594
10595 static void queue_id(struct rpt *myrpt)
10596 {
10597 if(myrpt->p.idtime){
10598 myrpt->mustid = myrpt->tailid = 0;
10599 myrpt->idtimer = myrpt->p.idtime;
10600 rpt_mutex_unlock(&myrpt->lock);
10601 rpt_telemetry(myrpt,ID,NULL);
10602 rpt_mutex_lock(&myrpt->lock);
10603 }
10604 }
10605
10606
10607
10608
10609 static void do_scheduler(struct rpt *myrpt)
10610 {
10611 int i,res;
10612
10613 #ifdef NEW_ASTERISK
10614 struct ast_tm tmnow;
10615 #else
10616 struct tm tmnow;
10617 #endif
10618 struct ast_variable *skedlist;
10619 char *strs[5],*vp,*val,value[100];
10620
10621 memcpy(&myrpt->lasttv, &myrpt->curtv, sizeof(struct timeval));
10622
10623 if( (res = gettimeofday(&myrpt->curtv, NULL)) < 0)
10624 ast_log(LOG_NOTICE, "Scheduler gettime of day returned: %s\n", strerror(res));
10625
10626
10627
10628 if(myrpt->lasttv.tv_sec == myrpt->curtv.tv_sec)
10629 return;
10630
10631 rpt_localtime(&myrpt->curtv.tv_sec, &tmnow);
10632
10633
10634
10635 if((tmnow.tm_hour == 0)&&(tmnow.tm_min == 0)&&(tmnow.tm_sec == 0)){
10636 myrpt->dailykeyups = 0;
10637 myrpt->dailytxtime = 0;
10638 myrpt->dailykerchunks = 0;
10639 myrpt->dailyexecdcommands = 0;
10640 }
10641
10642 if(tmnow.tm_sec != 0)
10643 return;
10644
10645
10646
10647
10648
10649
10650 if (myrpt->remote)
10651 return;
10652
10653
10654
10655 if(myrpt->p.s[myrpt->p.sysstate_cur].schedulerdisable){
10656 if(debug > 6)
10657 ast_log(LOG_NOTICE, "Scheduler disabled\n");
10658 return;
10659 }
10660
10661 if(!myrpt->p.skedstanzaname){
10662 if(debug > 6)
10663 ast_log(LOG_NOTICE,"No stanza for scheduler in rpt.conf\n");
10664 return;
10665 }
10666
10667
10668 skedlist = ast_variable_browse(myrpt->cfg, myrpt->p.skedstanzaname);
10669
10670 if(debug > 6){
10671 ast_log(LOG_NOTICE, "Time now: %02d:%02d %02d %02d %02d\n",
10672 tmnow.tm_hour,tmnow.tm_min,tmnow.tm_mday,tmnow.tm_mon + 1, tmnow.tm_wday);
10673 }
10674
10675 for(; skedlist; skedlist = skedlist->next){
10676 if(debug > 6)
10677 ast_log(LOG_NOTICE, "Scheduler entry %s = %s being considered\n",skedlist->name, skedlist->value);
10678 strncpy(value,skedlist->value,99);
10679 value[99] = 0;
10680
10681 for( i = 0, vp = value ; i < 5; i++){
10682 if(!*vp)
10683 break;
10684 while((*vp == ' ') || (*vp == 0x09))
10685 vp++;
10686 strs[i] = vp;
10687 while((*vp != ' ') && (*vp != 0x09) && (*vp != 0))
10688 vp++;
10689 if(*vp)
10690 *vp++ = 0;
10691 }
10692 if(debug > 6)
10693 ast_log(LOG_NOTICE, "i = %d, min = %s, hour = %s, mday=%s, mon=%s, wday=%s\n",i,
10694 strs[0], strs[1], strs[2], strs[3], strs[4]);
10695 if(i == 5){
10696 if((*strs[0] != '*')&&(atoi(strs[0]) != tmnow.tm_min))
10697 continue;
10698 if((*strs[1] != '*')&&(atoi(strs[1]) != tmnow.tm_hour))
10699 continue;
10700 if((*strs[2] != '*')&&(atoi(strs[2]) != tmnow.tm_mday))
10701 continue;
10702 if((*strs[3] != '*')&&(atoi(strs[3]) != tmnow.tm_mon + 1))
10703 continue;
10704 if(atoi(strs[4]) == 7)
10705 strs[4] = "0";
10706 if((*strs[4] != '*')&&(atoi(strs[4]) != tmnow.tm_wday))
10707 continue;
10708 if(debug)
10709 ast_log(LOG_NOTICE, "Executing scheduler entry %s = %s\n", skedlist->name, skedlist->value);
10710 if(atoi(skedlist->name) == 0)
10711 return;
10712 val = (char *) ast_variable_retrieve(myrpt->cfg, myrpt->p.macro, skedlist->name);
10713 if (!val){
10714 ast_log(LOG_WARNING,"Scheduler could not find macro %s\n",skedlist->name);
10715 return;
10716 }
10717 if ((MAXMACRO - strlen(myrpt->macrobuf)) < strlen(val)){
10718 ast_log(LOG_WARNING, "Scheduler could not execute macro %s: Macro buffer full\n",
10719 skedlist->name);
10720 return;
10721 }
10722 myrpt->macrotimer = MACROTIME;
10723 strncat(myrpt->macrobuf,val,MAXMACRO - 1);
10724 }
10725 else{
10726 ast_log(LOG_WARNING,"Malformed scheduler entry in rpt.conf: %s = %s\n",
10727 skedlist->name, skedlist->value);
10728 }
10729 }
10730
10731 }
10732
10733
10734 static void *rpt(void *this)
10735 {
10736 struct rpt *myrpt = (struct rpt *)this;
10737 char *tele,*idtalkover,c,myfirst,*p;
10738 int ms = MSWAIT,i,lasttx=0,val,remrx=0,identqueued,othertelemqueued;
10739 int tailmessagequeued,ctqueued,dtmfed,lastmyrx,localmsgqueued;
10740 struct ast_channel *who;
10741 struct dahdi_confinfo ci;
10742 time_t t;
10743 struct rpt_link *l,*m;
10744 struct rpt_tele *telem;
10745 char tmpstr[300],lstr[MAXLINKLIST];
10746
10747
10748 if (myrpt->p.archivedir) mkdir(myrpt->p.archivedir,0600);
10749 sprintf(tmpstr,"%s/%s",myrpt->p.archivedir,myrpt->name);
10750 mkdir(tmpstr,0600);
10751 rpt_mutex_lock(&myrpt->lock);
10752
10753 telem = myrpt->tele.next;
10754 while(telem != &myrpt->tele)
10755 {
10756 ast_softhangup(telem->chan,AST_SOFTHANGUP_DEV);
10757 telem = telem->next;
10758 }
10759 rpt_mutex_unlock(&myrpt->lock);
10760
10761 for(i = 0; i < nrpts; i++)
10762 {
10763 if (&rpt_vars[i] == myrpt)
10764 {
10765 load_rpt_vars(i,0);
10766 break;
10767 }
10768 }
10769
10770 rpt_mutex_lock(&myrpt->lock);
10771 while(myrpt->xlink)
10772 {
10773 myrpt->xlink = 3;
10774 rpt_mutex_unlock(&myrpt->lock);
10775 usleep(100000);
10776 rpt_mutex_lock(&myrpt->lock);
10777 }
10778 #ifdef HAVE_IOPERM
10779 if ((!strcmp(myrpt->remoterig, remote_rig_rbi)) &&
10780 (ioperm(myrpt->p.iobase,1,1) == -1))
10781 {
10782 rpt_mutex_unlock(&myrpt->lock);
10783 ast_log(LOG_WARNING, "Cant get io permission on IO port %x hex\n",myrpt->p.iobase);
10784 myrpt->rpt_thread = AST_PTHREADT_STOP;
10785 pthread_exit(NULL);
10786 }
10787 #endif
10788 strncpy(tmpstr,myrpt->rxchanname,sizeof(tmpstr) - 1);
10789 tele = strchr(tmpstr,'/');
10790 if (!tele)
10791 {
10792 fprintf(stderr,"rpt:Rxchannel Dial number (%s) must be in format tech/number\n",myrpt->rxchanname);
10793 rpt_mutex_unlock(&myrpt->lock);
10794 myrpt->rpt_thread = AST_PTHREADT_STOP;
10795 pthread_exit(NULL);
10796 }
10797 *tele++ = 0;
10798 myrpt->rxchannel = ast_request(tmpstr, AST_FORMAT_SLINEAR, NULL, tele, NULL);
10799 myrpt->dahdirxchannel = NULL;
10800 if (!strcasecmp(tmpstr,"DAHDI"))
10801 myrpt->dahdirxchannel = myrpt->rxchannel;
10802 if (myrpt->rxchannel)
10803 {
10804 if (myrpt->rxchannel->_state == AST_STATE_BUSY)
10805 {
10806 fprintf(stderr,"rpt:Sorry unable to obtain Rx channel\n");
10807 rpt_mutex_unlock(&myrpt->lock);
10808 ast_hangup(myrpt->rxchannel);
10809 myrpt->rpt_thread = AST_PTHREADT_STOP;
10810 pthread_exit(NULL);
10811 }
10812 ast_set_read_format(myrpt->rxchannel,AST_FORMAT_SLINEAR);
10813 ast_set_write_format(myrpt->rxchannel,AST_FORMAT_SLINEAR);
10814 #ifdef AST_CDR_FLAG_POST_DISABLED
10815 if (myrpt->rxchannel->cdr)
10816 ast_set_flag(myrpt->rxchannel->cdr,AST_CDR_FLAG_POST_DISABLED);
10817 #endif
10818 #ifndef NEW_ASTERISK
10819 myrpt->rxchannel->whentohangup = 0;
10820 #endif
10821 myrpt->rxchannel->appl = "Apprpt";
10822 myrpt->rxchannel->data = "(Repeater Rx)";
10823 if (option_verbose > 2)
10824 ast_verbose(VERBOSE_PREFIX_3 "rpt (Rx) initiating call to %s/%s on %s\n",
10825 tmpstr,tele,myrpt->rxchannel->name);
10826 ast_call(myrpt->rxchannel,tele,999);
10827 if (myrpt->rxchannel->_state != AST_STATE_UP)
10828 {
10829 rpt_mutex_unlock(&myrpt->lock);
10830 ast_hangup(myrpt->rxchannel);
10831 myrpt->rpt_thread = AST_PTHREADT_STOP;
10832 pthread_exit(NULL);
10833 }
10834 }
10835 else
10836 {
10837 fprintf(stderr,"rpt:Sorry unable to obtain Rx channel\n");
10838 rpt_mutex_unlock(&myrpt->lock);
10839 myrpt->rpt_thread = AST_PTHREADT_STOP;
10840 pthread_exit(NULL);
10841 }
10842 myrpt->dahditxchannel = NULL;
10843 if (myrpt->txchanname)
10844 {
10845 strncpy(tmpstr,myrpt->txchanname,sizeof(tmpstr) - 1);
10846 tele = strchr(tmpstr,'/');
10847 if (!tele)
10848 {
10849 fprintf(stderr,"rpt:Txchannel Dial number (%s) must be in format tech/number\n",myrpt->txchanname);
10850 rpt_mutex_unlock(&myrpt->lock);
10851 ast_hangup(myrpt->rxchannel);
10852 myrpt->rpt_thread = AST_PTHREADT_STOP;
10853 pthread_exit(NULL);
10854 }
10855 *tele++ = 0;
10856 myrpt->txchannel = ast_request(tmpstr, AST_FORMAT_SLINEAR, NULL, tele, NULL);
10857 if (!strcasecmp(tmpstr,"DAHDI"))
10858 myrpt->dahditxchannel = myrpt->txchannel;
10859 if (myrpt->txchannel)
10860 {
10861 if (myrpt->txchannel->_state == AST_STATE_BUSY)
10862 {
10863 fprintf(stderr,"rpt:Sorry unable to obtain Tx channel\n");
10864 rpt_mutex_unlock(&myrpt->lock);
10865 ast_hangup(myrpt->txchannel);
10866 ast_hangup(myrpt->rxchannel);
10867 myrpt->rpt_thread = AST_PTHREADT_STOP;
10868 pthread_exit(NULL);
10869 }
10870 ast_set_read_format(myrpt->txchannel,AST_FORMAT_SLINEAR);
10871 ast_set_write_format(myrpt->txchannel,AST_FORMAT_SLINEAR);
10872 #ifdef AST_CDR_FLAG_POST_DISABLED
10873 if (myrpt->txchannel->cdr)
10874 ast_set_flag(myrpt->txchannel->cdr,AST_CDR_FLAG_POST_DISABLED);
10875 #endif
10876 #ifndef NEW_ASTERISK
10877 myrpt->txchannel->whentohangup = 0;
10878 #endif
10879 myrpt->txchannel->appl = "Apprpt";
10880 myrpt->txchannel->data = "(Repeater Tx)";
10881 if (option_verbose > 2)
10882 ast_verbose(VERBOSE_PREFIX_3 "rpt (Tx) initiating call to %s/%s on %s\n",
10883 tmpstr,tele,myrpt->txchannel->name);
10884 ast_call(myrpt->txchannel,tele,999);
10885 if (myrpt->rxchannel->_state != AST_STATE_UP)
10886 {
10887 rpt_mutex_unlock(&myrpt->lock);
10888 ast_hangup(myrpt->rxchannel);
10889 ast_hangup(myrpt->txchannel);
10890 myrpt->rpt_thread = AST_PTHREADT_STOP;
10891 pthread_exit(NULL);
10892 }
10893 }
10894 else
10895 {
10896 fprintf(stderr,"rpt:Sorry unable to obtain Tx channel\n");
10897 rpt_mutex_unlock(&myrpt->lock);
10898 ast_hangup(myrpt->rxchannel);
10899 myrpt->rpt_thread = AST_PTHREADT_STOP;
10900 pthread_exit(NULL);
10901 }
10902 }
10903 else
10904 {
10905 myrpt->txchannel = myrpt->rxchannel;
10906 if (!strncasecmp(myrpt->rxchanname,"DAHDI",3))
10907 myrpt->dahditxchannel = myrpt->txchannel;
10908 }
10909 ast_indicate(myrpt->txchannel,AST_CONTROL_RADIO_KEY);
10910 ast_indicate(myrpt->txchannel,AST_CONTROL_RADIO_UNKEY);
10911
10912 myrpt->pchannel = ast_request("DAHDI", AST_FORMAT_SLINEAR, NULL, "pseudo", NULL);
10913 if (!myrpt->pchannel)
10914 {
10915 fprintf(stderr,"rpt:Sorry unable to obtain pseudo channel\n");
10916 rpt_mutex_unlock(&myrpt->lock);
10917 if (myrpt->txchannel != myrpt->rxchannel)
10918 ast_hangup(myrpt->txchannel);
10919 ast_hangup(myrpt->rxchannel);
10920 myrpt->rpt_thread = AST_PTHREADT_STOP;
10921 pthread_exit(NULL);
10922 }
10923 #ifdef AST_CDR_FLAG_POST_DISABLED
10924 if (myrpt->pchannel->cdr)
10925 ast_set_flag(myrpt->pchannel->cdr,AST_CDR_FLAG_POST_DISABLED);
10926 #endif
10927 if (!myrpt->dahdirxchannel) myrpt->dahdirxchannel = myrpt->pchannel;
10928 if (!myrpt->dahditxchannel)
10929 {
10930
10931 myrpt->dahditxchannel = ast_request("DAHDI", AST_FORMAT_SLINEAR, NULL, "pseudo", NULL);
10932 if (!myrpt->dahditxchannel)
10933 {
10934 fprintf(stderr,"rpt:Sorry unable to obtain pseudo channel\n");
10935 rpt_mutex_unlock(&myrpt->lock);
10936 if (myrpt->txchannel != myrpt->rxchannel)
10937 ast_hangup(myrpt->txchannel);
10938 ast_hangup(myrpt->rxchannel);
10939 myrpt->rpt_thread = AST_PTHREADT_STOP;
10940 pthread_exit(NULL);
10941 }
10942 ast_set_read_format(myrpt->dahditxchannel,AST_FORMAT_SLINEAR);
10943 ast_set_write_format(myrpt->dahditxchannel,AST_FORMAT_SLINEAR);
10944 #ifdef AST_CDR_FLAG_POST_DISABLED
10945 if (myrpt->dahditxchannel->cdr)
10946 ast_set_flag(myrpt->dahditxchannel->cdr,AST_CDR_FLAG_POST_DISABLED);
10947 #endif
10948 }
10949
10950 myrpt->monchannel = ast_request("DAHDI", AST_FORMAT_SLINEAR, NULL, "pseudo", NULL);
10951 if (!myrpt->monchannel)
10952 {
10953 fprintf(stderr,"rpt:Sorry unable to obtain pseudo channel\n");
10954 rpt_mutex_unlock(&myrpt->lock);
10955 if (myrpt->txchannel != myrpt->rxchannel)
10956 ast_hangup(myrpt->txchannel);
10957 ast_hangup(myrpt->rxchannel);
10958 myrpt->rpt_thread = AST_PTHREADT_STOP;
10959 pthread_exit(NULL);
10960 }
10961 ast_set_read_format(myrpt->monchannel,AST_FORMAT_SLINEAR);
10962 ast_set_write_format(myrpt->monchannel,AST_FORMAT_SLINEAR);
10963 #ifdef AST_CDR_FLAG_POST_DISABLED
10964 if (myrpt->monchannel->cdr)
10965 ast_set_flag(myrpt->monchannel->cdr,AST_CDR_FLAG_POST_DISABLED);
10966 #endif
10967
10968 ci.chan = 0;
10969 ci.confno = -1;
10970 ci.confmode = DAHDI_CONF_CONF | DAHDI_CONF_LISTENER;
10971
10972 if (ioctl(myrpt->dahditxchannel->fds[0],DAHDI_SETCONF,&ci) == -1)
10973 {
10974 ast_log(LOG_WARNING, "Unable to set conference mode to Announce\n");
10975 rpt_mutex_unlock(&myrpt->lock);
10976 ast_hangup(myrpt->pchannel);
10977 ast_hangup(myrpt->monchannel);
10978 if (myrpt->txchannel != myrpt->rxchannel)
10979 ast_hangup(myrpt->txchannel);
10980 ast_hangup(myrpt->rxchannel);
10981 myrpt->rpt_thread = AST_PTHREADT_STOP;
10982 pthread_exit(NULL);
10983 }
10984
10985 myrpt->txconf = ci.confno;
10986
10987 ci.chan = 0;
10988 ci.confno = -1;
10989 ci.confmode = ((myrpt->p.duplex == 2) || (myrpt->p.duplex == 4)) ? DAHDI_CONF_CONFANNMON :
10990 (DAHDI_CONF_CONF | DAHDI_CONF_LISTENER | DAHDI_CONF_TALKER);
10991
10992 if (ioctl(myrpt->pchannel->fds[0],DAHDI_SETCONF,&ci) == -1)
10993 {
10994 ast_log(LOG_WARNING, "Unable to set conference mode to Announce\n");
10995 rpt_mutex_unlock(&myrpt->lock);
10996 ast_hangup(myrpt->pchannel);
10997 ast_hangup(myrpt->monchannel);
10998 if (myrpt->txchannel != myrpt->rxchannel)
10999 ast_hangup(myrpt->txchannel);
11000 ast_hangup(myrpt->rxchannel);
11001 myrpt->rpt_thread = AST_PTHREADT_STOP;
11002 pthread_exit(NULL);
11003 }
11004
11005 myrpt->conf = ci.confno;
11006
11007 ci.chan = 0;
11008 if ((strstr(myrpt->txchannel->name,"pseudo") == NULL) &&
11009 (myrpt->dahditxchannel == myrpt->txchannel))
11010 {
11011
11012 if (ioctl(myrpt->txchannel->fds[0],DAHDI_CHANNO,&ci.confno) == -1)
11013 {
11014 ast_log(LOG_WARNING, "Unable to set tx channel's chan number\n");
11015 rpt_mutex_unlock(&myrpt->lock);
11016 ast_hangup(myrpt->pchannel);
11017 ast_hangup(myrpt->monchannel);
11018 if (myrpt->txchannel != myrpt->rxchannel)
11019 ast_hangup(myrpt->txchannel);
11020 ast_hangup(myrpt->rxchannel);
11021 myrpt->rpt_thread = AST_PTHREADT_STOP;
11022 pthread_exit(NULL);
11023 }
11024 ci.confmode = DAHDI_CONF_MONITORTX;
11025 }
11026 else
11027 {
11028 ci.confno = myrpt->txconf;
11029 ci.confmode = DAHDI_CONF_CONFANNMON;
11030 }
11031
11032 if (ioctl(myrpt->monchannel->fds[0],DAHDI_SETCONF,&ci) == -1)
11033 {
11034 ast_log(LOG_WARNING, "Unable to set conference mode for monitor\n");
11035 rpt_mutex_unlock(&myrpt->lock);
11036 ast_hangup(myrpt->pchannel);
11037 ast_hangup(myrpt->monchannel);
11038 if (myrpt->txchannel != myrpt->rxchannel)
11039 ast_hangup(myrpt->txchannel);
11040 ast_hangup(myrpt->rxchannel);
11041 myrpt->rpt_thread = AST_PTHREADT_STOP;
11042 pthread_exit(NULL);
11043 }
11044
11045 myrpt->parrotchannel = ast_request("DAHDI", AST_FORMAT_SLINEAR, NULL, "pseudo", NULL);
11046 if (!myrpt->parrotchannel)
11047 {
11048 fprintf(stderr,"rpt:Sorry unable to obtain pseudo channel\n");
11049 rpt_mutex_unlock(&myrpt->lock);
11050 if (myrpt->txchannel != myrpt->rxchannel)
11051 ast_hangup(myrpt->txchannel);
11052 ast_hangup(myrpt->rxchannel);
11053 myrpt->rpt_thread = AST_PTHREADT_STOP;
11054 pthread_exit(NULL);
11055 }
11056 ast_set_read_format(myrpt->parrotchannel,AST_FORMAT_SLINEAR);
11057 ast_set_write_format(myrpt->parrotchannel,AST_FORMAT_SLINEAR);
11058 #ifdef AST_CDR_FLAG_POST_DISABLED
11059 if (myrpt->parrotchannel->cdr)
11060 ast_set_flag(myrpt->parrotchannel->cdr,AST_CDR_FLAG_POST_DISABLED);
11061 #endif
11062
11063 myrpt->voxchannel = ast_request("DAHDI", AST_FORMAT_SLINEAR, NULL, "pseudo", NULL);
11064 if (!myrpt->voxchannel)
11065 {
11066 fprintf(stderr,"rpt:Sorry unable to obtain pseudo channel\n");
11067 rpt_mutex_unlock(&myrpt->lock);
11068 if (myrpt->txchannel != myrpt->rxchannel)
11069 ast_hangup(myrpt->txchannel);
11070 ast_hangup(myrpt->rxchannel);
11071 myrpt->rpt_thread = AST_PTHREADT_STOP;
11072 pthread_exit(NULL);
11073 }
11074 ast_set_read_format(myrpt->voxchannel,AST_FORMAT_SLINEAR);
11075 ast_set_write_format(myrpt->voxchannel,AST_FORMAT_SLINEAR);
11076 #ifdef AST_CDR_FLAG_POST_DISABLED
11077 if (myrpt->voxchannel->cdr)
11078 ast_set_flag(myrpt->voxchannel->cdr,AST_CDR_FLAG_POST_DISABLED);
11079 #endif
11080
11081 myrpt->txpchannel = ast_request("DAHDI", AST_FORMAT_SLINEAR, NULL, "pseudo", NULL);
11082 if (!myrpt->txpchannel)
11083 {
11084 fprintf(stderr,"rpt:Sorry unable to obtain pseudo channel\n");
11085 rpt_mutex_unlock(&myrpt->lock);
11086 ast_hangup(myrpt->pchannel);
11087 ast_hangup(myrpt->monchannel);
11088 if (myrpt->txchannel != myrpt->rxchannel)
11089 ast_hangup(myrpt->txchannel);
11090 ast_hangup(myrpt->rxchannel);
11091 myrpt->rpt_thread = AST_PTHREADT_STOP;
11092 pthread_exit(NULL);
11093 }
11094 #ifdef AST_CDR_FLAG_POST_DISABLED
11095 if (myrpt->txpchannel->cdr)
11096 ast_set_flag(myrpt->txpchannel->cdr,AST_CDR_FLAG_POST_DISABLED);
11097 #endif
11098
11099 ci.chan = 0;
11100 ci.confno = myrpt->txconf;
11101 ci.confmode = DAHDI_CONF_CONF | DAHDI_CONF_TALKER ;
11102
11103 if (ioctl(myrpt->txpchannel->fds[0],DAHDI_SETCONF,&ci) == -1)
11104 {
11105 ast_log(LOG_WARNING, "Unable to set conference mode to Announce\n");
11106 rpt_mutex_unlock(&myrpt->lock);
11107 ast_hangup(myrpt->txpchannel);
11108 ast_hangup(myrpt->monchannel);
11109 if (myrpt->txchannel != myrpt->rxchannel)
11110 ast_hangup(myrpt->txchannel);
11111 ast_hangup(myrpt->rxchannel);
11112 myrpt->rpt_thread = AST_PTHREADT_STOP;
11113 pthread_exit(NULL);
11114 }
11115
11116 myrpt->iofd = -1;
11117 if (myrpt->p.ioport && ((myrpt->iofd = openserial(myrpt,myrpt->p.ioport)) == -1))
11118 {
11119 ast_log(LOG_ERROR, "Unable to open %s\n",myrpt->p.ioport);
11120 rpt_mutex_unlock(&myrpt->lock);
11121 ast_hangup(myrpt->pchannel);
11122 if (myrpt->txchannel != myrpt->rxchannel)
11123 ast_hangup(myrpt->txchannel);
11124 ast_hangup(myrpt->rxchannel);
11125 pthread_exit(NULL);
11126 }
11127
11128
11129
11130 myrpt->links.next = &myrpt->links;
11131 myrpt->links.prev = &myrpt->links;
11132 myrpt->tailtimer = 0;
11133 myrpt->totimer = 0;
11134 myrpt->tmsgtimer = myrpt->p.tailmessagetime;
11135 myrpt->idtimer = myrpt->p.politeid;
11136 myrpt->mustid = myrpt->tailid = 0;
11137 myrpt->callmode = 0;
11138 myrpt->tounkeyed = 0;
11139 myrpt->tonotify = 0;
11140 myrpt->retxtimer = 0;
11141 myrpt->rerxtimer = 0;
11142 myrpt->skedtimer = 0;
11143 myrpt->tailevent = 0;
11144 lasttx = 0;
11145 myrpt->keyed = 0;
11146 myrpt->txkeyed = 0;
11147 time(&myrpt->lastkeyedtime);
11148 myrpt->lastkeyedtime -= RPT_LOCKOUT_SECS;
11149 time(&myrpt->lasttxkeyedtime);
11150 myrpt->lasttxkeyedtime -= RPT_LOCKOUT_SECS;
11151 idtalkover = (char *) ast_variable_retrieve(myrpt->cfg, myrpt->name, "idtalkover");
11152 myrpt->dtmfidx = -1;
11153 myrpt->dtmfbuf[0] = 0;
11154 myrpt->rem_dtmfidx = -1;
11155 myrpt->rem_dtmfbuf[0] = 0;
11156 myrpt->dtmf_time = 0;
11157 myrpt->rem_dtmf_time = 0;
11158 myrpt->inpadtest = 0;
11159 myrpt->disgorgetime = 0;
11160 myrpt->lastnodewhichkeyedusup[0] = '\0';
11161 myrpt->dailytxtime = 0;
11162 myrpt->totaltxtime = 0;
11163 myrpt->dailykeyups = 0;
11164 myrpt->totalkeyups = 0;
11165 myrpt->dailykerchunks = 0;
11166 myrpt->totalkerchunks = 0;
11167 myrpt->dailyexecdcommands = 0;
11168 myrpt->totalexecdcommands = 0;
11169 myrpt->timeouts = 0;
11170 myrpt->exten[0] = '\0';
11171 myrpt->lastdtmfcommand[0] = '\0';
11172 voxinit_rpt(myrpt,1);
11173 myrpt->wasvox = 0;
11174 if (myrpt->p.startupmacro)
11175 {
11176 snprintf(myrpt->macrobuf,MAXMACRO - 1,"PPPP%s",myrpt->p.startupmacro);
11177 }
11178 rpt_mutex_unlock(&myrpt->lock);
11179 val = 1;
11180 ast_channel_setoption(myrpt->rxchannel,AST_OPTION_RELAXDTMF,&val,sizeof(char),0);
11181 val = 1;
11182 ast_channel_setoption(myrpt->rxchannel,AST_OPTION_TONE_VERIFY,&val,sizeof(char),0);
11183 if (myrpt->p.archivedir) donodelog(myrpt,"STARTUP");
11184 dtmfed = 0;
11185 if (myrpt->remoterig && !ISRIG_RTX(myrpt->remoterig)) setrem(myrpt);
11186 lastmyrx = 0;
11187 myfirst = 0;
11188 while (ms >= 0)
11189 {
11190 struct ast_frame *f,*f1,*f2;
11191 struct ast_channel *cs[300],*cs1[300];
11192 int totx=0,elap=0,n,x,toexit=0;
11193
11194
11195 if((myrpt->disgorgetime) && (time(NULL) >= myrpt->disgorgetime)){
11196 struct rpt_link *dl;
11197 struct rpt_tele *dt;
11198
11199 myrpt->disgorgetime = 0;
11200 ast_log(LOG_NOTICE,"********** Variable Dump Start (app_rpt) **********\n");
11201 ast_log(LOG_NOTICE,"totx = %d\n",totx);
11202 ast_log(LOG_NOTICE,"remrx = %d\n",remrx);
11203 ast_log(LOG_NOTICE,"lasttx = %d\n",lasttx);
11204 ast_log(LOG_NOTICE,"elap = %d\n",elap);
11205 ast_log(LOG_NOTICE,"toexit = %d\n",toexit);
11206
11207 ast_log(LOG_NOTICE,"myrpt->keyed = %d\n",myrpt->keyed);
11208 ast_log(LOG_NOTICE,"myrpt->localtx = %d\n",myrpt->localtx);
11209 ast_log(LOG_NOTICE,"myrpt->callmode = %d\n",myrpt->callmode);
11210 ast_log(LOG_NOTICE,"myrpt->mustid = %d\n",myrpt->mustid);
11211 ast_log(LOG_NOTICE,"myrpt->tounkeyed = %d\n",myrpt->tounkeyed);
11212 ast_log(LOG_NOTICE,"myrpt->tonotify = %d\n",myrpt->tonotify);
11213 ast_log(LOG_NOTICE,"myrpt->retxtimer = %ld\n",myrpt->retxtimer);
11214 ast_log(LOG_NOTICE,"myrpt->totimer = %d\n",myrpt->totimer);
11215 ast_log(LOG_NOTICE,"myrpt->tailtimer = %d\n",myrpt->tailtimer);
11216 ast_log(LOG_NOTICE,"myrpt->tailevent = %d\n",myrpt->tailevent);
11217
11218 dl = myrpt->links.next;
11219 while(dl != &myrpt->links){
11220 ast_log(LOG_NOTICE,"*** Link Name: %s ***\n",dl->name);
11221 ast_log(LOG_NOTICE," link->lasttx %d\n",dl->lasttx);
11222 ast_log(LOG_NOTICE," link->lastrx %d\n",dl->lastrx);
11223 ast_log(LOG_NOTICE," link->connected %d\n",dl->connected);
11224 ast_log(LOG_NOTICE," link->hasconnected %d\n",dl->hasconnected);
11225 ast_log(LOG_NOTICE," link->outbound %d\n",dl->outbound);
11226 ast_log(LOG_NOTICE," link->disced %d\n",dl->disced);
11227 ast_log(LOG_NOTICE," link->killme %d\n",dl->killme);
11228 ast_log(LOG_NOTICE," link->disctime %ld\n",dl->disctime);
11229 ast_log(LOG_NOTICE," link->retrytimer %ld\n",dl->retrytimer);
11230 ast_log(LOG_NOTICE," link->retries = %d\n",dl->retries);
11231 ast_log(LOG_NOTICE," link->reconnects = %d\n",dl->reconnects);
11232 ast_log(LOG_NOTICE," link->newkey = %d\n",dl->newkey);
11233 dl = dl->next;
11234 }
11235
11236 dt = myrpt->tele.next;
11237 if(dt != &myrpt->tele)
11238 ast_log(LOG_NOTICE,"*** Telemetry Queue ***\n");
11239 while(dt != &myrpt->tele){
11240 ast_log(LOG_NOTICE," Telemetry mode: %d\n",dt->mode);
11241 dt = dt->next;
11242 }
11243 ast_log(LOG_NOTICE,"******* Variable Dump End (app_rpt) *******\n");
11244
11245 }
11246
11247
11248 if (myrpt->reload)
11249 {
11250 struct rpt_tele *inner_telem;
11251
11252 rpt_mutex_lock(&myrpt->lock);
11253 inner_telem = myrpt->tele.next;
11254 while(inner_telem != &myrpt->tele)
11255 {
11256 ast_softhangup(inner_telem->chan,AST_SOFTHANGUP_DEV);
11257 inner_telem = inner_telem->next;
11258 }
11259 myrpt->reload = 0;
11260 rpt_mutex_unlock(&myrpt->lock);
11261 usleep(10000);
11262
11263 for(i = 0; i < nrpts; i++)
11264 {
11265 if (&rpt_vars[i] == myrpt)
11266 {
11267 load_rpt_vars(i,0);
11268 break;
11269 }
11270 }
11271 }
11272
11273 rpt_mutex_lock(&myrpt->lock);
11274 if (ast_check_hangup(myrpt->rxchannel)) break;
11275 if (ast_check_hangup(myrpt->txchannel)) break;
11276 if (ast_check_hangup(myrpt->pchannel)) break;
11277 if (ast_check_hangup(myrpt->monchannel)) break;
11278 if (myrpt->parrotchannel &&
11279 ast_check_hangup(myrpt->parrotchannel)) break;
11280 if (myrpt->voxchannel &&
11281 ast_check_hangup(myrpt->voxchannel)) break;
11282 if (ast_check_hangup(myrpt->txpchannel)) break;
11283 if (myrpt->dahditxchannel && ast_check_hangup(myrpt->dahditxchannel)) break;
11284
11285
11286 myrpt->localtx = myrpt->keyed;
11287
11288 l = myrpt->links.next;
11289 remrx = 0;
11290 while(l != &myrpt->links)
11291 {
11292 if (l->lastrx){
11293 remrx = 1;
11294 if(l->name[0] != '0')
11295 strcpy(myrpt->lastnodewhichkeyedusup, l->name);
11296 }
11297 l = l->next;
11298 }
11299
11300 if(myrpt->p.idtime)
11301 myrpt->mustid |= (myrpt->idtimer) && (myrpt->keyed || remrx) ;
11302
11303
11304 if (myrpt->p.duplex > 1)
11305 {
11306 totx = myrpt->callmode;
11307 totx = totx || myrpt->localtx;
11308 }
11309 else
11310 {
11311 int myrx = myrpt->localtx || remrx || (!myrpt->callmode);
11312
11313 if (lastmyrx != myrx)
11314 {
11315 voxinit_rpt(myrpt,!myrx);
11316 lastmyrx = myrx;
11317 }
11318 totx = 0;
11319 if (myrpt->callmode && (myrpt->voxtotimer <= 0))
11320 {
11321 if (myrpt->voxtostate)
11322 {
11323 myrpt->voxtotimer = myrpt->p.voxtimeout_ms;
11324 myrpt->voxtostate = 0;
11325 }
11326 else
11327 {
11328 myrpt->voxtotimer = myrpt->p.voxrecover_ms;
11329 myrpt->voxtostate = 1;
11330 }
11331 }
11332 if (!myrpt->voxtostate)
11333 totx = myrpt->callmode && myrpt->wasvox;
11334 }
11335
11336 identqueued = 0;
11337 localmsgqueued = 0;
11338 othertelemqueued = 0;
11339 tailmessagequeued = 0;
11340 ctqueued = 0;
11341 telem = myrpt->tele.next;
11342 while(telem != &myrpt->tele)
11343 {
11344 if((telem->mode == ID) || (telem->mode == IDTALKOVER)){
11345 identqueued = 1;
11346 }
11347 else if(telem->mode == TAILMSG)
11348 {
11349 tailmessagequeued = 1;
11350 }
11351 else if(telem->mode == STATS_TIME_LOCAL)
11352 {
11353 localmsgqueued = 1;
11354 }
11355 else
11356 {
11357 if ((telem->mode != UNKEY) && (telem->mode != LINKUNKEY))
11358 othertelemqueued = 1;
11359 else
11360 ctqueued = 1;
11361 }
11362 telem = telem->next;
11363 }
11364
11365
11366 if (!myrpt->p.notelemtx) totx = totx || othertelemqueued;
11367
11368
11369 myrpt->exttx = totx;
11370 totx = totx || myrpt->dtmf_local_timer;
11371
11372 if (myrpt->p.duplex < 2) myrpt->exttx = myrpt->exttx || myrpt->localtx;
11373
11374 totx = totx || remrx;
11375
11376 if (myrpt->p.duplex > 0)
11377 totx = totx || identqueued || ctqueued || localmsgqueued;
11378
11379 if (myrpt->p.duplex > 1)
11380 {
11381 totx = totx || (myrpt->dtmfidx > -1) ||
11382 myrpt->cmdnode[0];
11383 }
11384
11385 totx = totx || (myrpt->parrotstate > 1);
11386
11387 if (!totx)
11388 {
11389 myrpt->totimer = myrpt->p.totime;
11390 myrpt->tounkeyed = 0;
11391 myrpt->tonotify = 0;
11392 }
11393 else{
11394 myrpt->tailtimer = myrpt->p.s[myrpt->p.sysstate_cur].alternatetail ?
11395 myrpt->p.althangtime :
11396 myrpt->p.hangtime;
11397 }
11398
11399 totx = totx && myrpt->totimer;
11400
11401 if ((!myrpt->totimer) && (!myrpt->tonotify))
11402 {
11403 myrpt->tonotify = 1;
11404 myrpt->timeouts++;
11405 rpt_mutex_unlock(&myrpt->lock);
11406 rpt_telemetry(myrpt,TIMEOUT,NULL);
11407 rpt_mutex_lock(&myrpt->lock);
11408 }
11409
11410
11411 if ((!totx) && (!myrpt->totimer) && (!myrpt->tounkeyed) && (!myrpt->keyed))
11412 {
11413 myrpt->tounkeyed = 1;
11414 }
11415 if ((!totx) && (!myrpt->totimer) && myrpt->tounkeyed && myrpt->keyed)
11416 {
11417 myrpt->totimer = myrpt->p.totime;
11418 myrpt->tounkeyed = 0;
11419 myrpt->tonotify = 0;
11420 rpt_mutex_unlock(&myrpt->lock);
11421 continue;
11422 }
11423
11424 if ((!totx) && (!myrpt->totimer) && (myrpt->callmode == 4))
11425 {
11426 if(debug)
11427 ast_log(LOG_NOTICE, "timed-out and in circuit busy after call\n");
11428 myrpt->callmode = 0;
11429 myrpt->macropatch=0;
11430 channel_revert(myrpt);
11431 }
11432
11433 if (!myrpt->totimer) myrpt->tailtimer = 0;
11434
11435 if (myrpt->totimer) totx = totx || myrpt->tailtimer;
11436
11437
11438 if ((myrpt->keyed || remrx) && ((identqueued && idtalkover) || (tailmessagequeued))) {
11439 int hasid = 0,hastalkover = 0;
11440
11441 telem = myrpt->tele.next;
11442 while(telem != &myrpt->tele){
11443 if(telem->mode == ID){
11444 if (telem->chan) ast_softhangup(telem->chan, AST_SOFTHANGUP_DEV);
11445 hasid = 1;
11446 }
11447 if(telem->mode == TAILMSG){
11448 if (telem->chan) ast_softhangup(telem->chan, AST_SOFTHANGUP_DEV);
11449 }
11450 if (telem->mode == IDTALKOVER) hastalkover = 1;
11451 telem = telem->next;
11452 }
11453 rpt_mutex_unlock(&myrpt->lock);
11454 if (hasid && (!hastalkover)) rpt_telemetry(myrpt, IDTALKOVER, NULL);
11455 rpt_mutex_lock(&myrpt->lock);
11456 }
11457
11458
11459
11460
11461
11462 if(myrpt->mustid && (!myrpt->idtimer))
11463 queue_id(myrpt);
11464
11465 if ((myrpt->p.idtime && totx && (!myrpt->exttx) &&
11466 (myrpt->idtimer <= myrpt->p.politeid) && myrpt->tailtimer))
11467 {
11468 myrpt->tailid = 1;
11469 }
11470
11471
11472
11473 if(myrpt->tailevent){
11474 myrpt->tailevent = 0;
11475 if(myrpt->tailid){
11476 totx = 1;
11477 queue_id(myrpt);
11478 }
11479 else if ((myrpt->p.tailmessages[0]) &&
11480 (myrpt->p.tailmessagetime) && (myrpt->tmsgtimer == 0)){
11481 totx = 1;
11482 myrpt->tmsgtimer = myrpt->p.tailmessagetime;
11483 rpt_mutex_unlock(&myrpt->lock);
11484 rpt_telemetry(myrpt, TAILMSG, NULL);
11485 rpt_mutex_lock(&myrpt->lock);
11486 }
11487 }
11488
11489
11490
11491
11492 if (myrpt->p.duplex > 0) totx = totx || (myrpt->tele.next != &myrpt->tele);
11493 totx = totx && !myrpt->p.s[myrpt->p.sysstate_cur].txdisable;
11494 myrpt->txrealkeyed = totx;
11495 totx = totx || (!AST_LIST_EMPTY(&myrpt->txq));
11496 if (totx && (!lasttx))
11497 {
11498 char mydate[100],myfname[100];
11499 time_t myt;
11500
11501 if (myrpt->monstream) ast_closestream(myrpt->monstream);
11502 if (myrpt->p.archivedir)
11503 {
11504 long blocksleft;
11505
11506 time(&myt);
11507 strftime(mydate,sizeof(mydate) - 1,"%Y%m%d%H%M%S",
11508 localtime(&myt));
11509 sprintf(myfname,"%s/%s/%s",myrpt->p.archivedir,
11510 myrpt->name,mydate);
11511 myrpt->monstream = ast_writefile(myfname,"wav49",
11512 "app_rpt Air Archive",O_CREAT | O_APPEND,0,0600);
11513 if (myrpt->p.monminblocks)
11514 {
11515 blocksleft = diskavail(myrpt);
11516 if (blocksleft >= myrpt->p.monminblocks)
11517 donodelog(myrpt,"TXKEY,MAIN");
11518 } else donodelog(myrpt,"TXKEY,MAIN");
11519 }
11520 lasttx = 1;
11521 myrpt->txkeyed = 1;
11522 time(&myrpt->lasttxkeyedtime);
11523 myrpt->dailykeyups++;
11524 myrpt->totalkeyups++;
11525 rpt_mutex_unlock(&myrpt->lock);
11526 ast_indicate(myrpt->txchannel,AST_CONTROL_RADIO_KEY);
11527 rpt_mutex_lock(&myrpt->lock);
11528 }
11529 if ((!totx) && lasttx)
11530 {
11531 if (myrpt->monstream) ast_closestream(myrpt->monstream);
11532 myrpt->monstream = NULL;
11533
11534 lasttx = 0;
11535 myrpt->txkeyed = 0;
11536 time(&myrpt->lasttxkeyedtime);
11537 rpt_mutex_unlock(&myrpt->lock);
11538 ast_indicate(myrpt->txchannel,AST_CONTROL_RADIO_UNKEY);
11539 rpt_mutex_lock(&myrpt->lock);
11540 donodelog(myrpt,"TXUNKEY,MAIN");
11541 }
11542 time(&t);
11543
11544 if ((!myrpt->cmdnode[0]) && (myrpt->dtmfidx >= 0) && ((myrpt->dtmf_time + DTMF_TIMEOUT) < t))
11545 {
11546 myrpt->inpadtest = 0;
11547 myrpt->dtmfidx = -1;
11548 myrpt->dtmfbuf[0] = 0;
11549 }
11550
11551 if ((myrpt->rem_dtmfidx >= 0) && ((myrpt->rem_dtmf_time + DTMF_TIMEOUT) < t))
11552 {
11553 myrpt->inpadtest = 0;
11554 myrpt->rem_dtmfidx = -1;
11555 myrpt->rem_dtmfbuf[0] = 0;
11556 }
11557
11558 if (myrpt->exttx && myrpt->parrotchannel &&
11559 myrpt->p.parrotmode && (!myrpt->parrotstate))
11560 {
11561 char myfname[300];
11562
11563 ci.confno = myrpt->conf;
11564 ci.confmode = DAHDI_CONF_CONFANNMON;
11565 ci.chan = 0;
11566
11567
11568 if (ioctl(myrpt->parrotchannel->fds[0],DAHDI_SETCONF,&ci) == -1)
11569 {
11570 ast_log(LOG_WARNING, "Unable to set conference mode for parrot\n");
11571 break;
11572 }
11573
11574 sprintf(myfname,PARROTFILE,myrpt->name,myrpt->parrotcnt);
11575 strcat(myfname,".wav");
11576 unlink(myfname);
11577 sprintf(myfname,PARROTFILE,myrpt->name,myrpt->parrotcnt);
11578 myrpt->parrotstate = 1;
11579 myrpt->parrottimer = myrpt->p.parrottime;
11580 if (myrpt->parrotstream)
11581 ast_closestream(myrpt->parrotstream);
11582 myrpt->parrotstream = NULL;
11583 myrpt->parrotstream = ast_writefile(myfname,"wav",
11584 "app_rpt Parrot",O_CREAT | O_TRUNC,0,0600);
11585 }
11586
11587
11588
11589 l = myrpt->links.next;
11590 while(l != &myrpt->links)
11591 {
11592 if (l->killme)
11593 {
11594
11595 remque((struct qelem *) l);
11596 if (!strcmp(myrpt->cmdnode,l->name))
11597 myrpt->cmdnode[0] = 0;
11598 rpt_mutex_unlock(&myrpt->lock);
11599
11600 if (l->chan) ast_hangup(l->chan);
11601 ast_hangup(l->pchan);
11602 ast_free(l);
11603 rpt_mutex_lock(&myrpt->lock);
11604
11605 l = myrpt->links.next;
11606 continue;
11607 }
11608 l = l->next;
11609 }
11610 n = 0;
11611 cs[n++] = myrpt->rxchannel;
11612 cs[n++] = myrpt->pchannel;
11613 cs[n++] = myrpt->monchannel;
11614 if (myrpt->parrotchannel) cs[n++] = myrpt->parrotchannel;
11615 if (myrpt->voxchannel) cs[n++] = myrpt->voxchannel;
11616 cs[n++] = myrpt->txpchannel;
11617 if (myrpt->txchannel != myrpt->rxchannel) cs[n++] = myrpt->txchannel;
11618 if (myrpt->dahditxchannel != myrpt->txchannel)
11619 cs[n++] = myrpt->dahditxchannel;
11620 l = myrpt->links.next;
11621 while(l != &myrpt->links)
11622 {
11623 if ((!l->killme) && (!l->disctime) && l->chan)
11624 {
11625 cs[n++] = l->chan;
11626 cs[n++] = l->pchan;
11627 }
11628 l = l->next;
11629 }
11630 if ((myrpt->topkeystate == 1) &&
11631 ((t - myrpt->topkeytime) > TOPKEYWAIT))
11632 {
11633 myrpt->topkeystate = 2;
11634 qsort(myrpt->topkey,TOPKEYN,sizeof(struct rpt_topkey),
11635 topcompar);
11636 }
11637 rpt_mutex_unlock(&myrpt->lock);
11638
11639 if (myrpt->topkeystate == 2)
11640 {
11641 rpt_telemetry(myrpt,TOPKEY,NULL);
11642 myrpt->topkeystate = 3;
11643 }
11644 ms = MSWAIT;
11645 for(x = 0; x < n; x++)
11646 {
11647 int s = -(-x - myrpt->scram - 1) % n;
11648 cs1[x] = cs[s];
11649 }
11650 myrpt->scram++;
11651 who = ast_waitfor_n(cs1,n,&ms);
11652 if (who == NULL) ms = 0;
11653 elap = MSWAIT - ms;
11654 rpt_mutex_lock(&myrpt->lock);
11655 l = myrpt->links.next;
11656 while(l != &myrpt->links)
11657 {
11658 int myrx;
11659
11660 if (l->voxtotimer) l->voxtotimer -= elap;
11661 if (l->voxtotimer < 0) l->voxtotimer = 0;
11662
11663 if (l->lasttx != l->lasttx1)
11664 {
11665 voxinit_link(l,!l->lasttx);
11666 l->lasttx1 = l->lasttx;
11667 }
11668 myrx = l->lastrealrx;
11669 if ((l->phonemode) && (l->phonevox))
11670 {
11671 myrx = myrx || (!AST_LIST_EMPTY(&l->rxq));
11672 if (l->voxtotimer <= 0)
11673 {
11674 if (l->voxtostate)
11675 {
11676 l->voxtotimer = myrpt->p.voxtimeout_ms;
11677 l->voxtostate = 0;
11678 }
11679 else
11680 {
11681 l->voxtotimer = myrpt->p.voxrecover_ms;
11682 l->voxtostate = 1;
11683 }
11684 }
11685 if (!l->voxtostate)
11686 myrx = myrx || l->wasvox ;
11687 }
11688 l->lastrx = myrx;
11689 if (l->linklisttimer)
11690 {
11691 l->linklisttimer -= elap;
11692 if (l->linklisttimer < 0) l->linklisttimer = 0;
11693 }
11694 if ((!l->linklisttimer) && (l->name[0] != '0') && (!l->isremote))
11695 {
11696 struct ast_frame lf;
11697
11698 memset(&lf,0,sizeof(lf));
11699 lf.frametype = AST_FRAME_TEXT;
11700 lf.subclass.integer = 0;
11701 lf.offset = 0;
11702 lf.mallocd = 0;
11703 lf.samples = 0;
11704 l->linklisttimer = LINKLISTTIME;
11705 strcpy(lstr,"L ");
11706 __mklinklist(myrpt,l,lstr + 2);
11707 if (l->chan)
11708 {
11709 lf.datalen = strlen(lstr) + 1;
11710 lf.data.ptr = lstr;
11711 ast_write(l->chan,&lf);
11712 if (debug > 6) ast_log(LOG_NOTICE,
11713 "@@@@ node %s sent node string %s to node %s\n",
11714 myrpt->name,lstr,l->name);
11715 }
11716 }
11717 if (l->newkey)
11718 {
11719 if ((l->retxtimer += elap) >= REDUNDANT_TX_TIME)
11720 {
11721 l->retxtimer = 0;
11722 if (l->chan && l->phonemode == 0)
11723 {
11724 if (l->lasttx)
11725 ast_indicate(l->chan,AST_CONTROL_RADIO_KEY);
11726 else
11727 ast_indicate(l->chan,AST_CONTROL_RADIO_UNKEY);
11728 }
11729 }
11730 if ((l->rerxtimer += elap) >= (REDUNDANT_TX_TIME * 5))
11731 {
11732 if (debug == 7) printf("@@@@ rx un-key\n");
11733 l->lastrealrx = 0;
11734 l->rerxtimer = 0;
11735 if (l->lastrx1)
11736 {
11737 if (myrpt->p.archivedir)
11738 {
11739 char str[100];
11740
11741 sprintf(str,"RXUNKEY(T),%s",l->name);
11742 donodelog(myrpt,str);
11743 }
11744 if(myrpt->p.duplex)
11745 rpt_telemetry(myrpt,LINKUNKEY,l);
11746 l->lastrx1 = 0;
11747 }
11748 }
11749 }
11750 if (l->disctime)
11751 {
11752 l->disctime -= elap;
11753 if (l->disctime <= 0)
11754 l->disctime = 0;
11755 }
11756
11757 if (l->retrytimer)
11758 {
11759 l->retrytimer -= elap;
11760 if (l->retrytimer < 0) l->retrytimer = 0;
11761 }
11762
11763
11764 l->connecttime += elap;
11765
11766
11767 if (l->elaptime < 0)
11768 {
11769 l = l->next;
11770 continue;
11771 }
11772 l->elaptime += elap;
11773
11774 if ((l->elaptime > MAXCONNECTTIME) &&
11775 ((!l->chan) || (l->chan->_state != AST_STATE_UP)))
11776 {
11777 l->elaptime = 0;
11778 rpt_mutex_unlock(&myrpt->lock);
11779 if (l->chan) ast_softhangup(l->chan,AST_SOFTHANGUP_DEV);
11780 rpt_mutex_lock(&myrpt->lock);
11781 break;
11782 }
11783 if ((!l->chan) && (!l->retrytimer) && l->outbound &&
11784 (l->retries++ < l->max_retries) && (l->hasconnected))
11785 {
11786 if (l->chan) ast_hangup(l->chan);
11787 l->chan = 0;
11788 rpt_mutex_unlock(&myrpt->lock);
11789 if ((l->name[0] != '0') && (!l->isremote))
11790 {
11791 if (attempt_reconnect(myrpt,l) == -1)
11792 {
11793 l->retrytimer = RETRY_TIMER_MS;
11794 }
11795 }
11796 else
11797 {
11798 l->retrytimer = l->max_retries + 1;
11799 }
11800
11801 rpt_mutex_lock(&myrpt->lock);
11802 break;
11803 }
11804 if ((!l->chan) && (!l->retrytimer) && l->outbound &&
11805 (l->retries >= l->max_retries))
11806 {
11807
11808 remque((struct qelem *) l);
11809 if (!strcmp(myrpt->cmdnode,l->name))
11810 myrpt->cmdnode[0] = 0;
11811 rpt_mutex_unlock(&myrpt->lock);
11812 if (l->name[0] != '0')
11813 {
11814 if (!l->hasconnected)
11815 rpt_telemetry(myrpt,CONNFAIL,l);
11816 else rpt_telemetry(myrpt,REMDISC,l);
11817 }
11818 if (myrpt->p.archivedir)
11819 {
11820 char str[100];
11821
11822 if (!l->hasconnected)
11823 sprintf(str,"LINKFAIL,%s",l->name);
11824 else
11825 sprintf(str,"LINKDISC,%s",l->name);
11826 donodelog(myrpt,str);
11827 }
11828
11829 ast_hangup(l->pchan);
11830 ast_free(l);
11831 rpt_mutex_lock(&myrpt->lock);
11832 break;
11833 }
11834 if ((!l->chan) && (!l->disctime) && (!l->outbound))
11835 {
11836 if(debug)ast_log(LOG_NOTICE, "LINKDISC AA\n");
11837
11838 remque((struct qelem *) l);
11839 if(myrpt->links.next==&myrpt->links)channel_revert(myrpt);
11840 if (!strcmp(myrpt->cmdnode,l->name))myrpt->cmdnode[0] = 0;
11841 rpt_mutex_unlock(&myrpt->lock);
11842 if (l->name[0] != '0')
11843 {
11844 rpt_telemetry(myrpt,REMDISC,l);
11845 }
11846 if (myrpt->p.archivedir)
11847 {
11848 char str[100];
11849 sprintf(str,"LINKDISC,%s",l->name);
11850 donodelog(myrpt,str);
11851 }
11852
11853 ast_hangup(l->pchan);
11854 ast_free(l);
11855 rpt_mutex_lock(&myrpt->lock);
11856 break;
11857 }
11858 l = l->next;
11859 }
11860 if (myrpt->linkposttimer)
11861 {
11862 myrpt->linkposttimer -= elap;
11863 if (myrpt->linkposttimer < 0) myrpt->linkposttimer = 0;
11864 }
11865 if (myrpt->linkposttimer <= 0)
11866 {
11867 int nstr;
11868 char lst,*str;
11869 time_t now;
11870
11871 myrpt->linkposttimer = LINKPOSTTIME;
11872 nstr = 0;
11873 for(l = myrpt->links.next; l != &myrpt->links; l = l->next)
11874 {
11875
11876 if (l->name[0] == '0') continue;
11877 nstr += strlen(l->name) + 1;
11878 }
11879 str = ast_malloc(nstr + 256);
11880 if (!str)
11881 {
11882 ast_log(LOG_NOTICE,"Cannot ast_malloc()\n");
11883 break;
11884 }
11885 nstr = 0;
11886 strcpy(str,"nodes=");
11887 for(l = myrpt->links.next; l != &myrpt->links; l = l->next)
11888 {
11889
11890 if (l->name[0] == '0') continue;
11891 lst = 'T';
11892 if (!l->mode) lst = 'R';
11893 if (!l->thisconnected) lst = 'C';
11894 if (nstr) strcat(str,",");
11895 sprintf(str + strlen(str),"%c%s",lst,l->name);
11896 nstr = 1;
11897 }
11898 p = strstr(tdesc, "version");
11899 if(p){
11900 int vmajor,vminor;
11901 if(sscanf(p, "version %30d.%30d", &vmajor, &vminor) == 2)
11902 sprintf(str + strlen(str),"&apprptvers=%d.%d",vmajor,vminor);
11903 }
11904 time(&now);
11905 sprintf(str + strlen(str),"&apprptuptime=%d",(int)(now-starttime));
11906 sprintf(str + strlen(str),
11907 "&totalkerchunks=%d&totalkeyups=%d&totaltxtime=%d&timeouts=%d&totalexecdcommands=%d",
11908 myrpt->totalkerchunks,myrpt->totalkeyups,(int) myrpt->totaltxtime/1000,
11909 myrpt->timeouts,myrpt->totalexecdcommands);
11910 rpt_mutex_unlock(&myrpt->lock);
11911 statpost(myrpt,str);
11912 rpt_mutex_lock(&myrpt->lock);
11913 ast_free(str);
11914 }
11915 if (myrpt->keyposttimer)
11916 {
11917 myrpt->keyposttimer -= elap;
11918 if (myrpt->keyposttimer < 0) myrpt->keyposttimer = 0;
11919 }
11920 if (myrpt->keyposttimer <= 0)
11921 {
11922 char str[100];
11923 int diff = 0;
11924 time_t now;
11925
11926 myrpt->keyposttimer = KEYPOSTTIME;
11927 time(&now);
11928 if (myrpt->lastkeyedtime)
11929 {
11930 diff = (int)(now - myrpt->lastkeyedtime);
11931 }
11932 sprintf(str,"keyed=%d&keytime=%d",myrpt->keyed,diff);
11933 rpt_mutex_unlock(&myrpt->lock);
11934 statpost(myrpt,str);
11935 rpt_mutex_lock(&myrpt->lock);
11936 }
11937 if(totx){
11938 myrpt->dailytxtime += elap;
11939 myrpt->totaltxtime += elap;
11940 }
11941 i = myrpt->tailtimer;
11942 if (myrpt->tailtimer) myrpt->tailtimer -= elap;
11943 if (myrpt->tailtimer < 0) myrpt->tailtimer = 0;
11944 if((i) && (myrpt->tailtimer == 0))
11945 myrpt->tailevent = 1;
11946 if ((!myrpt->p.s[myrpt->p.sysstate_cur].totdisable) && myrpt->totimer) myrpt->totimer -= elap;
11947 if (myrpt->totimer < 0) myrpt->totimer = 0;
11948 if (myrpt->idtimer) myrpt->idtimer -= elap;
11949 if (myrpt->idtimer < 0) myrpt->idtimer = 0;
11950 if (myrpt->tmsgtimer) myrpt->tmsgtimer -= elap;
11951 if (myrpt->tmsgtimer < 0) myrpt->tmsgtimer = 0;
11952 if (myrpt->voxtotimer) myrpt->voxtotimer -= elap;
11953 if (myrpt->voxtotimer < 0) myrpt->voxtotimer = 0;
11954 if (myrpt->exttx)
11955 {
11956 myrpt->parrottimer = myrpt->p.parrottime;
11957 }
11958 else
11959 {
11960 if (myrpt->parrottimer) myrpt->parrottimer -= elap;
11961 if (myrpt->parrottimer < 0) myrpt->parrottimer = 0;
11962 }
11963
11964 if (myrpt->macrotimer) myrpt->macrotimer -= elap;
11965 if (myrpt->macrotimer < 0) myrpt->macrotimer = 0;
11966
11967 if (myrpt->dtmf_local_timer)
11968 {
11969 if (myrpt->dtmf_local_timer > 1) myrpt->dtmf_local_timer -= elap;
11970 if (myrpt->dtmf_local_timer < 1) myrpt->dtmf_local_timer = 1;
11971 }
11972 do_dtmf_local(myrpt,0);
11973
11974 if (myrpt->skedtimer <= 0){
11975 myrpt->skedtimer = 200;
11976 do_scheduler(myrpt);
11977 }
11978 else
11979 myrpt->skedtimer -=elap;
11980 if (!ms)
11981 {
11982 rpt_mutex_unlock(&myrpt->lock);
11983 continue;
11984 }
11985 if (myrpt->p.parrotmode && (myrpt->parrotstate == 1) &&
11986 (myrpt->parrottimer <= 0))
11987 {
11988
11989 ci.confno = 0;
11990 ci.confmode = 0;
11991 ci.chan = 0;
11992
11993
11994 if (ioctl(myrpt->parrotchannel->fds[0],DAHDI_SETCONF,&ci) == -1)
11995 {
11996 ast_log(LOG_WARNING, "Unable to set conference mode for parrot\n");
11997 break;
11998 }
11999 if (myrpt->parrotstream)
12000 ast_closestream(myrpt->parrotstream);
12001 myrpt->parrotstream = NULL;
12002 myrpt->parrotstate = 2;
12003 rpt_telemetry(myrpt,PARROT,(void *) ((intptr_t)myrpt->parrotcnt++));
12004 }
12005 if (myrpt->cmdAction.state == CMD_STATE_READY)
12006 {
12007 int status;
12008 myrpt->cmdAction.state = CMD_STATE_EXECUTING;
12009
12010 rpt_mutex_unlock(&myrpt->lock);
12011
12012 status = (*function_table[myrpt->cmdAction.functionNumber].function)(myrpt,myrpt->cmdAction.param, myrpt->cmdAction.digits, myrpt->cmdAction.command_source, NULL);
12013
12014 rpt_mutex_lock(&myrpt->lock);
12015 myrpt->cmdAction.state = CMD_STATE_IDLE;
12016 }
12017
12018 c = myrpt->macrobuf[0];
12019 time(&t);
12020 if (c && (!myrpt->macrotimer) &&
12021 starttime && (t > (starttime + START_DELAY)))
12022 {
12023 char cin = c & 0x7f;
12024 myrpt->macrotimer = MACROTIME;
12025 memmove(myrpt->macrobuf,myrpt->macrobuf + 1,MAXMACRO - 1);
12026 if ((cin == 'p') || (cin == 'P'))
12027 myrpt->macrotimer = MACROPTIME;
12028 rpt_mutex_unlock(&myrpt->lock);
12029 if (myrpt->p.archivedir)
12030 {
12031 char str[100];
12032
12033 sprintf(str,"DTMF(M),MAIN,%c",cin);
12034 donodelog(myrpt,str);
12035 }
12036 local_dtmf_helper(myrpt,c);
12037 } else rpt_mutex_unlock(&myrpt->lock);
12038 if (who == myrpt->rxchannel)
12039 {
12040 int ismuted;
12041
12042 f = ast_read(myrpt->rxchannel);
12043 if (!f)
12044 {
12045 if (debug) printf("@@@@ rpt:Hung Up\n");
12046 break;
12047 }
12048 if (f->frametype == AST_FRAME_VOICE)
12049 {
12050 #ifdef _MDC_DECODE_H_
12051 unsigned char ubuf[2560];
12052 short *sp;
12053 int n;
12054 #endif
12055
12056 if ((!myrpt->localtx) && (!myrpt->p.linktolink)) {
12057 memset(f->data.ptr,0,f->datalen);
12058 }
12059
12060 #ifdef _MDC_DECODE_H_
12061 sp = (short *) f->data;
12062
12063 for(n = 0; n < f->datalen / 2; n++)
12064 {
12065 ubuf[n] = (*sp++ >> 8) + 128;
12066 }
12067 n = mdc_decoder_process_samples(myrpt->mdc,ubuf,f->datalen / 2);
12068 if (n == 1)
12069 {
12070 unsigned char op,arg;
12071 unsigned short unitID;
12072
12073 mdc_decoder_get_packet(myrpt->mdc,&op,&arg,&unitID);
12074 if (debug > 2)
12075 {
12076 ast_log(LOG_NOTICE,"Got (single-length) packet:\n");
12077 ast_log(LOG_NOTICE,"op: %02x, arg: %02x, UnitID: %04x\n",
12078 op & 255,arg & 255,unitID);
12079 }
12080 if ((op == 1) && (arg == 0))
12081 {
12082 myrpt->lastunit = unitID;
12083 mdc1200_notify(myrpt,NULL,myrpt->lastunit);
12084 mdc1200_send(myrpt,myrpt->lastunit);
12085 }
12086 }
12087 if ((debug > 2) && (i == 2))
12088 {
12089 unsigned char op,arg,ex1,ex2,ex3,ex4;
12090 unsigned short unitID;
12091
12092 mdc_decoder_get_double_packet(myrpt->mdc,&op,&arg,&unitID,
12093 &ex1,&ex2,&ex3,&ex4);
12094 ast_log(LOG_NOTICE,"Got (double-length) packet:\n");
12095 ast_log(LOG_NOTICE,"op: %02x, arg: %02x, UnitID: %04x\n",
12096 op & 255,arg & 255,unitID);
12097 ast_log(LOG_NOTICE,"ex1: %02x, ex2: %02x, ex3: %02x, ex4: %02x\n",
12098 ex1 & 255, ex2 & 255, ex3 & 255, ex4 & 255);
12099 }
12100 #endif
12101 #ifdef __RPT_NOTCH
12102
12103 rpt_filter(myrpt,f->data,f->datalen / 2);
12104 #endif
12105 if (ioctl(myrpt->dahdirxchannel->fds[0], DAHDI_GETCONFMUTE, &ismuted) == -1)
12106 {
12107 ismuted = 0;
12108 }
12109 if (dtmfed) ismuted = 1;
12110 dtmfed = 0;
12111 if (ismuted)
12112 {
12113 memset(f->data.ptr,0,f->datalen);
12114 if (myrpt->lastf1)
12115 memset(myrpt->lastf1->data.ptr,0,myrpt->lastf1->datalen);
12116 if (myrpt->lastf2)
12117 memset(myrpt->lastf2->data.ptr,0,myrpt->lastf2->datalen);
12118 }
12119 if (f) f2 = ast_frdup(f);
12120 else f2 = NULL;
12121 f1 = myrpt->lastf2;
12122 myrpt->lastf2 = myrpt->lastf1;
12123 myrpt->lastf1 = f2;
12124 if (ismuted)
12125 {
12126 if (myrpt->lastf1)
12127 memset(myrpt->lastf1->data.ptr,0,myrpt->lastf1->datalen);
12128 if (myrpt->lastf2)
12129 memset(myrpt->lastf2->data.ptr,0,myrpt->lastf2->datalen);
12130 }
12131 if (f1)
12132 {
12133 ast_write(myrpt->pchannel,f1);
12134 ast_frfree(f1);
12135 }
12136 }
12137 #ifndef OLD_ASTERISK
12138 else if (f->frametype == AST_FRAME_DTMF_BEGIN)
12139 {
12140 if (myrpt->lastf1)
12141 memset(myrpt->lastf1->data.ptr,0,myrpt->lastf1->datalen);
12142 if (myrpt->lastf2)
12143 memset(myrpt->lastf2->data.ptr,0,myrpt->lastf2->datalen);
12144 dtmfed = 1;
12145 }
12146 #endif
12147 else if (f->frametype == AST_FRAME_DTMF)
12148 {
12149 c = (char) f->subclass.integer;
12150 ast_frfree(f);
12151 if (myrpt->lastf1)
12152 memset(myrpt->lastf1->data.ptr,0,myrpt->lastf1->datalen);
12153 if (myrpt->lastf2)
12154 memset(myrpt->lastf2->data.ptr,0,myrpt->lastf2->datalen);
12155 dtmfed = 1;
12156 if (!myrpt->keyed) continue;
12157 c = func_xlat(myrpt,c,&myrpt->p.inxlat);
12158 if (c) local_dtmf_helper(myrpt,c);
12159 continue;
12160 }
12161 else if (f->frametype == AST_FRAME_CONTROL)
12162 {
12163 if (f->subclass.integer == AST_CONTROL_HANGUP)
12164 {
12165 if (debug) printf("@@@@ rpt:Hung Up\n");
12166 ast_frfree(f);
12167 break;
12168 }
12169
12170 if (f->subclass.integer == AST_CONTROL_RADIO_KEY)
12171 {
12172 if ((!lasttx) || (myrpt->p.duplex > 1) || (myrpt->p.linktolink))
12173 {
12174 if (debug == 7) printf("@@@@ rx key\n");
12175 myrpt->keyed = 1;
12176 time(&myrpt->lastkeyedtime);
12177 myrpt->keyposttimer = KEYPOSTSHORTTIME;
12178 }
12179 if (myrpt->p.archivedir)
12180 {
12181 donodelog(myrpt,"RXKEY,MAIN");
12182 }
12183 if (f->datalen && f->data.ptr)
12184 {
12185 char busy = 0;
12186
12187 if (debug) ast_log(LOG_NOTICE,"Got PL %s on node %s\n",(char *)f->data.ptr,myrpt->name);
12188
12189 if (strstr((char *)f->data.ptr,"/M/")&& !myrpt->macropatch)
12190 {
12191 char value[16];
12192 strcat(value,"*6");
12193 myrpt->macropatch=1;
12194 rpt_mutex_lock(&myrpt->lock);
12195 if ((MAXMACRO - strlen(myrpt->macrobuf)) < strlen(value)){
12196 rpt_mutex_unlock(&myrpt->lock);
12197 busy=1;
12198 }
12199 if(!busy){
12200 myrpt->macrotimer = MACROTIME;
12201 strncat(myrpt->macrobuf,value,MAXMACRO - 1);
12202 if (!busy) strcpy(myrpt->lasttone,(char*)f->data.ptr);
12203 }
12204 rpt_mutex_unlock(&myrpt->lock);
12205 }
12206 else if (strcmp((char *)f->data.ptr,myrpt->lasttone))
12207 {
12208 char *value = (char *) ast_variable_retrieve(myrpt->cfg, myrpt->p.tonemacro, (char *)f->data.ptr);
12209 if (value)
12210 {
12211 if (debug) ast_log(LOG_NOTICE,"Tone %s doing %s on node %s\n",(char *) f->data.ptr,value,myrpt->name);
12212 rpt_mutex_lock(&myrpt->lock);
12213 if ((MAXMACRO - strlen(myrpt->macrobuf)) < strlen(value)){
12214 rpt_mutex_unlock(&myrpt->lock);
12215 busy=1;
12216 }
12217 if(!busy){
12218 myrpt->macrotimer = MACROTIME;
12219 strncat(myrpt->macrobuf,value,MAXMACRO - 1);
12220 }
12221 rpt_mutex_unlock(&myrpt->lock);
12222 }
12223 if (!busy) strcpy(myrpt->lasttone,(char*)f->data.ptr);
12224 }
12225 } else myrpt->lasttone[0] = 0;
12226 }
12227
12228 if (f->subclass.integer == AST_CONTROL_RADIO_UNKEY)
12229 {
12230 if ((!lasttx) || (myrpt->p.duplex > 1) || (myrpt->p.linktolink))
12231 {
12232 if (debug == 7) printf("@@@@ rx un-key\n");
12233 if(myrpt->p.duplex && myrpt->keyed) {
12234 rpt_telemetry(myrpt,UNKEY,NULL);
12235 }
12236 }
12237 myrpt->keyed = 0;
12238 time(&myrpt->lastkeyedtime);
12239 myrpt->keyposttimer = KEYPOSTSHORTTIME;
12240 if (myrpt->p.archivedir)
12241 {
12242 donodelog(myrpt,"RXUNKEY,MAIN");
12243 }
12244 }
12245 }
12246 ast_frfree(f);
12247 continue;
12248 }
12249 if (who == myrpt->pchannel)
12250 {
12251 f = ast_read(myrpt->pchannel);
12252 if (!f)
12253 {
12254 if (debug) printf("@@@@ rpt:Hung Up\n");
12255 break;
12256 }
12257 if (f->frametype == AST_FRAME_VOICE)
12258 {
12259 ast_write(myrpt->txpchannel,f);
12260 }
12261 if (f->frametype == AST_FRAME_CONTROL)
12262 {
12263 if (f->subclass.integer == AST_CONTROL_HANGUP)
12264 {
12265 if (debug) printf("@@@@ rpt:Hung Up\n");
12266 ast_frfree(f);
12267 break;
12268 }
12269 }
12270 ast_frfree(f);
12271 continue;
12272 }
12273 if (who == myrpt->txchannel)
12274 {
12275 f = ast_read(myrpt->txchannel);
12276 if (!f)
12277 {
12278 if (debug) printf("@@@@ rpt:Hung Up\n");
12279 break;
12280 }
12281 if (f->frametype == AST_FRAME_CONTROL)
12282 {
12283 if (f->subclass.integer == AST_CONTROL_HANGUP)
12284 {
12285 if (debug) printf("@@@@ rpt:Hung Up\n");
12286 ast_frfree(f);
12287 break;
12288 }
12289 }
12290 ast_frfree(f);
12291 continue;
12292 }
12293 if (who == myrpt->dahditxchannel)
12294 {
12295 f = ast_read(myrpt->dahditxchannel);
12296 if (!f)
12297 {
12298 if (debug) printf("@@@@ rpt:Hung Up\n");
12299 break;
12300 }
12301 if (f->frametype == AST_FRAME_VOICE)
12302 {
12303 struct ast_frame *vframe;
12304
12305 if (myrpt->p.duplex < 2)
12306 {
12307 if (myrpt->txrealkeyed)
12308 {
12309 if ((!myfirst) && myrpt->callmode)
12310 {
12311 x = 0;
12312 AST_LIST_TRAVERSE(&myrpt->txq, vframe,
12313 frame_list) x++;
12314 for(;x < myrpt->p.simplexpatchdelay; x++)
12315 {
12316 vframe = ast_frdup(f);
12317 memset(vframe->data.ptr,0,vframe->datalen);
12318 AST_LIST_INSERT_TAIL(&myrpt->txq,vframe,frame_list);
12319 }
12320 myfirst = 1;
12321 }
12322 vframe = ast_frdup(f);
12323 AST_LIST_INSERT_TAIL(&myrpt->txq,
12324 vframe,frame_list);
12325 } else myfirst = 0;
12326 x = 0;
12327 AST_LIST_TRAVERSE(&myrpt->txq, vframe,
12328 frame_list) x++;
12329 if (!x)
12330 {
12331 memset(f->data.ptr,0,f->datalen);
12332 }
12333 else
12334 {
12335 ast_frfree(f);
12336 f = AST_LIST_REMOVE_HEAD(&myrpt->txq,
12337 frame_list);
12338 }
12339 }
12340 else
12341 {
12342 while((vframe = AST_LIST_REMOVE_HEAD(&myrpt->txq,
12343 frame_list))) ast_frfree(vframe);
12344 }
12345 ast_write(myrpt->txchannel,f);
12346 }
12347 if (f->frametype == AST_FRAME_CONTROL)
12348 {
12349 if (f->subclass.integer == AST_CONTROL_HANGUP)
12350 {
12351 if (debug) printf("@@@@ rpt:Hung Up\n");
12352 ast_frfree(f);
12353 break;
12354 }
12355 }
12356 ast_frfree(f);
12357 continue;
12358 }
12359 toexit = 0;
12360 rpt_mutex_lock(&myrpt->lock);
12361 l = myrpt->links.next;
12362 while(l != &myrpt->links)
12363 {
12364 int remnomute;
12365 struct timeval now;
12366
12367 if (l->disctime)
12368 {
12369 l = l->next;
12370 continue;
12371 }
12372
12373 remrx = 0;
12374
12375 m = myrpt->links.next;
12376 while(m != &myrpt->links)
12377 {
12378
12379 if ((m != l) && (m->lastrx)) remrx = 1;
12380 m = m->next;
12381 }
12382 rpt_mutex_unlock(&myrpt->lock);
12383 now = ast_tvnow();
12384 if ((who == l->chan) || (!l->lastlinktv.tv_sec) ||
12385 (ast_tvdiff_ms(now,l->lastlinktv) >= 19))
12386 {
12387 l->lastlinktv = now;
12388 remnomute = myrpt->localtx &&
12389 (!(myrpt->cmdnode[0] ||
12390 (myrpt->dtmfidx > -1)));
12391 totx = (((l->isremote) ? (remnomute) :
12392 myrpt->exttx) || remrx) && l->mode;
12393 if (l->phonemode == 0 && l->chan && (l->lasttx != totx))
12394 {
12395 if (totx)
12396 {
12397 ast_indicate(l->chan,AST_CONTROL_RADIO_KEY);
12398 }
12399 else
12400 {
12401 ast_indicate(l->chan,AST_CONTROL_RADIO_UNKEY);
12402 }
12403 if (myrpt->p.archivedir)
12404 {
12405 char str[100];
12406
12407 if (totx)
12408 sprintf(str,"TXKEY,%s",l->name);
12409 else
12410 sprintf(str,"TXUNKEY,%s",l->name);
12411 donodelog(myrpt,str);
12412 }
12413 }
12414 l->lasttx = totx;
12415 }
12416 rpt_mutex_lock(&myrpt->lock);
12417 if (who == l->chan)
12418 {
12419 rpt_mutex_unlock(&myrpt->lock);
12420 f = ast_read(l->chan);
12421 if (!f)
12422 {
12423 rpt_mutex_lock(&myrpt->lock);
12424 __kickshort(myrpt);
12425 rpt_mutex_unlock(&myrpt->lock);
12426 if ((!l->disced) && (!l->outbound))
12427 {
12428 if ((l->name[0] == '0') || l->isremote)
12429 l->disctime = 1;
12430 else
12431 l->disctime = DISC_TIME;
12432 rpt_mutex_lock(&myrpt->lock);
12433 ast_hangup(l->chan);
12434 l->chan = 0;
12435 break;
12436 }
12437
12438 if (l->retrytimer)
12439 {
12440 ast_hangup(l->chan);
12441 l->chan = 0;
12442 rpt_mutex_lock(&myrpt->lock);
12443 break;
12444 }
12445 if (l->outbound && (l->retries++ < l->max_retries) && (l->hasconnected))
12446 {
12447 rpt_mutex_lock(&myrpt->lock);
12448 if (l->chan) ast_hangup(l->chan);
12449 l->chan = 0;
12450 l->hasconnected = 1;
12451 l->retrytimer = RETRY_TIMER_MS;
12452 l->elaptime = 0;
12453 l->connecttime = 0;
12454 l->thisconnected = 0;
12455 break;
12456 }
12457 rpt_mutex_lock(&myrpt->lock);
12458
12459 remque((struct qelem *) l);
12460 if (!strcmp(myrpt->cmdnode,l->name))
12461 myrpt->cmdnode[0] = 0;
12462 __kickshort(myrpt);
12463 rpt_mutex_unlock(&myrpt->lock);
12464 if (!l->hasconnected)
12465 rpt_telemetry(myrpt,CONNFAIL,l);
12466 else if (l->disced != 2) rpt_telemetry(myrpt,REMDISC,l);
12467 if (myrpt->p.archivedir)
12468 {
12469 char str[100];
12470
12471 if (!l->hasconnected)
12472 sprintf(str,"LINKFAIL,%s",l->name);
12473 else
12474 sprintf(str,"LINKDISC,%s",l->name);
12475 donodelog(myrpt,str);
12476 }
12477 if (l->lastf1) ast_frfree(l->lastf1);
12478 l->lastf1 = NULL;
12479 if (l->lastf2) ast_frfree(l->lastf2);
12480 l->lastf2 = NULL;
12481
12482 ast_hangup(l->chan);
12483 ast_hangup(l->pchan);
12484 ast_free(l);
12485 rpt_mutex_lock(&myrpt->lock);
12486 break;
12487 }
12488 if (f->frametype == AST_FRAME_VOICE)
12489 {
12490 int ismuted,n1;
12491
12492 if ((l->phonemode) && (l->phonevox))
12493 {
12494 n1 = dovox(&l->vox,
12495 f->data.ptr,f->datalen / 2);
12496 if (n1 != l->wasvox)
12497 {
12498 if (debug)ast_log(LOG_DEBUG,"Link Node %s, vox %d\n",l->name,n1);
12499 l->wasvox = n1;
12500 l->voxtostate = 0;
12501 if (n1) l->voxtotimer = myrpt->p.voxtimeout_ms;
12502 else l->voxtotimer = 0;
12503 }
12504 if (l->lastrealrx || n1)
12505 {
12506 if (!myfirst)
12507 {
12508 x = 0;
12509 AST_LIST_TRAVERSE(&l->rxq, f1,
12510 frame_list) x++;
12511 for(;x < myrpt->p.simplexphonedelay; x++)
12512 {
12513 f1 = ast_frdup(f);
12514 memset(f1->data.ptr,0,f1->datalen);
12515 AST_LIST_INSERT_TAIL(&l->rxq,
12516 f1,frame_list);
12517 }
12518 myfirst = 1;
12519 }
12520 f1 = ast_frdup(f);
12521 AST_LIST_INSERT_TAIL(&l->rxq,f1,frame_list);
12522 } else myfirst = 0;
12523 x = 0;
12524 AST_LIST_TRAVERSE(&l->rxq, f1,frame_list) x++;
12525 if (!x)
12526 {
12527 memset(f->data.ptr,0,f->datalen);
12528 }
12529 else
12530 {
12531 ast_frfree(f);
12532 f = AST_LIST_REMOVE_HEAD(&l->rxq,frame_list);
12533 }
12534 if (ioctl(l->chan->fds[0], DAHDI_GETCONFMUTE, &ismuted) == -1)
12535 {
12536 ismuted = 0;
12537 }
12538
12539 ismuted |= (!l->lastrx);
12540 if (l->dtmfed && l->phonemode) ismuted = 1;
12541 l->dtmfed = 0;
12542 if (ismuted)
12543 {
12544 memset(f->data.ptr,0,f->datalen);
12545 if (l->lastf1)
12546 memset(l->lastf1->data.ptr,0,l->lastf1->datalen);
12547 if (l->lastf2)
12548 memset(l->lastf2->data.ptr,0,l->lastf2->datalen);
12549 }
12550 if (f) f2 = ast_frdup(f);
12551 else f2 = NULL;
12552 f1 = l->lastf2;
12553 l->lastf2 = l->lastf1;
12554 l->lastf1 = f2;
12555 if (ismuted)
12556 {
12557 if (l->lastf1)
12558 memset(l->lastf1->data.ptr,0,l->lastf1->datalen);
12559 if (l->lastf2)
12560 memset(l->lastf2->data.ptr,0,l->lastf2->datalen);
12561 }
12562 if (f1)
12563 {
12564 ast_write(l->pchan,f1);
12565 ast_frfree(f1);
12566 }
12567 }
12568 else
12569 {
12570 if (!l->lastrx)
12571 memset(f->data.ptr,0,f->datalen);
12572 ast_write(l->pchan,f);
12573 }
12574 }
12575 #ifndef OLD_ASTERISK
12576 else if (f->frametype == AST_FRAME_DTMF_BEGIN)
12577 {
12578 if (l->lastf1)
12579 memset(l->lastf1->data.ptr,0,l->lastf1->datalen);
12580 if (l->lastf2)
12581 memset(l->lastf2->data.ptr,0,l->lastf2->datalen);
12582 l->dtmfed = 1;
12583 }
12584 #endif
12585 if (f->frametype == AST_FRAME_TEXT)
12586 {
12587 handle_link_data(myrpt,l,f->data.ptr);
12588 }
12589 if (f->frametype == AST_FRAME_DTMF)
12590 {
12591 if (l->lastf1)
12592 memset(l->lastf1->data.ptr,0,l->lastf1->datalen);
12593 if (l->lastf2)
12594 memset(l->lastf2->data.ptr,0,l->lastf2->datalen);
12595 l->dtmfed = 1;
12596 handle_link_phone_dtmf(myrpt,l,f->subclass.integer);
12597 }
12598 if (f->frametype == AST_FRAME_CONTROL)
12599 {
12600 if (f->subclass.integer == AST_CONTROL_ANSWER)
12601 {
12602 char lconnected = l->connected;
12603
12604 __kickshort(myrpt);
12605 l->connected = 1;
12606 l->hasconnected = 1;
12607 l->thisconnected = 1;
12608 l->elaptime = -1;
12609 if (!l->phonemode) send_newkey(l->chan);
12610 if (!l->isremote) l->retries = 0;
12611 if (!lconnected)
12612 {
12613 rpt_telemetry(myrpt,CONNECTED,l);
12614 if (myrpt->p.archivedir)
12615 {
12616 char str[100];
12617
12618 if (l->mode)
12619 sprintf(str,"LINKTRX,%s",l->name);
12620 else
12621 sprintf(str,"LINKMONITOR,%s",l->name);
12622 donodelog(myrpt,str);
12623 }
12624 }
12625 else
12626 l->reconnects++;
12627 }
12628
12629 if (f->subclass.integer == AST_CONTROL_RADIO_KEY)
12630 {
12631 if (debug == 7 ) printf("@@@@ rx key\n");
12632 l->lastrealrx = 1;
12633 l->rerxtimer = 0;
12634 if (!l->lastrx1)
12635 {
12636 if (myrpt->p.archivedir)
12637 {
12638 char str[100];
12639
12640 sprintf(str,"RXKEY,%s",l->name);
12641 donodelog(myrpt,str);
12642 }
12643 l->lastrx1 = 1;
12644 }
12645 }
12646
12647 if (f->subclass.integer == AST_CONTROL_RADIO_UNKEY)
12648 {
12649 if (debug == 7) printf("@@@@ rx un-key\n");
12650 l->lastrealrx = 0;
12651 l->rerxtimer = 0;
12652 if (l->lastrx1)
12653 {
12654 if (myrpt->p.archivedir)
12655 {
12656 char str[100];
12657
12658 sprintf(str,"RXUNKEY,%s",l->name);
12659 donodelog(myrpt,str);
12660 }
12661 l->lastrx1 = 0;
12662 if(myrpt->p.duplex)
12663 rpt_telemetry(myrpt,LINKUNKEY,l);
12664 }
12665 }
12666 if (f->subclass.integer == AST_CONTROL_HANGUP)
12667 {
12668 ast_frfree(f);
12669 rpt_mutex_lock(&myrpt->lock);
12670 __kickshort(myrpt);
12671 rpt_mutex_unlock(&myrpt->lock);
12672 if ((!l->outbound) && (!l->disced))
12673 {
12674 if ((l->name[0] == '0') || l->isremote)
12675 l->disctime = 1;
12676 else
12677 l->disctime = DISC_TIME;
12678 rpt_mutex_lock(&myrpt->lock);
12679 ast_hangup(l->chan);
12680 l->chan = 0;
12681 break;
12682 }
12683 if (l->retrytimer)
12684 {
12685 if (l->chan) ast_hangup(l->chan);
12686 l->chan = 0;
12687 rpt_mutex_lock(&myrpt->lock);
12688 break;
12689 }
12690 if (l->outbound && (l->retries++ < l->max_retries) && (l->hasconnected))
12691 {
12692 rpt_mutex_lock(&myrpt->lock);
12693 if (l->chan) ast_hangup(l->chan);
12694 l->chan = 0;
12695 l->hasconnected = 1;
12696 l->elaptime = 0;
12697 l->retrytimer = RETRY_TIMER_MS;
12698 l->connecttime = 0;
12699 l->thisconnected = 0;
12700 break;
12701 }
12702 rpt_mutex_lock(&myrpt->lock);
12703
12704 remque((struct qelem *) l);
12705 if (!strcmp(myrpt->cmdnode,l->name))
12706 myrpt->cmdnode[0] = 0;
12707 __kickshort(myrpt);
12708 rpt_mutex_unlock(&myrpt->lock);
12709 if (!l->hasconnected)
12710 rpt_telemetry(myrpt,CONNFAIL,l);
12711 else if (l->disced != 2) rpt_telemetry(myrpt,REMDISC,l);
12712 if (myrpt->p.archivedir)
12713 {
12714 char str[100];
12715
12716 if (!l->hasconnected)
12717 sprintf(str,"LINKFAIL,%s",l->name);
12718 else
12719 sprintf(str,"LINKDISC,%s",l->name);
12720 donodelog(myrpt,str);
12721 }
12722 if (l->lastf1) ast_frfree(l->lastf1);
12723 l->lastf1 = NULL;
12724 if (l->lastf2) ast_frfree(l->lastf2);
12725 l->lastf2 = NULL;
12726
12727 ast_hangup(l->chan);
12728 ast_hangup(l->pchan);
12729 ast_free(l);
12730 rpt_mutex_lock(&myrpt->lock);
12731 break;
12732 }
12733 }
12734 ast_frfree(f);
12735 rpt_mutex_lock(&myrpt->lock);
12736 break;
12737 }
12738 if (who == l->pchan)
12739 {
12740 rpt_mutex_unlock(&myrpt->lock);
12741 f = ast_read(l->pchan);
12742 if (!f)
12743 {
12744 if (debug) printf("@@@@ rpt:Hung Up\n");
12745 toexit = 1;
12746 rpt_mutex_lock(&myrpt->lock);
12747 break;
12748 }
12749 if (f->frametype == AST_FRAME_VOICE)
12750 {
12751 if (l->chan) ast_write(l->chan,f);
12752 }
12753 if (f->frametype == AST_FRAME_CONTROL)
12754 {
12755 if (f->subclass.integer == AST_CONTROL_HANGUP)
12756 {
12757 if (debug) printf("@@@@ rpt:Hung Up\n");
12758 ast_frfree(f);
12759 toexit = 1;
12760 rpt_mutex_lock(&myrpt->lock);
12761 break;
12762 }
12763 }
12764 ast_frfree(f);
12765 rpt_mutex_lock(&myrpt->lock);
12766 break;
12767 }
12768 l = l->next;
12769 }
12770 rpt_mutex_unlock(&myrpt->lock);
12771 if (toexit) break;
12772 if (who == myrpt->monchannel)
12773 {
12774 f = ast_read(myrpt->monchannel);
12775 if (!f)
12776 {
12777 if (debug) printf("@@@@ rpt:Hung Up\n");
12778 break;
12779 }
12780 if (f->frametype == AST_FRAME_VOICE)
12781 {
12782 if (myrpt->monstream)
12783 ast_writestream(myrpt->monstream,f);
12784 }
12785 if (f->frametype == AST_FRAME_CONTROL)
12786 {
12787 if (f->subclass.integer == AST_CONTROL_HANGUP)
12788 {
12789 if (debug) printf("@@@@ rpt:Hung Up\n");
12790 ast_frfree(f);
12791 break;
12792 }
12793 }
12794 ast_frfree(f);
12795 continue;
12796 }
12797 if (myrpt->parrotchannel && (who == myrpt->parrotchannel))
12798 {
12799 f = ast_read(myrpt->parrotchannel);
12800 if (!f)
12801 {
12802 if (debug) printf("@@@@ rpt:Hung Up\n");
12803 break;
12804 }
12805 if (!myrpt->p.parrotmode)
12806 {
12807 char myfname[300];
12808
12809 if (myrpt->parrotstream)
12810 {
12811 ast_closestream(myrpt->parrotstream);
12812 myrpt->parrotstream = 0;
12813 }
12814 sprintf(myfname,PARROTFILE,myrpt->name,myrpt->parrotcnt);
12815 strcat(myfname,".wav");
12816 unlink(myfname);
12817 } else if (f->frametype == AST_FRAME_VOICE)
12818 {
12819 if (myrpt->parrotstream)
12820 ast_writestream(myrpt->parrotstream,f);
12821 }
12822 if (f->frametype == AST_FRAME_CONTROL)
12823 {
12824 if (f->subclass.integer == AST_CONTROL_HANGUP)
12825 {
12826 if (debug) printf("@@@@ rpt:Hung Up\n");
12827 ast_frfree(f);
12828 break;
12829 }
12830 }
12831 ast_frfree(f);
12832 continue;
12833 }
12834 if (myrpt->voxchannel && (who == myrpt->voxchannel))
12835 {
12836 f = ast_read(myrpt->voxchannel);
12837 if (!f)
12838 {
12839 if (debug) printf("@@@@ rpt:Hung Up\n");
12840 break;
12841 }
12842 if (f->frametype == AST_FRAME_VOICE)
12843 {
12844 n = dovox(&myrpt->vox,f->data.ptr,f->datalen / 2);
12845 if (n != myrpt->wasvox)
12846 {
12847 if (debug) ast_log(LOG_DEBUG,"Node %s, vox %d\n",myrpt->name,n);
12848 myrpt->wasvox = n;
12849 myrpt->voxtostate = 0;
12850 if (n) myrpt->voxtotimer = myrpt->p.voxtimeout_ms;
12851 else myrpt->voxtotimer = 0;
12852 }
12853 }
12854 if (f->frametype == AST_FRAME_CONTROL)
12855 {
12856 if (f->subclass.integer == AST_CONTROL_HANGUP)
12857 {
12858 if (debug) printf("@@@@ rpt:Hung Up\n");
12859 ast_frfree(f);
12860 break;
12861 }
12862 }
12863 ast_frfree(f);
12864 continue;
12865 }
12866 if (who == myrpt->txpchannel)
12867 {
12868 f = ast_read(myrpt->txpchannel);
12869 if (!f)
12870 {
12871 if (debug) printf("@@@@ rpt:Hung Up\n");
12872 break;
12873 }
12874 if (f->frametype == AST_FRAME_CONTROL)
12875 {
12876 if (f->subclass.integer == AST_CONTROL_HANGUP)
12877 {
12878 if (debug) printf("@@@@ rpt:Hung Up\n");
12879 ast_frfree(f);
12880 break;
12881 }
12882 }
12883 ast_frfree(f);
12884 continue;
12885 }
12886 }
12887 usleep(100000);
12888 ast_hangup(myrpt->pchannel);
12889 ast_hangup(myrpt->monchannel);
12890 if (myrpt->parrotchannel) ast_hangup(myrpt->parrotchannel);
12891 myrpt->parrotstate = 0;
12892 if (myrpt->voxchannel) ast_hangup(myrpt->voxchannel);
12893 ast_hangup(myrpt->txpchannel);
12894 if (myrpt->txchannel != myrpt->rxchannel) ast_hangup(myrpt->txchannel);
12895 if (myrpt->dahditxchannel != myrpt->txchannel) ast_hangup(myrpt->dahditxchannel);
12896 if (myrpt->lastf1) ast_frfree(myrpt->lastf1);
12897 myrpt->lastf1 = NULL;
12898 if (myrpt->lastf2) ast_frfree(myrpt->lastf2);
12899 myrpt->lastf2 = NULL;
12900 ast_hangup(myrpt->rxchannel);
12901 rpt_mutex_lock(&myrpt->lock);
12902 l = myrpt->links.next;
12903 while(l != &myrpt->links)
12904 {
12905 struct rpt_link *ll = l;
12906
12907 remque((struct qelem *) l);
12908
12909 if (l->chan) ast_hangup(l->chan);
12910 ast_hangup(l->pchan);
12911 l = l->next;
12912 ast_free(ll);
12913 }
12914 if (myrpt->xlink == 1) myrpt->xlink = 2;
12915 rpt_mutex_unlock(&myrpt->lock);
12916 if (debug) printf("@@@@ rpt:Hung up channel\n");
12917 myrpt->rpt_thread = AST_PTHREADT_STOP;
12918 pthread_exit(NULL);
12919 return NULL;
12920 }
12921
12922
12923 static void *rpt_master(void *ignore)
12924 {
12925 int i,n;
12926 pthread_attr_t attr;
12927 struct ast_config *cfg;
12928 char *this,*val;
12929
12930
12931 nodelog.next = nodelog.prev = &nodelog;
12932
12933 this = NULL;
12934 n = 0;
12935 #ifndef OLD_ASTERISK
12936
12937 while(!ast_test_flag(&ast_options,AST_OPT_FLAG_FULLY_BOOTED))
12938 usleep(250000);
12939 #endif
12940 #ifdef NEW_ASTERISK
12941 rpt_vars[n].cfg = ast_config_load("rpt.conf",config_flags);
12942 #else
12943 rpt_vars[n].cfg = ast_config_load("rpt.conf");
12944 #endif
12945 cfg = rpt_vars[n].cfg;
12946 if (!cfg || cfg == CONFIG_STATUS_FILEINVALID) {
12947 ast_log(LOG_NOTICE, "Unable to open radio repeater configuration rpt.conf. Radio Repeater disabled.\n");
12948 pthread_exit(NULL);
12949 }
12950 while((this = ast_category_browse(cfg,this)) != NULL)
12951 {
12952 for(i = 0 ; i < strlen(this) ; i++){
12953 if((this[i] < '0') || (this[i] > '9'))
12954 break;
12955 }
12956 if(i != strlen(this)) continue;
12957 memset(&rpt_vars[n],0,sizeof(rpt_vars[n]));
12958 rpt_vars[n].name = ast_strdup(this);
12959 val = (char *) ast_variable_retrieve(cfg,this,"rxchannel");
12960 if (val) rpt_vars[n].rxchanname = ast_strdup(val);
12961 val = (char *) ast_variable_retrieve(cfg,this,"txchannel");
12962 if (val) rpt_vars[n].txchanname = ast_strdup(val);
12963 rpt_vars[n].remote = 0;
12964 rpt_vars[n].remoterig = "";
12965 val = (char *) ast_variable_retrieve(cfg,this,"remote");
12966 if (val)
12967 {
12968 rpt_vars[n].remoterig = ast_strdup(val);
12969 rpt_vars[n].remote = 1;
12970 }
12971 val = (char *) ast_variable_retrieve(cfg,this,"radiotype");
12972 if (val) rpt_vars[n].remoterig = ast_strdup(val);
12973 ast_mutex_init(&rpt_vars[n].lock);
12974 ast_mutex_init(&rpt_vars[n].remlock);
12975 ast_mutex_init(&rpt_vars[n].statpost_lock);
12976 rpt_vars[n].tele.next = &rpt_vars[n].tele;
12977 rpt_vars[n].tele.prev = &rpt_vars[n].tele;
12978 rpt_vars[n].rpt_thread = AST_PTHREADT_NULL;
12979 rpt_vars[n].tailmessagen = 0;
12980 #ifdef _MDC_DECODE_H_
12981 rpt_vars[n].mdc = mdc_decoder_new(8000);
12982 #endif
12983 n++;
12984 }
12985 nrpts = n;
12986 ast_config_destroy(cfg);
12987
12988
12989 for(i = 0; i < n; i++)
12990 {
12991 load_rpt_vars(i,1);
12992
12993
12994 if (rpt_vars[i].remote)
12995 {
12996 if(retreive_memory(&rpt_vars[i],"init")){
12997 if (!strcmp(rpt_vars[i].remoterig,remote_rig_rtx450))
12998 strncpy(rpt_vars[i].freq, "446.500", sizeof(rpt_vars[i].freq) - 1);
12999 else
13000 strncpy(rpt_vars[i].freq, "146.580", sizeof(rpt_vars[i].freq) - 1);
13001 strncpy(rpt_vars[i].rxpl, "100.0", sizeof(rpt_vars[i].rxpl) - 1);
13002
13003 strncpy(rpt_vars[i].txpl, "100.0", sizeof(rpt_vars[i].txpl) - 1);
13004 rpt_vars[i].remmode = REM_MODE_FM;
13005 rpt_vars[i].offset = REM_SIMPLEX;
13006 rpt_vars[i].powerlevel = REM_LOWPWR;
13007 }
13008 continue;
13009 }
13010 else
13011 {
13012 rpt_vars[i].p.memory = rpt_vars[i].name;
13013 if(retreive_memory(&rpt_vars[i],"radiofreq")){
13014 if (!strcmp(rpt_vars[i].remoterig,remote_rig_rtx450))
13015 strncpy(rpt_vars[i].freq, "446.500", sizeof(rpt_vars[i].freq) - 1);
13016 else if (!strcmp(rpt_vars[i].remoterig,remote_rig_rtx150))
13017 strncpy(rpt_vars[i].freq, "146.580", sizeof(rpt_vars[i].freq) - 1);
13018 strncpy(rpt_vars[i].rxpl, "100.0", sizeof(rpt_vars[i].rxpl) - 1);
13019
13020 strncpy(rpt_vars[i].txpl, "100.0", sizeof(rpt_vars[i].txpl) - 1);
13021 rpt_vars[i].remmode = REM_MODE_FM;
13022 rpt_vars[i].offset = REM_SIMPLEX;
13023 rpt_vars[i].powerlevel = REM_LOWPWR;
13024 }
13025 ast_log(LOG_NOTICE,"Normal Repeater Init %s %s %s\n",rpt_vars[i].name, rpt_vars[i].remoterig, rpt_vars[i].freq);
13026 }
13027 if (!rpt_vars[i].p.ident)
13028 {
13029 ast_log(LOG_WARNING,"Did not specify ident for node %s\n",rpt_vars[i].name);
13030 ast_config_destroy(cfg);
13031 pthread_exit(NULL);
13032 }
13033 pthread_attr_init(&attr);
13034 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
13035 ast_pthread_create(&rpt_vars[i].rpt_thread,&attr,rpt,(void *) &rpt_vars[i]);
13036 }
13037 usleep(500000);
13038 time(&starttime);
13039 for(;;)
13040 {
13041
13042 for(i = 0; i < n; i++)
13043 {
13044 int rv;
13045 if (rpt_vars[i].remote) continue;
13046 if (rpt_vars[i].rpt_thread == AST_PTHREADT_STOP)
13047 rv = -1;
13048 else
13049 rv = pthread_kill(rpt_vars[i].rpt_thread,0);
13050 if (rv)
13051 {
13052 if(time(NULL) - rpt_vars[i].lastthreadrestarttime <= 15)
13053 {
13054 if(rpt_vars[i].threadrestarts >= 5)
13055 {
13056 ast_log(LOG_ERROR,"Continual RPT thread restarts, killing Asterisk\n");
13057 exit(1);
13058 }
13059 else
13060 {
13061 ast_log(LOG_NOTICE,"RPT thread restarted on %s\n",rpt_vars[i].name);
13062 rpt_vars[i].threadrestarts++;
13063 }
13064 }
13065 else
13066 rpt_vars[i].threadrestarts = 0;
13067
13068 rpt_vars[i].lastthreadrestarttime = time(NULL);
13069 pthread_attr_init(&attr);
13070 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
13071 ast_pthread_create(&rpt_vars[i].rpt_thread,&attr,rpt,(void *) &rpt_vars[i]);
13072
13073 ast_log(LOG_WARNING, "rpt_thread restarted on node %s\n", rpt_vars[i].name);
13074 }
13075
13076 }
13077 for(;;)
13078 {
13079 struct nodelog *nodep;
13080 char *space,datestr[100],fname[300];
13081 int fd;
13082
13083 ast_mutex_lock(&nodeloglock);
13084 nodep = nodelog.next;
13085 if(nodep == &nodelog)
13086 {
13087 ast_mutex_unlock(&nodeloglock);
13088 break;
13089 }
13090 remque((struct qelem *)nodep);
13091 ast_mutex_unlock(&nodeloglock);
13092 space = strchr(nodep->str,' ');
13093 if (!space)
13094 {
13095 ast_free(nodep);
13096 continue;
13097 }
13098 *space = 0;
13099 strftime(datestr,sizeof(datestr) - 1,"%Y%m%d",
13100 localtime(&nodep->timestamp));
13101 sprintf(fname,"%s/%s/%s.txt",nodep->archivedir,
13102 nodep->str,datestr);
13103 fd = open(fname,O_WRONLY | O_CREAT | O_APPEND,0600);
13104 if (fd == -1)
13105 {
13106 ast_log(LOG_ERROR,"Cannot open node log file %s for write",space + 1);
13107 ast_free(nodep);
13108 continue;
13109 }
13110 if (write(fd,space + 1,strlen(space + 1)) !=
13111 strlen(space + 1))
13112 {
13113 ast_log(LOG_ERROR,"Cannot write node log file %s for write",space + 1);
13114 ast_free(nodep);
13115 continue;
13116 }
13117 close(fd);
13118 ast_free(nodep);
13119 }
13120 sleep(2);
13121 }
13122 ast_config_destroy(cfg);
13123 pthread_exit(NULL);
13124 }
13125
13126 static int rpt_exec(struct ast_channel *chan, const char *data)
13127 {
13128 int res=-1,i,rem_totx,rem_rx,remkeyed,n,phone_mode = 0;
13129 int iskenwood_pci4,authtold,authreq,setting,notremming,reming;
13130 int ismuted,dtmfed,phone_vox = 0;
13131 #ifdef OLD_ASTERISK
13132 struct localuser *u;
13133 #endif
13134 char tmp[256], keyed = 0,keyed1 = 0;
13135 char *options,*stringp,*tele,c,*altp,*memp;
13136 char sx[320],*sy;
13137 struct rpt *myrpt;
13138 struct ast_frame *f,*f1,*f2;
13139 struct ast_channel *who;
13140 struct ast_channel *cs[20];
13141 struct rpt_link *l;
13142 struct dahdi_confinfo ci;
13143 struct dahdi_params par;
13144 int ms,elap,nullfd;
13145 time_t t,last_timeout_warning;
13146 struct dahdi_radio_param z;
13147 struct rpt_tele *telem;
13148 int numlinks;
13149
13150 nullfd = open("/dev/null",O_RDWR);
13151 if (ast_strlen_zero(data)) {
13152 ast_log(LOG_WARNING, "Rpt requires an argument (system node)\n");
13153 return -1;
13154 }
13155
13156 strncpy(tmp, (char *)data, sizeof(tmp)-1);
13157 time(&t);
13158
13159 if (t < starttime) t = starttime + START_DELAY;
13160 if ((!starttime) || (t < (starttime + START_DELAY)))
13161 {
13162 ast_log(LOG_NOTICE,"Node %s rejecting call: too soon!\n",tmp);
13163 ast_safe_sleep(chan,3000);
13164 return -1;
13165 }
13166
13167 ast_log(LOG_NOTICE,"parsing argument=%s \n",tmp);
13168
13169 altp=strstr(tmp, "|*");
13170 if(altp){
13171 altp[0]=0;
13172 altp++;
13173 }
13174
13175 memp=strstr(tmp, "|M");
13176 if(memp){
13177 memp[0]=0;
13178 memp+=2;
13179 }
13180
13181 stringp=tmp;
13182 strsep(&stringp, "|");
13183 options = stringp;
13184
13185 ast_log(LOG_NOTICE,"options=%s \n",options);
13186 if(memp>0)ast_log(LOG_NOTICE,"memp=%s \n",memp);
13187 if(altp>0)ast_log(LOG_NOTICE,"altp=%s \n",altp);
13188
13189 myrpt = NULL;
13190
13191 for(i = 0; i < nrpts; i++)
13192 {
13193
13194 if (!strcmp(tmp,rpt_vars[i].name))
13195 {
13196 myrpt = &rpt_vars[i];
13197 break;
13198 }
13199 }
13200
13201 pbx_builtin_setvar_helper(chan, "RPT_STAT_ERR", "");
13202
13203 if (myrpt == NULL)
13204 {
13205 pbx_builtin_setvar_helper(chan, "RPT_STAT_ERR", "NODE_NOT_FOUND");
13206 ast_log(LOG_WARNING, "Cannot find specified system node %s\n",tmp);
13207 return (priority_jump(NULL,chan));
13208 }
13209
13210 numlinks=linkcount(myrpt);
13211
13212 if(options && *options == 'q')
13213 {
13214 char buf2[128];
13215
13216 if(myrpt->keyed)
13217 pbx_builtin_setvar_helper(chan, "RPT_STAT_RXKEYED", "1");
13218 else
13219 pbx_builtin_setvar_helper(chan, "RPT_STAT_RXKEYED", "0");
13220
13221 if(myrpt->txkeyed)
13222 pbx_builtin_setvar_helper(chan, "RPT_STAT_TXKEYED", "1");
13223 else
13224 pbx_builtin_setvar_helper(chan, "RPT_STAT_TXKEYED", "0");
13225
13226 snprintf(buf2,sizeof(buf2),"%s=%i", "RPT_STAT_XLINK", myrpt->xlink);
13227 pbx_builtin_setvar(chan, buf2);
13228 snprintf(buf2,sizeof(buf2),"%s=%i", "RPT_STAT_LINKS", numlinks);
13229 pbx_builtin_setvar(chan, buf2);
13230 snprintf(buf2,sizeof(buf2),"%s=%d", "RPT_STAT_WASCHAN", myrpt->waschan);
13231 pbx_builtin_setvar(chan, buf2);
13232 snprintf(buf2,sizeof(buf2),"%s=%d", "RPT_STAT_NOWCHAN", myrpt->nowchan);
13233 pbx_builtin_setvar(chan, buf2);
13234 snprintf(buf2,sizeof(buf2),"%s=%d", "RPT_STAT_DUPLEX", myrpt->p.duplex);
13235 pbx_builtin_setvar(chan, buf2);
13236 snprintf(buf2,sizeof(buf2),"%s=%d", "RPT_STAT_PARROT", myrpt->p.parrotmode);
13237 pbx_builtin_setvar(chan, buf2);
13238
13239
13240
13241
13242 snprintf(buf2,sizeof(buf2),"%s=%d", "RPT_STAT_CALLMODE", myrpt->callmode);
13243 pbx_builtin_setvar(chan, buf2);
13244 snprintf(buf2,sizeof(buf2),"%s=%s", "RPT_STAT_LASTTONE", myrpt->lasttone);
13245 pbx_builtin_setvar(chan, buf2);
13246
13247 return priority_jump(myrpt,chan);
13248 }
13249
13250 if(options && *options == 'o')
13251 {
13252 return(channel_revert(myrpt));
13253 }
13254
13255 #if 0
13256 if((altp)&&(*options == 'Z'))
13257 {
13258 rpt_push_alt_macro(myrpt,altp);
13259 return 0;
13260 }
13261 #endif
13262
13263
13264
13265 if (options && ((*options == 'P') || (*options == 'D') || (*options == 'R') || (*options == 'S')))
13266 {
13267 int val;
13268
13269 pbx_builtin_setvar_helper(chan, "RPT_STAT_BUSY", "0");
13270
13271 myrpt->bargechan=0;
13272 if(options && strstr(options, "f")>0)
13273 {
13274 myrpt->bargechan=1;
13275 }
13276
13277 if(memp>0)
13278 {
13279 char radiochan;
13280 radiochan=strtod(data,NULL);
13281
13282
13283 if(numlinks>0 && radiochan!=myrpt->nowchan && !myrpt->bargechan)
13284 {
13285 pbx_builtin_setvar_helper(chan, "RPT_STAT_BUSY", "1");
13286 ast_log(LOG_NOTICE, "Radio Channel Busy.\n");
13287 return (priority_jump(myrpt,chan));
13288 }
13289 else if(radiochan!=myrpt->nowchan || myrpt->bargechan)
13290 {
13291 channel_steer(myrpt,memp);
13292 }
13293 }
13294 if(altp)rpt_push_alt_macro(myrpt,altp);
13295 phone_mode = 1;
13296 if (*options == 'D') phone_mode = 2;
13297 if (*options == 'S') phone_mode = 3;
13298 ast_set_callerid(chan,"0","app_rpt user","0");
13299 val = 1;
13300 ast_channel_setoption(chan,AST_OPTION_TONE_VERIFY,&val,sizeof(char),0);
13301 if ((*(options + 1) == 'V') || (*(options + 1) == 'v')) phone_vox = 1;
13302 }
13303 else
13304 {
13305 #ifdef ALLOW_LOCAL_CHANNELS
13306
13307 if ( (strncmp(chan->name,"IAX2",4)) && (strncmp(chan->name,"Local",5)) ) {
13308 ast_log(LOG_WARNING, "We only accept links via IAX2 or Local!!\n");
13309 return -1;
13310 }
13311 #else
13312 if (strncmp(chan->name,"IAX2",4))
13313 {
13314 ast_log(LOG_WARNING, "We only accept links via IAX2!!\n");
13315 return -1;
13316 }
13317 #endif
13318 if(myrpt->p.s[myrpt->p.sysstate_cur].txdisable){
13319 ast_log(LOG_NOTICE, "Connect attempt to node %s with tx disabled", myrpt->name);
13320 return -1;
13321 }
13322 }
13323 if (options && (*options == 'R'))
13324 {
13325
13326 char *return_context;
13327 int length, m, lot, timeout = 0;
13328 char buffer[256],*template;
13329 char *working, *context, *exten, *priority;
13330 char *s,*orig_s;
13331
13332 rpt_mutex_lock(&myrpt->lock);
13333 m = myrpt->callmode;
13334 rpt_mutex_unlock(&myrpt->lock);
13335
13336 if ((!myrpt->p.nobusyout) && m)
13337 {
13338 if (chan->_state != AST_STATE_UP)
13339 {
13340 ast_indicate(chan,AST_CONTROL_BUSY);
13341 }
13342 while(ast_safe_sleep(chan,10000) != -1);
13343 return -1;
13344 }
13345
13346 if (chan->_state != AST_STATE_UP)
13347 {
13348 ast_answer(chan);
13349 if (!phone_mode) send_newkey(chan);
13350 }
13351
13352 length=strlen(options)+2;
13353 orig_s=ast_malloc(length);
13354 if(!orig_s) {
13355 ast_log(LOG_WARNING, "Out of memory\n");
13356 return -1;
13357 }
13358 s=orig_s;
13359 strncpy(s,options,length);
13360
13361 template=strsep(&s,"|");
13362 if(!template) {
13363 ast_log(LOG_WARNING, "An announce template must be defined\n");
13364 ast_free(orig_s);
13365 return -1;
13366 }
13367
13368 if(s) {
13369 timeout = atoi(strsep(&s, "|"));
13370 timeout *= 1000;
13371 }
13372
13373 return_context = s;
13374
13375 if(return_context != NULL) {
13376
13377
13378 working = return_context;
13379 context = strsep(&working, "|");
13380 exten = strsep(&working, "|");
13381 if(!exten) {
13382
13383 priority = context;
13384 exten = NULL;
13385 context = NULL;
13386 } else {
13387 priority = strsep(&working, "|");
13388 if(!priority) {
13389
13390 priority = exten;
13391 exten = context;
13392 context = NULL;
13393 }
13394 }
13395 if(atoi(priority) < 0) {
13396 ast_log(LOG_WARNING, "Priority '%s' must be a number > 0\n", priority);
13397 ast_free(orig_s);
13398 return -1;
13399 }
13400
13401 chan->priority = atoi(priority);
13402 #ifdef OLD_ASTERISK
13403 if(exten && strcasecmp(exten, "BYEXTENSION"))
13404 #else
13405 if(exten)
13406 #endif
13407 strncpy(chan->exten, exten, sizeof(chan->exten)-1);
13408 if(context)
13409 strncpy(chan->context, context, sizeof(chan->context)-1);
13410 } else {
13411 chan->priority++;
13412 }
13413
13414 if(option_verbose > 2) {
13415 ast_verbose(VERBOSE_PREFIX_3 "Return Context: (%s,%s,%d) ID: %s\n",
13416 chan->context, chan->exten, chan->priority,
13417 S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, ""));
13418 if(!ast_exists_extension(chan, chan->context, chan->exten, chan->priority,
13419 S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, NULL))) {
13420 ast_verbose( VERBOSE_PREFIX_3 "Warning: Return Context Invalid, call will return to default|s\n");
13421 }
13422 }
13423
13424
13425
13426
13427 ast_masq_park_call(chan, NULL, timeout, &lot);
13428
13429 if (option_verbose > 2) ast_verbose( VERBOSE_PREFIX_3 "Call Parking Called, lot: %d, timeout: %d, context: %s\n", lot, timeout, return_context);
13430
13431 snprintf(buffer, sizeof(buffer) - 1, "%d,%s", lot, template + 1);
13432
13433 rpt_telemetry(myrpt,REV_PATCH,buffer);
13434
13435 ast_free(orig_s);
13436
13437 return 0;
13438
13439 }
13440
13441 if (!options)
13442 {
13443 struct ast_hostent ahp;
13444 struct hostent *hp;
13445 struct in_addr ia;
13446 char hisip[100],nodeip[100],*val, *s, *s1, *s2, *s3, *b,*b1;
13447
13448
13449 b = S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, NULL);
13450 if (!b)
13451 {
13452 ast_log(LOG_WARNING, "Does not have callerid on %s\n",tmp);
13453 return -1;
13454 }
13455
13456 memset(hisip,0,sizeof(hisip));
13457 #ifdef ALLOW_LOCAL_CHANNELS
13458
13459 if (strncmp(chan->name,"Local",5)==0) {
13460 strcpy(hisip,"127.0.0.1");
13461 } else {
13462 pbx_substitute_variables_helper(chan,"${IAXPEER(CURRENTCHANNEL)}",hisip,sizeof(hisip) - 1);
13463 }
13464 #else
13465 pbx_substitute_variables_helper(chan,"${IAXPEER(CURRENTCHANNEL)}",hisip,sizeof(hisip) - 1);
13466 #endif
13467
13468 if (!hisip[0])
13469 {
13470 ast_log(LOG_WARNING, "Link IP address cannot be determined!!\n");
13471 return -1;
13472 }
13473
13474 b1 = ast_strdupa(b);
13475 ast_shrink_phone_number(b1);
13476 if (!strcmp(myrpt->name,b1))
13477 {
13478 ast_log(LOG_WARNING, "Trying to link to self!!\n");
13479 return -1;
13480 }
13481
13482 if (*b1 < '1')
13483 {
13484 ast_log(LOG_WARNING, "Node %s Invalid for connection here!!\n",b1);
13485 return -1;
13486 }
13487
13488
13489
13490 val = node_lookup(myrpt,b1);
13491 if (!val)
13492 {
13493 ast_log(LOG_WARNING, "Reported node %s cannot be found!!\n",b1);
13494 return -1;
13495 }
13496 strncpy(tmp,val,sizeof(tmp) - 1);
13497 s = tmp;
13498 s1 = strsep(&s,",");
13499 if (!strchr(s1,':') && strchr(s1,'/') && strncasecmp(s1, "local/", 6))
13500 {
13501 sy = strchr(s1,'/');
13502 *sy = 0;
13503 sprintf(sx,"%s:4569/%s",s1,sy + 1);
13504 s1 = sx;
13505 }
13506 s2 = strsep(&s,",");
13507 if (!s2)
13508 {
13509 ast_log(LOG_WARNING, "Reported node %s not in correct format!!\n",b1);
13510 return -1;
13511 }
13512 if (strcmp(s2,"NONE")) {
13513 hp = ast_gethostbyname(s2, &ahp);
13514 if (!hp)
13515 {
13516 ast_log(LOG_WARNING, "Reported node %s, name %s cannot be found!!\n",b1,s2);
13517 return -1;
13518 }
13519 memcpy(&ia,hp->h_addr,sizeof(in_addr_t));
13520 #ifdef OLD_ASTERISK
13521 ast_inet_ntoa(nodeip,sizeof(nodeip) - 1,ia);
13522 #else
13523 strncpy(nodeip,ast_inet_ntoa(ia),sizeof(nodeip) - 1);
13524 #endif
13525 s3 = strchr(hisip,':');
13526 if (s3) *s3 = 0;
13527 if (strcmp(hisip,nodeip))
13528 {
13529 s3 = strchr(s1,'@');
13530 if (s3) s1 = s3 + 1;
13531 s3 = strchr(s1,'/');
13532 if (s3) *s3 = 0;
13533 s3 = strchr(s1,':');
13534 if (s3) *s3 = 0;
13535 hp = ast_gethostbyname(s1, &ahp);
13536 if (!hp)
13537 {
13538 ast_log(LOG_WARNING, "Reported node %s, name %s cannot be found!!\n",b1,s1);
13539 return -1;
13540 }
13541 memcpy(&ia,hp->h_addr,sizeof(in_addr_t));
13542 #ifdef OLD_ASTERISK
13543 ast_inet_ntoa(nodeip,sizeof(nodeip) - 1,ia);
13544 #else
13545 strncpy(nodeip,ast_inet_ntoa(ia),sizeof(nodeip) - 1);
13546 #endif
13547 if (strcmp(hisip,nodeip))
13548 {
13549 ast_log(LOG_WARNING, "Node %s IP %s does not match link IP %s!!\n",b1,nodeip,hisip);
13550 return -1;
13551 }
13552 }
13553 }
13554 }
13555
13556
13557 if (!myrpt->remote)
13558 {
13559 char *b,*b1;
13560 int reconnects = 0;
13561
13562 rpt_mutex_lock(&myrpt->lock);
13563 i = myrpt->xlink;
13564 rpt_mutex_unlock(&myrpt->lock);
13565 if (i)
13566 {
13567 ast_log(LOG_WARNING, "Cannot connect to node %s, system busy\n",myrpt->name);
13568 return -1;
13569 }
13570
13571 b = S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, NULL);
13572 if (!b)
13573 {
13574 ast_log(LOG_WARNING, "Doesnt have callerid on %s\n",tmp);
13575 return -1;
13576 }
13577
13578 b1 = ast_strdupa(b);
13579 ast_shrink_phone_number(b1);
13580 if (!strcmp(myrpt->name,b1))
13581 {
13582 ast_log(LOG_WARNING, "Trying to link to self!!\n");
13583 return -1;
13584 }
13585 rpt_mutex_lock(&myrpt->lock);
13586 l = myrpt->links.next;
13587
13588 while(l != &myrpt->links)
13589 {
13590 if (l->name[0] == '0')
13591 {
13592 l = l->next;
13593 continue;
13594 }
13595
13596 if (!strcmp(l->name,b1)) break;
13597 l = l->next;
13598 }
13599
13600 if (l != &myrpt->links)
13601 {
13602 l->killme = 1;
13603 l->retries = l->max_retries + 1;
13604 l->disced = 2;
13605 reconnects = l->reconnects;
13606 reconnects++;
13607 rpt_mutex_unlock(&myrpt->lock);
13608 usleep(500000);
13609 } else
13610 rpt_mutex_unlock(&myrpt->lock);
13611
13612 l = ast_malloc(sizeof(struct rpt_link));
13613 if (!l)
13614 {
13615 ast_log(LOG_WARNING, "Unable to malloc\n");
13616 pthread_exit(NULL);
13617 }
13618
13619 memset((char *)l,0,sizeof(struct rpt_link));
13620 l->mode = 1;
13621 strncpy(l->name,b1,MAXNODESTR - 1);
13622 l->isremote = 0;
13623 l->chan = chan;
13624 l->connected = 1;
13625 l->thisconnected = 1;
13626 l->hasconnected = 1;
13627 l->reconnects = reconnects;
13628 l->phonemode = phone_mode;
13629 l->phonevox = phone_vox;
13630 l->lastf1 = NULL;
13631 l->lastf2 = NULL;
13632 l->dtmfed = 0;
13633 voxinit_link(l,1);
13634 ast_set_read_format(l->chan,AST_FORMAT_SLINEAR);
13635 ast_set_write_format(l->chan,AST_FORMAT_SLINEAR);
13636
13637 l->pchan = ast_request("DAHDI", AST_FORMAT_SLINEAR, NULL, "pseudo", NULL);
13638 if (!l->pchan)
13639 {
13640 fprintf(stderr,"rpt:Sorry unable to obtain pseudo channel\n");
13641 pthread_exit(NULL);
13642 }
13643 ast_set_read_format(l->pchan,AST_FORMAT_SLINEAR);
13644 ast_set_write_format(l->pchan,AST_FORMAT_SLINEAR);
13645 #ifdef AST_CDR_FLAG_POST_DISABLED
13646 if (l->pchan->cdr)
13647 ast_set_flag(l->pchan->cdr,AST_CDR_FLAG_POST_DISABLED);
13648 #endif
13649
13650 ci.chan = 0;
13651 ci.confno = myrpt->conf;
13652 ci.confmode = DAHDI_CONF_CONF | DAHDI_CONF_LISTENER | DAHDI_CONF_TALKER;
13653
13654 if (ioctl(l->pchan->fds[0],DAHDI_SETCONF,&ci) == -1)
13655 {
13656 ast_log(LOG_WARNING, "Unable to set conference mode to Announce\n");
13657 pthread_exit(NULL);
13658 }
13659 rpt_mutex_lock(&myrpt->lock);
13660 if ((phone_mode == 2) && (!phone_vox)) l->lastrealrx = 1;
13661 l->max_retries = MAX_RETRIES;
13662
13663 insque((struct qelem *)l,(struct qelem *)myrpt->links.next);
13664 __kickshort(myrpt);
13665 rpt_mutex_unlock(&myrpt->lock);
13666 if (chan->_state != AST_STATE_UP) {
13667 ast_answer(chan);
13668 if (!phone_mode) send_newkey(chan);
13669 }
13670 if (myrpt->p.archivedir)
13671 {
13672 char str[100];
13673
13674 if (l->phonemode)
13675 sprintf(str,"LINK(P),%s",l->name);
13676 else
13677 sprintf(str,"LINK,%s",l->name);
13678 donodelog(myrpt,str);
13679 }
13680 if (!phone_mode) send_newkey(chan);
13681 return 0;
13682 }
13683
13684 rpt_mutex_lock(&myrpt->lock);
13685
13686 if (myrpt->remoteon)
13687 {
13688 rpt_mutex_unlock(&myrpt->lock);
13689 usleep(500000);
13690 if (myrpt->remoteon)
13691 {
13692 ast_log(LOG_WARNING, "Trying to use busy link on %s\n",tmp);
13693 #ifdef AST_CDR_FLAG_POST_DISABLED
13694 if (chan->cdr)
13695 ast_set_flag(chan->cdr,AST_CDR_FLAG_POST_DISABLED);
13696 #endif
13697 return -1;
13698 }
13699 rpt_mutex_lock(&myrpt->lock);
13700 }
13701 if (myrpt->p.rptnode)
13702 {
13703 char killedit = 0;
13704 time_t now;
13705
13706 time(&now);
13707 for(i = 0; i < nrpts; i++)
13708 {
13709 if (!strcasecmp(rpt_vars[i].name,myrpt->p.rptnode))
13710 {
13711 if ((rpt_vars[i].links.next != &rpt_vars[i].links) ||
13712 rpt_vars[i].keyed ||
13713 ((rpt_vars[i].lastkeyedtime + RPT_LOCKOUT_SECS) > now) ||
13714 rpt_vars[i].txkeyed ||
13715 ((rpt_vars[i].lasttxkeyedtime + RPT_LOCKOUT_SECS) > now))
13716 {
13717 rpt_mutex_unlock(&myrpt->lock);
13718 ast_log(LOG_WARNING, "Trying to use busy link (repeater node %s) on %s\n",rpt_vars[i].name,tmp);
13719 #ifdef AST_CDR_FLAG_POST_DISABLED
13720 if (chan->cdr)
13721 ast_set_flag(chan->cdr,AST_CDR_FLAG_POST_DISABLED);
13722 #endif
13723 return -1;
13724 }
13725 while(rpt_vars[i].xlink != 3)
13726 {
13727 if (!killedit)
13728 {
13729 ast_softhangup(rpt_vars[i].rxchannel,AST_SOFTHANGUP_DEV);
13730 rpt_vars[i].xlink = 1;
13731 killedit = 1;
13732 }
13733 rpt_mutex_unlock(&myrpt->lock);
13734 if (ast_safe_sleep(chan,500) == -1)
13735 {
13736 #ifdef AST_CDR_FLAG_POST_DISABLED
13737 if (chan->cdr)
13738 ast_set_flag(chan->cdr,AST_CDR_FLAG_POST_DISABLED);
13739 #endif
13740 return -1;
13741 }
13742 rpt_mutex_lock(&myrpt->lock);
13743 }
13744 break;
13745 }
13746 }
13747 }
13748
13749 #ifdef HAVE_IOPERM
13750 if ( (!strcmp(myrpt->remoterig, remote_rig_rbi)||!strcmp(myrpt->remoterig, remote_rig_ppp16)) &&
13751 (ioperm(myrpt->p.iobase,1,1) == -1))
13752 {
13753 rpt_mutex_unlock(&myrpt->lock);
13754 ast_log(LOG_WARNING, "Can't get io permission on IO port %x hex\n",myrpt->p.iobase);
13755 return -1;
13756 }
13757 #endif
13758 myrpt->remoteon = 1;
13759 #ifdef OLD_ASTERISK
13760 LOCAL_USER_ADD(u);
13761 #endif
13762 rpt_mutex_unlock(&myrpt->lock);
13763
13764 for(i = 0; i < nrpts; i++)
13765 {
13766 if (&rpt_vars[i] == myrpt)
13767 {
13768 load_rpt_vars(i,0);
13769 break;
13770 }
13771 }
13772 rpt_mutex_lock(&myrpt->lock);
13773 tele = strchr(myrpt->rxchanname,'/');
13774 if (!tele)
13775 {
13776 fprintf(stderr,"rpt:Dial number must be in format tech/number\n");
13777 rpt_mutex_unlock(&myrpt->lock);
13778 pthread_exit(NULL);
13779 }
13780 *tele++ = 0;
13781 myrpt->rxchannel = ast_request(myrpt->rxchanname, AST_FORMAT_SLINEAR, NULL, tele, NULL);
13782 myrpt->dahdirxchannel = NULL;
13783 if (!strcasecmp(myrpt->rxchanname,"DAHDI"))
13784 myrpt->dahdirxchannel = myrpt->rxchannel;
13785 if (myrpt->rxchannel)
13786 {
13787 ast_set_read_format(myrpt->rxchannel,AST_FORMAT_SLINEAR);
13788 ast_set_write_format(myrpt->rxchannel,AST_FORMAT_SLINEAR);
13789 #ifdef AST_CDR_FLAG_POST_DISABLED
13790 if (myrpt->rxchannel->cdr)
13791 ast_set_flag(myrpt->rxchannel->cdr,AST_CDR_FLAG_POST_DISABLED);
13792 #endif
13793 #ifndef NEW_ASTERISK
13794 myrpt->rxchannel->whentohangup = 0;
13795 #endif
13796 myrpt->rxchannel->appl = "Apprpt";
13797 myrpt->rxchannel->data = "(Link Rx)";
13798 if (option_verbose > 2)
13799 ast_verbose(VERBOSE_PREFIX_3 "rpt (Rx) initiating call to %s/%s on %s\n",
13800 myrpt->rxchanname,tele,myrpt->rxchannel->name);
13801 rpt_mutex_unlock(&myrpt->lock);
13802 ast_call(myrpt->rxchannel,tele,999);
13803 rpt_mutex_lock(&myrpt->lock);
13804 }
13805 else
13806 {
13807 fprintf(stderr,"rpt:Sorry unable to obtain Rx channel\n");
13808 rpt_mutex_unlock(&myrpt->lock);
13809 pthread_exit(NULL);
13810 }
13811 *--tele = '/';
13812 myrpt->dahditxchannel = NULL;
13813 if (myrpt->txchanname)
13814 {
13815 tele = strchr(myrpt->txchanname,'/');
13816 if (!tele)
13817 {
13818 fprintf(stderr,"rpt:Dial number must be in format tech/number\n");
13819 rpt_mutex_unlock(&myrpt->lock);
13820 ast_hangup(myrpt->rxchannel);
13821 pthread_exit(NULL);
13822 }
13823 *tele++ = 0;
13824 myrpt->txchannel = ast_request(myrpt->txchanname, AST_FORMAT_SLINEAR, NULL, tele, NULL);
13825 if (!strncasecmp(myrpt->txchanname,"DAHDI",3))
13826 myrpt->dahditxchannel = myrpt->txchannel;
13827 if (myrpt->txchannel)
13828 {
13829 ast_set_read_format(myrpt->txchannel,AST_FORMAT_SLINEAR);
13830 ast_set_write_format(myrpt->txchannel,AST_FORMAT_SLINEAR);
13831 #ifdef AST_CDR_FLAG_POST_DISABLED
13832 if (myrpt->txchannel->cdr)
13833 ast_set_flag(myrpt->txchannel->cdr,AST_CDR_FLAG_POST_DISABLED);
13834 #endif
13835 #ifndef NEW_ASTERISK
13836 myrpt->txchannel->whentohangup = 0;
13837 #endif
13838 myrpt->txchannel->appl = "Apprpt";
13839 myrpt->txchannel->data = "(Link Tx)";
13840 if (option_verbose > 2)
13841 ast_verbose(VERBOSE_PREFIX_3 "rpt (Tx) initiating call to %s/%s on %s\n",
13842 myrpt->txchanname,tele,myrpt->txchannel->name);
13843 rpt_mutex_unlock(&myrpt->lock);
13844 ast_call(myrpt->txchannel,tele,999);
13845 rpt_mutex_lock(&myrpt->lock);
13846 }
13847 else
13848 {
13849 fprintf(stderr,"rpt:Sorry unable to obtain Tx channel\n");
13850 rpt_mutex_unlock(&myrpt->lock);
13851 ast_hangup(myrpt->rxchannel);
13852 pthread_exit(NULL);
13853 }
13854 *--tele = '/';
13855 }
13856 else
13857 {
13858 myrpt->txchannel = myrpt->rxchannel;
13859 if (!strncasecmp(myrpt->rxchanname,"DAHDI",3))
13860 myrpt->dahditxchannel = myrpt->rxchannel;
13861 }
13862
13863 myrpt->pchannel = ast_request("DAHDI", AST_FORMAT_SLINEAR, NULL, "pseudo", NULL);
13864 if (!myrpt->pchannel)
13865 {
13866 fprintf(stderr,"rpt:Sorry unable to obtain pseudo channel\n");
13867 rpt_mutex_unlock(&myrpt->lock);
13868 if (myrpt->txchannel != myrpt->rxchannel)
13869 ast_hangup(myrpt->txchannel);
13870 ast_hangup(myrpt->rxchannel);
13871 pthread_exit(NULL);
13872 }
13873 ast_set_read_format(myrpt->pchannel,AST_FORMAT_SLINEAR);
13874 ast_set_write_format(myrpt->pchannel,AST_FORMAT_SLINEAR);
13875 #ifdef AST_CDR_FLAG_POST_DISABLED
13876 if (myrpt->pchannel->cdr)
13877 ast_set_flag(myrpt->pchannel->cdr,AST_CDR_FLAG_POST_DISABLED);
13878 #endif
13879 if (!myrpt->dahdirxchannel) myrpt->dahdirxchannel = myrpt->pchannel;
13880 if (!myrpt->dahditxchannel) myrpt->dahditxchannel = myrpt->pchannel;
13881
13882 ci.chan = 0;
13883 ci.confno = -1;
13884 ci.confmode = DAHDI_CONF_CONFANNMON ;
13885
13886 if (ioctl(myrpt->pchannel->fds[0],DAHDI_SETCONF,&ci) == -1)
13887 {
13888 ast_log(LOG_WARNING, "Unable to set conference mode to Announce\n");
13889 rpt_mutex_unlock(&myrpt->lock);
13890 ast_hangup(myrpt->pchannel);
13891 if (myrpt->txchannel != myrpt->rxchannel)
13892 ast_hangup(myrpt->txchannel);
13893 ast_hangup(myrpt->rxchannel);
13894 pthread_exit(NULL);
13895 }
13896
13897 myrpt->conf = myrpt->txconf = ci.confno;
13898
13899 myrpt->iofd = -1;
13900 if (myrpt->p.ioport && ((myrpt->iofd = openserial(myrpt,myrpt->p.ioport)) == -1))
13901 {
13902 rpt_mutex_unlock(&myrpt->lock);
13903 ast_hangup(myrpt->pchannel);
13904 if (myrpt->txchannel != myrpt->rxchannel)
13905 ast_hangup(myrpt->txchannel);
13906 ast_hangup(myrpt->rxchannel);
13907 pthread_exit(NULL);
13908 }
13909 iskenwood_pci4 = 0;
13910 memset(&z,0,sizeof(z));
13911 if ((myrpt->iofd < 1) && (myrpt->txchannel == myrpt->dahditxchannel))
13912 {
13913 z.radpar = DAHDI_RADPAR_REMMODE;
13914 z.data = DAHDI_RADPAR_REM_NONE;
13915 res = ioctl(myrpt->dahditxchannel->fds[0],DAHDI_RADIO_SETPARAM,&z);
13916
13917 if ((!res) && (!strcmp(myrpt->remoterig,remote_rig_kenwood)))
13918 {
13919 z.radpar = DAHDI_RADPAR_UIOMODE;
13920 z.data = 1;
13921 if (ioctl(myrpt->dahditxchannel->fds[0],DAHDI_RADIO_SETPARAM,&z) == -1)
13922 {
13923 ast_log(LOG_ERROR,"Cannot set UIOMODE\n");
13924 return -1;
13925 }
13926 z.radpar = DAHDI_RADPAR_UIODATA;
13927 z.data = 3;
13928 if (ioctl(myrpt->dahditxchannel->fds[0],DAHDI_RADIO_SETPARAM,&z) == -1)
13929 {
13930 ast_log(LOG_ERROR,"Cannot set UIODATA\n");
13931 return -1;
13932 }
13933 i = DAHDI_OFFHOOK;
13934 if (ioctl(myrpt->dahditxchannel->fds[0],DAHDI_HOOK,&i) == -1)
13935 {
13936 ast_log(LOG_ERROR,"Cannot set hook\n");
13937 return -1;
13938 }
13939 iskenwood_pci4 = 1;
13940 }
13941 }
13942 if (myrpt->txchannel == myrpt->dahditxchannel)
13943 {
13944 i = DAHDI_ONHOOK;
13945 ioctl(myrpt->dahditxchannel->fds[0],DAHDI_HOOK,&i);
13946
13947 if ((myrpt->iofd < 1) && (!res) &&
13948 ((!strcmp(myrpt->remoterig,remote_rig_ft897)) ||
13949 (!strcmp(myrpt->remoterig,remote_rig_ic706)) ||
13950 (!strcmp(myrpt->remoterig,remote_rig_tm271))))
13951 {
13952 z.radpar = DAHDI_RADPAR_UIOMODE;
13953 z.data = 1;
13954 if (ioctl(myrpt->dahditxchannel->fds[0],DAHDI_RADIO_SETPARAM,&z) == -1)
13955 {
13956 ast_log(LOG_ERROR,"Cannot set UIOMODE\n");
13957 return -1;
13958 }
13959 z.radpar = DAHDI_RADPAR_UIODATA;
13960 z.data = 3;
13961 if (ioctl(myrpt->dahditxchannel->fds[0],DAHDI_RADIO_SETPARAM,&z) == -1)
13962 {
13963 ast_log(LOG_ERROR,"Cannot set UIODATA\n");
13964 return -1;
13965 }
13966 }
13967 }
13968 myrpt->remoterx = 0;
13969 myrpt->remotetx = 0;
13970 myrpt->retxtimer = 0;
13971 myrpt->rerxtimer = 0;
13972 myrpt->remoteon = 1;
13973 myrpt->dtmfidx = -1;
13974 myrpt->dtmfbuf[0] = 0;
13975 myrpt->dtmf_time_rem = 0;
13976 myrpt->hfscanmode = 0;
13977 myrpt->hfscanstatus = 0;
13978 if (myrpt->p.startupmacro)
13979 {
13980 snprintf(myrpt->macrobuf,MAXMACRO - 1,"PPPP%s",myrpt->p.startupmacro);
13981 }
13982 time(&myrpt->start_time);
13983 myrpt->last_activity_time = myrpt->start_time;
13984 last_timeout_warning = 0;
13985 myrpt->reload = 0;
13986 myrpt->tele.next = &myrpt->tele;
13987 myrpt->tele.prev = &myrpt->tele;
13988 myrpt->newkey = 0;
13989 rpt_mutex_unlock(&myrpt->lock);
13990 ast_set_write_format(chan, AST_FORMAT_SLINEAR);
13991 ast_set_read_format(chan, AST_FORMAT_SLINEAR);
13992 rem_rx = 0;
13993 remkeyed = 0;
13994
13995 if (myrpt->remote && (myrpt->rxchannel == myrpt->txchannel))
13996 {
13997 i = 128;
13998 ioctl(myrpt->dahdirxchannel->fds[0],DAHDI_ECHOCANCEL,&i);
13999 }
14000 if (chan->_state != AST_STATE_UP) {
14001 ast_answer(chan);
14002 if (!phone_mode) send_newkey(chan);
14003 }
14004
14005 if (myrpt->rxchannel == myrpt->dahdirxchannel)
14006 {
14007 if (ioctl(myrpt->dahdirxchannel->fds[0],DAHDI_GET_PARAMS,&par) != -1)
14008 {
14009 if (par.rxisoffhook)
14010 {
14011 ast_indicate(chan,AST_CONTROL_RADIO_KEY);
14012 myrpt->remoterx = 1;
14013 remkeyed = 1;
14014 }
14015 }
14016 }
14017 if (myrpt->p.archivedir)
14018 {
14019 char mycmd[100],mydate[100],*b,*b1;
14020 time_t myt;
14021 long blocksleft;
14022
14023
14024 mkdir(myrpt->p.archivedir,0600);
14025 sprintf(mycmd,"%s/%s",myrpt->p.archivedir,myrpt->name);
14026 mkdir(mycmd,0600);
14027 time(&myt);
14028 strftime(mydate,sizeof(mydate) - 1,"%Y%m%d%H%M%S",
14029 localtime(&myt));
14030 sprintf(mycmd,"mixmonitor start %s %s/%s/%s.wav49 a",chan->name,
14031 myrpt->p.archivedir,myrpt->name,mydate);
14032 if (myrpt->p.monminblocks)
14033 {
14034 blocksleft = diskavail(myrpt);
14035 if (myrpt->p.remotetimeout)
14036 {
14037 blocksleft -= (myrpt->p.remotetimeout *
14038 MONITOR_DISK_BLOCKS_PER_MINUTE) / 60;
14039 }
14040 if (blocksleft >= myrpt->p.monminblocks)
14041 ast_cli_command(nullfd,mycmd);
14042 } else ast_cli_command(nullfd,mycmd);
14043
14044 b = S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, NULL);
14045 if (!b)
14046 {
14047 b1 = "0";
14048 } else {
14049 b1 = ast_strdupa(b);
14050 ast_shrink_phone_number(b1);
14051 }
14052 sprintf(mycmd,"CONNECT,%s",b1);
14053 donodelog(myrpt,mycmd);
14054 }
14055 myrpt->loginuser[0] = 0;
14056 myrpt->loginlevel[0] = 0;
14057 myrpt->authtelltimer = 0;
14058 myrpt->authtimer = 0;
14059 authtold = 0;
14060 authreq = 0;
14061 if (myrpt->p.authlevel > 1) authreq = 1;
14062 setrem(myrpt);
14063 n = 0;
14064 dtmfed = 0;
14065 cs[n++] = chan;
14066 cs[n++] = myrpt->rxchannel;
14067 cs[n++] = myrpt->pchannel;
14068 if (myrpt->rxchannel != myrpt->txchannel)
14069 cs[n++] = myrpt->txchannel;
14070 if (!phone_mode) send_newkey(chan);
14071
14072 for(;;)
14073 {
14074 if (ast_check_hangup(chan)) break;
14075 if (ast_check_hangup(myrpt->rxchannel)) break;
14076 notremming = 0;
14077 setting = 0;
14078 reming = 0;
14079 telem = myrpt->tele.next;
14080 while(telem != &myrpt->tele)
14081 {
14082 if (telem->mode == SETREMOTE) setting = 1;
14083 if ((telem->mode == SETREMOTE) ||
14084 (telem->mode == SCAN) ||
14085 (telem->mode == TUNE)) reming = 1;
14086 else notremming = 1;
14087 telem = telem->next;
14088 }
14089 if (myrpt->reload)
14090 {
14091 myrpt->reload = 0;
14092
14093 for(i = 0; i < nrpts; i++)
14094 {
14095 if (&rpt_vars[i] == myrpt)
14096 {
14097 load_rpt_vars(i,0);
14098 break;
14099 }
14100 }
14101 }
14102 time(&t);
14103 if (myrpt->p.remotetimeout)
14104 {
14105 time_t r;
14106
14107 r = (t - myrpt->start_time);
14108 if (r >= myrpt->p.remotetimeout)
14109 {
14110 saynode(myrpt,chan,myrpt->name);
14111 sayfile(chan,"rpt/timeout");
14112 ast_safe_sleep(chan,1000);
14113 break;
14114 }
14115 if ((myrpt->p.remotetimeoutwarning) &&
14116 (r >= (myrpt->p.remotetimeout -
14117 myrpt->p.remotetimeoutwarning)) &&
14118 (r <= (myrpt->p.remotetimeout -
14119 myrpt->p.remotetimeoutwarningfreq)))
14120 {
14121 if (myrpt->p.remotetimeoutwarningfreq)
14122 {
14123 if ((t - last_timeout_warning) >=
14124 myrpt->p.remotetimeoutwarningfreq)
14125 {
14126 time(&last_timeout_warning);
14127 rpt_telemetry(myrpt,TIMEOUT_WARNING,0);
14128 }
14129 }
14130 else
14131 {
14132 if (!last_timeout_warning)
14133 {
14134 time(&last_timeout_warning);
14135 rpt_telemetry(myrpt,TIMEOUT_WARNING,0);
14136 }
14137 }
14138 }
14139 }
14140 if (myrpt->p.remoteinacttimeout && myrpt->last_activity_time)
14141 {
14142 time_t r;
14143
14144 r = (t - myrpt->last_activity_time);
14145 if (r >= myrpt->p.remoteinacttimeout)
14146 {
14147 saynode(myrpt,chan,myrpt->name);
14148 ast_safe_sleep(chan,1000);
14149 break;
14150 }
14151 if ((myrpt->p.remotetimeoutwarning) &&
14152 (r >= (myrpt->p.remoteinacttimeout -
14153 myrpt->p.remotetimeoutwarning)) &&
14154 (r <= (myrpt->p.remoteinacttimeout -
14155 myrpt->p.remotetimeoutwarningfreq)))
14156 {
14157 if (myrpt->p.remotetimeoutwarningfreq)
14158 {
14159 if ((t - last_timeout_warning) >=
14160 myrpt->p.remotetimeoutwarningfreq)
14161 {
14162 time(&last_timeout_warning);
14163 rpt_telemetry(myrpt,ACT_TIMEOUT_WARNING,0);
14164 }
14165 }
14166 else
14167 {
14168 if (!last_timeout_warning)
14169 {
14170 time(&last_timeout_warning);
14171 rpt_telemetry(myrpt,ACT_TIMEOUT_WARNING,0);
14172 }
14173 }
14174 }
14175 }
14176 ms = MSWAIT;
14177 who = ast_waitfor_n(cs,n,&ms);
14178 if (who == NULL) ms = 0;
14179 elap = MSWAIT - ms;
14180 if (myrpt->macrotimer) myrpt->macrotimer -= elap;
14181 if (myrpt->macrotimer < 0) myrpt->macrotimer = 0;
14182 if (!ms) continue;
14183
14184 if (myrpt->dtmf_local_timer)
14185 {
14186 if (myrpt->dtmf_local_timer > 1) myrpt->dtmf_local_timer -= elap;
14187 if (myrpt->dtmf_local_timer < 1) myrpt->dtmf_local_timer = 1;
14188 }
14189 rpt_mutex_lock(&myrpt->lock);
14190 do_dtmf_local(myrpt,0);
14191 rpt_mutex_unlock(&myrpt->lock);
14192
14193 rem_totx = myrpt->dtmf_local_timer && (!phone_mode);
14194 rem_totx |= keyed && (!myrpt->tunerequest);
14195 rem_rx = (remkeyed && (!setting)) || (myrpt->tele.next != &myrpt->tele);
14196 if(!strcmp(myrpt->remoterig, remote_rig_ic706))
14197 rem_totx |= myrpt->tunerequest;
14198
14199 if((debug > 6) && rem_totx) {
14200 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);
14201 }
14202 if (keyed && (!keyed1))
14203 {
14204 keyed1 = 1;
14205 }
14206
14207 if (!keyed && (keyed1))
14208 {
14209 time_t myt;
14210
14211 keyed1 = 0;
14212 time(&myt);
14213
14214 if ((myrpt->p.authlevel) &&
14215 (!myrpt->loginlevel[0]) &&
14216 (myt > (t + 3)))
14217 {
14218 authreq = 1;
14219 authtold = 0;
14220 myrpt->authtelltimer = AUTHTELLTIME - AUTHTXTIME;
14221 }
14222 }
14223
14224 if (rem_rx && (!myrpt->remoterx))
14225 {
14226 myrpt->remoterx = 1;
14227 ast_indicate(chan,AST_CONTROL_RADIO_KEY);
14228 }
14229 if ((!rem_rx) && (myrpt->remoterx))
14230 {
14231 myrpt->remoterx = 0;
14232 ast_indicate(chan,AST_CONTROL_RADIO_UNKEY);
14233 }
14234
14235 if (authreq && (!myrpt->loginlevel[0]))
14236 {
14237 if ((!authtold) && ((myrpt->authtelltimer += elap)
14238 >= AUTHTELLTIME))
14239 {
14240 authtold = 1;
14241 rpt_telemetry(myrpt,LOGINREQ,NULL);
14242 }
14243 if ((myrpt->authtimer += elap) >= AUTHLOGOUTTIME)
14244 {
14245 break;
14246 }
14247 }
14248 if (myrpt->newkey)
14249 {
14250 if ((myrpt->retxtimer += elap) >= REDUNDANT_TX_TIME)
14251 {
14252 myrpt->retxtimer = 0;
14253 if ((myrpt->remoterx) && (!myrpt->remotetx))
14254 ast_indicate(chan,AST_CONTROL_RADIO_KEY);
14255 else
14256 ast_indicate(chan,AST_CONTROL_RADIO_UNKEY);
14257 }
14258
14259 if ((myrpt->rerxtimer += elap) >= (REDUNDANT_TX_TIME * 2))
14260 {
14261 keyed = 0;
14262 myrpt->rerxtimer = 0;
14263 }
14264 }
14265 if (rem_totx && (!myrpt->remotetx))
14266 {
14267
14268 if ((!myrpt->p.authlevel) || myrpt->loginlevel[0])
14269 {
14270 if(debug > 6)
14271 ast_log(LOG_NOTICE,"Handle rem_totx=%i. dtmf_local_timer=%i tunerequest=%i\n",rem_totx,myrpt->dtmf_local_timer,myrpt->tunerequest);
14272
14273 myrpt->remotetx = 1;
14274
14275 if((myrpt->remtxfreqok = check_tx_freq(myrpt)))
14276 {
14277 time(&myrpt->last_activity_time);
14278 if ((iskenwood_pci4) && (myrpt->txchannel == myrpt->dahditxchannel))
14279 {
14280 z.radpar = DAHDI_RADPAR_UIODATA;
14281 z.data = 1;
14282 if (ioctl(myrpt->dahditxchannel->fds[0],DAHDI_RADIO_SETPARAM,&z) == -1)
14283 {
14284 ast_log(LOG_ERROR,"Cannot set UIODATA\n");
14285 return -1;
14286 }
14287 }
14288 else
14289 {
14290 ast_indicate(myrpt->txchannel,AST_CONTROL_RADIO_KEY);
14291 }
14292 if (myrpt->p.archivedir) donodelog(myrpt,"TXKEY");
14293 }
14294 }
14295 }
14296 if ((!rem_totx) && myrpt->remotetx)
14297 {
14298 myrpt->remotetx = 0;
14299 if(!myrpt->remtxfreqok){
14300 rpt_telemetry(myrpt,UNAUTHTX,NULL);
14301 }
14302 if ((iskenwood_pci4) && (myrpt->txchannel == myrpt->dahditxchannel))
14303 {
14304 z.radpar = DAHDI_RADPAR_UIODATA;
14305 z.data = 3;
14306 if (ioctl(myrpt->dahditxchannel->fds[0],DAHDI_RADIO_SETPARAM,&z) == -1)
14307 {
14308 ast_log(LOG_ERROR,"Cannot set UIODATA\n");
14309 return -1;
14310 }
14311 }
14312 else
14313 {
14314 ast_indicate(myrpt->txchannel,AST_CONTROL_RADIO_UNKEY);
14315 }
14316 if (myrpt->p.archivedir) donodelog(myrpt,"TXUNKEY");
14317 }
14318 if (myrpt->hfscanmode){
14319 myrpt->scantimer -= elap;
14320 if(myrpt->scantimer <= 0){
14321 if (!reming)
14322 {
14323 myrpt->scantimer = REM_SCANTIME;
14324 rpt_telemetry(myrpt,SCAN,0);
14325 } else myrpt->scantimer = 1;
14326 }
14327 }
14328 rpt_mutex_lock(&myrpt->lock);
14329 c = myrpt->macrobuf[0];
14330 if (c && (!myrpt->macrotimer))
14331 {
14332 myrpt->macrotimer = MACROTIME;
14333 memmove(myrpt->macrobuf,myrpt->macrobuf + 1,MAXMACRO - 1);
14334 if ((c == 'p') || (c == 'P'))
14335 myrpt->macrotimer = MACROPTIME;
14336 rpt_mutex_unlock(&myrpt->lock);
14337 if (myrpt->p.archivedir)
14338 {
14339 char str[100];
14340 sprintf(str,"DTMF(M),%c",c);
14341 donodelog(myrpt,str);
14342 }
14343 if (handle_remote_dtmf_digit(myrpt,c,&keyed,0) == -1) break;
14344 continue;
14345 } else rpt_mutex_unlock(&myrpt->lock);
14346 if (who == chan)
14347 {
14348 f = ast_read(chan);
14349 if (!f)
14350 {
14351 if (debug) printf("@@@@ link:Hung Up\n");
14352 break;
14353 }
14354 if (f->frametype == AST_FRAME_VOICE)
14355 {
14356 if (ioctl(chan->fds[0], DAHDI_GETCONFMUTE, &ismuted) == -1)
14357 {
14358 ismuted = 0;
14359 }
14360
14361 ismuted |= (!myrpt->remotetx);
14362 if (dtmfed && phone_mode) ismuted = 1;
14363 dtmfed = 0;
14364 if (ismuted)
14365 {
14366 memset(f->data.ptr,0,f->datalen);
14367 if (myrpt->lastf1)
14368 memset(myrpt->lastf1->data.ptr,0,myrpt->lastf1->datalen);
14369 if (myrpt->lastf2)
14370 memset(myrpt->lastf2->data.ptr,0,myrpt->lastf2->datalen);
14371 }
14372 if (f) f2 = ast_frdup(f);
14373 else f2 = NULL;
14374 f1 = myrpt->lastf2;
14375 myrpt->lastf2 = myrpt->lastf1;
14376 myrpt->lastf1 = f2;
14377 if (ismuted)
14378 {
14379 if (myrpt->lastf1)
14380 memset(myrpt->lastf1->data.ptr,0,myrpt->lastf1->datalen);
14381 if (myrpt->lastf2)
14382 memset(myrpt->lastf2->data.ptr,0,myrpt->lastf2->datalen);
14383 }
14384 if (f1)
14385 {
14386 if (phone_mode)
14387 ast_write(myrpt->txchannel,f1);
14388 else
14389 ast_write(myrpt->txchannel,f);
14390 ast_frfree(f1);
14391 }
14392 }
14393 #ifndef OLD_ASTERISK
14394 else if (f->frametype == AST_FRAME_DTMF_BEGIN)
14395 {
14396 if (myrpt->lastf1)
14397 memset(myrpt->lastf1->data.ptr,0,myrpt->lastf1->datalen);
14398 if (myrpt->lastf2)
14399 memset(myrpt->lastf2->data.ptr,0,myrpt->lastf2->datalen);
14400 dtmfed = 1;
14401 }
14402 #endif
14403 if (f->frametype == AST_FRAME_DTMF)
14404 {
14405 if (myrpt->lastf1)
14406 memset(myrpt->lastf1->data.ptr,0,myrpt->lastf1->datalen);
14407 if (myrpt->lastf2)
14408 memset(myrpt->lastf2->data.ptr,0,myrpt->lastf2->datalen);
14409 dtmfed = 1;
14410 if (handle_remote_phone_dtmf(myrpt,f->subclass.integer,&keyed,phone_mode) == -1)
14411 {
14412 if (debug) printf("@@@@ rpt:Hung Up\n");
14413 ast_frfree(f);
14414 break;
14415 }
14416 }
14417 if (f->frametype == AST_FRAME_TEXT)
14418 {
14419 if (handle_remote_data(myrpt,f->data.ptr) == -1)
14420 {
14421 if (debug) printf("@@@@ rpt:Hung Up\n");
14422 ast_frfree(f);
14423 break;
14424 }
14425 }
14426 if (f->frametype == AST_FRAME_CONTROL)
14427 {
14428 if (f->subclass.integer == AST_CONTROL_HANGUP)
14429 {
14430 if (debug) printf("@@@@ rpt:Hung Up\n");
14431 ast_frfree(f);
14432 break;
14433 }
14434
14435 if (f->subclass.integer == AST_CONTROL_RADIO_KEY)
14436 {
14437 if (debug == 7) printf("@@@@ rx key\n");
14438 keyed = 1;
14439 myrpt->rerxtimer = 0;
14440 }
14441
14442 if (f->subclass.integer == AST_CONTROL_RADIO_UNKEY)
14443 {
14444 myrpt->rerxtimer = 0;
14445 if (debug == 7) printf("@@@@ rx un-key\n");
14446 keyed = 0;
14447 }
14448 }
14449 ast_frfree(f);
14450 continue;
14451 }
14452 if (who == myrpt->rxchannel)
14453 {
14454 f = ast_read(myrpt->rxchannel);
14455 if (!f)
14456 {
14457 if (debug) printf("@@@@ link:Hung Up\n");
14458 break;
14459 }
14460 if (f->frametype == AST_FRAME_VOICE)
14461 {
14462 int myreming = 0;
14463
14464 if(!strcmp(myrpt->remoterig, remote_rig_kenwood))
14465 myreming = reming;
14466
14467 if (myreming || (!remkeyed) ||
14468 ((myrpt->remote) && (myrpt->remotetx)) ||
14469 ((myrpt->remmode != REM_MODE_FM) &&
14470 notremming))
14471 memset(f->data.ptr,0,f->datalen);
14472 ast_write(myrpt->pchannel,f);
14473 }
14474 else if (f->frametype == AST_FRAME_CONTROL)
14475 {
14476 if (f->subclass.integer == AST_CONTROL_HANGUP)
14477 {
14478 if (debug) printf("@@@@ rpt:Hung Up\n");
14479 ast_frfree(f);
14480 break;
14481 }
14482
14483 if (f->subclass.integer == AST_CONTROL_RADIO_KEY)
14484 {
14485 if (debug == 7) printf("@@@@ remote rx key\n");
14486 if (!myrpt->remotetx)
14487 {
14488 remkeyed = 1;
14489 }
14490 }
14491
14492 if (f->subclass.integer == AST_CONTROL_RADIO_UNKEY)
14493 {
14494 if (debug == 7) printf("@@@@ remote rx un-key\n");
14495 if (!myrpt->remotetx)
14496 {
14497 remkeyed = 0;
14498 }
14499 }
14500 }
14501 ast_frfree(f);
14502 continue;
14503 }
14504 if (who == myrpt->pchannel)
14505 {
14506 f = ast_read(myrpt->pchannel);
14507 if (!f)
14508 {
14509 if (debug) printf("@@@@ link:Hung Up\n");
14510 break;
14511 }
14512 if (f->frametype == AST_FRAME_VOICE)
14513 {
14514 ast_write(chan,f);
14515 }
14516 if (f->frametype == AST_FRAME_CONTROL)
14517 {
14518 if (f->subclass.integer == AST_CONTROL_HANGUP)
14519 {
14520 if (debug) printf("@@@@ rpt:Hung Up\n");
14521 ast_frfree(f);
14522 break;
14523 }
14524 }
14525 ast_frfree(f);
14526 continue;
14527 }
14528 if ((myrpt->rxchannel != myrpt->txchannel) &&
14529 (who == myrpt->txchannel))
14530 {
14531 f = ast_read(myrpt->txchannel);
14532 if (!f)
14533 {
14534 if (debug) printf("@@@@ link:Hung Up\n");
14535 break;
14536 }
14537 if (f->frametype == AST_FRAME_CONTROL)
14538 {
14539 if (f->subclass.integer == AST_CONTROL_HANGUP)
14540 {
14541 if (debug) printf("@@@@ rpt:Hung Up\n");
14542 ast_frfree(f);
14543 break;
14544 }
14545 }
14546 ast_frfree(f);
14547 continue;
14548 }
14549 }
14550 if (myrpt->p.archivedir)
14551 {
14552 char mycmd[100],*b,*b1;
14553
14554
14555 b = S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, NULL);
14556 if (!b)
14557 {
14558 b1 = "0";
14559 } else {
14560 b1 = ast_strdupa(b);
14561 ast_shrink_phone_number(b1);
14562 }
14563 sprintf(mycmd,"DISCONNECT,%s",b1);
14564 donodelog(myrpt,mycmd);
14565 }
14566
14567 while(myrpt->tele.next != &myrpt->tele) usleep(100000);
14568 sprintf(tmp,"mixmonitor stop %s",chan->name);
14569 ast_cli_command(nullfd,tmp);
14570 close(nullfd);
14571 rpt_mutex_lock(&myrpt->lock);
14572 myrpt->hfscanmode = 0;
14573 myrpt->hfscanstatus = 0;
14574 myrpt->remoteon = 0;
14575 rpt_mutex_unlock(&myrpt->lock);
14576 if (myrpt->lastf1) ast_frfree(myrpt->lastf1);
14577 myrpt->lastf1 = NULL;
14578 if (myrpt->lastf2) ast_frfree(myrpt->lastf2);
14579 myrpt->lastf2 = NULL;
14580 if ((iskenwood_pci4) && (myrpt->txchannel == myrpt->dahditxchannel))
14581 {
14582 z.radpar = DAHDI_RADPAR_UIOMODE;
14583 z.data = 3;
14584 if (ioctl(myrpt->dahditxchannel->fds[0],DAHDI_RADIO_SETPARAM,&z) == -1)
14585 {
14586 ast_log(LOG_ERROR,"Cannot set UIOMODE\n");
14587 return -1;
14588 }
14589 z.radpar = DAHDI_RADPAR_UIODATA;
14590 z.data = 3;
14591 if (ioctl(myrpt->dahditxchannel->fds[0],DAHDI_RADIO_SETPARAM,&z) == -1)
14592 {
14593 ast_log(LOG_ERROR,"Cannot set UIODATA\n");
14594 return -1;
14595 }
14596 i = DAHDI_OFFHOOK;
14597 if (ioctl(myrpt->dahditxchannel->fds[0],DAHDI_HOOK,&i) == -1)
14598 {
14599 ast_log(LOG_ERROR,"Cannot set hook\n");
14600 return -1;
14601 }
14602 }
14603 if (myrpt->iofd) close(myrpt->iofd);
14604 myrpt->iofd = -1;
14605 ast_hangup(myrpt->pchannel);
14606 if (myrpt->rxchannel != myrpt->txchannel) ast_hangup(myrpt->txchannel);
14607 ast_hangup(myrpt->rxchannel);
14608 closerem(myrpt);
14609 if (myrpt->p.rptnode)
14610 {
14611 rpt_mutex_lock(&myrpt->lock);
14612 for(i = 0; i < nrpts; i++)
14613 {
14614 if (!strcasecmp(rpt_vars[i].name,myrpt->p.rptnode))
14615 {
14616 rpt_vars[i].xlink = 0;
14617 break;
14618 }
14619 }
14620 rpt_mutex_unlock(&myrpt->lock);
14621 }
14622 #ifdef OLD_ASTERISK
14623 LOCAL_USER_REMOVE(u);
14624 #endif
14625 return res;
14626 }
14627
14628 #ifndef OLD_ASTERISK
14629
14630
14631
14632 static int manager_rpt_local_nodes(struct mansession *s, const struct message *m)
14633 {
14634 int i;
14635 astman_append(s, "<?xml version=\"1.0\"?>\r\n");
14636 astman_append(s, "<nodes>\r\n");
14637 for (i=0; i< nrpts; i++)
14638 {
14639 astman_append(s, " <node>%s</node>\r\n", rpt_vars[i].name);
14640 }
14641 astman_append(s, "</nodes>\r\n");
14642 astman_append(s, "\r\n");
14643 return RESULT_SUCCESS;
14644 }
14645
14646
14647
14648
14649
14650
14651
14652 static void rpt_manager_success(struct mansession *s, const struct message *m)
14653 {
14654 const char *id = astman_get_header(m, "ActionID");
14655 if (!ast_strlen_zero(id))
14656 astman_append(s, "ActionID: %s\r\n", id);
14657 astman_append(s, "Response: Success\r\n");
14658 }
14659
14660
14661
14662
14663
14664 static int rpt_manager_do_stats(struct mansession *s, const struct message *m, char *str)
14665 {
14666 int i,j,numoflinks;
14667 int dailytxtime, dailykerchunks;
14668 time_t now;
14669 int totalkerchunks, dailykeyups, totalkeyups, timeouts;
14670 int totalexecdcommands, dailyexecdcommands, hours, minutes, seconds;
14671 long long totaltxtime;
14672 struct rpt_link *l;
14673 char *listoflinks[MAX_STAT_LINKS];
14674 char *lastdtmfcommand,*parrot_ena;
14675 char *tot_state, *ider_state, *patch_state;
14676 char *reverse_patch_state, *sys_ena, *tot_ena, *link_ena, *patch_ena;
14677 char *sch_ena, *input_signal, *called_number, *user_funs, *tail_type;
14678 char *transmitterkeyed;
14679 const char *node = astman_get_header(m, "Node");
14680 struct rpt *myrpt;
14681
14682 static char *not_applicable = "N/A";
14683
14684 tot_state = ider_state =
14685 patch_state = reverse_patch_state =
14686 input_signal = not_applicable;
14687 called_number = lastdtmfcommand = transmitterkeyed = NULL;
14688
14689 time(&now);
14690 for(i = 0; i < nrpts; i++)
14691 {
14692 if ((node)&&(!strcmp(node,rpt_vars[i].name))){
14693 rpt_manager_success(s,m);
14694
14695 myrpt = &rpt_vars[i];
14696
14697 if(myrpt->remote){
14698 char *loginuser, *loginlevel, *freq, *rxpl, *txpl, *modestr;
14699 char offset = 0, powerlevel = 0, rxplon = 0, txplon = 0, remoteon, remmode = 0, reportfmstuff;
14700 char offsetc,powerlevelc;
14701
14702 loginuser = loginlevel = freq = rxpl = txpl = NULL;
14703
14704 rpt_mutex_lock(&myrpt->lock);
14705 if((remoteon = myrpt->remoteon)){
14706 if(!ast_strlen_zero(myrpt->loginuser))
14707 loginuser = ast_strdup(myrpt->loginuser);
14708 if(!ast_strlen_zero(myrpt->loginlevel))
14709 loginlevel = ast_strdup(myrpt->loginlevel);
14710 if(!ast_strlen_zero(myrpt->freq))
14711 freq = ast_strdup(myrpt->freq);
14712 if(!ast_strlen_zero(myrpt->rxpl))
14713 rxpl = ast_strdup(myrpt->rxpl);
14714 if(!ast_strlen_zero(myrpt->txpl))
14715 txpl = ast_strdup(myrpt->txpl);
14716 remmode = myrpt->remmode;
14717 offset = myrpt->offset;
14718 powerlevel = myrpt->powerlevel;
14719 rxplon = myrpt->rxplon;
14720 txplon = myrpt->txplon;
14721 }
14722 rpt_mutex_unlock(&myrpt->lock);
14723 astman_append(s, "IsRemoteBase: YES\r\n");
14724 astman_append(s, "RemoteOn: %s\r\n",(remoteon) ? "YES": "NO");
14725 if(remoteon){
14726 if(loginuser){
14727 astman_append(s, "LogInUser: %s\r\n", loginuser);
14728 ast_free(loginuser);
14729 }
14730 if(loginlevel){
14731 astman_append(s, "LogInLevel: %s\r\n", loginlevel);
14732 ast_free(loginlevel);
14733 }
14734 if(freq){
14735 astman_append(s, "Freq: %s\r\n", freq);
14736 ast_free(freq);
14737 }
14738 reportfmstuff = 0;
14739 switch(remmode){
14740 case REM_MODE_FM:
14741 modestr = "FM";
14742 reportfmstuff = 1;
14743 break;
14744 case REM_MODE_AM:
14745 modestr = "AM";
14746 break;
14747 case REM_MODE_USB:
14748 modestr = "USB";
14749 break;
14750 default:
14751 modestr = "LSB";
14752 break;
14753 }
14754 astman_append(s, "RemMode: %s\r\n", modestr);
14755 if(reportfmstuff){
14756 switch(offset){
14757 case REM_SIMPLEX:
14758 offsetc = 'S';
14759 break;
14760 case REM_MINUS:
14761 offsetc = '-';
14762 break;
14763 default:
14764 offsetc = '+';
14765 break;
14766 }
14767 astman_append(s, "RemOffset: %c\r\n", offsetc);
14768 if(rxplon && rxpl){
14769 astman_append(s, "RxPl: %s\r\n",rxpl);
14770 ast_free(rxpl);
14771 }
14772 if(txplon && txpl){
14773 astman_append(s, "TxPl: %s\r\n",txpl);
14774 ast_free(txpl);
14775 }
14776 }
14777 switch(powerlevel){
14778 case REM_LOWPWR:
14779 powerlevelc = 'L';
14780 break;
14781 case REM_MEDPWR:
14782 powerlevelc = 'M';
14783 break;
14784 default:
14785 powerlevelc = 'H';
14786 break;
14787 }
14788 astman_append(s,"PowerLevel: %c\r\n", powerlevelc);
14789 }
14790 astman_append(s, "\r\n");
14791 return 0;
14792 }
14793
14794
14795
14796 rpt_mutex_lock(&myrpt->lock);
14797 dailytxtime = myrpt->dailytxtime;
14798 totaltxtime = myrpt->totaltxtime;
14799 dailykeyups = myrpt->dailykeyups;
14800 totalkeyups = myrpt->totalkeyups;
14801 dailykerchunks = myrpt->dailykerchunks;
14802 totalkerchunks = myrpt->totalkerchunks;
14803 dailyexecdcommands = myrpt->dailyexecdcommands;
14804 totalexecdcommands = myrpt->totalexecdcommands;
14805 timeouts = myrpt->timeouts;
14806
14807
14808
14809 reverse_patch_state = "DOWN";
14810 numoflinks = 0;
14811 l = myrpt->links.next;
14812 while(l && (l != &myrpt->links)){
14813 if(numoflinks >= MAX_STAT_LINKS){
14814 ast_log(LOG_NOTICE,
14815 "maximum number of links exceeds %d in rpt_do_stats()!",MAX_STAT_LINKS);
14816 break;
14817 }
14818 if (l->name[0] == '0'){
14819 reverse_patch_state = "UP";
14820 l = l->next;
14821 continue;
14822 }
14823 listoflinks[numoflinks] = ast_strdup(l->name);
14824 if(listoflinks[numoflinks] == NULL){
14825 break;
14826 }
14827 else{
14828 numoflinks++;
14829 }
14830 l = l->next;
14831 }
14832
14833 if(myrpt->keyed)
14834 input_signal = "YES";
14835 else
14836 input_signal = "NO";
14837
14838 if(myrpt->txkeyed)
14839 transmitterkeyed = "YES";
14840 else
14841 transmitterkeyed = "NO";
14842
14843 if(myrpt->p.parrotmode)
14844 parrot_ena = "ENABLED";
14845 else
14846 parrot_ena = "DISABLED";
14847
14848 if(myrpt->p.s[myrpt->p.sysstate_cur].txdisable)
14849 sys_ena = "DISABLED";
14850 else
14851 sys_ena = "ENABLED";
14852
14853 if(myrpt->p.s[myrpt->p.sysstate_cur].totdisable)
14854 tot_ena = "DISABLED";
14855 else
14856 tot_ena = "ENABLED";
14857
14858 if(myrpt->p.s[myrpt->p.sysstate_cur].linkfundisable)
14859 link_ena = "DISABLED";
14860 else
14861 link_ena = "ENABLED";
14862
14863 if(myrpt->p.s[myrpt->p.sysstate_cur].autopatchdisable)
14864 patch_ena = "DISABLED";
14865 else
14866 patch_ena = "ENABLED";
14867
14868 if(myrpt->p.s[myrpt->p.sysstate_cur].schedulerdisable)
14869 sch_ena = "DISABLED";
14870 else
14871 sch_ena = "ENABLED";
14872
14873 if(myrpt->p.s[myrpt->p.sysstate_cur].userfundisable)
14874 user_funs = "DISABLED";
14875 else
14876 user_funs = "ENABLED";
14877
14878 if(myrpt->p.s[myrpt->p.sysstate_cur].alternatetail)
14879 tail_type = "ALTERNATE";
14880 else
14881 tail_type = "STANDARD";
14882
14883 if(!myrpt->totimer)
14884 tot_state = "TIMED OUT!";
14885 else if(myrpt->totimer != myrpt->p.totime)
14886 tot_state = "ARMED";
14887 else
14888 tot_state = "RESET";
14889
14890 if(myrpt->tailid)
14891 ider_state = "QUEUED IN TAIL";
14892 else if(myrpt->mustid)
14893 ider_state = "QUEUED FOR CLEANUP";
14894 else
14895 ider_state = "CLEAN";
14896
14897 switch(myrpt->callmode){
14898 case 1:
14899 patch_state = "DIALING";
14900 break;
14901 case 2:
14902 patch_state = "CONNECTING";
14903 break;
14904 case 3:
14905 patch_state = "UP";
14906 break;
14907
14908 case 4:
14909 patch_state = "CALL FAILED";
14910 break;
14911
14912 default:
14913 patch_state = "DOWN";
14914 }
14915
14916 if(strlen(myrpt->exten)){
14917 called_number = ast_strdup(myrpt->exten);
14918 }
14919
14920 if(strlen(myrpt->lastdtmfcommand)){
14921 lastdtmfcommand = ast_strdup(myrpt->lastdtmfcommand);
14922 }
14923 rpt_mutex_unlock(&myrpt->lock);
14924
14925 astman_append(s, "IsRemoteBase: NO\r\n");
14926 astman_append(s, "NodeState: %d\r\n", myrpt->p.sysstate_cur);
14927 astman_append(s, "SignalOnInput: %s\r\n", input_signal);
14928 astman_append(s, "TransmitterKeyed: %s\r\n", transmitterkeyed);
14929 astman_append(s, "Transmitter: %s\r\n", sys_ena);
14930 astman_append(s, "Parrot: %s\r\n", parrot_ena);
14931 astman_append(s, "Scheduler: %s\r\n", sch_ena);
14932 astman_append(s, "TailLength: %s\r\n", tail_type);
14933 astman_append(s, "TimeOutTimer: %s\r\n", tot_ena);
14934 astman_append(s, "TimeOutTimerState: %s\r\n", tot_state);
14935 astman_append(s, "TimeOutsSinceSystemInitialization: %d\r\n", timeouts);
14936 astman_append(s, "IdentifierState: %s\r\n", ider_state);
14937 astman_append(s, "KerchunksToday: %d\r\n", dailykerchunks);
14938 astman_append(s, "KerchunksSinceSystemInitialization: %d\r\n", totalkerchunks);
14939 astman_append(s, "KeyupsToday: %d\r\n", dailykeyups);
14940 astman_append(s, "KeyupsSinceSystemInitialization: %d\r\n", totalkeyups);
14941 astman_append(s, "DtmfCommandsToday: %d\r\n", dailyexecdcommands);
14942 astman_append(s, "DtmfCommandsSinceSystemInitialization: %d\r\n", totalexecdcommands);
14943 astman_append(s, "LastDtmfCommandExecuted: %s\r\n",
14944 (lastdtmfcommand && strlen(lastdtmfcommand)) ? lastdtmfcommand : not_applicable);
14945 hours = dailytxtime/3600000;
14946 dailytxtime %= 3600000;
14947 minutes = dailytxtime/60000;
14948 dailytxtime %= 60000;
14949 seconds = dailytxtime/1000;
14950 dailytxtime %= 1000;
14951
14952 astman_append(s, "TxTimeToday: %02d:%02d:%02d.%d\r\n",
14953 hours, minutes, seconds, dailytxtime);
14954
14955 hours = (int) totaltxtime/3600000;
14956 totaltxtime %= 3600000;
14957 minutes = (int) totaltxtime/60000;
14958 totaltxtime %= 60000;
14959 seconds = (int) totaltxtime/1000;
14960 totaltxtime %= 1000;
14961
14962 astman_append(s, "TxTimeSinceSystemInitialization: %02d:%02d:%02d.%d\r\n",
14963 hours, minutes, seconds, (int) totaltxtime);
14964
14965 sprintf(str, "NodesCurrentlyConnectedToUs: ");
14966 if(!numoflinks){
14967 strcat(str,"<NONE>");
14968 }
14969 else{
14970 for(j = 0 ;j < numoflinks; j++){
14971 sprintf(str+strlen(str), "%s", listoflinks[j]);
14972 if(j < numoflinks - 1)
14973 strcat(str,",");
14974 }
14975 }
14976 astman_append(s,"%s\r\n", str);
14977
14978 astman_append(s, "Autopatch: %s\r\n", patch_ena);
14979 astman_append(s, "AutopatchState: %s\r\n", patch_state);
14980 astman_append(s, "AutopatchCalledNumber: %s\r\n",
14981 (called_number && strlen(called_number)) ? called_number : not_applicable);
14982 astman_append(s, "ReversePatchIaxrptConnected: %s\r\n", reverse_patch_state);
14983 astman_append(s, "UserLinkingCommands: %s\r\n", link_ena);
14984 astman_append(s, "UserFunctions: %s\r\n", user_funs);
14985
14986 for(j = 0; j < numoflinks; j++){
14987 ast_free(listoflinks[j]);
14988 }
14989 if(called_number){
14990 ast_free(called_number);
14991 }
14992 if(lastdtmfcommand){
14993 ast_free(lastdtmfcommand);
14994 }
14995 astman_append(s, "\r\n");
14996 return 0;
14997 }
14998 }
14999 astman_send_error(s, m, "RptStatus unknown or missing node");
15000 return -1;
15001 }
15002
15003
15004
15005
15006
15007
15008
15009 static int manager_rpt_status(struct mansession *s, const struct message *m)
15010 {
15011 int i,res,len,idx;
15012 int uptime,hours,minutes;
15013 time_t now;
15014 const char *cmd = astman_get_header(m, "Command");
15015 char *str;
15016 enum {MGRCMD_RPTSTAT,MGRCMD_NODESTAT};
15017 struct mgrcmdtbl{
15018 const char *cmd;
15019 int index;
15020 };
15021 static struct mgrcmdtbl mct[] = {
15022 {"RptStat",MGRCMD_RPTSTAT},
15023 {"NodeStat",MGRCMD_NODESTAT},
15024 {NULL,0}
15025 };
15026
15027 time(&now);
15028
15029 len = 1024;
15030 if(!(str = ast_malloc(len)))
15031 return -1;
15032
15033
15034 if(ast_strlen_zero(cmd)){
15035 astman_send_error(s, m, "RptStatus missing command");
15036 ast_free(str);
15037 return 0;
15038 }
15039
15040 for(i = 0 ; mct[i].cmd ; i++){
15041 if(!strcmp(mct[i].cmd, cmd))
15042 break;
15043 }
15044
15045 if(!mct[i].cmd){
15046 astman_send_error(s, m, "RptStatus unknown command");
15047 ast_free(str);
15048 return 0;
15049 }
15050 else
15051 idx = mct[i].index;
15052
15053 switch(idx){
15054
15055 case MGRCMD_RPTSTAT:
15056
15057 if((res = snprintf(str, len, "Nodes: ")) > -1)
15058 len -= res;
15059 else{
15060 ast_free(str);
15061 return 0;
15062 }
15063 for(i = 0; i < nrpts; i++){
15064 if(i < nrpts - 1){
15065 if((res = snprintf(str+strlen(str), len, "%s,",rpt_vars[i].name)) < 0){
15066 ast_free(str);
15067 return 0;
15068 }
15069 }
15070 else{
15071 if((res = snprintf(str+strlen(str), len, "%s",rpt_vars[i].name)) < 0){
15072 ast_free(str);
15073 return 0;
15074 }
15075 }
15076 len -= res;
15077 }
15078
15079 rpt_manager_success(s,m);
15080
15081 if(!nrpts)
15082 astman_append(s, "<NONE>\r\n");
15083 else
15084 astman_append(s, "%s\r\n", str);
15085
15086 uptime = (int)(now - starttime);
15087 hours = uptime/3600;
15088 uptime %= 3600;
15089 minutes = uptime/60;
15090 uptime %= 60;
15091
15092 astman_append(s, "RptUptime: %02d:%02d:%02d\r\n",
15093 hours, minutes, uptime);
15094
15095 astman_append(s, "\r\n");
15096 break;
15097
15098 case MGRCMD_NODESTAT:
15099 res = rpt_manager_do_stats(s,m,str);
15100 ast_free(str);
15101 return res;
15102
15103 default:
15104 astman_send_error(s, m, "RptStatus invalid command");
15105 break;
15106 }
15107 ast_free(str);
15108 return 0;
15109 }
15110
15111 #endif
15112
15113 #ifdef OLD_ASTERISK
15114 int unload_module()
15115 #else
15116 static int unload_module(void)
15117 #endif
15118 {
15119 int i, res;
15120
15121 #ifdef OLD_ASTERISK
15122 STANDARD_HANGUP_LOCALUSERS;
15123 #endif
15124 for(i = 0; i < nrpts; i++) {
15125 if (!strcmp(rpt_vars[i].name,rpt_vars[i].p.nodes)) continue;
15126 ast_mutex_destroy(&rpt_vars[i].lock);
15127 ast_mutex_destroy(&rpt_vars[i].remlock);
15128 }
15129 res = ast_unregister_application(app);
15130
15131 #ifdef NEW_ASTERISK
15132 ast_cli_unregister_multiple(rpt_cli, ARRAY_LEN(rpt_cli));
15133 #else
15134
15135 ast_cli_unregister(&cli_debug);
15136 ast_cli_unregister(&cli_dump);
15137 ast_cli_unregister(&cli_stats);
15138 ast_cli_unregister(&cli_lstats);
15139 ast_cli_unregister(&cli_nodes);
15140 ast_cli_unregister(&cli_local_nodes);
15141 ast_cli_unregister(&cli_reload);
15142 ast_cli_unregister(&cli_restart);
15143 ast_cli_unregister(&cli_fun);
15144 ast_cli_unregister(&cli_fun1);
15145 res |= ast_cli_unregister(&cli_cmd);
15146 #endif
15147 #ifndef OLD_ASTERISK
15148 res |= ast_manager_unregister("RptLocalNodes");
15149 res |= ast_manager_unregister("RptStatus");
15150 #endif
15151 return res;
15152 }
15153
15154 #ifdef OLD_ASTERISK
15155 int load_module()
15156 #else
15157 static int load_module(void)
15158 #endif
15159 {
15160 int res;
15161 ast_pthread_create(&rpt_master_thread,NULL,rpt_master,NULL);
15162
15163 #ifdef NEW_ASTERISK
15164 ast_cli_register_multiple(rpt_cli, ARRAY_LEN(rpt_cli));
15165 res = 0;
15166 #else
15167
15168 ast_cli_register(&cli_debug);
15169 ast_cli_register(&cli_dump);
15170 ast_cli_register(&cli_stats);
15171 ast_cli_register(&cli_lstats);
15172 ast_cli_register(&cli_nodes);
15173 ast_cli_register(&cli_local_nodes);
15174 ast_cli_register(&cli_reload);
15175 ast_cli_register(&cli_restart);
15176 ast_cli_register(&cli_fun);
15177 ast_cli_register(&cli_fun1);
15178 res = ast_cli_register(&cli_cmd);
15179 #endif
15180 #ifndef OLD_ASTERISK
15181 res |= ast_manager_register("RptLocalNodes", 0, manager_rpt_local_nodes, "List local node numbers");
15182 res |= ast_manager_register("RptStatus", 0, manager_rpt_status, "Return Rpt Status for CGI");
15183
15184 #endif
15185 res |= ast_register_application(app, rpt_exec, synopsis, descrip);
15186 return res;
15187 }
15188
15189 #ifdef OLD_ASTERISK
15190 char *description()
15191 {
15192 return tdesc;
15193 }
15194 int usecount(void)
15195 {
15196 int res;
15197 STANDARD_USECOUNT(res);
15198 return res;
15199 }
15200
15201 char *key()
15202 {
15203 return ASTERISK_GPL_KEY;
15204 }
15205 #endif
15206
15207 #ifdef OLD_ASTERISK
15208 int reload()
15209 #else
15210 static int reload(void)
15211 #endif
15212 {
15213 int n;
15214
15215 for(n = 0; n < nrpts; n++) rpt_vars[n].reload = 1;
15216 return(0);
15217 }
15218
15219
15220 #ifndef OLD_ASTERISK
15221
15222 AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_DEFAULT, "Radio Repeater/Remote Base Application",
15223 .load = load_module,
15224 .unload = unload_module,
15225 .reload = reload,
15226 );
15227 #endif
15228