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: 211569 $")
00318
00319 #include <signal.h>
00320 #include <stdio.h>
00321 #include <stdint.h>
00322 #include <unistd.h>
00323 #include <string.h>
00324 #include <stdlib.h>
00325 #include <search.h>
00326 #include <sys/types.h>
00327 #include <sys/stat.h>
00328 #include <errno.h>
00329 #include <dirent.h>
00330 #include <ctype.h>
00331 #include <sys/stat.h>
00332 #include <sys/time.h>
00333 #include <sys/file.h>
00334 #include <sys/ioctl.h>
00335 #ifdef HAVE_SYS_IO_H
00336 #include <sys/io.h>
00337 #endif
00338 #include <sys/vfs.h>
00339 #include <math.h>
00340 #include <dahdi/user.h>
00341 #include <dahdi/tonezone.h>
00342 #include <netinet/in.h>
00343 #include <arpa/inet.h>
00344
00345 #include "asterisk/utils.h"
00346 #include "asterisk/lock.h"
00347 #include "asterisk/file.h"
00348 #include "asterisk/logger.h"
00349 #include "asterisk/channel.h"
00350 #include "asterisk/callerid.h"
00351 #include "asterisk/pbx.h"
00352 #include "asterisk/module.h"
00353 #include "asterisk/translate.h"
00354 #include "asterisk/features.h"
00355 #include "asterisk/options.h"
00356 #include "asterisk/cli.h"
00357 #include "asterisk/config.h"
00358 #include "asterisk/say.h"
00359 #include "asterisk/localtime.h"
00360 #include "asterisk/cdr.h"
00361 #include "asterisk/options.h"
00362 #include "asterisk/manager.h"
00363 #include "asterisk/app.h"
00364
00365 #include <termios.h>
00366
00367 #ifdef NEW_ASTERISK
00368 struct ast_flags config_flags = { CONFIG_FLAG_WITHCOMMENTS };
00369 #endif
00370
00371
00372
00373 int ast_playtones_start(struct ast_channel *chan, int vol, const char* tonelist, int interruptible);
00374
00375 void ast_playtones_stop(struct ast_channel *chan);
00376
00377 static char *tdesc = "Radio Repeater / Remote Base version 0.115 5/12/2008";
00378
00379 static char *app = "Rpt";
00380
00381 static char *synopsis = "Radio Repeater/Remote Base Control System";
00382
00383 static char *descrip =
00384 " Rpt(nodename[|options][|M][|*]): \n"
00385 " Radio Remote Link or Remote Base Link Endpoint Process.\n"
00386 "\n"
00387 " Not specifying an option puts it in normal endpoint mode (where source\n"
00388 " IP and nodename are verified).\n"
00389 "\n"
00390 " Options are as follows:\n"
00391 "\n"
00392 " X - Normal endpoint mode WITHOUT security check. Only specify\n"
00393 " this if you have checked security already (like with an IAX2\n"
00394 " user/password or something).\n"
00395 "\n"
00396 " Rannounce-string[|timeout[|timeout-destination]] - Amateur Radio\n"
00397 " Reverse Autopatch. Caller is put on hold, and announcement (as\n"
00398 " specified by the 'announce-string') is played on radio system.\n"
00399 " Users of radio system can access autopatch, dial specified\n"
00400 " code, and pick up call. Announce-string is list of names of\n"
00401 " recordings, or \"PARKED\" to substitute code for un-parking,\n"
00402 " or \"NODE\" to substitute node number.\n"
00403 "\n"
00404 " P - Phone Control mode. This allows a regular phone user to have\n"
00405 " full control and audio access to the radio system. For the\n"
00406 " user to have DTMF control, the 'phone_functions' parameter\n"
00407 " must be specified for the node in 'rpt.conf'. An additional\n"
00408 " function (cop,6) must be listed so that PTT control is available.\n"
00409 "\n"
00410 " D - Dumb Phone Control mode. This allows a regular phone user to\n"
00411 " have full control and audio access to the radio system. In this\n"
00412 " mode, the PTT is activated for the entire length of the call.\n"
00413 " For the user to have DTMF control (not generally recomended in\n"
00414 " this mode), the 'dphone_functions' parameter must be specified\n"
00415 " for the node in 'rpt.conf'. Otherwise no DTMF control will be\n"
00416 " available to the phone user.\n"
00417 "\n"
00418 " S - Simplex Dumb Phone Control mode. This allows a regular phone user\n"
00419 " audio-only access to the radio system. In this mode, the\n"
00420 " transmitter is toggled on and off when the phone user presses the\n"
00421 " funcchar (*) key on the telephone set. In addition, the transmitter\n"
00422 " will turn off if the endchar (#) key is pressed. When a user first\n"
00423 " calls in, the transmitter will be off, and the user can listen for\n"
00424 " radio traffic. When the user wants to transmit, they press the *\n"
00425 " key, start talking, then press the * key again or the # key to turn\n"
00426 " the transmitter off. No other functions can be executed by the\n"
00427 " user on the phone when this mode is selected. Note: If your\n"
00428 " radio system is full-duplex, we recommend using either P or D\n"
00429 " modes as they provide more flexibility.\n"
00430 "\n"
00431 " q - Query Status. Sets channel variables and returns + 101 in plan.\n"
00432 "\n"
00433 " M - Memory Channel Steer as MXX where XX is the memory channel number.\n"
00434 "\n"
00435 " * - Alt Macro to execute (e.g. *7 for status)\n"
00436 "\n";
00437 ;
00438
00439 static int debug = 0;
00440 static int nrpts = 0;
00441
00442 static char remdtmfstr[] = "0123456789*#ABCD";
00443
00444 enum {TOP_TOP,TOP_WON,WON_BEFREAD,BEFREAD_AFTERREAD};
00445
00446 int max_chan_stat [] = {22000,1000,22000,100,22000,2000,22000};
00447
00448 #define NRPTSTAT 7
00449
00450 struct rpt_chan_stat
00451 {
00452 struct timeval last;
00453 long long total;
00454 unsigned long count;
00455 unsigned long largest;
00456 struct timeval largest_time;
00457 };
00458
00459 char *discstr = "!!DISCONNECT!!";
00460 char *newkeystr = "!NEWKEY!";
00461 static char *remote_rig_ft897="ft897";
00462 static char *remote_rig_rbi="rbi";
00463 static char *remote_rig_kenwood="kenwood";
00464 static char *remote_rig_tm271="tm271";
00465 static char *remote_rig_ic706="ic706";
00466 static char *remote_rig_rtx150="rtx150";
00467 static char *remote_rig_rtx450="rtx450";
00468 static char *remote_rig_ppp16="ppp16";
00469
00470 #define ISRIG_RTX(x) ((!strcmp(x,remote_rig_rtx150)) || (!strcmp(x,remote_rig_rtx450)))
00471 #define IS_XPMR(x) (!strncasecmp(x->rxchanname,"rad",3))
00472
00473 #ifdef OLD_ASTERISK
00474 STANDARD_LOCAL_USER;
00475 LOCAL_USER_DECL;
00476 #endif
00477
00478 #define MSWAIT 200
00479 #define HANGTIME 5000
00480 #define TOTIME 180000
00481 #define IDTIME 300000
00482 #define MAXRPTS 20
00483 #define MAX_STAT_LINKS 32
00484 #define POLITEID 30000
00485 #define FUNCTDELAY 1500
00486
00487 #define MAXXLAT 20
00488 #define MAXXLATTIME 3
00489
00490 #define MAX_SYSSTATES 10
00491
00492 struct vox {
00493 float speech_energy;
00494 float noise_energy;
00495 int enacount;
00496 char voxena;
00497 char lastvox;
00498 int offdebcnt;
00499 int ondebcnt;
00500 } ;
00501
00502 #define mymax(x,y) ((x > y) ? x : y)
00503 #define mymin(x,y) ((x < y) ? x : y)
00504
00505 struct rpt_topkey
00506 {
00507 char node[TOPKEYMAXSTR];
00508 int timesince;
00509 int keyed;
00510 } ;
00511
00512 struct rpt_xlat
00513 {
00514 char funccharseq[MAXXLAT];
00515 char endcharseq[MAXXLAT];
00516 char passchars[MAXXLAT];
00517 int funcindex;
00518 int endindex;
00519 time_t lastone;
00520 } ;
00521
00522 static time_t starttime = 0;
00523
00524 static pthread_t rpt_master_thread;
00525
00526 struct rpt;
00527
00528 struct rpt_link
00529 {
00530 struct rpt_link *next;
00531 struct rpt_link *prev;
00532 char mode;
00533 char isremote;
00534 char phonemode;
00535 char phonevox;
00536 char name[MAXNODESTR];
00537 char lasttx;
00538 char lasttx1;
00539 char lastrx;
00540 char lastrealrx;
00541 char lastrx1;
00542 char connected;
00543 char hasconnected;
00544 char perma;
00545 char thisconnected;
00546 char outbound;
00547 char disced;
00548 char killme;
00549 long elaptime;
00550 long disctime;
00551 long retrytimer;
00552 long retxtimer;
00553 long rerxtimer;
00554 int retries;
00555 int max_retries;
00556 int reconnects;
00557 long long connecttime;
00558 struct ast_channel *chan;
00559 struct ast_channel *pchan;
00560 char linklist[MAXLINKLIST];
00561 time_t linklistreceived;
00562 long linklisttimer;
00563 int dtmfed;
00564 int linkunkeytocttimer;
00565 struct timeval lastlinktv;
00566 struct ast_frame *lastf1,*lastf2;
00567 struct rpt_chan_stat chan_stat[NRPTSTAT];
00568 struct vox vox;
00569 char wasvox;
00570 int voxtotimer;
00571 char voxtostate;
00572 char newkey;
00573 #ifdef OLD_ASTERISK
00574 AST_LIST_HEAD(, ast_frame) rxq;
00575 #else
00576 AST_LIST_HEAD_NOLOCK(, ast_frame) rxq;
00577 #endif
00578 } ;
00579
00580 struct rpt_lstat
00581 {
00582 struct rpt_lstat *next;
00583 struct rpt_lstat *prev;
00584 char peer[MAXPEERSTR];
00585 char name[MAXNODESTR];
00586 char mode;
00587 char outbound;
00588 char reconnects;
00589 char thisconnected;
00590 long long connecttime;
00591 struct rpt_chan_stat chan_stat[NRPTSTAT];
00592 } ;
00593
00594 struct rpt_tele
00595 {
00596 struct rpt_tele *next;
00597 struct rpt_tele *prev;
00598 struct rpt *rpt;
00599 struct ast_channel *chan;
00600 int mode;
00601 struct rpt_link mylink;
00602 char param[TELEPARAMSIZE];
00603 intptr_t submode;
00604 uintptr_t parrot;
00605 pthread_t threadid;
00606 } ;
00607
00608 struct function_table_tag
00609 {
00610 char action[ACTIONSIZE];
00611 int (*function)(struct rpt *myrpt, char *param, char *digitbuf,
00612 int command_source, struct rpt_link *mylink);
00613 } ;
00614
00615
00616
00617 struct morse_bits
00618 {
00619 int len;
00620 int ddcomb;
00621 } ;
00622
00623 struct telem_defaults
00624 {
00625 char name[20];
00626 char value[80];
00627 } ;
00628
00629
00630 struct sysstate
00631 {
00632 char txdisable;
00633 char totdisable;
00634 char linkfundisable;
00635 char autopatchdisable;
00636 char schedulerdisable;
00637 char userfundisable;
00638 char alternatetail;
00639 };
00640
00641
00642 #define CMD_DEPTH 1
00643 #define CMD_STATE_IDLE 0
00644 #define CMD_STATE_BUSY 1
00645 #define CMD_STATE_READY 2
00646 #define CMD_STATE_EXECUTING 3
00647
00648 struct rpt_cmd_struct
00649 {
00650 int state;
00651 int functionNumber;
00652 char param[MAXDTMF];
00653 char digits[MAXDTMF];
00654 int command_source;
00655 };
00656
00657 static struct rpt
00658 {
00659 ast_mutex_t lock;
00660 ast_mutex_t remlock;
00661 ast_mutex_t statpost_lock;
00662 struct ast_config *cfg;
00663 char reload;
00664 char xlink;
00665 unsigned int statpost_seqno;
00666
00667 char *name;
00668 char *rxchanname;
00669 char *txchanname;
00670 char remote;
00671 char *remoterig;
00672 struct rpt_chan_stat chan_stat[NRPTSTAT];
00673 unsigned int scram;
00674
00675 struct {
00676 char *ourcontext;
00677 char *ourcallerid;
00678 char *acctcode;
00679 char *ident;
00680 char *tonezone;
00681 char simple;
00682 char *functions;
00683 char *link_functions;
00684 char *phone_functions;
00685 char *dphone_functions;
00686 char *alt_functions;
00687 char *nodes;
00688 char *extnodes;
00689 char *extnodefile;
00690 int hangtime;
00691 int althangtime;
00692 int totime;
00693 int idtime;
00694 int tailmessagetime;
00695 int tailsquashedtime;
00696 int duplex;
00697 int politeid;
00698 char *tailmessages[500];
00699 int tailmessagemax;
00700 char *memory;
00701 char *macro;
00702 char *tonemacro;
00703 char *startupmacro;
00704 int iobase;
00705 char *ioport;
00706 char funcchar;
00707 char endchar;
00708 char nobusyout;
00709 char notelemtx;
00710 char propagate_dtmf;
00711 char propagate_phonedtmf;
00712 char linktolink;
00713 unsigned char civaddr;
00714 struct rpt_xlat inxlat;
00715 struct rpt_xlat outxlat;
00716 char *archivedir;
00717 int authlevel;
00718 char *csstanzaname;
00719 char *skedstanzaname;
00720 char *txlimitsstanzaname;
00721 long monminblocks;
00722 int remoteinacttimeout;
00723 int remotetimeout;
00724 int remotetimeoutwarning;
00725 int remotetimeoutwarningfreq;
00726 int sysstate_cur;
00727 struct sysstate s[MAX_SYSSTATES];
00728 char parrotmode;
00729 int parrottime;
00730 char *rptnode;
00731 char remote_mars;
00732 int voxtimeout_ms;
00733 int voxrecover_ms;
00734 int simplexpatchdelay;
00735 int simplexphonedelay;
00736 char *statpost_program;
00737 char *statpost_url;
00738 } p;
00739 struct rpt_link links;
00740 int unkeytocttimer;
00741 time_t lastkeyedtime;
00742 time_t lasttxkeyedtime;
00743 char keyed;
00744 char txkeyed;
00745 char exttx;
00746 char localtx;
00747 char remoterx;
00748 char remotetx;
00749 char remoteon;
00750 char remtxfreqok;
00751 char tounkeyed;
00752 char tonotify;
00753 char dtmfbuf[MAXDTMF];
00754 char macrobuf[MAXMACRO];
00755 char rem_dtmfbuf[MAXDTMF];
00756 char lastdtmfcommand[MAXDTMF];
00757 char cmdnode[50];
00758 char nowchan;
00759 char waschan;
00760 char bargechan;
00761 char macropatch;
00762 char parrotstate;
00763 int parrottimer;
00764 unsigned int parrotcnt;
00765 struct ast_channel *rxchannel,*txchannel, *monchannel, *parrotchannel;
00766 struct ast_channel *pchannel,*txpchannel, *dahdirxchannel, *dahditxchannel;
00767 struct ast_channel *voxchannel;
00768 struct ast_frame *lastf1,*lastf2;
00769 struct rpt_tele tele;
00770 struct timeval lasttv,curtv;
00771 pthread_t rpt_call_thread,rpt_thread;
00772 time_t dtmf_time,rem_dtmf_time,dtmf_time_rem;
00773 int calldigittimer;
00774 int tailtimer,totimer,idtimer,txconf,conf,callmode,cidx,scantimer,tmsgtimer,skedtimer;
00775 int mustid,tailid;
00776 int tailevent;
00777 int telemrefcount;
00778 int dtmfidx,rem_dtmfidx;
00779 int dailytxtime,dailykerchunks,totalkerchunks,dailykeyups,totalkeyups,timeouts;
00780 int totalexecdcommands, dailyexecdcommands;
00781 long retxtimer;
00782 long rerxtimer;
00783 long long totaltxtime;
00784 char mydtmf;
00785 char exten[AST_MAX_EXTENSION];
00786 char freq[MAXREMSTR],rxpl[MAXREMSTR],txpl[MAXREMSTR];
00787 char offset;
00788 char powerlevel;
00789 char txplon;
00790 char rxplon;
00791 char remmode;
00792 char tunerequest;
00793 char hfscanmode;
00794 int hfscanstatus;
00795 char hfscanstop;
00796 char lastlinknode[MAXNODESTR];
00797 char savednodes[MAXNODESTR];
00798 int stopgen;
00799 char patchfarenddisconnect;
00800 char patchnoct;
00801 char patchquiet;
00802 char patchcontext[MAXPATCHCONTEXT];
00803 int patchdialtime;
00804 int macro_longest;
00805 int phone_longestfunc;
00806 int alt_longestfunc;
00807 int dphone_longestfunc;
00808 int link_longestfunc;
00809 int longestfunc;
00810 int longestnode;
00811 int threadrestarts;
00812 int tailmessagen;
00813 time_t disgorgetime;
00814 time_t lastthreadrestarttime;
00815 long macrotimer;
00816 char lastnodewhichkeyedusup[MAXNODESTR];
00817 int dtmf_local_timer;
00818 char dtmf_local_str[100];
00819 struct ast_filestream *monstream,*parrotstream;
00820 char loginuser[50];
00821 char loginlevel[10];
00822 long authtelltimer;
00823 long authtimer;
00824 int iofd;
00825 time_t start_time,last_activity_time;
00826 char lasttone[32];
00827 struct rpt_tele *active_telem;
00828 struct rpt_topkey topkey[TOPKEYN];
00829 int topkeystate;
00830 time_t topkeytime;
00831 int topkeylong;
00832 struct vox vox;
00833 char wasvox;
00834 int voxtotimer;
00835 char voxtostate;
00836 int linkposttimer;
00837 int keyposttimer;
00838 char newkey;
00839 char inpadtest;
00840 #ifdef OLD_ASTERISK
00841 AST_LIST_HEAD(, ast_frame) txq;
00842 #else
00843 AST_LIST_HEAD_NOLOCK(, ast_frame) txq;
00844 #endif
00845 char txrealkeyed;
00846 #ifdef __RPT_NOTCH
00847 struct rptfilter
00848 {
00849 char desc[100];
00850 float x0;
00851 float x1;
00852 float x2;
00853 float y0;
00854 float y1;
00855 float y2;
00856 float gain;
00857 float const0;
00858 float const1;
00859 float const2;
00860 } filters[MAXFILTERS];
00861 #endif
00862 #ifdef _MDC_DECODE_H_
00863 mdc_decoder_t *mdc;
00864 unsigned short lastunit;
00865 #endif
00866 struct rpt_cmd_struct cmdAction;
00867 } rpt_vars[MAXRPTS];
00868
00869 struct nodelog {
00870 struct nodelog *next;
00871 struct nodelog *prev;
00872 time_t timestamp;
00873 char archivedir[MAXNODESTR];
00874 char str[MAXNODESTR * 2];
00875 } nodelog;
00876
00877 static int service_scan(struct rpt *myrpt);
00878 static int set_mode_ft897(struct rpt *myrpt, char newmode);
00879 static int set_mode_ic706(struct rpt *myrpt, char newmode);
00880 static int simple_command_ft897(struct rpt *myrpt, char command);
00881 static int setrem(struct rpt *myrpt);
00882 static int setrtx_check(struct rpt *myrpt);
00883 static int channel_revert(struct rpt *myrpt);
00884 static int channel_steer(struct rpt *myrpt, char *data);
00885
00886 AST_MUTEX_DEFINE_STATIC(nodeloglock);
00887
00888 AST_MUTEX_DEFINE_STATIC(nodelookuplock);
00889
00890 #ifdef APP_RPT_LOCK_DEBUG
00891
00892 #warning COMPILING WITH LOCK-DEBUGGING ENABLED!!
00893
00894 #define MAXLOCKTHREAD 100
00895
00896 #define rpt_mutex_lock(x) _rpt_mutex_lock(x,myrpt,__LINE__)
00897 #define rpt_mutex_unlock(x) _rpt_mutex_unlock(x,myrpt,__LINE__)
00898
00899 struct lockthread
00900 {
00901 pthread_t id;
00902 int lockcount;
00903 int lastlock;
00904 int lastunlock;
00905 } lockthreads[MAXLOCKTHREAD];
00906
00907
00908 struct by_lightning
00909 {
00910 int line;
00911 struct timeval tv;
00912 struct rpt *rpt;
00913 struct lockthread lockthread;
00914 } lock_ring[32];
00915
00916 int lock_ring_index = 0;
00917
00918 AST_MUTEX_DEFINE_STATIC(locklock);
00919
00920 static struct lockthread *get_lockthread(pthread_t id)
00921 {
00922 int i;
00923
00924 for(i = 0; i < MAXLOCKTHREAD; i++)
00925 {
00926 if (lockthreads[i].id == id) return(&lockthreads[i]);
00927 }
00928 return(NULL);
00929 }
00930
00931 static struct lockthread *put_lockthread(pthread_t id)
00932 {
00933 int i;
00934
00935 for(i = 0; i < MAXLOCKTHREAD; i++)
00936 {
00937 if (lockthreads[i].id == id)
00938 return(&lockthreads[i]);
00939 }
00940 for(i = 0; i < MAXLOCKTHREAD; i++)
00941 {
00942 if (!lockthreads[i].id)
00943 {
00944 lockthreads[i].lockcount = 0;
00945 lockthreads[i].lastlock = 0;
00946 lockthreads[i].lastunlock = 0;
00947 lockthreads[i].id = id;
00948 return(&lockthreads[i]);
00949 }
00950 }
00951 return(NULL);
00952 }
00953
00954
00955 static void rpt_mutex_spew(void)
00956 {
00957 struct by_lightning lock_ring_copy[32];
00958 int lock_ring_index_copy;
00959 int i,j;
00960 long long diff;
00961 char a[100];
00962 struct timeval lasttv;
00963
00964 ast_mutex_lock(&locklock);
00965 memcpy(&lock_ring_copy, &lock_ring, sizeof(lock_ring_copy));
00966 lock_ring_index_copy = lock_ring_index;
00967 ast_mutex_unlock(&locklock);
00968
00969 lasttv.tv_sec = lasttv.tv_usec = 0;
00970 for(i = 0 ; i < 32 ; i++)
00971 {
00972 j = (i + lock_ring_index_copy) % 32;
00973 strftime(a,sizeof(a) - 1,"%m/%d/%Y %H:%M:%S",
00974 localtime(&lock_ring_copy[j].tv.tv_sec));
00975 diff = 0;
00976 if(lasttv.tv_sec)
00977 {
00978 diff = (lock_ring_copy[j].tv.tv_sec - lasttv.tv_sec)
00979 * 1000000;
00980 diff += (lock_ring_copy[j].tv.tv_usec - lasttv.tv_usec);
00981 }
00982 lasttv.tv_sec = lock_ring_copy[j].tv.tv_sec;
00983 lasttv.tv_usec = lock_ring_copy[j].tv.tv_usec;
00984 if (!lock_ring_copy[j].tv.tv_sec) continue;
00985 if (lock_ring_copy[j].line < 0)
00986 {
00987 ast_log(LOG_NOTICE,"LOCKDEBUG [#%d] UNLOCK app_rpt.c:%d node %s pid %x diff %lld us at %s.%06d\n",
00988 i - 31,-lock_ring_copy[j].line,lock_ring_copy[j].rpt->name,(int) lock_ring_copy[j].lockthread.id,diff,a,(int)lock_ring_copy[j].tv.tv_usec);
00989 }
00990 else
00991 {
00992 ast_log(LOG_NOTICE,"LOCKDEBUG [#%d] LOCK app_rpt.c:%d node %s pid %x diff %lld us at %s.%06d\n",
00993 i - 31,lock_ring_copy[j].line,lock_ring_copy[j].rpt->name,(int) lock_ring_copy[j].lockthread.id,diff,a,(int)lock_ring_copy[j].tv.tv_usec);
00994 }
00995 }
00996 }
00997
00998
00999 static void _rpt_mutex_lock(ast_mutex_t *lockp, struct rpt *myrpt, int line)
01000 {
01001 struct lockthread *t;
01002 pthread_t id;
01003
01004 id = pthread_self();
01005 ast_mutex_lock(&locklock);
01006 t = put_lockthread(id);
01007 if (!t)
01008 {
01009 ast_mutex_unlock(&locklock);
01010 return;
01011 }
01012 if (t->lockcount)
01013 {
01014 int lastline = t->lastlock;
01015 ast_mutex_unlock(&locklock);
01016 ast_log(LOG_NOTICE,"rpt_mutex_lock: Double lock request line %d node %s pid %x, last lock was line %d\n",line,myrpt->name,(int) t->id,lastline);
01017 rpt_mutex_spew();
01018 return;
01019 }
01020 t->lastlock = line;
01021 t->lockcount = 1;
01022 gettimeofday(&lock_ring[lock_ring_index].tv, NULL);
01023 lock_ring[lock_ring_index].rpt = myrpt;
01024 memcpy(&lock_ring[lock_ring_index].lockthread,t,sizeof(struct lockthread));
01025 lock_ring[lock_ring_index++].line = line;
01026 if(lock_ring_index == 32)
01027 lock_ring_index = 0;
01028 ast_mutex_unlock(&locklock);
01029 ast_mutex_lock(lockp);
01030 }
01031
01032
01033 static void _rpt_mutex_unlock(ast_mutex_t *lockp, struct rpt *myrpt, int line)
01034 {
01035 struct lockthread *t;
01036 pthread_t id;
01037
01038 id = pthread_self();
01039 ast_mutex_lock(&locklock);
01040 t = put_lockthread(id);
01041 if (!t)
01042 {
01043 ast_mutex_unlock(&locklock);
01044 return;
01045 }
01046 if (!t->lockcount)
01047 {
01048 int lastline = t->lastunlock;
01049 ast_mutex_unlock(&locklock);
01050 ast_log(LOG_NOTICE,"rpt_mutex_lock: Double un-lock request line %d node %s pid %x, last un-lock was line %d\n",line,myrpt->name,(int) t->id,lastline);
01051 rpt_mutex_spew();
01052 return;
01053 }
01054 t->lastunlock = line;
01055 t->lockcount = 0;
01056 gettimeofday(&lock_ring[lock_ring_index].tv, NULL);
01057 lock_ring[lock_ring_index].rpt = myrpt;
01058 memcpy(&lock_ring[lock_ring_index].lockthread,t,sizeof(struct lockthread));
01059 lock_ring[lock_ring_index++].line = -line;
01060 if(lock_ring_index == 32)
01061 lock_ring_index = 0;
01062 ast_mutex_unlock(&locklock);
01063 ast_mutex_unlock(lockp);
01064 }
01065
01066 #else
01067
01068 #define rpt_mutex_lock(x) ast_mutex_lock(x)
01069 #define rpt_mutex_unlock(x) ast_mutex_unlock(x)
01070
01071 #endif
01072
01073
01074
01075
01076
01077 static int multimode_capable(struct rpt *myrpt)
01078 {
01079 if(!strcmp(myrpt->remoterig, remote_rig_ft897))
01080 return 1;
01081 if(!strcmp(myrpt->remoterig, remote_rig_ic706))
01082 return 1;
01083 return 0;
01084 }
01085
01086 static void voxinit_rpt(struct rpt *myrpt,char enable)
01087 {
01088
01089 myrpt->vox.speech_energy = 0.0;
01090 myrpt->vox.noise_energy = 0.0;
01091 myrpt->vox.enacount = 0;
01092 myrpt->vox.voxena = 0;
01093 if (!enable) myrpt->vox.voxena = -1;
01094 myrpt->vox.lastvox = 0;
01095 myrpt->vox.ondebcnt = VOX_ON_DEBOUNCE_COUNT;
01096 myrpt->vox.offdebcnt = VOX_OFF_DEBOUNCE_COUNT;
01097 myrpt->wasvox = 0;
01098 myrpt->voxtotimer = 0;
01099 myrpt->voxtostate = 0;
01100 }
01101
01102 static void voxinit_link(struct rpt_link *mylink,char enable)
01103 {
01104
01105 mylink->vox.speech_energy = 0.0;
01106 mylink->vox.noise_energy = 0.0;
01107 mylink->vox.enacount = 0;
01108 mylink->vox.voxena = 0;
01109 if (!enable) mylink->vox.voxena = -1;
01110 mylink->vox.lastvox = 0;
01111 mylink->vox.ondebcnt = VOX_ON_DEBOUNCE_COUNT;
01112 mylink->vox.offdebcnt = VOX_OFF_DEBOUNCE_COUNT;
01113 mylink->wasvox = 0;
01114 mylink->voxtotimer = 0;
01115 mylink->voxtostate = 0;
01116 }
01117
01118 static int dovox(struct vox *v,short *buf,int bs)
01119 {
01120
01121 int i;
01122 float esquare = 0.0;
01123 float energy = 0.0;
01124 float threshold = 0.0;
01125
01126 if (v->voxena < 0) return(v->lastvox);
01127 for(i = 0; i < bs; i++)
01128 {
01129 esquare += (float) buf[i] * (float) buf[i];
01130 }
01131 energy = sqrt(esquare);
01132
01133 if (energy >= v->speech_energy)
01134 v->speech_energy += (energy - v->speech_energy) / 4;
01135 else
01136 v->speech_energy += (energy - v->speech_energy) / 64;
01137
01138 if (energy >= v->noise_energy)
01139 v->noise_energy += (energy - v->noise_energy) / 64;
01140 else
01141 v->noise_energy += (energy - v->noise_energy) / 4;
01142
01143 if (v->voxena) threshold = v->speech_energy / 8;
01144 else
01145 {
01146 threshold = mymax(v->speech_energy / 16,v->noise_energy * 2);
01147 threshold = mymin(threshold,VOX_MAX_THRESHOLD);
01148 }
01149 threshold = mymax(threshold,VOX_MIN_THRESHOLD);
01150 if (energy > threshold)
01151 {
01152 if (v->voxena) v->noise_energy *= 0.75;
01153 v->voxena = 1;
01154 } else v->voxena = 0;
01155 if (v->lastvox != v->voxena)
01156 {
01157 if (v->enacount++ >= ((v->lastvox) ? v->offdebcnt : v->ondebcnt))
01158 {
01159 v->lastvox = v->voxena;
01160 v->enacount = 0;
01161 }
01162 } else v->enacount = 0;
01163 return(v->lastvox);
01164 }
01165
01166
01167
01168
01169
01170
01171
01172
01173
01174 static int rpt_do_debug(int fd, int argc, char *argv[]);
01175 static int rpt_do_dump(int fd, int argc, char *argv[]);
01176 static int rpt_do_stats(int fd, int argc, char *argv[]);
01177 static int rpt_do_lstats(int fd, int argc, char *argv[]);
01178 static int rpt_do_nodes(int fd, int argc, char *argv[]);
01179 static int rpt_do_local_nodes(int fd, int argc, char *argv[]);
01180 static int rpt_do_reload(int fd, int argc, char *argv[]);
01181 static int rpt_do_restart(int fd, int argc, char *argv[]);
01182 static int rpt_do_fun(int fd, int argc, char *argv[]);
01183 static int rpt_do_fun1(int fd, int argc, char *argv[]);
01184 static int rpt_do_cmd(int fd, int argc, char *argv[]);
01185
01186 static char debug_usage[] =
01187 "Usage: rpt debug level {0-7}\n"
01188 " Enables debug messages in app_rpt\n";
01189
01190 static char dump_usage[] =
01191 "Usage: rpt dump <nodename>\n"
01192 " Dumps struct debug info to log\n";
01193
01194 static char dump_stats[] =
01195 "Usage: rpt stats <nodename>\n"
01196 " Dumps node statistics to console\n";
01197
01198 static char dump_lstats[] =
01199 "Usage: rpt lstats <nodename>\n"
01200 " Dumps link statistics to console\n";
01201
01202 static char dump_nodes[] =
01203 "Usage: rpt nodes <nodename>\n"
01204 " Dumps a list of directly and indirectly connected nodes to the console\n";
01205
01206 static char usage_local_nodes[] =
01207 "Usage: rpt localnodes\n"
01208 " Dumps a list of the locally configured node numbers to the console.\n";
01209
01210 static char reload_usage[] =
01211 "Usage: rpt reload\n"
01212 " Reloads app_rpt running config parameters\n";
01213
01214 static char restart_usage[] =
01215 "Usage: rpt restart\n"
01216 " Restarts app_rpt\n";
01217
01218 static char fun_usage[] =
01219 "Usage: rpt fun <nodename> <command>\n"
01220 " Send a DTMF function to a node\n";
01221
01222 static char cmd_usage[] =
01223 "Usage: rpt cmd <nodename> <cmd-name> <cmd-index> <cmd-args.\n"
01224 " Send a command to a node.\n i.e. rpt cmd 2000 ilink 3 2001\n";
01225
01226 #ifndef NEW_ASTERISK
01227
01228 static struct ast_cli_entry cli_debug =
01229 { { "rpt", "debug", "level" }, rpt_do_debug,
01230 "Enable app_rpt debugging", debug_usage };
01231
01232 static struct ast_cli_entry cli_dump =
01233 { { "rpt", "dump" }, rpt_do_dump,
01234 "Dump app_rpt structs for debugging", dump_usage };
01235
01236 static struct ast_cli_entry cli_stats =
01237 { { "rpt", "stats" }, rpt_do_stats,
01238 "Dump node statistics", dump_stats };
01239
01240 static struct ast_cli_entry cli_nodes =
01241 { { "rpt", "nodes" }, rpt_do_nodes,
01242 "Dump node list", dump_nodes };
01243
01244 static struct ast_cli_entry cli_local_nodes =
01245 { { "rpt", "localnodes" }, rpt_do_local_nodes,
01246 "Dump list of local node numbers", usage_local_nodes };
01247
01248 static struct ast_cli_entry cli_lstats =
01249 { { "rpt", "lstats" }, rpt_do_lstats,
01250 "Dump link statistics", dump_lstats };
01251
01252 static struct ast_cli_entry cli_reload =
01253 { { "rpt", "reload" }, rpt_do_reload,
01254 "Reload app_rpt config", reload_usage };
01255
01256 static struct ast_cli_entry cli_restart =
01257 { { "rpt", "restart" }, rpt_do_restart,
01258 "Restart app_rpt", restart_usage };
01259
01260 static struct ast_cli_entry cli_fun =
01261 { { "rpt", "fun" }, rpt_do_fun,
01262 "Execute a DTMF function", fun_usage };
01263
01264 static struct ast_cli_entry cli_fun1 =
01265 { { "rpt", "fun1" }, rpt_do_fun1,
01266 "Execute a DTMF function", fun_usage };
01267
01268 static struct ast_cli_entry cli_cmd =
01269 { { "rpt", "cmd" }, rpt_do_cmd,
01270 "Execute a DTMF function", cmd_usage };
01271
01272 #endif
01273
01274
01275
01276
01277
01278
01279 static struct telem_defaults tele_defs[] = {
01280 {"ct1","|t(350,0,100,3072)(500,0,100,3072)(660,0,100,3072)"},
01281 {"ct2","|t(660,880,150,3072)"},
01282 {"ct3","|t(440,0,150,3072)"},
01283 {"ct4","|t(550,0,150,3072)"},
01284 {"ct5","|t(660,0,150,3072)"},
01285 {"ct6","|t(880,0,150,3072)"},
01286 {"ct7","|t(660,440,150,3072)"},
01287 {"ct8","|t(700,1100,150,3072)"},
01288 {"remotemon","|t(1600,0,75,2048)"},
01289 {"remotetx","|t(2000,0,75,2048)(0,0,75,0)(1600,0,75,2048)"},
01290 {"cmdmode","|t(900,904,200,2048)"},
01291 {"functcomplete","|t(1000,0,100,2048)(0,0,100,0)(1000,0,100,2048)"}
01292 } ;
01293
01294
01295
01296
01297
01298 static int setrbi(struct rpt *myrpt);
01299 static int set_ft897(struct rpt *myrpt);
01300 static int set_ic706(struct rpt *myrpt);
01301 static int setkenwood(struct rpt *myrpt);
01302 static int set_tm271(struct rpt *myrpt);
01303 static int setrbi_check(struct rpt *myrpt);
01304
01305
01306
01307
01308
01309
01310
01311 static int function_ilink(struct rpt *myrpt, char *param, char *digitbuf, int command_source, struct rpt_link *mylink);
01312 static int function_autopatchup(struct rpt *myrpt, char *param, char *digitbuf, int command_source, struct rpt_link *mylink);
01313 static int function_autopatchdn(struct rpt *myrpt, char *param, char *digitbuf, int command_source, struct rpt_link *mylink);
01314 static int function_status(struct rpt *myrpt, char *param, char *digitbuf, int command_source, struct rpt_link *mylink);
01315 static int function_cop(struct rpt *myrpt, char *param, char *digitbuf, int command_source, struct rpt_link *mylink);
01316 static int function_remote(struct rpt *myrpt, char *param, char *digitbuf, int command_source, struct rpt_link *mylink);
01317 static int function_macro(struct rpt *myrpt, char *param, char *digitbuf, int command_source, struct rpt_link *mylink);
01318 static int function_playback(struct rpt *myrpt, char *param, char *digitbuf, int command_source, struct rpt_link *mylink);
01319
01320
01321
01322
01323 static struct function_table_tag function_table[] = {
01324 {"cop", function_cop},
01325 {"autopatchup", function_autopatchup},
01326 {"autopatchdn", function_autopatchdn},
01327 {"ilink", function_ilink},
01328 {"status", function_status},
01329 {"remote", function_remote},
01330 {"macro", function_macro},
01331 {"playback", function_playback}
01332 } ;
01333
01334 static long diskavail(struct rpt *myrpt)
01335 {
01336 struct statfs statfsbuf;
01337
01338 if (!myrpt->p.archivedir) return(0);
01339 if (statfs(myrpt->p.archivedir,&statfsbuf) == -1)
01340 {
01341 ast_log(LOG_WARNING,"Cannot get filesystem size for %s node %s\n",
01342 myrpt->p.archivedir,myrpt->name);
01343 return(-1);
01344 }
01345 return(statfsbuf.f_bavail);
01346 }
01347
01348 static void flush_telem(struct rpt *myrpt)
01349 {
01350 struct rpt_tele *telem;
01351 if(debug > 2)
01352 ast_log(LOG_NOTICE, "flush_telem()!!");
01353 rpt_mutex_lock(&myrpt->lock);
01354 telem = myrpt->tele.next;
01355 while(telem != &myrpt->tele)
01356 {
01357 if (telem->mode != SETREMOTE) ast_softhangup(telem->chan,AST_SOFTHANGUP_DEV);
01358 telem = telem->next;
01359 }
01360 rpt_mutex_unlock(&myrpt->lock);
01361 }
01362
01363
01364
01365 static int priority_jump(struct rpt *myrpt, struct ast_channel *chan)
01366 {
01367 int res=0;
01368
01369
01370 if (ast_goto_if_exists(chan, chan->context, chan->exten, chan->priority + 101) == 0){
01371 res = 0;
01372 } else {
01373 res = -1;
01374 }
01375 return res;
01376 }
01377
01378
01379 static int linkcount(struct rpt *myrpt)
01380 {
01381 struct rpt_link *l;
01382 char *reverse_patch_state;
01383 int numoflinks;
01384
01385 reverse_patch_state = "DOWN";
01386 numoflinks = 0;
01387 l = myrpt->links.next;
01388 while(l && (l != &myrpt->links)){
01389 if(numoflinks >= MAX_STAT_LINKS){
01390 ast_log(LOG_WARNING,
01391 "maximum number of links exceeds %d in rpt_do_stats()!",MAX_STAT_LINKS);
01392 break;
01393 }
01394
01395
01396
01397
01398
01399 numoflinks++;
01400
01401 l = l->next;
01402 }
01403 ast_log(LOG_NOTICE, "numoflinks=%i\n",numoflinks);
01404 return numoflinks;
01405 }
01406
01407
01408
01409
01410
01411
01412 static int retreive_memory(struct rpt *myrpt, char *memory)
01413 {
01414 char tmp[30], *s, *s1, *val;
01415
01416 if (debug)ast_log(LOG_NOTICE, "memory=%s block=%s\n",memory,myrpt->p.memory);
01417
01418 val = (char *) ast_variable_retrieve(myrpt->cfg, myrpt->p.memory, memory);
01419 if (!val){
01420 return -1;
01421 }
01422 strncpy(tmp,val,sizeof(tmp) - 1);
01423 tmp[sizeof(tmp)-1] = 0;
01424
01425 s = strchr(tmp,',');
01426 if (!s)
01427 return 1;
01428 *s++ = 0;
01429 s1 = strchr(s,',');
01430 if (!s1)
01431 return 1;
01432 *s1++ = 0;
01433 strncpy(myrpt->freq, tmp, sizeof(myrpt->freq) - 1);
01434 strncpy(myrpt->rxpl, s, sizeof(myrpt->rxpl) - 1);
01435 strncpy(myrpt->txpl, s, sizeof(myrpt->rxpl) - 1);
01436 myrpt->remmode = REM_MODE_FM;
01437 myrpt->offset = REM_SIMPLEX;
01438 myrpt->powerlevel = REM_MEDPWR;
01439 myrpt->txplon = myrpt->rxplon = 0;
01440 while(*s1){
01441 switch(*s1++){
01442 case 'A':
01443 case 'a':
01444 strcpy(myrpt->rxpl, "100.0");
01445 strcpy(myrpt->txpl, "100.0");
01446 myrpt->remmode = REM_MODE_AM;
01447 break;
01448 case 'B':
01449 case 'b':
01450 strcpy(myrpt->rxpl, "100.0");
01451 strcpy(myrpt->txpl, "100.0");
01452 myrpt->remmode = REM_MODE_LSB;
01453 break;
01454 case 'F':
01455 myrpt->remmode = REM_MODE_FM;
01456 break;
01457 case 'L':
01458 case 'l':
01459 myrpt->powerlevel = REM_LOWPWR;
01460 break;
01461 case 'H':
01462 case 'h':
01463 myrpt->powerlevel = REM_HIPWR;
01464 break;
01465
01466 case 'M':
01467 case 'm':
01468 myrpt->powerlevel = REM_MEDPWR;
01469 break;
01470
01471 case '-':
01472 myrpt->offset = REM_MINUS;
01473 break;
01474
01475 case '+':
01476 myrpt->offset = REM_PLUS;
01477 break;
01478
01479 case 'S':
01480 case 's':
01481 myrpt->offset = REM_SIMPLEX;
01482 break;
01483
01484 case 'T':
01485 case 't':
01486 myrpt->txplon = 1;
01487 break;
01488
01489 case 'R':
01490 case 'r':
01491 myrpt->rxplon = 1;
01492 break;
01493
01494 case 'U':
01495 case 'u':
01496 strcpy(myrpt->rxpl, "100.0");
01497 strcpy(myrpt->txpl, "100.0");
01498 myrpt->remmode = REM_MODE_USB;
01499 break;
01500 default:
01501 return 1;
01502 }
01503 }
01504 return 0;
01505 }
01506
01507
01508
01509 static void birdbath(struct rpt *myrpt)
01510 {
01511 struct rpt_tele *telem;
01512 if(debug > 2)
01513 ast_log(LOG_NOTICE, "birdbath!!");
01514 rpt_mutex_lock(&myrpt->lock);
01515 telem = myrpt->tele.next;
01516 while(telem != &myrpt->tele)
01517 {
01518 if (telem->mode == PARROT) ast_softhangup(telem->chan,AST_SOFTHANGUP_DEV);
01519 telem = telem->next;
01520 }
01521 rpt_mutex_unlock(&myrpt->lock);
01522 }
01523
01524 static void do_dtmf_phone(struct rpt *myrpt, struct rpt_link *mylink, char c)
01525 {
01526 struct rpt_link *l;
01527
01528 l = myrpt->links.next;
01529
01530 while(l != &myrpt->links)
01531 {
01532 if (!l->phonemode)
01533 {
01534 l = l->next;
01535 continue;
01536 }
01537
01538 if (mylink && (l == mylink))
01539 {
01540 l = l->next;
01541 continue;
01542 }
01543 #ifdef NEW_ASTERISK
01544 if (l->chan) ast_senddigit(l->chan,c,0);
01545 #else
01546 if (l->chan) ast_senddigit(l->chan,c);
01547 #endif
01548 l = l->next;
01549 }
01550 return;
01551 }
01552
01553
01554 static void donodelog(struct rpt *myrpt,char *str)
01555 {
01556 struct nodelog *nodep;
01557 char datestr[100];
01558
01559 if (!myrpt->p.archivedir) return;
01560 nodep = (struct nodelog *)ast_malloc(sizeof(struct nodelog));
01561 if (nodep == NULL)
01562 {
01563 ast_log(LOG_ERROR,"Cannot get memory for node log");
01564 return;
01565 }
01566 time(&nodep->timestamp);
01567 strncpy(nodep->archivedir,myrpt->p.archivedir,
01568 sizeof(nodep->archivedir) - 1);
01569 strftime(datestr,sizeof(datestr) - 1,"%Y%m%d%H%M%S",
01570 localtime(&nodep->timestamp));
01571 snprintf(nodep->str,sizeof(nodep->str) - 1,"%s %s,%s\n",
01572 myrpt->name,datestr,str);
01573 ast_mutex_lock(&nodeloglock);
01574 insque((struct qelem *) nodep, (struct qelem *) nodelog.prev);
01575 ast_mutex_unlock(&nodeloglock);
01576 }
01577
01578
01579 static void do_dtmf_local(struct rpt *myrpt, char c)
01580 {
01581 int i;
01582 char digit;
01583 static const char* dtmf_tones[] = {
01584 "!941+1336/200,!0/200",
01585 "!697+1209/200,!0/200",
01586 "!697+1336/200,!0/200",
01587 "!697+1477/200,!0/200",
01588 "!770+1209/200,!0/200",
01589 "!770+1336/200,!0/200",
01590 "!770+1477/200,!0/200",
01591 "!852+1209/200,!0/200",
01592 "!852+1336/200,!0/200",
01593 "!852+1477/200,!0/200",
01594 "!697+1633/200,!0/200",
01595 "!770+1633/200,!0/200",
01596 "!852+1633/200,!0/200",
01597 "!941+1633/200,!0/200",
01598 "!941+1209/200,!0/200",
01599 "!941+1477/200,!0/200" };
01600
01601
01602 if (c)
01603 {
01604 snprintf(myrpt->dtmf_local_str + strlen(myrpt->dtmf_local_str),sizeof(myrpt->dtmf_local_str) - 1,"%c",c);
01605 if (!myrpt->dtmf_local_timer)
01606 myrpt->dtmf_local_timer = DTMF_LOCAL_STARTTIME;
01607 }
01608
01609 if (myrpt->dtmf_local_timer == 1)
01610 {
01611 if(debug > 6)
01612 ast_log(LOG_NOTICE,"time out dtmf_local_timer=%i\n",myrpt->dtmf_local_timer);
01613
01614
01615 if (myrpt->dtmf_local_str[0])
01616 {
01617 digit = myrpt->dtmf_local_str[0];
01618 myrpt->dtmf_local_str[0] = 0;
01619 for(i = 1; myrpt->dtmf_local_str[i]; i++)
01620 {
01621 myrpt->dtmf_local_str[i - 1] =
01622 myrpt->dtmf_local_str[i];
01623 }
01624 myrpt->dtmf_local_str[i - 1] = 0;
01625 myrpt->dtmf_local_timer = DTMF_LOCAL_TIME;
01626 rpt_mutex_unlock(&myrpt->lock);
01627 if (digit >= '0' && digit <='9')
01628 ast_playtones_start(myrpt->txchannel, 0, dtmf_tones[digit-'0'], 0);
01629 else if (digit >= 'A' && digit <= 'D')
01630 ast_playtones_start(myrpt->txchannel, 0, dtmf_tones[digit-'A'+10], 0);
01631 else if (digit == '*')
01632 ast_playtones_start(myrpt->txchannel, 0, dtmf_tones[14], 0);
01633 else if (digit == '#')
01634 ast_playtones_start(myrpt->txchannel, 0, dtmf_tones[15], 0);
01635 else {
01636
01637 ast_log(LOG_DEBUG, "Unable to generate DTMF tone '%c' for '%s'\n", digit, myrpt->txchannel->name);
01638 }
01639 rpt_mutex_lock(&myrpt->lock);
01640 }
01641 else
01642 {
01643 myrpt->dtmf_local_timer = 0;
01644 }
01645 }
01646 }
01647
01648 static int setdtr(int fd, int enable)
01649 {
01650 struct termios mode;
01651
01652 if (fd < 0) return -1;
01653 if (tcgetattr(fd, &mode)) {
01654 ast_log(LOG_WARNING, "Unable to get serial parameters for dtr: %s\n", strerror(errno));
01655 return -1;
01656 }
01657 if (enable)
01658 {
01659 cfsetspeed(&mode, B9600);
01660 }
01661 else
01662 {
01663 cfsetspeed(&mode, B0);
01664 usleep(100000);
01665 }
01666 if (tcsetattr(fd, TCSADRAIN, &mode)) {
01667 ast_log(LOG_WARNING, "Unable to set serial parameters for dtr: %s\n", strerror(errno));
01668 return -1;
01669 }
01670 if (enable) usleep(100000);
01671 return 0;
01672 }
01673
01674 static int openserial(struct rpt *myrpt,char *fname)
01675 {
01676 struct termios mode;
01677 int fd;
01678
01679 fd = open(fname,O_RDWR);
01680 if (fd == -1)
01681 {
01682 ast_log(LOG_WARNING,"Cannot open serial port %s\n",fname);
01683 return -1;
01684 }
01685 memset(&mode, 0, sizeof(mode));
01686 if (tcgetattr(fd, &mode)) {
01687 ast_log(LOG_WARNING, "Unable to get serial parameters on %s: %s\n", fname, strerror(errno));
01688 return -1;
01689 }
01690 #ifndef SOLARIS
01691 cfmakeraw(&mode);
01692 #else
01693 mode.c_iflag &= ~(IGNBRK|BRKINT|PARMRK|ISTRIP
01694 |INLCR|IGNCR|ICRNL|IXON);
01695 mode.c_lflag &= ~(ECHO|ECHONL|ICANON|ISIG|IEXTEN);
01696 mode.c_cflag &= ~(CSIZE|PARENB|CRTSCTS);
01697 mode.c_cflag |= CS8;
01698 mode.c_cc[VTIME] = 3;
01699 mode.c_cc[VMIN] = 1;
01700 #endif
01701
01702 cfsetispeed(&mode, B9600);
01703 cfsetospeed(&mode, B9600);
01704 if (tcsetattr(fd, TCSANOW, &mode))
01705 ast_log(LOG_WARNING, "Unable to set serial parameters on %s: %s\n", fname, strerror(errno));
01706 if(!strcmp(myrpt->remoterig, remote_rig_kenwood)) setdtr(fd,0);
01707 usleep(100000);
01708 if (debug)ast_log(LOG_NOTICE,"Opened serial port %s\n",fname);
01709 return(fd);
01710 }
01711
01712 static void mdc1200_notify(struct rpt *myrpt,char *fromnode, unsigned int unit)
01713 {
01714 if (!fromnode)
01715 {
01716 ast_verbose("Got MDC-1200 ID %04X from local system (%s)\n",
01717 unit,myrpt->name);
01718 }
01719 else
01720 {
01721 ast_verbose("Got MDC-1200 ID %04X from node %s (%s)\n",
01722 unit,fromnode,myrpt->name);
01723 }
01724 }
01725
01726 #ifdef _MDC_DECODE_H_
01727
01728 static void mdc1200_send(struct rpt *myrpt, unsigned int unit)
01729 {
01730 struct rpt_link *l;
01731 struct ast_frame wf;
01732 char str[200];
01733
01734
01735 sprintf(str,"I %s %04X",myrpt->name,unit);
01736
01737 wf.frametype = AST_FRAME_TEXT;
01738 wf.subclass = 0;
01739 wf.offset = 0;
01740 wf.mallocd = 0;
01741 wf.datalen = strlen(str) + 1;
01742 wf.samples = 0;
01743
01744
01745 l = myrpt->links.next;
01746
01747 while(l != &myrpt->links)
01748 {
01749 if (l->name[0] == '0')
01750 {
01751 l = l->next;
01752 continue;
01753 }
01754 wf.data = str;
01755 if (l->chan) ast_write(l->chan,&wf);
01756 l = l->next;
01757 }
01758 return;
01759 }
01760
01761 #endif
01762
01763 static char func_xlat(struct rpt *myrpt,char c,struct rpt_xlat *xlat)
01764 {
01765 time_t now;
01766 int gotone;
01767
01768 time(&now);
01769 gotone = 0;
01770
01771 if ((now - xlat->lastone) > MAXXLATTIME)
01772 {
01773 xlat->funcindex = xlat->endindex = 0;
01774 }
01775 if (xlat->funccharseq[0] && (c == xlat->funccharseq[xlat->funcindex++]))
01776 {
01777 time(&xlat->lastone);
01778 gotone = 1;
01779 if (!xlat->funccharseq[xlat->funcindex])
01780 {
01781 xlat->funcindex = xlat->endindex = 0;
01782 return(myrpt->p.funcchar);
01783 }
01784 } else xlat->funcindex = 0;
01785 if (xlat->endcharseq[0] && (c == xlat->endcharseq[xlat->endindex++]))
01786 {
01787 time(&xlat->lastone);
01788 gotone = 1;
01789 if (!xlat->endcharseq[xlat->endindex])
01790 {
01791 xlat->funcindex = xlat->endindex = 0;
01792 return(myrpt->p.endchar);
01793 }
01794 } else xlat->endindex = 0;
01795
01796 if (gotone) return(0);
01797
01798 if (!xlat->passchars[0]) return(c);
01799
01800 if (strchr(xlat->passchars,c)) return(c);
01801 return(0);
01802 }
01803
01804
01805
01806
01807
01808 static char *eatwhite(char *s)
01809 {
01810 while((*s == ' ') || (*s == 0x09)){
01811 if(!*s)
01812 break;
01813 s++;
01814 }
01815 return s;
01816 }
01817
01818
01819
01820
01821
01822
01823
01824
01825
01826
01827
01828 static int finddelim(char *str, char *strp[], int limit)
01829 {
01830 int i,l,inquo;
01831
01832 inquo = 0;
01833 i = 0;
01834 strp[i++] = str;
01835 if (!*str)
01836 {
01837 strp[0] = 0;
01838 return(0);
01839 }
01840 for(l = 0; *str && (l < limit) ; str++)
01841 {
01842 if (*str == QUOTECHR)
01843 {
01844 if (inquo)
01845 {
01846 *str = 0;
01847 inquo = 0;
01848 }
01849 else
01850 {
01851 strp[i - 1] = str + 1;
01852 inquo = 1;
01853 }
01854 }
01855 if ((*str == DELIMCHR) && (!inquo))
01856 {
01857 *str = 0;
01858 l++;
01859 strp[i++] = str + 1;
01860 }
01861 }
01862 strp[i] = 0;
01863 return(i);
01864
01865 }
01866
01867
01868
01869 static int send_usb_txt(struct rpt *myrpt, char *txt)
01870 {
01871 struct ast_frame wf;
01872
01873 if (debug)ast_log(LOG_NOTICE, "send_usb_txt %s\n",txt);
01874 wf.frametype = AST_FRAME_TEXT;
01875 wf.subclass = 0;
01876 wf.offset = 0;
01877 wf.mallocd = 0;
01878 wf.datalen = strlen(txt) + 1;
01879 wf.data.ptr = txt;
01880 wf.samples = 0;
01881 ast_write(myrpt->txchannel,&wf);
01882 return 0;
01883 }
01884
01885 static void __mklinklist(struct rpt *myrpt, struct rpt_link *mylink, char *buf)
01886 {
01887 struct rpt_link *l;
01888 char mode;
01889 int i,spos;
01890
01891 buf[0] = 0;
01892 if (myrpt->remote) return;
01893
01894 for(l = myrpt->links.next; l != &myrpt->links; l = l->next)
01895 {
01896
01897 if (l->name[0] == '0') continue;
01898
01899 if (l == mylink) continue;
01900 if (mylink && (!strcmp(l->name,mylink->name))) continue;
01901
01902 mode = 'T';
01903 if (!l->mode) mode = 'R';
01904 if (!l->thisconnected) mode = 'C';
01905 spos = strlen(buf);
01906 if (spos)
01907 {
01908 strcat(buf,",");
01909 spos++;
01910 }
01911
01912 if (l->linklist[0])
01913 {
01914 snprintf(buf + spos,MAXLINKLIST - spos,
01915 "%c%s,%s",mode,l->name,l->linklist);
01916 }
01917 else
01918 {
01919 snprintf(buf + spos,MAXLINKLIST - spos,
01920 "%c%s",mode,l->name);
01921 }
01922
01923 if (mode == 'T') continue;
01924
01925 for(i = spos; buf[i]; i++)
01926 {
01927 if (buf[i] == 'T') buf[i] = mode;
01928 if ((buf[i] == 'R') && (mode == 'C')) buf[i] = mode;
01929 }
01930 }
01931 return;
01932 }
01933
01934
01935 static void __kickshort(struct rpt *myrpt)
01936 {
01937 struct rpt_link *l;
01938
01939 for(l = myrpt->links.next; l != &myrpt->links; l = l->next)
01940 {
01941
01942 if (l->name[0] == '0') continue;
01943 l->linklisttimer = LINKLISTSHORTTIME;
01944 }
01945 myrpt->linkposttimer = LINKPOSTSHORTTIME;
01946 return;
01947 }
01948
01949 static void statpost(struct rpt *myrpt,char *pairs)
01950 {
01951 char *str,*astr;
01952 char *astrs[100];
01953 int n,pid;
01954 time_t now;
01955 unsigned int seq;
01956
01957 if (!myrpt->p.statpost_url) return;
01958 str = ast_malloc(strlen(pairs) + strlen(myrpt->p.statpost_url) + 200);
01959 astr = ast_strdup(myrpt->p.statpost_program);
01960 if ((!str) || (!astr)) return;
01961 n = finddelim(astr,astrs,100);
01962 if (n < 1) return;
01963 ast_mutex_lock(&myrpt->statpost_lock);
01964 seq = ++myrpt->statpost_seqno;
01965 ast_mutex_unlock(&myrpt->statpost_lock);
01966 astrs[n++] = str;
01967 astrs[n] = NULL;
01968 time(&now);
01969 sprintf(str,"%s?node=%s&time=%u&seqno=%u",myrpt->p.statpost_url,
01970 myrpt->name,(unsigned int) now,seq);
01971 if (pairs) sprintf(str + strlen(str),"&%s",pairs);
01972 if (!(pid = ast_safe_fork(0)))
01973 {
01974 execv(astrs[0],astrs);
01975 ast_log(LOG_ERROR, "exec of %s failed.\n", astrs[0]);
01976 perror("asterisk");
01977 exit(0);
01978 }
01979 ast_free(astr);
01980 ast_free(str);
01981 return;
01982 }
01983
01984 static char *node_lookup(struct rpt *myrpt,char *digitbuf)
01985 {
01986
01987 char *val;
01988 int longestnode,j;
01989 struct stat mystat;
01990 static time_t last = 0;
01991 static struct ast_config *ourcfg = NULL;
01992 struct ast_variable *vp;
01993
01994
01995 val = (char *) ast_variable_retrieve(myrpt->cfg, myrpt->p.nodes, digitbuf);
01996 if (val) return(val);
01997 ast_mutex_lock(&nodelookuplock);
01998
01999 if (stat(myrpt->p.extnodefile,&mystat) == -1)
02000 {
02001 if (ourcfg) ast_config_destroy(ourcfg);
02002 ourcfg = NULL;
02003 ast_mutex_unlock(&nodelookuplock);
02004 return(NULL);
02005 }
02006
02007 if (mystat.st_mtime > last)
02008 {
02009 if (ourcfg) ast_config_destroy(ourcfg);
02010 #ifdef NEW_ASTERISK
02011 ourcfg = ast_config_load(myrpt->p.extnodefile,config_flags);
02012 #else
02013 ourcfg = ast_config_load(myrpt->p.extnodefile);
02014 #endif
02015
02016 if (!ourcfg)
02017 {
02018 ast_mutex_unlock(&nodelookuplock);
02019 return(NULL);
02020 }
02021
02022 last = mystat.st_mtime;
02023
02024
02025 longestnode = 0;
02026 vp = ast_variable_browse(myrpt->cfg, myrpt->p.nodes);
02027 while(vp){
02028 j = strlen(vp->name);
02029 if (j > longestnode)
02030 longestnode = j;
02031 vp = vp->next;
02032 }
02033
02034 vp = ast_variable_browse(ourcfg, myrpt->p.extnodes);
02035 while(vp){
02036 j = strlen(vp->name);
02037 if (j > longestnode)
02038 longestnode = j;
02039 vp = vp->next;
02040 }
02041
02042 myrpt->longestnode = longestnode;
02043 }
02044 val = NULL;
02045 if (ourcfg)
02046 val = (char *) ast_variable_retrieve(ourcfg, myrpt->p.extnodes, digitbuf);
02047 ast_mutex_unlock(&nodelookuplock);
02048 return(val);
02049 }
02050
02051
02052
02053
02054
02055
02056 static int matchkeyword(char *string, char **param, char *keywords[])
02057 {
02058 int i,ls;
02059 for( i = 0 ; keywords[i] ; i++){
02060 ls = strlen(keywords[i]);
02061 if(!ls){
02062 *param = NULL;
02063 return 0;
02064 }
02065 if(!strncmp(string, keywords[i], ls)){
02066 if(param)
02067 *param = string + ls;
02068 return i + 1;
02069 }
02070 }
02071 *param = NULL;
02072 return 0;
02073 }
02074
02075
02076
02077
02078
02079
02080 static char *skipchars(char *string, char *charlist)
02081 {
02082 int i;
02083 while(*string){
02084 for(i = 0; charlist[i] ; i++){
02085 if(*string == charlist[i]){
02086 string++;
02087 break;
02088 }
02089 }
02090 if(!charlist[i])
02091 return string;
02092 }
02093 return string;
02094 }
02095
02096
02097
02098 static int myatoi(char *str)
02099 {
02100 int ret;
02101
02102 if (str == NULL) return -1;
02103
02104 if (sscanf(str, "%30i", &ret) != 1)
02105 return -1;
02106 return ret;
02107 }
02108
02109 static int mycompar(const void *a, const void *b)
02110 {
02111 char **x = (char **) a;
02112 char **y = (char **) b;
02113 int xoff,yoff;
02114
02115 if ((**x < '0') || (**x > '9')) xoff = 1; else xoff = 0;
02116 if ((**y < '0') || (**y > '9')) yoff = 1; else yoff = 0;
02117 return(strcmp((*x) + xoff,(*y) + yoff));
02118 }
02119
02120 static int topcompar(const void *a, const void *b)
02121 {
02122 struct rpt_topkey *x = (struct rpt_topkey *) a;
02123 struct rpt_topkey *y = (struct rpt_topkey *) b;
02124
02125 return(x->timesince - y->timesince);
02126 }
02127
02128 #ifdef __RPT_NOTCH
02129
02130
02131 static void rpt_filter(struct rpt *myrpt, volatile short *buf, int len)
02132 {
02133 int i,j;
02134 struct rptfilter *f;
02135
02136 for(i = 0; i < len; i++)
02137 {
02138 for(j = 0; j < MAXFILTERS; j++)
02139 {
02140 f = &myrpt->filters[j];
02141 if (!*f->desc) continue;
02142 f->x0 = f->x1; f->x1 = f->x2;
02143 f->x2 = ((float)buf[i]) / f->gain;
02144 f->y0 = f->y1; f->y1 = f->y2;
02145 f->y2 = (f->x0 + f->x2) + f->const0 * f->x1
02146 + (f->const1 * f->y0) + (f->const2 * f->y1);
02147 buf[i] = (short)f->y2;
02148 }
02149 }
02150 }
02151
02152 #endif
02153
02154
02155
02156
02157
02158
02159
02160
02161
02162
02163
02164
02165
02166
02167
02168
02169
02170
02171 #ifdef NEW_ASTERISK
02172 static void rpt_localtime( time_t * t, struct ast_tm *lt)
02173 {
02174 struct timeval when;
02175
02176 when.tv_sec = *t;
02177 when.tv_usec = 0;
02178 ast_localtime(&when, lt, NULL);
02179 }
02180
02181 #else
02182 static void rpt_localtime( time_t * t, struct tm *lt)
02183 {
02184 #ifdef OLD_ASTERISK
02185 localtime_r(t, lt);
02186 #else
02187 ast_localtime(t, lt, NULL);
02188 #endif
02189 }
02190 #endif
02191
02192
02193
02194
02195 static int retrieve_astcfgint(struct rpt *myrpt,char *category, char *name, int min, int max, int defl)
02196 {
02197 char *var;
02198 int ret;
02199 char include_zero = 0;
02200
02201 if(min < 0){
02202 min = -min;
02203 include_zero = 1;
02204 }
02205
02206 var = (char *) ast_variable_retrieve(myrpt->cfg, category, name);
02207 if(var){
02208 ret = myatoi(var);
02209 if(include_zero && !ret)
02210 return 0;
02211 if(ret < min)
02212 ret = min;
02213 if(ret > max)
02214 ret = max;
02215 }
02216 else
02217 ret = defl;
02218 return ret;
02219 }
02220
02221
02222 static void load_rpt_vars(int n,int init)
02223 {
02224 char *this,*val;
02225 int i,j,longestnode;
02226 struct ast_variable *vp;
02227 struct ast_config *cfg;
02228 char *strs[100];
02229 char s1[256];
02230 static char *cs_keywords[] = {"rptena","rptdis","apena","apdis","lnkena","lnkdis","totena","totdis","skena","skdis",
02231 "ufena","ufdis","atena","atdis",NULL};
02232
02233 if (option_verbose > 2)
02234 ast_verbose(VERBOSE_PREFIX_3 "%s config for repeater %s\n",
02235 (init) ? "Loading initial" : "Re-Loading",rpt_vars[n].name);
02236 ast_mutex_lock(&rpt_vars[n].lock);
02237 if (rpt_vars[n].cfg) ast_config_destroy(rpt_vars[n].cfg);
02238 #ifdef NEW_ASTERISK
02239 cfg = ast_config_load("rpt.conf",config_flags);
02240 #else
02241 cfg = ast_config_load("rpt.conf");
02242 #endif
02243 if (!cfg) {
02244 ast_mutex_unlock(&rpt_vars[n].lock);
02245 ast_log(LOG_NOTICE, "Unable to open radio repeater configuration rpt.conf. Radio Repeater disabled.\n");
02246 pthread_exit(NULL);
02247 }
02248 rpt_vars[n].cfg = cfg;
02249 this = rpt_vars[n].name;
02250 memset(&rpt_vars[n].p,0,sizeof(rpt_vars[n].p));
02251 if (init)
02252 {
02253 char *cp;
02254 int savearea = (char *)&rpt_vars[n].p - (char *)&rpt_vars[n];
02255
02256 cp = (char *) &rpt_vars[n].p;
02257 memset(cp + sizeof(rpt_vars[n].p),0,
02258 sizeof(rpt_vars[n]) - (sizeof(rpt_vars[n].p) + savearea));
02259 rpt_vars[n].tele.next = &rpt_vars[n].tele;
02260 rpt_vars[n].tele.prev = &rpt_vars[n].tele;
02261 rpt_vars[n].rpt_thread = AST_PTHREADT_NULL;
02262 rpt_vars[n].tailmessagen = 0;
02263 }
02264 #ifdef __RPT_NOTCH
02265
02266 memset(&rpt_vars[n].filters,0,sizeof(rpt_vars[n].filters));
02267 #endif
02268 val = (char *) ast_variable_retrieve(cfg,this,"context");
02269 if (val) rpt_vars[n].p.ourcontext = val;
02270 else rpt_vars[n].p.ourcontext = this;
02271 val = (char *) ast_variable_retrieve(cfg,this,"callerid");
02272 if (val) rpt_vars[n].p.ourcallerid = val;
02273 val = (char *) ast_variable_retrieve(cfg,this,"accountcode");
02274 if (val) rpt_vars[n].p.acctcode = val;
02275 val = (char *) ast_variable_retrieve(cfg,this,"idrecording");
02276 if (val) rpt_vars[n].p.ident = val;
02277 val = (char *) ast_variable_retrieve(cfg,this,"hangtime");
02278 if (val) rpt_vars[n].p.hangtime = atoi(val);
02279 else rpt_vars[n].p.hangtime = HANGTIME;
02280 val = (char *) ast_variable_retrieve(cfg,this,"althangtime");
02281 if (val) rpt_vars[n].p.althangtime = atoi(val);
02282 else rpt_vars[n].p.althangtime = HANGTIME;
02283 val = (char *) ast_variable_retrieve(cfg,this,"totime");
02284 if (val) rpt_vars[n].p.totime = atoi(val);
02285 else rpt_vars[n].p.totime = TOTIME;
02286 val = (char *) ast_variable_retrieve(cfg,this,"voxtimeout");
02287 if (val) rpt_vars[n].p.voxtimeout_ms = atoi(val);
02288 else rpt_vars[n].p.voxtimeout_ms = VOX_TIMEOUT_MS;
02289 val = (char *) ast_variable_retrieve(cfg,this,"voxrecover");
02290 if (val) rpt_vars[n].p.voxrecover_ms = atoi(val);
02291 else rpt_vars[n].p.voxrecover_ms = VOX_RECOVER_MS;
02292 val = (char *) ast_variable_retrieve(cfg,this,"simplexpatchdelay");
02293 if (val) rpt_vars[n].p.simplexpatchdelay = atoi(val);
02294 else rpt_vars[n].p.simplexpatchdelay = SIMPLEX_PATCH_DELAY;
02295 val = (char *) ast_variable_retrieve(cfg,this,"simplexphonedelay");
02296 if (val) rpt_vars[n].p.simplexphonedelay = atoi(val);
02297 else rpt_vars[n].p.simplexphonedelay = SIMPLEX_PHONE_DELAY;
02298 val = (char *) ast_variable_retrieve(cfg,this,"statpost_program");
02299 if (val) rpt_vars[n].p.statpost_program = val;
02300 else rpt_vars[n].p.statpost_program = STATPOST_PROGRAM;
02301 rpt_vars[n].p.statpost_url =
02302 (char *) ast_variable_retrieve(cfg,this,"statpost_url");
02303 rpt_vars[n].p.tailmessagetime = retrieve_astcfgint(&rpt_vars[n],this, "tailmessagetime", 0, 2400000, 0);
02304 rpt_vars[n].p.tailsquashedtime = retrieve_astcfgint(&rpt_vars[n],this, "tailsquashedtime", 0, 2400000, 0);
02305 rpt_vars[n].p.duplex = retrieve_astcfgint(&rpt_vars[n],this,"duplex",0,4,2);
02306 rpt_vars[n].p.idtime = retrieve_astcfgint(&rpt_vars[n],this, "idtime", -60000, 2400000, IDTIME);
02307 rpt_vars[n].p.politeid = retrieve_astcfgint(&rpt_vars[n],this, "politeid", 30000, 300000, POLITEID);
02308 val = (char *) ast_variable_retrieve(cfg,this,"tonezone");
02309 if (val) rpt_vars[n].p.tonezone = val;
02310 rpt_vars[n].p.tailmessages[0] = 0;
02311 rpt_vars[n].p.tailmessagemax = 0;
02312 val = (char *) ast_variable_retrieve(cfg,this,"tailmessagelist");
02313 if (val) rpt_vars[n].p.tailmessagemax = finddelim(val, rpt_vars[n].p.tailmessages, 500);
02314 val = (char *) ast_variable_retrieve(cfg,this,"memory");
02315 if (!val) val = MEMORY;
02316 rpt_vars[n].p.memory = val;
02317 val = (char *) ast_variable_retrieve(cfg,this,"macro");
02318 if (!val) val = MACRO;
02319 rpt_vars[n].p.macro = val;
02320 val = (char *) ast_variable_retrieve(cfg,this,"tonemacro");
02321 if (!val) val = TONEMACRO;
02322 rpt_vars[n].p.tonemacro = val;
02323 val = (char *) ast_variable_retrieve(cfg,this,"startup_macro");
02324 if (val) rpt_vars[n].p.startupmacro = val;
02325 val = (char *) ast_variable_retrieve(cfg,this,"iobase");
02326
02327
02328
02329 if ((!val) || (sscanf(val, "%30i", &rpt_vars[n].p.iobase) != 1))
02330 rpt_vars[n].p.iobase = DEFAULT_IOBASE;
02331 val = (char *) ast_variable_retrieve(cfg,this,"ioport");
02332 rpt_vars[n].p.ioport = val;
02333 val = (char *) ast_variable_retrieve(cfg,this,"functions");
02334 if (!val)
02335 {
02336 val = FUNCTIONS;
02337 rpt_vars[n].p.simple = 1;
02338 }
02339 rpt_vars[n].p.functions = val;
02340 val = (char *) ast_variable_retrieve(cfg,this,"link_functions");
02341 if (val) rpt_vars[n].p.link_functions = val;
02342 else
02343 rpt_vars[n].p.link_functions = rpt_vars[n].p.functions;
02344 val = (char *) ast_variable_retrieve(cfg,this,"phone_functions");
02345 if (val) rpt_vars[n].p.phone_functions = val;
02346 val = (char *) ast_variable_retrieve(cfg,this,"dphone_functions");
02347 if (val) rpt_vars[n].p.dphone_functions = val;
02348 val = (char *) ast_variable_retrieve(cfg,this,"alt_functions");
02349 if (val) rpt_vars[n].p.alt_functions = val;
02350 val = (char *) ast_variable_retrieve(cfg,this,"funcchar");
02351 if (!val) rpt_vars[n].p.funcchar = FUNCCHAR; else
02352 rpt_vars[n].p.funcchar = *val;
02353 val = (char *) ast_variable_retrieve(cfg,this,"endchar");
02354 if (!val) rpt_vars[n].p.endchar = ENDCHAR; else
02355 rpt_vars[n].p.endchar = *val;
02356 val = (char *) ast_variable_retrieve(cfg,this,"nobusyout");
02357 if (val) rpt_vars[n].p.nobusyout = ast_true(val);
02358 val = (char *) ast_variable_retrieve(cfg,this,"notelemtx");
02359 if (val) rpt_vars[n].p.notelemtx = ast_true(val);
02360 val = (char *) ast_variable_retrieve(cfg,this,"propagate_dtmf");
02361 if (val) rpt_vars[n].p.propagate_dtmf = ast_true(val);
02362 val = (char *) ast_variable_retrieve(cfg,this,"propagate_phonedtmf");
02363 if (val) rpt_vars[n].p.propagate_phonedtmf = ast_true(val);
02364 val = (char *) ast_variable_retrieve(cfg,this,"linktolink");
02365 if (val) rpt_vars[n].p.linktolink = ast_true(val);
02366 val = (char *) ast_variable_retrieve(cfg,this,"nodes");
02367 if (!val) val = NODES;
02368 rpt_vars[n].p.nodes = val;
02369 val = (char *) ast_variable_retrieve(cfg,this,"extnodes");
02370 if (!val) val = EXTNODES;
02371 rpt_vars[n].p.extnodes = val;
02372 val = (char *) ast_variable_retrieve(cfg,this,"extnodefile");
02373 if (!val) val = EXTNODEFILE;
02374 rpt_vars[n].p.extnodefile = val;
02375 val = (char *) ast_variable_retrieve(cfg,this,"archivedir");
02376 if (val) rpt_vars[n].p.archivedir = val;
02377 val = (char *) ast_variable_retrieve(cfg,this,"authlevel");
02378 if (val) rpt_vars[n].p.authlevel = atoi(val);
02379 else rpt_vars[n].p.authlevel = 0;
02380 val = (char *) ast_variable_retrieve(cfg,this,"parrot");
02381 if (val) rpt_vars[n].p.parrotmode = ast_true(val) * 2;
02382 else rpt_vars[n].p.parrotmode = 0;
02383 val = (char *) ast_variable_retrieve(cfg,this,"parrottime");
02384 if (val) rpt_vars[n].p.parrottime = atoi(val);
02385 else rpt_vars[n].p.parrottime = PARROTTIME;
02386 val = (char *) ast_variable_retrieve(cfg,this,"rptnode");
02387 rpt_vars[n].p.rptnode = val;
02388 val = (char *) ast_variable_retrieve(cfg,this,"mars");
02389 if (val) rpt_vars[n].p.remote_mars = atoi(val);
02390 else rpt_vars[n].p.remote_mars = 0;
02391 val = (char *) ast_variable_retrieve(cfg,this,"monminblocks");
02392 if (val) rpt_vars[n].p.monminblocks = atol(val);
02393 else rpt_vars[n].p.monminblocks = DEFAULT_MONITOR_MIN_DISK_BLOCKS;
02394 val = (char *) ast_variable_retrieve(cfg,this,"remote_inact_timeout");
02395 if (val) rpt_vars[n].p.remoteinacttimeout = atoi(val);
02396 else rpt_vars[n].p.remoteinacttimeout = DEFAULT_REMOTE_INACT_TIMEOUT;
02397 val = (char *) ast_variable_retrieve(cfg,this,"civaddr");
02398 if (val) rpt_vars[n].p.civaddr = atoi(val);
02399 else rpt_vars[n].p.civaddr = DEFAULT_CIV_ADDR;
02400 val = (char *) ast_variable_retrieve(cfg,this,"remote_timeout");
02401 if (val) rpt_vars[n].p.remotetimeout = atoi(val);
02402 else rpt_vars[n].p.remotetimeout = DEFAULT_REMOTE_TIMEOUT;
02403 val = (char *) ast_variable_retrieve(cfg,this,"remote_timeout_warning");
02404 if (val) rpt_vars[n].p.remotetimeoutwarning = atoi(val);
02405 else rpt_vars[n].p.remotetimeoutwarning = DEFAULT_REMOTE_TIMEOUT_WARNING;
02406 val = (char *) ast_variable_retrieve(cfg,this,"remote_timeout_warning_freq");
02407 if (val) rpt_vars[n].p.remotetimeoutwarningfreq = atoi(val);
02408 else rpt_vars[n].p.remotetimeoutwarningfreq = DEFAULT_REMOTE_TIMEOUT_WARNING_FREQ;
02409 #ifdef __RPT_NOTCH
02410 val = (char *) ast_variable_retrieve(cfg,this,"rxnotch");
02411 if (val) {
02412 i = finddelim(val,strs,MAXFILTERS * 2);
02413 i &= ~1;
02414 if (i >= 2) for(j = 0; j < i; j += 2)
02415 {
02416 rpt_mknotch(atof(strs[j]),atof(strs[j + 1]),
02417 &rpt_vars[n].filters[j >> 1].gain,
02418 &rpt_vars[n].filters[j >> 1].const0,
02419 &rpt_vars[n].filters[j >> 1].const1,
02420 &rpt_vars[n].filters[j >> 1].const2);
02421 sprintf(rpt_vars[n].filters[j >> 1].desc,"%s Hz, BW = %s",
02422 strs[j],strs[j + 1]);
02423 }
02424
02425 }
02426 #endif
02427 val = (char *) ast_variable_retrieve(cfg,this,"inxlat");
02428 if (val) {
02429 memset(&rpt_vars[n].p.inxlat,0,sizeof(struct rpt_xlat));
02430 i = finddelim(val,strs,3);
02431 if (i) strncpy(rpt_vars[n].p.inxlat.funccharseq,strs[0],MAXXLAT - 1);
02432 if (i > 1) strncpy(rpt_vars[n].p.inxlat.endcharseq,strs[1],MAXXLAT - 1);
02433 if (i > 2) strncpy(rpt_vars[n].p.inxlat.passchars,strs[2],MAXXLAT - 1);
02434 }
02435 val = (char *) ast_variable_retrieve(cfg,this,"outxlat");
02436 if (val) {
02437 memset(&rpt_vars[n].p.outxlat,0,sizeof(struct rpt_xlat));
02438 i = finddelim(val,strs,3);
02439 if (i) strncpy(rpt_vars[n].p.outxlat.funccharseq,strs[0],MAXXLAT - 1);
02440 if (i > 1) strncpy(rpt_vars[n].p.outxlat.endcharseq,strs[1],MAXXLAT - 1);
02441 if (i > 2) strncpy(rpt_vars[n].p.outxlat.passchars,strs[2],MAXXLAT - 1);
02442 }
02443
02444 val = (char *) ast_variable_retrieve(cfg,this,"controlstates");
02445 rpt_vars[n].p.csstanzaname = val;
02446
02447
02448 val = (char *) ast_variable_retrieve(cfg,this,"scheduler");
02449 rpt_vars[n].p.skedstanzaname = val;
02450
02451
02452 val = (char *) ast_variable_retrieve(cfg,this,"txlimits");
02453 rpt_vars[n].p.txlimitsstanzaname = val;
02454
02455 longestnode = 0;
02456
02457 vp = ast_variable_browse(cfg, rpt_vars[n].p.nodes);
02458
02459 while(vp){
02460 j = strlen(vp->name);
02461 if (j > longestnode)
02462 longestnode = j;
02463 vp = vp->next;
02464 }
02465
02466 rpt_vars[n].longestnode = longestnode;
02467
02468
02469
02470
02471 rpt_vars[n].longestfunc = 0;
02472 vp = ast_variable_browse(cfg, rpt_vars[n].p.functions);
02473 while(vp){
02474 j = strlen(vp->name);
02475 if (j > rpt_vars[n].longestfunc)
02476 rpt_vars[n].longestfunc = j;
02477 vp = vp->next;
02478 }
02479
02480
02481
02482 rpt_vars[n].link_longestfunc = 0;
02483 vp = ast_variable_browse(cfg, rpt_vars[n].p.link_functions);
02484 while(vp){
02485 j = strlen(vp->name);
02486 if (j > rpt_vars[n].link_longestfunc)
02487 rpt_vars[n].link_longestfunc = j;
02488 vp = vp->next;
02489 }
02490 rpt_vars[n].phone_longestfunc = 0;
02491 if (rpt_vars[n].p.phone_functions)
02492 {
02493 vp = ast_variable_browse(cfg, rpt_vars[n].p.phone_functions);
02494 while(vp){
02495 j = strlen(vp->name);
02496 if (j > rpt_vars[n].phone_longestfunc)
02497 rpt_vars[n].phone_longestfunc = j;
02498 vp = vp->next;
02499 }
02500 }
02501 rpt_vars[n].dphone_longestfunc = 0;
02502 if (rpt_vars[n].p.dphone_functions)
02503 {
02504 vp = ast_variable_browse(cfg, rpt_vars[n].p.dphone_functions);
02505 while(vp){
02506 j = strlen(vp->name);
02507 if (j > rpt_vars[n].dphone_longestfunc)
02508 rpt_vars[n].dphone_longestfunc = j;
02509 vp = vp->next;
02510 }
02511 }
02512 rpt_vars[n].alt_longestfunc = 0;
02513 if (rpt_vars[n].p.alt_functions)
02514 {
02515 vp = ast_variable_browse(cfg, rpt_vars[n].p.alt_functions);
02516 while(vp){
02517 j = strlen(vp->name);
02518 if (j > rpt_vars[n].alt_longestfunc)
02519 rpt_vars[n].alt_longestfunc = j;
02520 vp = vp->next;
02521 }
02522 }
02523 rpt_vars[n].macro_longest = 1;
02524 vp = ast_variable_browse(cfg, rpt_vars[n].p.macro);
02525 while(vp){
02526 j = strlen(vp->name);
02527 if (j > rpt_vars[n].macro_longest)
02528 rpt_vars[n].macro_longest = j;
02529 vp = vp->next;
02530 }
02531
02532
02533 if(rpt_vars[n].p.csstanzaname)
02534 vp = ast_variable_browse(cfg, rpt_vars[n].p.csstanzaname);
02535 else
02536 vp = NULL;
02537 for( i = 0 ; vp && (i < MAX_SYSSTATES) ; i++){
02538 int k,nukw,statenum;
02539 statenum=atoi(vp->name);
02540 strncpy(s1, vp->value, 255);
02541 s1[255] = 0;
02542 nukw = finddelim(s1,strs,32);
02543
02544 for (k = 0 ; k < nukw ; k++){
02545 for(j = 0 ; cs_keywords[j] != NULL ; j++){
02546 if(!strcmp(strs[k],cs_keywords[j])){
02547 switch(j){
02548 case 0:
02549 rpt_vars[n].p.s[statenum].txdisable = 0;
02550 break;
02551 case 1:
02552 rpt_vars[n].p.s[statenum].txdisable = 1;
02553 break;
02554
02555 case 2:
02556 rpt_vars[n].p.s[statenum].autopatchdisable = 0;
02557 break;
02558
02559 case 3:
02560 rpt_vars[n].p.s[statenum].autopatchdisable = 1;
02561 break;
02562
02563 case 4:
02564 rpt_vars[n].p.s[statenum].linkfundisable = 0;
02565 break;
02566
02567 case 5:
02568 rpt_vars[n].p.s[statenum].linkfundisable = 1;
02569 break;
02570
02571 case 6:
02572 rpt_vars[n].p.s[statenum].totdisable = 0;
02573 break;
02574
02575 case 7:
02576 rpt_vars[n].p.s[statenum].totdisable = 1;
02577 break;
02578
02579 case 8:
02580 rpt_vars[n].p.s[statenum].schedulerdisable = 0;
02581 break;
02582
02583 case 9:
02584 rpt_vars[n].p.s[statenum].schedulerdisable = 1;
02585 break;
02586
02587 case 10:
02588 rpt_vars[n].p.s[statenum].userfundisable = 0;
02589 break;
02590
02591 case 11:
02592 rpt_vars[n].p.s[statenum].userfundisable = 1;
02593 break;
02594
02595 case 12:
02596 rpt_vars[n].p.s[statenum].alternatetail = 1;
02597 break;
02598
02599 case 13:
02600 rpt_vars[n].p.s[statenum].alternatetail = 0;
02601 break;
02602
02603 default:
02604 ast_log(LOG_WARNING,
02605 "Unhandled control state keyword %s", cs_keywords[i]);
02606 break;
02607 }
02608 }
02609 }
02610 }
02611 vp = vp->next;
02612 }
02613 ast_mutex_unlock(&rpt_vars[n].lock);
02614 }
02615
02616
02617
02618
02619
02620 static int rpt_do_debug(int fd, int argc, char *argv[])
02621 {
02622 int newlevel;
02623
02624 if (argc != 4)
02625 return RESULT_SHOWUSAGE;
02626 newlevel = myatoi(argv[3]);
02627 if((newlevel < 0) || (newlevel > 7))
02628 return RESULT_SHOWUSAGE;
02629 if(newlevel)
02630 ast_cli(fd, "app_rpt Debugging enabled, previous level: %d, new level: %d\n", debug, newlevel);
02631 else
02632 ast_cli(fd, "app_rpt Debugging disabled\n");
02633
02634 debug = newlevel;
02635 return RESULT_SUCCESS;
02636 }
02637
02638
02639
02640
02641
02642 static int rpt_do_dump(int fd, int argc, char *argv[])
02643 {
02644 int i;
02645
02646 if (argc != 3)
02647 return RESULT_SHOWUSAGE;
02648
02649 for(i = 0; i < nrpts; i++)
02650 {
02651 if (!strcmp(argv[2],rpt_vars[i].name))
02652 {
02653 rpt_vars[i].disgorgetime = time(NULL) + 10;
02654 ast_cli(fd, "app_rpt struct dump requested for node %s\n",argv[2]);
02655 return RESULT_SUCCESS;
02656 }
02657 }
02658 return RESULT_FAILURE;
02659 }
02660
02661
02662
02663
02664
02665 static int rpt_do_stats(int fd, int argc, char *argv[])
02666 {
02667 int i,j,numoflinks;
02668 int dailytxtime, dailykerchunks;
02669 time_t now;
02670 int totalkerchunks, dailykeyups, totalkeyups, timeouts;
02671 int totalexecdcommands, dailyexecdcommands, hours, minutes, seconds;
02672 int uptime;
02673 long long totaltxtime;
02674 struct rpt_link *l;
02675 char *listoflinks[MAX_STAT_LINKS];
02676 char *lastdtmfcommand,*parrot_ena;
02677 char *tot_state, *ider_state, *patch_state;
02678 char *reverse_patch_state, *sys_ena, *tot_ena, *link_ena, *patch_ena;
02679 char *sch_ena, *input_signal, *called_number, *user_funs, *tail_type;
02680 struct rpt *myrpt;
02681
02682 static char *not_applicable = "N/A";
02683
02684 if(argc != 3)
02685 return RESULT_SHOWUSAGE;
02686
02687 tot_state = ider_state =
02688 patch_state = reverse_patch_state =
02689 input_signal = not_applicable;
02690 called_number = lastdtmfcommand = NULL;
02691
02692 time(&now);
02693 for(i = 0; i < nrpts; i++)
02694 {
02695 if (!strcmp(argv[2],rpt_vars[i].name)){
02696
02697 myrpt = &rpt_vars[i];
02698 rpt_mutex_lock(&myrpt->lock);
02699 uptime = (int)(now - starttime);
02700 dailytxtime = myrpt->dailytxtime;
02701 totaltxtime = myrpt->totaltxtime;
02702 dailykeyups = myrpt->dailykeyups;
02703 totalkeyups = myrpt->totalkeyups;
02704 dailykerchunks = myrpt->dailykerchunks;
02705 totalkerchunks = myrpt->totalkerchunks;
02706 dailyexecdcommands = myrpt->dailyexecdcommands;
02707 totalexecdcommands = myrpt->totalexecdcommands;
02708 timeouts = myrpt->timeouts;
02709
02710
02711 reverse_patch_state = "DOWN";
02712 numoflinks = 0;
02713 l = myrpt->links.next;
02714 while(l && (l != &myrpt->links)){
02715 if(numoflinks >= MAX_STAT_LINKS){
02716 ast_log(LOG_NOTICE,
02717 "maximum number of links exceeds %d in rpt_do_stats()!",MAX_STAT_LINKS);
02718 break;
02719 }
02720 if (l->name[0] == '0'){
02721 reverse_patch_state = "UP";
02722 l = l->next;
02723 continue;
02724 }
02725 listoflinks[numoflinks] = ast_strdup(l->name);
02726 if(listoflinks[numoflinks] == NULL){
02727 break;
02728 }
02729 else{
02730 numoflinks++;
02731 }
02732 l = l->next;
02733 }
02734
02735 if(myrpt->keyed)
02736 input_signal = "YES";
02737 else
02738 input_signal = "NO";
02739
02740 if(myrpt->p.parrotmode)
02741 parrot_ena = "ENABLED";
02742 else
02743 parrot_ena = "DISABLED";
02744
02745 if(myrpt->p.s[myrpt->p.sysstate_cur].txdisable)
02746 sys_ena = "DISABLED";
02747 else
02748 sys_ena = "ENABLED";
02749
02750 if(myrpt->p.s[myrpt->p.sysstate_cur].totdisable)
02751 tot_ena = "DISABLED";
02752 else
02753 tot_ena = "ENABLED";
02754
02755 if(myrpt->p.s[myrpt->p.sysstate_cur].linkfundisable)
02756 link_ena = "DISABLED";
02757 else
02758 link_ena = "ENABLED";
02759
02760 if(myrpt->p.s[myrpt->p.sysstate_cur].autopatchdisable)
02761 patch_ena = "DISABLED";
02762 else
02763 patch_ena = "ENABLED";
02764
02765 if(myrpt->p.s[myrpt->p.sysstate_cur].schedulerdisable)
02766 sch_ena = "DISABLED";
02767 else
02768 sch_ena = "ENABLED";
02769
02770 if(myrpt->p.s[myrpt->p.sysstate_cur].userfundisable)
02771 user_funs = "DISABLED";
02772 else
02773 user_funs = "ENABLED";
02774
02775 if(myrpt->p.s[myrpt->p.sysstate_cur].alternatetail)
02776 tail_type = "ALTERNATE";
02777 else
02778 tail_type = "STANDARD";
02779
02780 if(!myrpt->totimer)
02781 tot_state = "TIMED OUT!";
02782 else if(myrpt->totimer != myrpt->p.totime)
02783 tot_state = "ARMED";
02784 else
02785 tot_state = "RESET";
02786
02787 if(myrpt->tailid)
02788 ider_state = "QUEUED IN TAIL";
02789 else if(myrpt->mustid)
02790 ider_state = "QUEUED FOR CLEANUP";
02791 else
02792 ider_state = "CLEAN";
02793
02794 switch(myrpt->callmode){
02795 case 1:
02796 patch_state = "DIALING";
02797 break;
02798 case 2:
02799 patch_state = "CONNECTING";
02800 break;
02801 case 3:
02802 patch_state = "UP";
02803 break;
02804
02805 case 4:
02806 patch_state = "CALL FAILED";
02807 break;
02808
02809 default:
02810 patch_state = "DOWN";
02811 }
02812
02813 if(strlen(myrpt->exten)){
02814 called_number = ast_strdup(myrpt->exten);
02815 }
02816
02817 if(strlen(myrpt->lastdtmfcommand)){
02818 lastdtmfcommand = ast_strdup(myrpt->lastdtmfcommand);
02819 }
02820 rpt_mutex_unlock(&myrpt->lock);
02821
02822 ast_cli(fd, "************************ NODE %s STATISTICS *************************\n\n", myrpt->name);
02823 ast_cli(fd, "Selected system state............................: %d\n", myrpt->p.sysstate_cur);
02824 ast_cli(fd, "Signal on input..................................: %s\n", input_signal);
02825 ast_cli(fd, "System...........................................: %s\n", sys_ena);
02826 ast_cli(fd, "Parrot Mode......................................: %s\n", parrot_ena);
02827 ast_cli(fd, "Scheduler........................................: %s\n", sch_ena);
02828 ast_cli(fd, "Tail Time........................................: %s\n", tail_type);
02829 ast_cli(fd, "Time out timer...................................: %s\n", tot_ena);
02830 ast_cli(fd, "Time out timer state.............................: %s\n", tot_state);
02831 ast_cli(fd, "Time outs since system initialization............: %d\n", timeouts);
02832 ast_cli(fd, "Identifier state.................................: %s\n", ider_state);
02833 ast_cli(fd, "Kerchunks today..................................: %d\n", dailykerchunks);
02834 ast_cli(fd, "Kerchunks since system initialization............: %d\n", totalkerchunks);
02835 ast_cli(fd, "Keyups today.....................................: %d\n", dailykeyups);
02836 ast_cli(fd, "Keyups since system initialization...............: %d\n", totalkeyups);
02837 ast_cli(fd, "DTMF commands today..............................: %d\n", dailyexecdcommands);
02838 ast_cli(fd, "DTMF commands since system initialization........: %d\n", totalexecdcommands);
02839 ast_cli(fd, "Last DTMF command executed.......................: %s\n",
02840 (lastdtmfcommand && strlen(lastdtmfcommand)) ? lastdtmfcommand : not_applicable);
02841 hours = dailytxtime/3600000;
02842 dailytxtime %= 3600000;
02843 minutes = dailytxtime/60000;
02844 dailytxtime %= 60000;
02845 seconds = dailytxtime/1000;
02846 dailytxtime %= 1000;
02847
02848 ast_cli(fd, "TX time today....................................: %02d:%02d:%02d.%d\n",
02849 hours, minutes, seconds, dailytxtime);
02850
02851 hours = (int) totaltxtime/3600000;
02852 totaltxtime %= 3600000;
02853 minutes = (int) totaltxtime/60000;
02854 totaltxtime %= 60000;
02855 seconds = (int) totaltxtime/1000;
02856 totaltxtime %= 1000;
02857
02858 ast_cli(fd, "TX time since system initialization..............: %02d:%02d:%02d.%d\n",
02859 hours, minutes, seconds, (int) totaltxtime);
02860
02861 hours = uptime/3600;
02862 uptime %= 3600;
02863 minutes = uptime/60;
02864 uptime %= 60;
02865
02866 ast_cli(fd, "Uptime...........................................: %02d:%02d:%02d\n",
02867 hours, minutes, uptime);
02868
02869 ast_cli(fd, "Nodes currently connected to us..................: ");
02870 if(!numoflinks){
02871 ast_cli(fd,"<NONE>");
02872 }
02873 else{
02874 for(j = 0 ;j < numoflinks; j++){
02875 ast_cli(fd, "%s", listoflinks[j]);
02876 if(j % 4 == 3){
02877 ast_cli(fd, "\n");
02878 ast_cli(fd, " : ");
02879 }
02880 else{
02881 if((numoflinks - 1) - j > 0)
02882 ast_cli(fd, ", ");
02883 }
02884 }
02885 }
02886 ast_cli(fd,"\n");
02887
02888 ast_cli(fd, "Autopatch........................................: %s\n", patch_ena);
02889 ast_cli(fd, "Autopatch state..................................: %s\n", patch_state);
02890 ast_cli(fd, "Autopatch called number..........................: %s\n",
02891 (called_number && strlen(called_number)) ? called_number : not_applicable);
02892 ast_cli(fd, "Reverse patch/IAXRPT connected...................: %s\n", reverse_patch_state);
02893 ast_cli(fd, "User linking commands............................: %s\n", link_ena);
02894 ast_cli(fd, "User functions...................................: %s\n\n", user_funs);
02895
02896 for(j = 0; j < numoflinks; j++){
02897 ast_free(listoflinks[j]);
02898 }
02899 if(called_number){
02900 ast_free(called_number);
02901 }
02902 if(lastdtmfcommand){
02903 ast_free(lastdtmfcommand);
02904 }
02905 return RESULT_SUCCESS;
02906 }
02907 }
02908 return RESULT_FAILURE;
02909 }
02910
02911
02912
02913
02914
02915 static int rpt_do_lstats(int fd, int argc, char *argv[])
02916 {
02917 int i,j;
02918 char *connstate;
02919 struct rpt *myrpt;
02920 struct rpt_link *l;
02921 struct rpt_lstat *s,*t;
02922 struct rpt_lstat s_head;
02923 if(argc != 3)
02924 return RESULT_SHOWUSAGE;
02925
02926 s = NULL;
02927 s_head.next = &s_head;
02928 s_head.prev = &s_head;
02929
02930 for(i = 0; i < nrpts; i++)
02931 {
02932 if (!strcmp(argv[2],rpt_vars[i].name)){
02933
02934 myrpt = &rpt_vars[i];
02935 rpt_mutex_lock(&myrpt->lock);
02936
02937 j = 0;
02938 l = myrpt->links.next;
02939 while(l && (l != &myrpt->links)){
02940 if (l->name[0] == '0'){
02941 l = l->next;
02942 continue;
02943 }
02944 if((s = (struct rpt_lstat *) ast_malloc(sizeof(struct rpt_lstat))) == NULL){
02945 ast_log(LOG_ERROR, "Malloc failed in rpt_do_lstats\n");
02946 rpt_mutex_unlock(&myrpt->lock);
02947 return RESULT_FAILURE;
02948 }
02949 memset(s, 0, sizeof(struct rpt_lstat));
02950 strncpy(s->name, l->name, MAXREMSTR - 1);
02951 if (l->chan) pbx_substitute_variables_helper(l->chan, "${IAXPEER(CURRENTCHANNEL)}", s->peer, MAXPEERSTR - 1);
02952 else strcpy(s->peer,"(none)");
02953 s->mode = l->mode;
02954 s->outbound = l->outbound;
02955 s->reconnects = l->reconnects;
02956 s->connecttime = l->connecttime;
02957 s->thisconnected = l->thisconnected;
02958 memcpy(s->chan_stat,l->chan_stat,NRPTSTAT * sizeof(struct rpt_chan_stat));
02959 insque((struct qelem *) s, (struct qelem *) s_head.next);
02960 memset(l->chan_stat,0,NRPTSTAT * sizeof(struct rpt_chan_stat));
02961 l = l->next;
02962 }
02963 rpt_mutex_unlock(&myrpt->lock);
02964 ast_cli(fd, "NODE PEER RECONNECTS DIRECTION CONNECT TIME CONNECT STATE\n");
02965 ast_cli(fd, "---- ---- ---------- --------- ------------ -------------\n");
02966
02967 for(s = s_head.next; s != &s_head; s = s->next){
02968 int hours, minutes, seconds;
02969 long long connecttime = s->connecttime;
02970 char conntime[21];
02971 hours = (int) connecttime/3600000;
02972 connecttime %= 3600000;
02973 minutes = (int) connecttime/60000;
02974 connecttime %= 60000;
02975 seconds = (int) connecttime/1000;
02976 connecttime %= 1000;
02977 snprintf(conntime, 20, "%02d:%02d:%02d.%d",
02978 hours, minutes, seconds, (int) connecttime);
02979 conntime[20] = 0;
02980 if(s->thisconnected)
02981 connstate = "ESTABLISHED";
02982 else
02983 connstate = "CONNECTING";
02984 ast_cli(fd, "%-10s%-20s%-12d%-11s%-20s%-20s\n",
02985 s->name, s->peer, s->reconnects, (s->outbound)? "OUT":"IN", conntime, connstate);
02986 }
02987
02988 s = s_head.next;
02989 while(s != &s_head){
02990 t = s;
02991 s = s->next;
02992 remque((struct qelem *)t);
02993 ast_free(t);
02994 }
02995 return RESULT_SUCCESS;
02996 }
02997 }
02998 return RESULT_FAILURE;
02999 }
03000
03001
03002
03003
03004
03005 static int rpt_do_nodes(int fd, int argc, char *argv[])
03006 {
03007 int i,j;
03008 char ns;
03009 char lbuf[MAXLINKLIST],*strs[MAXLINKLIST];
03010 struct rpt *myrpt;
03011 if(argc != 3)
03012 return RESULT_SHOWUSAGE;
03013
03014 for(i = 0; i < nrpts; i++)
03015 {
03016 if (!strcmp(argv[2],rpt_vars[i].name)){
03017
03018 myrpt = &rpt_vars[i];
03019 rpt_mutex_lock(&myrpt->lock);
03020 __mklinklist(myrpt,NULL,lbuf);
03021 rpt_mutex_unlock(&myrpt->lock);
03022
03023 ns = finddelim(lbuf,strs,MAXLINKLIST);
03024
03025 if (ns) qsort((void *)strs,ns,sizeof(char *),mycompar);
03026 ast_cli(fd,"\n");
03027 ast_cli(fd, "************************* CONNECTED NODES *************************\n\n");
03028 for(j = 0 ;; j++){
03029 if(!strs[j]){
03030 if(!j){
03031 ast_cli(fd,"<NONE>");
03032 }
03033 break;
03034 }
03035 ast_cli(fd, "%s", strs[j]);
03036 if(j % 8 == 7){
03037 ast_cli(fd, "\n");
03038 }
03039 else{
03040 if(strs[j + 1])
03041 ast_cli(fd, ", ");
03042 }
03043 }
03044 ast_cli(fd,"\n\n");
03045 return RESULT_SUCCESS;
03046 }
03047 }
03048 return RESULT_FAILURE;
03049 }
03050
03051
03052
03053
03054
03055 static int rpt_do_local_nodes(int fd, int argc, char *argv[])
03056 {
03057
03058 int i;
03059 ast_cli(fd, "\nNode\n----\n");
03060 for (i=0; i< nrpts; i++)
03061 {
03062 ast_cli(fd, "%s\n", rpt_vars[i].name);
03063 }
03064 ast_cli(fd,"\n");
03065 return RESULT_SUCCESS;
03066 }
03067
03068
03069
03070
03071
03072
03073 static int rpt_do_reload(int fd, int argc, char *argv[])
03074 {
03075 int n;
03076
03077 if (argc > 2) return RESULT_SHOWUSAGE;
03078
03079 for(n = 0; n < nrpts; n++) rpt_vars[n].reload = 1;
03080
03081 return RESULT_FAILURE;
03082 }
03083
03084
03085
03086
03087
03088 static int rpt_do_restart(int fd, int argc, char *argv[])
03089 {
03090 int i;
03091
03092 if (argc > 2) return RESULT_SHOWUSAGE;
03093 for(i = 0; i < nrpts; i++)
03094 {
03095 if (rpt_vars[i].rxchannel) ast_softhangup(rpt_vars[i].rxchannel,AST_SOFTHANGUP_DEV);
03096 }
03097 return RESULT_FAILURE;
03098 }
03099
03100
03101
03102
03103
03104
03105 static int rpt_do_fun(int fd, int argc, char *argv[])
03106 {
03107 int i,busy=0;
03108
03109 if (argc != 4) return RESULT_SHOWUSAGE;
03110
03111 for(i = 0; i < nrpts; i++){
03112 if(!strcmp(argv[2], rpt_vars[i].name)){
03113 struct rpt *myrpt = &rpt_vars[i];
03114 rpt_mutex_lock(&myrpt->lock);
03115 if ((MAXMACRO - strlen(myrpt->macrobuf)) < strlen(argv[3])){
03116 rpt_mutex_unlock(&myrpt->lock);
03117 busy=1;
03118 }
03119 if(!busy){
03120 myrpt->macrotimer = MACROTIME;
03121 strncat(myrpt->macrobuf,argv[3],MAXMACRO - 1);
03122 }
03123 rpt_mutex_unlock(&myrpt->lock);
03124 }
03125 }
03126 if(busy){
03127 ast_cli(fd, "Function decoder busy");
03128 }
03129 return RESULT_FAILURE;
03130 }
03131
03132
03133
03134
03135
03136
03137
03138
03139 static int rpt_push_alt_macro(struct rpt *myrpt, char *sptr)
03140 {
03141 int busy=0;
03142
03143 rpt_mutex_lock(&myrpt->lock);
03144 if ((MAXMACRO - strlen(myrpt->macrobuf)) < strlen(sptr)){
03145 rpt_mutex_unlock(&myrpt->lock);
03146 busy=1;
03147 }
03148 if(!busy){
03149 int x;
03150 if (debug)ast_log(LOG_NOTICE, "rpt_push_alt_macro %s\n",sptr);
03151 myrpt->macrotimer = MACROTIME;
03152 for(x = 0; *(sptr + x); x++)
03153 myrpt->macrobuf[x] = *(sptr + x) | 0x80;
03154 *(sptr + x) = 0;
03155 }
03156 rpt_mutex_unlock(&myrpt->lock);
03157
03158 if(busy)ast_log(LOG_WARNING, "Function decoder busy on app_rpt command macro.\n");
03159
03160 return busy;
03161 }
03162
03163
03164
03165 static int rpt_do_fun1(int fd, int argc, char *argv[])
03166 {
03167 int i;
03168
03169 if (argc != 4) return RESULT_SHOWUSAGE;
03170
03171 for(i = 0; i < nrpts; i++){
03172 if(!strcmp(argv[2], rpt_vars[i].name)){
03173 struct rpt *myrpt = &rpt_vars[i];
03174 rpt_push_alt_macro(myrpt,argv[3]);
03175 }
03176 }
03177 return RESULT_FAILURE;
03178 }
03179
03180
03181
03182
03183 static int rpt_do_cmd(int fd, int argc, char *argv[])
03184 {
03185 int i, l;
03186 int busy=0;
03187 int maxActions = sizeof(function_table)/sizeof(struct function_table_tag);
03188
03189 int thisRpt = -1;
03190 int thisAction = -1;
03191 struct rpt *myrpt = NULL;
03192 if (argc != 6) return RESULT_SHOWUSAGE;
03193
03194 for(i = 0; i < nrpts; i++)
03195 {
03196 if(!strcmp(argv[2], rpt_vars[i].name))
03197 {
03198 thisRpt = i;
03199 myrpt = &rpt_vars[i];
03200 break;
03201 }
03202 }
03203
03204 if (thisRpt < 0)
03205 {
03206 ast_cli(fd, "Unknown node number %s.\n", argv[2]);
03207 return RESULT_FAILURE;
03208 }
03209
03210
03211 l = strlen(argv[3]);
03212 for(i = 0 ; i < maxActions; i++)
03213 {
03214 if(!strncasecmp(argv[3], function_table[i].action, l))
03215 {
03216 thisAction = i;
03217 break;
03218 }
03219 }
03220
03221 if (thisAction < 0)
03222 {
03223 ast_cli(fd, "Unknown action name %s.\n", argv[3]);
03224 return RESULT_FAILURE;
03225 }
03226
03227
03228
03229 rpt_mutex_lock(&myrpt->lock);
03230
03231 if (rpt_vars[thisRpt].cmdAction.state == CMD_STATE_IDLE)
03232 {
03233 rpt_vars[thisRpt].cmdAction.state = CMD_STATE_BUSY;
03234 rpt_vars[thisRpt].cmdAction.functionNumber = thisAction;
03235 strncpy(rpt_vars[thisRpt].cmdAction.param, argv[4], MAXDTMF);
03236 strncpy(rpt_vars[thisRpt].cmdAction.digits, argv[5], MAXDTMF);
03237 rpt_vars[thisRpt].cmdAction.command_source = SOURCE_RPT;
03238 rpt_vars[thisRpt].cmdAction.state = CMD_STATE_READY;
03239 }
03240 else
03241 {
03242 busy = 1;
03243 }
03244 rpt_mutex_unlock(&myrpt->lock);
03245
03246 return (busy ? RESULT_FAILURE : RESULT_SUCCESS);
03247 }
03248
03249 static int play_tone_pair(struct ast_channel *chan, int f1, int f2, int duration, int amplitude)
03250 {
03251 int res;
03252
03253 if ((res = ast_tonepair_start(chan, f1, f2, duration, amplitude)))
03254 return res;
03255
03256 while(chan->generatordata) {
03257 if (ast_safe_sleep(chan,1)) return -1;
03258 }
03259
03260 return 0;
03261 }
03262
03263 static int play_tone(struct ast_channel *chan, int freq, int duration, int amplitude)
03264 {
03265 return play_tone_pair(chan, freq, 0, duration, amplitude);
03266 }
03267
03268 static int play_silence(struct ast_channel *chan, int duration)
03269 {
03270 return play_tone_pair(chan, 0, 0, duration, 0);
03271 }
03272
03273 #ifdef NEW_ASTERISK
03274
03275 static char *res2cli(int r)
03276
03277 {
03278 switch (r)
03279 {
03280 case RESULT_SUCCESS:
03281 return(CLI_SUCCESS);
03282 case RESULT_SHOWUSAGE:
03283 return(CLI_SHOWUSAGE);
03284 default:
03285 return(CLI_FAILURE);
03286 }
03287 }
03288
03289 static char *handle_cli_debug(struct ast_cli_entry *e,
03290 int cmd, struct ast_cli_args *a)
03291 {
03292 switch (cmd) {
03293 case CLI_INIT:
03294 e->command = "rpt debug level";
03295 e->usage = debug_usage;
03296 return NULL;
03297 case CLI_GENERATE:
03298 return NULL;
03299 }
03300 return res2cli(rpt_do_debug(a->fd,a->argc,a->argv));
03301 }
03302
03303 static char *handle_cli_dump(struct ast_cli_entry *e,
03304 int cmd, struct ast_cli_args *a)
03305 {
03306 switch (cmd) {
03307 case CLI_INIT:
03308 e->command = "rpt dump level";
03309 e->usage = dump_usage;
03310 return NULL;
03311 case CLI_GENERATE:
03312 return NULL;
03313 }
03314 return res2cli(rpt_do_dump(a->fd,a->argc,a->argv));
03315 }
03316
03317
03318 static char *handle_cli_stats(struct ast_cli_entry *e,
03319 int cmd, struct ast_cli_args *a)
03320 {
03321 switch (cmd) {
03322 case CLI_INIT:
03323 e->command = "rpt stats";
03324 e->usage = dump_stats;
03325 return NULL;
03326 case CLI_GENERATE:
03327 return NULL;
03328 }
03329 return res2cli(rpt_do_stats(a->fd,a->argc,a->argv));
03330 }
03331
03332 static char *handle_cli_nodes(struct ast_cli_entry *e,
03333 int cmd, struct ast_cli_args *a)
03334 {
03335 switch (cmd) {
03336 case CLI_INIT:
03337 e->command = "rpt nodes";
03338 e->usage = dump_nodes;
03339 return NULL;
03340 case CLI_GENERATE:
03341 return NULL;
03342 }
03343 return res2cli(rpt_do_nodes(a->fd,a->argc,a->argv));
03344 }
03345
03346 static char *handle_cli_local_nodes(struct ast_cli_entry *e,
03347 int cmd, struct ast_cli_args *a)
03348 {
03349 switch (cmd) {
03350 case CLI_INIT:
03351 e->command = "rpt localnodes";
03352 e->usage = usage_local_nodes;
03353 return NULL;
03354 case CLI_GENERATE:
03355 return NULL;
03356 }
03357 return res2cli(rpt_do_local_nodes(a->fd,a->argc,a->argv));
03358 }
03359
03360 static char *handle_cli_lstats(struct ast_cli_entry *e,
03361 int cmd, struct ast_cli_args *a)
03362 {
03363 switch (cmd) {
03364 case CLI_INIT:
03365 e->command = "rpt lstats";
03366 e->usage = dump_lstats;
03367 return NULL;
03368 case CLI_GENERATE:
03369 return NULL;
03370 }
03371 return res2cli(rpt_do_lstats(a->fd,a->argc,a->argv));
03372 }
03373
03374 static char *handle_cli_reload(struct ast_cli_entry *e,
03375 int cmd, struct ast_cli_args *a)
03376 {
03377 switch (cmd) {
03378 case CLI_INIT:
03379 e->command = "rpt reload";
03380 e->usage = reload_usage;
03381 return NULL;
03382 case CLI_GENERATE:
03383 return NULL;
03384 }
03385 return res2cli(rpt_do_reload(a->fd,a->argc,a->argv));
03386 }
03387
03388 static char *handle_cli_restart(struct ast_cli_entry *e,
03389 int cmd, struct ast_cli_args *a)
03390 {
03391 switch (cmd) {
03392 case CLI_INIT:
03393 e->command = "rpt restart";
03394 e->usage = restart_usage;
03395 return NULL;
03396 case CLI_GENERATE:
03397 return NULL;
03398 }
03399 return res2cli(rpt_do_restart(a->fd,a->argc,a->argv));
03400 }
03401
03402 static char *handle_cli_fun(struct ast_cli_entry *e,
03403 int cmd, struct ast_cli_args *a)
03404 {
03405 switch (cmd) {
03406 case CLI_INIT:
03407 e->command = "rpt fun";
03408 e->usage = fun_usage;
03409 return NULL;
03410 case CLI_GENERATE:
03411 return NULL;
03412 }
03413 return res2cli(rpt_do_fun(a->fd,a->argc,a->argv));
03414 }
03415
03416 static char *handle_cli_fun1(struct ast_cli_entry *e,
03417 int cmd, struct ast_cli_args *a)
03418 {
03419 switch (cmd) {
03420 case CLI_INIT:
03421 e->command = "rpt fun1";
03422 e->usage = fun_usage;
03423 return NULL;
03424 case CLI_GENERATE:
03425 return NULL;
03426 }
03427 return res2cli(rpt_do_fun1(a->fd,a->argc,a->argv));
03428 }
03429
03430 static char *handle_cli_cmd(struct ast_cli_entry *e,
03431 int cmd, struct ast_cli_args *a)
03432 {
03433 switch (cmd) {
03434 case CLI_INIT:
03435 e->command = "rpt cmd";
03436 e->usage = cmd_usage;
03437 return NULL;
03438 case CLI_GENERATE:
03439 return NULL;
03440 }
03441 return res2cli(rpt_do_cmd(a->fd,a->argc,a->argv));
03442 }
03443
03444 static struct ast_cli_entry rpt_cli[] = {
03445 AST_CLI_DEFINE(handle_cli_debug,"Enable app_rpt debugging"),
03446 AST_CLI_DEFINE(handle_cli_dump,"Dump app_rpt structs for debugging"),
03447 AST_CLI_DEFINE(handle_cli_stats,"Dump node statistics"),
03448 AST_CLI_DEFINE(handle_cli_nodes,"Dump node list"),
03449 AST_CLI_DEFINE(handle_cli_local_nodes, "Dump list of local node numbers"),
03450 AST_CLI_DEFINE(handle_cli_lstats,"Dump link statistics"),
03451 AST_CLI_DEFINE(handle_cli_reload,"Reload app_rpt config"),
03452 AST_CLI_DEFINE(handle_cli_restart,"Restart app_rpt"),
03453 AST_CLI_DEFINE(handle_cli_fun,"Execute a DTMF function"),
03454 AST_CLI_DEFINE(handle_cli_fun1,"Execute a DTMF function"),
03455 AST_CLI_DEFINE(handle_cli_cmd,"Execute a DTMF function")
03456 };
03457
03458 #endif
03459
03460 static int send_morse(struct ast_channel *chan, char *string, int speed, int freq, int amplitude)
03461 {
03462
03463 static struct morse_bits mbits[] = {
03464 {0, 0},
03465 {0, 0},
03466 {6, 18},
03467 {0, 0},
03468 {7, 72},
03469 {0, 0},
03470 {0, 0},
03471 {6, 30},
03472 {5, 13},
03473 {6, 29},
03474 {0, 0},
03475 {5, 10},
03476 {6, 51},
03477 {6, 33},
03478 {6, 42},
03479 {5, 9},
03480 {5, 31},
03481 {5, 30},
03482 {5, 28},
03483 {5, 24},
03484 {5, 16},
03485 {5, 0},
03486 {5, 1},
03487 {5, 3},
03488 {5, 7},
03489 {5, 15},
03490 {6, 7},
03491 {6, 21},
03492 {0, 0},
03493 {5, 33},
03494 {0, 0},
03495 {6, 12},
03496 {0, 0},
03497 {2, 2},
03498 {4, 1},
03499 {4, 5},
03500 {3, 1},
03501 {1, 0},
03502 {4, 4},
03503 {3, 3},
03504 {4, 0},
03505 {2, 0},
03506 {4, 14},
03507 {3, 5},
03508 {4, 2},
03509 {2, 3},
03510 {2, 1},
03511 {3, 7},
03512 {4, 6},
03513 {4, 11},
03514 {3, 2},
03515 {3, 0},
03516 {1, 1},
03517 {3, 4},
03518 {4, 8},
03519 {3, 6},
03520 {4, 9},
03521 {4, 13},
03522 {4, 3}
03523 };
03524
03525
03526 int dottime;
03527 int dashtime;
03528 int intralettertime;
03529 int interlettertime;
03530 int interwordtime;
03531 int len, ddcomb;
03532 int res;
03533 int c;
03534 int i;
03535 int flags;
03536
03537 res = 0;
03538
03539
03540
03541 dottime = 900/speed;
03542
03543
03544
03545 dashtime = 3 * dottime;
03546 intralettertime = dottime;
03547 interlettertime = dottime * 4 ;
03548 interwordtime = dottime * 7;
03549
03550 for(;(*string) && (!res); string++){
03551
03552 c = *string;
03553
03554
03555
03556 if((c >= 'a') && (c <= 'z'))
03557 c -= 0x20;
03558
03559
03560
03561 if(c > 'Z')
03562 continue;
03563
03564
03565
03566 if(c == ' '){
03567 if(!res)
03568 res = play_silence(chan, interwordtime);
03569 continue;
03570 }
03571
03572
03573
03574 c -= 0x20;
03575
03576
03577
03578 len = mbits[c].len;
03579 ddcomb = mbits[c].ddcomb;
03580
03581
03582
03583 for(; len ; len--){
03584 if(!res)
03585 res = play_tone(chan, freq, (ddcomb & 1) ? dashtime : dottime, amplitude);
03586 if(!res)
03587 res = play_silence(chan, intralettertime);
03588 ddcomb >>= 1;
03589 }
03590
03591
03592
03593 if(!res)
03594 res = play_silence(chan, interlettertime - intralettertime);
03595 }
03596
03597
03598
03599 if (!res)
03600 res = ast_waitstream(chan, "");
03601 ast_stopstream(chan);
03602
03603
03604
03605
03606
03607 for(i = 0; i < 20 ; i++){
03608 flags = DAHDI_IOMUX_WRITEEMPTY | DAHDI_IOMUX_NOWAIT;
03609 res = ioctl(chan->fds[0], DAHDI_IOMUX, &flags);
03610 if(flags & DAHDI_IOMUX_WRITEEMPTY)
03611 break;
03612 if( ast_safe_sleep(chan, 50)){
03613 res = -1;
03614 break;
03615 }
03616 }
03617
03618
03619 return res;
03620 }
03621
03622 static int send_tone_telemetry(struct ast_channel *chan, char *tonestring)
03623 {
03624 char *p,*stringp;
03625 char *tonesubset;
03626 int f1,f2;
03627 int duration;
03628 int amplitude;
03629 int res;
03630 int i;
03631 int flags;
03632
03633 res = 0;
03634
03635 if(!tonestring)
03636 return res;
03637
03638 p = stringp = ast_strdup(tonestring);
03639
03640 for(;tonestring;){
03641 tonesubset = strsep(&stringp,")");
03642 if(!tonesubset)
03643 break;
03644 if(sscanf(tonesubset,"(%30d,%30d,%30d,%30d", &f1, &f2, &duration, &litude) != 4)
03645 break;
03646 res = play_tone_pair(chan, f1, f2, duration, amplitude);
03647 if(res)
03648 break;
03649 }
03650 if(p)
03651 ast_free(p);
03652 if(!res)
03653 res = play_tone_pair(chan, 0, 0, 100, 0);
03654
03655 if (!res)
03656 res = ast_waitstream(chan, "");
03657
03658 ast_stopstream(chan);
03659
03660
03661
03662
03663
03664 for(i = 0; i < 20 ; i++){
03665 flags = DAHDI_IOMUX_WRITEEMPTY | DAHDI_IOMUX_NOWAIT;
03666 res = ioctl(chan->fds[0], DAHDI_IOMUX, &flags);
03667 if(flags & DAHDI_IOMUX_WRITEEMPTY)
03668 break;
03669 if( ast_safe_sleep(chan, 50)){
03670 res = -1;
03671 break;
03672 }
03673 }
03674
03675 return res;
03676
03677 }
03678
03679 static int sayfile(struct ast_channel *mychannel,char *fname)
03680 {
03681 int res;
03682
03683 res = ast_streamfile(mychannel, fname, mychannel->language);
03684 if (!res)
03685 res = ast_waitstream(mychannel, "");
03686 else
03687 ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", mychannel->name);
03688 ast_stopstream(mychannel);
03689 return res;
03690 }
03691
03692 static int saycharstr(struct ast_channel *mychannel,char *str)
03693 {
03694 int res;
03695
03696 res = ast_say_character_str(mychannel,str,NULL,mychannel->language);
03697 if (!res)
03698 res = ast_waitstream(mychannel, "");
03699 else
03700 ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", mychannel->name);
03701 ast_stopstream(mychannel);
03702 return res;
03703 }
03704
03705 static int saynum(struct ast_channel *mychannel, int num)
03706 {
03707 int res;
03708 res = ast_say_number(mychannel, num, NULL, mychannel->language, NULL);
03709 if(!res)
03710 res = ast_waitstream(mychannel, "");
03711 else
03712 ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", mychannel->name);
03713 ast_stopstream(mychannel);
03714 return res;
03715 }
03716
03717
03718
03719
03720 static int saynode(struct rpt *myrpt, struct ast_channel *mychannel, char *name)
03721 {
03722 int res;
03723 char *val,fname[300];
03724
03725 val = (char *) ast_variable_retrieve(myrpt->cfg, myrpt->name, "nodenames");
03726 if (!val) val = NODENAMES;
03727 snprintf(fname,sizeof(fname) - 1,"%s/%s",val,name);
03728 if (ast_fileexists(fname,NULL,mychannel->language) > 0)
03729 return(sayfile(mychannel,fname));
03730 res = sayfile(mychannel,"rpt/node");
03731 if (!res)
03732 res = ast_say_character_str(mychannel,name,NULL,mychannel->language);
03733 return res;
03734 }
03735
03736 static int telem_any(struct rpt *myrpt,struct ast_channel *chan, char *entry)
03737 {
03738 int res;
03739 char c;
03740
03741 static int morsespeed;
03742 static int morsefreq;
03743 static int morseampl;
03744 static int morseidfreq = 0;
03745 static int morseidampl;
03746 static char mcat[] = MORSE;
03747
03748 res = 0;
03749
03750 if(!morseidfreq){
03751 morsespeed = retrieve_astcfgint(myrpt, mcat, "speed", 5, 20, 20);
03752 morsefreq = retrieve_astcfgint(myrpt, mcat, "frequency", 300, 3000, 800);
03753 morseampl = retrieve_astcfgint(myrpt, mcat, "amplitude", 200, 8192, 4096);
03754 morseidampl = retrieve_astcfgint(myrpt, mcat, "idamplitude", 200, 8192, 2048);
03755 morseidfreq = retrieve_astcfgint(myrpt, mcat, "idfrequency", 300, 3000, 330);
03756 }
03757
03758
03759
03760 if(entry[0] == '|'){
03761 c = entry[1];
03762 if((c >= 'a')&&(c <= 'z'))
03763 c -= 0x20;
03764
03765 switch(c){
03766 case 'I':
03767 res = send_morse(chan, entry + 2, morsespeed, morseidfreq, morseidampl);
03768 break;
03769
03770 case 'M':
03771 res = send_morse(chan, entry + 2, morsespeed, morsefreq, morseampl);
03772 break;
03773
03774 case 'T':
03775 res = send_tone_telemetry(chan, entry + 2);
03776 break;
03777 default:
03778 res = -1;
03779 }
03780 }
03781 else
03782 res = sayfile(chan, entry);
03783 return res;
03784 }
03785
03786
03787
03788
03789
03790
03791
03792 static int telem_lookup(struct rpt *myrpt,struct ast_channel *chan, char *node, char *name)
03793 {
03794
03795 int res;
03796 int i;
03797 char *entry;
03798 char *telemetry;
03799 char *telemetry_save;
03800
03801 res = 0;
03802 telemetry_save = NULL;
03803 entry = NULL;
03804
03805
03806 telemetry = (char *) ast_variable_retrieve(myrpt->cfg, node, TELEMETRY);
03807 if(telemetry ){
03808 telemetry_save = ast_strdup(telemetry);
03809 if(!telemetry_save){
03810 ast_log(LOG_WARNING,"ast_strdup() failed in telem_lookup()\n");
03811 return res;
03812 }
03813 entry = (char *) ast_variable_retrieve(myrpt->cfg, telemetry_save, name);
03814 }
03815
03816
03817
03818 if(!entry){
03819
03820 for(i = 0; i < sizeof(tele_defs)/sizeof(struct telem_defaults) ; i++){
03821 if(!strcasecmp(tele_defs[i].name, name))
03822 entry = tele_defs[i].value;
03823 }
03824 }
03825 if(entry){
03826 if(strlen(entry))
03827 if (chan) telem_any(myrpt,chan, entry);
03828 }
03829 else{
03830 res = -1;
03831 }
03832 if(telemetry_save)
03833 ast_free(telemetry_save);
03834 return res;
03835 }
03836
03837
03838
03839
03840
03841 static int get_wait_interval(struct rpt *myrpt, int type)
03842 {
03843 int interval;
03844 char *wait_times;
03845 char *wait_times_save;
03846
03847 wait_times_save = NULL;
03848 wait_times = (char *) ast_variable_retrieve(myrpt->cfg, myrpt->name, "wait_times");
03849
03850 if(wait_times){
03851 wait_times_save = ast_strdup(wait_times);
03852 if(!wait_times_save)
03853 return 0;
03854
03855 }
03856
03857 switch(type){
03858 case DLY_TELEM:
03859 if(wait_times)
03860 interval = retrieve_astcfgint(myrpt,wait_times_save, "telemwait", 500, 5000, 1000);
03861 else
03862 interval = 1000;
03863 break;
03864
03865 case DLY_ID:
03866 if(wait_times)
03867 interval = retrieve_astcfgint(myrpt,wait_times_save, "idwait",250,5000,500);
03868 else
03869 interval = 500;
03870 break;
03871
03872 case DLY_UNKEY:
03873 if(wait_times)
03874 interval = retrieve_astcfgint(myrpt,wait_times_save, "unkeywait",50,5000,1000);
03875 else
03876 interval = 1000;
03877 break;
03878
03879 case DLY_LINKUNKEY:
03880 if(wait_times)
03881 interval = retrieve_astcfgint(myrpt,wait_times_save, "linkunkeywait",500,5000,1000);
03882 else
03883 interval = 1000;
03884 break;
03885
03886 case DLY_CALLTERM:
03887 if(wait_times)
03888 interval = retrieve_astcfgint(myrpt,wait_times_save, "calltermwait",500,5000,1500);
03889 else
03890 interval = 1500;
03891 break;
03892
03893 case DLY_COMP:
03894 if(wait_times)
03895 interval = retrieve_astcfgint(myrpt,wait_times_save, "compwait",500,5000,200);
03896 else
03897 interval = 200;
03898 break;
03899
03900 case DLY_PARROT:
03901 if(wait_times)
03902 interval = retrieve_astcfgint(myrpt,wait_times_save, "parrotwait",500,5000,200);
03903 else
03904 interval = 200;
03905 break;
03906
03907 default:
03908 interval = 0;
03909 break;
03910 }
03911 if(wait_times_save)
03912 ast_free(wait_times_save);
03913 return interval;
03914 }
03915
03916
03917
03918
03919
03920 static void wait_interval(struct rpt *myrpt, int type, struct ast_channel *chan)
03921 {
03922 int interval;
03923 interval = get_wait_interval(myrpt, type);
03924 if(debug)
03925 ast_log(LOG_NOTICE,"Delay interval = %d\n", interval);
03926 if(interval)
03927 ast_safe_sleep(chan,interval);
03928 if(debug)
03929 ast_log(LOG_NOTICE,"Delay complete\n");
03930 return;
03931 }
03932
03933 static int split_freq(char *mhz, char *decimals, char *freq);
03934
03935 static void *rpt_tele_thread(void *this)
03936 {
03937 struct dahdi_confinfo ci;
03938 int res = 0,haslink,hastx,hasremote,imdone = 0, unkeys_queued, x;
03939 struct rpt_tele *mytele = (struct rpt_tele *)this;
03940 struct rpt_tele *tlist;
03941 struct rpt *myrpt;
03942 struct rpt_link *l,*l1,linkbase;
03943 struct ast_channel *mychannel;
03944 int vmajor, vminor, m;
03945 char *p,*ct,*ct_copy,*ident, *nodename,*cp;
03946 time_t t;
03947 #ifdef NEW_ASTERISK
03948 struct ast_tm localtm;
03949 #else
03950 struct tm localtm;
03951 #endif
03952 char lbuf[MAXLINKLIST],*strs[MAXLINKLIST];
03953 int i,ns,rbimode;
03954 char mhz[MAXREMSTR];
03955 char decimals[MAXREMSTR];
03956 char mystr[200];
03957 struct dahdi_params par;
03958
03959
03960
03961 myrpt = mytele->rpt;
03962
03963
03964 rpt_mutex_lock(&myrpt->lock);
03965 nodename = ast_strdup(myrpt->name);
03966 if(!nodename)
03967 {
03968 fprintf(stderr,"rpt:Sorry unable strdup nodename\n");
03969 rpt_mutex_lock(&myrpt->lock);
03970 remque((struct qelem *)mytele);
03971 ast_log(LOG_NOTICE,"Telemetry thread aborted at line %d, mode: %d\n",__LINE__, mytele->mode);
03972 rpt_mutex_unlock(&myrpt->lock);
03973 ast_free(mytele);
03974 pthread_exit(NULL);
03975 }
03976
03977 if (myrpt->p.ident){
03978 ident = ast_strdup(myrpt->p.ident);
03979 if(!ident)
03980 {
03981 fprintf(stderr,"rpt:Sorry unable strdup ident\n");
03982 rpt_mutex_lock(&myrpt->lock);
03983 remque((struct qelem *)mytele);
03984 ast_log(LOG_NOTICE,"Telemetry thread aborted at line %d, mode: %d\n",
03985 __LINE__, mytele->mode);
03986 rpt_mutex_unlock(&myrpt->lock);
03987 ast_free(nodename);
03988 ast_free(mytele);
03989 pthread_exit(NULL);
03990 }
03991 }
03992 else
03993 {
03994 ident = "";
03995 }
03996 rpt_mutex_unlock(&myrpt->lock);
03997
03998
03999
04000
04001 mychannel = ast_request("DAHDI",AST_FORMAT_SLINEAR,"pseudo",NULL);
04002 if (!mychannel)
04003 {
04004 fprintf(stderr,"rpt:Sorry unable to obtain pseudo channel\n");
04005 rpt_mutex_lock(&myrpt->lock);
04006 remque((struct qelem *)mytele);
04007 ast_log(LOG_NOTICE,"Telemetry thread aborted at line %d, mode: %d\n",__LINE__, mytele->mode);
04008 rpt_mutex_unlock(&myrpt->lock);
04009 ast_free(nodename);
04010 ast_free(ident);
04011 ast_free(mytele);
04012 pthread_exit(NULL);
04013 }
04014 #ifdef AST_CDR_FLAG_POST_DISABLED
04015 if (mychannel->cdr)
04016 ast_set_flag(mychannel->cdr,AST_CDR_FLAG_POST_DISABLED);
04017 #endif
04018 rpt_mutex_lock(&myrpt->lock);
04019 mytele->chan = mychannel;
04020 rpt_mutex_unlock(&myrpt->lock);
04021
04022 while((mytele->mode != SETREMOTE) && (mytele->mode != UNKEY) &&
04023 (mytele->mode != LINKUNKEY))
04024 {
04025 rpt_mutex_lock(&myrpt->lock);
04026 if (!myrpt->active_telem)
04027 {
04028 myrpt->active_telem = mytele;
04029 rpt_mutex_unlock(&myrpt->lock);
04030 break;
04031 }
04032 rpt_mutex_unlock(&myrpt->lock);
04033 usleep(100000);
04034 }
04035
04036
04037 ci.chan = 0;
04038
04039
04040
04041 ci.confno = (((mytele->mode == ID) || (mytele->mode == IDTALKOVER) || (mytele->mode == UNKEY) ||
04042 (mytele->mode == TAILMSG) || (mytele->mode == LINKUNKEY) || (mytele->mode == TIMEOUT) ||
04043 (mytele->mode == PARROT) || (mytele->mode == STATS_TIME_LOCAL)) ?
04044 myrpt->txconf : myrpt->conf);
04045 ci.confmode = DAHDI_CONF_CONFANN;
04046
04047 if (ioctl(mychannel->fds[0],DAHDI_SETCONF,&ci) == -1)
04048 {
04049 ast_log(LOG_WARNING, "Unable to set conference mode to Announce\n");
04050 rpt_mutex_lock(&myrpt->lock);
04051 myrpt->active_telem = NULL;
04052 remque((struct qelem *)mytele);
04053 rpt_mutex_unlock(&myrpt->lock);
04054 ast_log(LOG_NOTICE,"Telemetry thread aborted at line %d, mode: %d\n",__LINE__, mytele->mode);
04055 ast_free(nodename);
04056 ast_free(ident);
04057 ast_free(mytele);
04058 ast_hangup(mychannel);
04059 pthread_exit(NULL);
04060 }
04061 ast_stopstream(mychannel);
04062 switch(mytele->mode)
04063 {
04064 case ID:
04065 case ID1:
04066
04067 wait_interval(myrpt, (mytele->mode == ID) ? DLY_ID : DLY_TELEM,mychannel);
04068 res = telem_any(myrpt,mychannel, ident);
04069 imdone=1;
04070 break;
04071
04072 case TAILMSG:
04073 res = ast_streamfile(mychannel, myrpt->p.tailmessages[myrpt->tailmessagen], mychannel->language);
04074 break;
04075
04076 case IDTALKOVER:
04077 p = (char *) ast_variable_retrieve(myrpt->cfg, nodename, "idtalkover");
04078 if(p)
04079 res = telem_any(myrpt,mychannel, p);
04080 imdone=1;
04081 break;
04082
04083 case PROC:
04084
04085 wait_interval(myrpt, DLY_TELEM, mychannel);
04086 res = telem_lookup(myrpt, mychannel, myrpt->name, "patchup");
04087 if(res < 0){
04088 res = ast_streamfile(mychannel, "rpt/callproceeding", mychannel->language);
04089 }
04090 break;
04091 case TERM:
04092
04093 wait_interval(myrpt, DLY_CALLTERM, mychannel);
04094 res = telem_lookup(myrpt, mychannel, myrpt->name, "patchdown");
04095 if(res < 0){
04096 res = ast_streamfile(mychannel, "rpt/callterminated", mychannel->language);
04097 }
04098 break;
04099 case COMPLETE:
04100
04101 wait_interval(myrpt, DLY_TELEM, mychannel);
04102 res = telem_lookup(myrpt,mychannel, myrpt->name, "functcomplete");
04103 break;
04104 case MACRO_NOTFOUND:
04105
04106 wait_interval(myrpt, DLY_TELEM, mychannel);
04107 res = ast_streamfile(mychannel, "rpt/macro_notfound", mychannel->language);
04108 break;
04109 case MACRO_BUSY:
04110
04111 wait_interval(myrpt, DLY_TELEM, mychannel);
04112 res = ast_streamfile(mychannel, "rpt/macro_busy", mychannel->language);
04113 break;
04114 case UNKEY:
04115 if(myrpt->patchnoct && myrpt->callmode){
04116 imdone = 1;
04117 break;
04118 }
04119
04120
04121
04122
04123
04124 x = get_wait_interval(myrpt, DLY_UNKEY);
04125 rpt_mutex_lock(&myrpt->lock);
04126 myrpt->unkeytocttimer = x;
04127 rpt_mutex_unlock(&myrpt->lock);
04128
04129
04130
04131
04132
04133 tlist = myrpt->tele.next;
04134 unkeys_queued = 0;
04135 if (tlist != &myrpt->tele)
04136 {
04137 rpt_mutex_lock(&myrpt->lock);
04138 while(tlist != &myrpt->tele){
04139 if (tlist->mode == UNKEY) unkeys_queued++;
04140 tlist = tlist->next;
04141 }
04142 rpt_mutex_unlock(&myrpt->lock);
04143 }
04144 if( unkeys_queued > 1){
04145 imdone = 1;
04146 break;
04147 }
04148
04149
04150
04151 while(myrpt->unkeytocttimer)
04152 {
04153 int ctint;
04154 if(myrpt->unkeytocttimer > 100)
04155 ctint = 100;
04156 else
04157 ctint = myrpt->unkeytocttimer;
04158 ast_safe_sleep(mychannel, ctint);
04159 rpt_mutex_lock(&myrpt->lock);
04160 if(myrpt->unkeytocttimer < ctint)
04161 myrpt->unkeytocttimer = 0;
04162 else
04163 myrpt->unkeytocttimer -= ctint;
04164 rpt_mutex_unlock(&myrpt->lock);
04165 }
04166
04167
04168
04169
04170
04171 if(myrpt->keyed){
04172 imdone = 1;
04173 break;
04174 }
04175
04176 rpt_mutex_lock(&myrpt->lock);
04177 myrpt->dailykerchunks++;
04178 myrpt->totalkerchunks++;
04179 rpt_mutex_unlock(&myrpt->lock);
04180
04181 haslink = 0;
04182 hastx = 0;
04183 hasremote = 0;
04184 l = myrpt->links.next;
04185 if (l != &myrpt->links)
04186 {
04187 rpt_mutex_lock(&myrpt->lock);
04188 while(l != &myrpt->links)
04189 {
04190 if (l->name[0] == '0')
04191 {
04192 l = l->next;
04193 continue;
04194 }
04195 haslink = 1;
04196 if (l->mode) {
04197 hastx++;
04198 if (l->isremote) hasremote++;
04199 }
04200 l = l->next;
04201 }
04202 rpt_mutex_unlock(&myrpt->lock);
04203 }
04204 if (haslink)
04205 {
04206
04207 res = telem_lookup(myrpt,mychannel, myrpt->name, (!hastx) ? "remotemon" : "remotetx");
04208 if(res)
04209 ast_log(LOG_WARNING, "telem_lookup:remotexx failed on %s\n", mychannel->name);
04210
04211
04212
04213 if (myrpt->cmdnode[0])
04214 {
04215 ast_safe_sleep(mychannel,200);
04216 res = telem_lookup(myrpt,mychannel, myrpt->name, "cmdmode");
04217 if(res)
04218 ast_log(LOG_WARNING, "telem_lookup:cmdmode failed on %s\n", mychannel->name);
04219 ast_stopstream(mychannel);
04220 }
04221 }
04222 else if((ct = (char *) ast_variable_retrieve(myrpt->cfg, nodename, "unlinkedct"))){
04223 ct_copy = ast_strdup(ct);
04224 if(ct_copy)
04225 {
04226 res = telem_lookup(myrpt,mychannel, myrpt->name, ct_copy);
04227 ast_free(ct_copy);
04228 }
04229 else
04230 res = -1;
04231 if(res)
04232 ast_log(LOG_WARNING, "telem_lookup:ctx failed on %s\n", mychannel->name);
04233 }
04234 if (hasremote && (!myrpt->cmdnode[0]))
04235 {
04236
04237 ci.chan = 0;
04238 ci.confno = myrpt->conf;
04239 ci.confmode = DAHDI_CONF_CONFANN;
04240
04241 if (ioctl(mychannel->fds[0],DAHDI_SETCONF,&ci) == -1)
04242 {
04243 ast_log(LOG_WARNING, "Unable to set conference mode to Announce\n");
04244 rpt_mutex_lock(&myrpt->lock);
04245 myrpt->active_telem = NULL;
04246 remque((struct qelem *)mytele);
04247 rpt_mutex_unlock(&myrpt->lock);
04248 ast_log(LOG_NOTICE,"Telemetry thread aborted at line %d, mode: %d\n",__LINE__, mytele->mode);
04249 ast_free(nodename);
04250 ast_free(ident);
04251 ast_free(mytele);
04252 ast_hangup(mychannel);
04253 pthread_exit(NULL);
04254 }
04255 if((ct = (char *) ast_variable_retrieve(myrpt->cfg, nodename, "remotect"))){
04256 ast_safe_sleep(mychannel,200);
04257 ct_copy = ast_strdup(ct);
04258 if(ct_copy)
04259 {
04260 res = telem_lookup(myrpt,mychannel, myrpt->name, ct_copy);
04261 ast_free(ct_copy);
04262 }
04263 else
04264 res = -1;
04265
04266 if(res)
04267 ast_log(LOG_WARNING, "telem_lookup:ctx failed on %s\n", mychannel->name);
04268 }
04269 }
04270 #if defined(_MDC_DECODE_H_) && defined(MDC_SAY_WHEN_DOING_CT)
04271 if (myrpt->lastunit)
04272 {
04273 char mystr[10];
04274
04275 ast_safe_sleep(mychannel,200);
04276
04277 ci.chan = 0;
04278 ci.confno = myrpt->txconf;
04279 ci.confmode = DAHDI_CONF_CONFANN;
04280
04281 if (ioctl(mychannel->fds[0],DAHDI_SETCONF,&ci) == -1)
04282 {
04283 ast_log(LOG_WARNING, "Unable to set conference mode to Announce\n");
04284 rpt_mutex_lock(&myrpt->lock);
04285 myrpt->active_telem = NULL;
04286 remque((struct qelem *)mytele);
04287 rpt_mutex_unlock(&myrpt->lock);
04288 ast_log(LOG_NOTICE,"Telemetry thread aborted at line %d, mode: %d\n",__LINE__, mytele->mode);
04289 ast_free(nodename);
04290 ast_free(ident);
04291 ast_free(mytele);
04292 ast_hangup(mychannel);
04293 pthread_exit(NULL);
04294 }
04295 sprintf(mystr,"%04x",myrpt->lastunit);
04296 myrpt->lastunit = 0;
04297 ast_say_character_str(mychannel,mystr,NULL,mychannel->language);
04298 break;
04299 }
04300 #endif
04301 imdone = 1;
04302 break;
04303 case LINKUNKEY:
04304 if(myrpt->patchnoct && myrpt->callmode){
04305 imdone = 1;
04306 break;
04307 }
04308
04309
04310
04311
04312
04313 x = get_wait_interval(myrpt, DLY_LINKUNKEY);
04314 mytele->mylink.linkunkeytocttimer = x;
04315
04316
04317
04318
04319
04320 tlist = myrpt->tele.next;
04321 unkeys_queued = 0;
04322 if (tlist != &myrpt->tele)
04323 {
04324 rpt_mutex_lock(&myrpt->lock);
04325 while(tlist != &myrpt->tele){
04326 if (tlist->mode == LINKUNKEY) unkeys_queued++;
04327 tlist = tlist->next;
04328 }
04329 rpt_mutex_unlock(&myrpt->lock);
04330 }
04331 if( unkeys_queued > 1){
04332 imdone = 1;
04333 break;
04334 }
04335
04336
04337
04338 while(mytele->mylink.linkunkeytocttimer)
04339 {
04340 int ctint;
04341 if(mytele->mylink.linkunkeytocttimer > 100)
04342 ctint = 100;
04343 else
04344 ctint = mytele->mylink.linkunkeytocttimer;
04345 ast_safe_sleep(mychannel, ctint);
04346 rpt_mutex_lock(&myrpt->lock);
04347 if(mytele->mylink.linkunkeytocttimer < ctint)
04348 mytele->mylink.linkunkeytocttimer = 0;
04349 else
04350 mytele->mylink.linkunkeytocttimer -= ctint;
04351 rpt_mutex_unlock(&myrpt->lock);
04352 }
04353
04354 if((ct = (char *) ast_variable_retrieve(myrpt->cfg, nodename, "linkunkeyct"))){
04355 ct_copy = ast_strdup(ct);
04356 if(ct_copy){
04357 res = telem_lookup(myrpt,mychannel, myrpt->name, ct_copy);
04358 ast_free(ct_copy);
04359 }
04360 else
04361 res = -1;
04362 if(res)
04363 ast_log(LOG_WARNING, "telem_lookup:ctx failed on %s\n", mychannel->name);
04364 }
04365 imdone = 1;
04366 break;
04367 case REMDISC:
04368
04369 wait_interval(myrpt, DLY_TELEM, mychannel);
04370 l = myrpt->links.next;
04371 haslink = 0;
04372
04373 if (l != &myrpt->links)
04374 {
04375 rpt_mutex_lock(&myrpt->lock);
04376 while(l != &myrpt->links)
04377 {
04378 if (l->name[0] == '0')
04379 {
04380 l = l->next;
04381 continue;
04382 }
04383 if (!strcmp(l->name,mytele->mylink.name))
04384 {
04385 haslink = 1;
04386 break;
04387 }
04388 l = l->next;
04389 }
04390 rpt_mutex_unlock(&myrpt->lock);
04391 }
04392 if (haslink)
04393 {
04394 imdone = 1;
04395 break;
04396 }
04397 res = saynode(myrpt,mychannel,mytele->mylink.name);
04398 if (!res)
04399 res = ast_streamfile(mychannel, ((mytele->mylink.hasconnected) ?
04400 "rpt/remote_disc" : "rpt/remote_busy"), mychannel->language);
04401 break;
04402 case REMALREADY:
04403
04404 wait_interval(myrpt, DLY_TELEM, mychannel);
04405 res = ast_streamfile(mychannel, "rpt/remote_already", mychannel->language);
04406 break;
04407 case REMNOTFOUND:
04408
04409 wait_interval(myrpt, DLY_TELEM, mychannel);
04410 res = ast_streamfile(mychannel, "rpt/remote_notfound", mychannel->language);
04411 break;
04412 case REMGO:
04413
04414 wait_interval(myrpt, DLY_TELEM, mychannel);
04415 res = ast_streamfile(mychannel, "rpt/remote_go", mychannel->language);
04416 break;
04417 case CONNECTED:
04418
04419 wait_interval(myrpt, DLY_TELEM, mychannel);
04420 res = saynode(myrpt,mychannel,mytele->mylink.name);
04421 if (!res)
04422 res = ast_streamfile(mychannel, "rpt/connected", mychannel->language);
04423 if (!res)
04424 res = ast_waitstream(mychannel, "");
04425 else
04426 ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", mychannel->name);
04427 ast_stopstream(mychannel);
04428 res = ast_streamfile(mychannel, "digits/2", 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 = saynode(myrpt,mychannel,myrpt->name);
04435 imdone = 1;
04436 break;
04437 case CONNFAIL:
04438 res = saynode(myrpt,mychannel,mytele->mylink.name);
04439 if (!res)
04440 res = ast_streamfile(mychannel, "rpt/connection_failed", mychannel->language);
04441 break;
04442 case MEMNOTFOUND:
04443
04444 wait_interval(myrpt, DLY_TELEM, mychannel);
04445 res = ast_streamfile(mychannel, "rpt/memory_notfound", mychannel->language);
04446 break;
04447 case PLAYBACK:
04448
04449 wait_interval(myrpt, DLY_TELEM, mychannel);
04450 res = ast_streamfile(mychannel, mytele->param, mychannel->language);
04451 break;
04452 case TOPKEY:
04453
04454 wait_interval(myrpt, DLY_TELEM, mychannel);
04455 for(i = 0; i < TOPKEYN; i++)
04456 {
04457 if (!myrpt->topkey[i].node[0]) continue;
04458 if ((!myrpt->topkeylong) && (myrpt->topkey[i].keyed)) continue;
04459 res = saynode(myrpt, mychannel, myrpt->topkey[i].node);
04460 if (!res) res = sayfile(mychannel,(myrpt->topkey[i].keyed) ?
04461 "rpt/keyedfor" : "rpt/unkeyedfor");
04462 if (!res) res = saynum(mychannel,
04463 myrpt->topkey[i].timesince);
04464 if (!res) res = sayfile(mychannel,"rpt/seconds");
04465 if (!myrpt->topkeylong) break;
04466 }
04467 imdone = 1;
04468 break;
04469 case SETREMOTE:
04470 ast_mutex_lock(&myrpt->remlock);
04471 res = 0;
04472 if(!strcmp(myrpt->remoterig, remote_rig_ft897))
04473 {
04474 res = set_ft897(myrpt);
04475 }
04476 else if(!strcmp(myrpt->remoterig, remote_rig_tm271))
04477 {
04478 res = set_tm271(myrpt);
04479 }
04480 else if(!strcmp(myrpt->remoterig, remote_rig_ic706))
04481 {
04482 res = set_ic706(myrpt);
04483 }
04484 #ifdef HAVE_IOPERM
04485 else if(!strcmp(myrpt->remoterig, remote_rig_rbi)||!strcmp(myrpt->remoterig, remote_rig_ppp16))
04486 {
04487 if (ioperm(myrpt->p.iobase,1,1) == -1)
04488 {
04489 rpt_mutex_unlock(&myrpt->lock);
04490 ast_log(LOG_WARNING, "Cant get io permission on IO port %x hex\n",myrpt->p.iobase);
04491 res = -1;
04492 }
04493 else res = setrbi(myrpt);
04494 }
04495 #endif
04496 else if(!strcmp(myrpt->remoterig, remote_rig_kenwood))
04497 {
04498 if (myrpt->iofd >= 0) setdtr(myrpt->iofd,1);
04499 res = setkenwood(myrpt);
04500 if (myrpt->iofd >= 0) setdtr(myrpt->iofd,0);
04501 if (ast_safe_sleep(mychannel,200) == -1)
04502 {
04503 ast_mutex_unlock(&myrpt->remlock);
04504 res = -1;
04505 break;
04506 }
04507 if (myrpt->iofd < 0)
04508 {
04509 i = DAHDI_FLUSH_EVENT;
04510 if (ioctl(myrpt->dahditxchannel->fds[0],DAHDI_FLUSH,&i) == -1)
04511 {
04512 ast_mutex_unlock(&myrpt->remlock);
04513 ast_log(LOG_ERROR,"Cant flush events");
04514 res = -1;
04515 break;
04516 }
04517 if (ioctl(myrpt->dahdirxchannel->fds[0],DAHDI_GET_PARAMS,&par) == -1)
04518 {
04519 ast_mutex_unlock(&myrpt->remlock);
04520 ast_log(LOG_ERROR,"Cant get params");
04521 res = -1;
04522 break;
04523 }
04524 myrpt->remoterx =
04525 (par.rxisoffhook || (myrpt->tele.next != &myrpt->tele));
04526 }
04527 }
04528
04529 ast_mutex_unlock(&myrpt->remlock);
04530 if (!res)
04531 {
04532 imdone = 1;
04533 break;
04534 }
04535
04536 case INVFREQ:
04537
04538 wait_interval(myrpt, DLY_TELEM, mychannel);
04539 res = ast_streamfile(mychannel, "rpt/invalid-freq", mychannel->language);
04540 break;
04541 case REMMODE:
04542 cp = 0;
04543 wait_interval(myrpt, DLY_TELEM, mychannel);
04544 switch(myrpt->remmode)
04545 {
04546 case REM_MODE_FM:
04547 saycharstr(mychannel,"FM");
04548 break;
04549 case REM_MODE_USB:
04550 saycharstr(mychannel,"USB");
04551 break;
04552 case REM_MODE_LSB:
04553 saycharstr(mychannel,"LSB");
04554 break;
04555 case REM_MODE_AM:
04556 saycharstr(mychannel,"AM");
04557 break;
04558 }
04559 wait_interval(myrpt, DLY_COMP, mychannel);
04560 if (!res) res = telem_lookup(myrpt,mychannel, myrpt->name, "functcomplete");
04561 break;
04562 case LOGINREQ:
04563 wait_interval(myrpt, DLY_TELEM, mychannel);
04564 sayfile(mychannel,"rpt/login");
04565 saycharstr(mychannel,myrpt->name);
04566 break;
04567 case REMLOGIN:
04568 wait_interval(myrpt, DLY_TELEM, mychannel);
04569 saycharstr(mychannel,myrpt->loginuser);
04570 saynode(myrpt,mychannel,myrpt->name);
04571 wait_interval(myrpt, DLY_COMP, mychannel);
04572 if (!res) res = telem_lookup(myrpt,mychannel, myrpt->name, "functcomplete");
04573 break;
04574 case REMXXX:
04575 wait_interval(myrpt, DLY_TELEM, mychannel);
04576 res = 0;
04577 switch(mytele->submode)
04578 {
04579 case 100:
04580 sayfile(mychannel, "rpt/rxpl");
04581 sayfile(mychannel, "rpt/off");
04582 break;
04583 case 101:
04584 sayfile(mychannel, "rpt/rxpl");
04585 sayfile(mychannel, "rpt/on");
04586 break;
04587 case 102:
04588 sayfile(mychannel, "rpt/txpl");
04589 sayfile(mychannel, "rpt/off");
04590 break;
04591 case 103:
04592 sayfile(mychannel, "rpt/txpl");
04593 sayfile(mychannel, "rpt/on");
04594 break;
04595 case 104:
04596 sayfile(mychannel, "rpt/lopwr");
04597 break;
04598 case 105:
04599 sayfile(mychannel, "rpt/medpwr");
04600 break;
04601 case 106:
04602 sayfile(mychannel, "rpt/hipwr");
04603 break;
04604 case 113:
04605 sayfile(mychannel,"rpt/down");
04606 sayfile(mychannel, "rpt/slow");
04607 break;
04608 case 114:
04609 sayfile(mychannel,"rpt/down");
04610 sayfile(mychannel, "rpt/quick");
04611 break;
04612 case 115:
04613 sayfile(mychannel,"rpt/down");
04614 sayfile(mychannel, "rpt/fast");
04615 break;
04616 case 116:
04617 sayfile(mychannel,"rpt/up");
04618 sayfile(mychannel, "rpt/slow");
04619 break;
04620 case 117:
04621 sayfile(mychannel,"rpt/up");
04622 sayfile(mychannel, "rpt/quick");
04623 break;
04624 case 118:
04625 sayfile(mychannel,"rpt/up");
04626 sayfile(mychannel, "rpt/fast");
04627 break;
04628 default:
04629 res = -1;
04630 }
04631 wait_interval(myrpt, DLY_COMP, mychannel);
04632 if (!res) res = telem_lookup(myrpt,mychannel, myrpt->name, "functcomplete");
04633 break;
04634 case SCAN:
04635 ast_mutex_lock(&myrpt->remlock);
04636 if (myrpt->hfscanstop)
04637 {
04638 myrpt->hfscanstatus = 0;
04639 myrpt->hfscanmode = 0;
04640 myrpt->hfscanstop = 0;
04641 mytele->mode = SCANSTAT;
04642 ast_mutex_unlock(&myrpt->remlock);
04643 if (ast_safe_sleep(mychannel,1000) == -1) break;
04644 sayfile(mychannel, "rpt/stop");
04645 imdone = 1;
04646 break;
04647 }
04648 if (myrpt->hfscanstatus > -2) service_scan(myrpt);
04649 i = myrpt->hfscanstatus;
04650 myrpt->hfscanstatus = 0;
04651 if (i) mytele->mode = SCANSTAT;
04652 ast_mutex_unlock(&myrpt->remlock);
04653 if (i < 0) sayfile(mychannel, "rpt/stop");
04654 else if (i > 0) saynum(mychannel,i);
04655 imdone = 1;
04656 break;
04657 case TUNE:
04658 ast_mutex_lock(&myrpt->remlock);
04659 if (!strcmp(myrpt->remoterig,remote_rig_ic706))
04660 {
04661 set_mode_ic706(myrpt, REM_MODE_AM);
04662 if(play_tone(mychannel, 800, 6000, 8192) == -1) break;
04663 ast_safe_sleep(mychannel,500);
04664 set_mode_ic706(myrpt, myrpt->remmode);
04665 myrpt->tunerequest = 0;
04666 ast_mutex_unlock(&myrpt->remlock);
04667 imdone = 1;
04668 break;
04669 }
04670 set_mode_ft897(myrpt, REM_MODE_AM);
04671 simple_command_ft897(myrpt, 8);
04672 if(play_tone(mychannel, 800, 6000, 8192) == -1) break;
04673 simple_command_ft897(myrpt, 0x88);
04674 ast_safe_sleep(mychannel,500);
04675 set_mode_ft897(myrpt, myrpt->remmode);
04676 myrpt->tunerequest = 0;
04677 ast_mutex_unlock(&myrpt->remlock);
04678 imdone = 1;
04679 break;
04680 case REMSHORTSTATUS:
04681 case REMLONGSTATUS:
04682 wait_interval(myrpt, DLY_TELEM, mychannel);
04683 res = saynode(myrpt,mychannel,myrpt->name);
04684 if(!res)
04685 res = sayfile(mychannel,"rpt/frequency");
04686 if(!res)
04687 res = split_freq(mhz, decimals, myrpt->freq);
04688 if (!multimode_capable(myrpt)) decimals[3] = 0;
04689 if(!res){
04690 m = atoi(mhz);
04691 if(m < 100)
04692 res = saynum(mychannel, m);
04693 else
04694 res = saycharstr(mychannel, mhz);
04695 }
04696 if(!res)
04697 res = sayfile(mychannel, "letters/dot");
04698 if(!res)
04699 res = saycharstr(mychannel, decimals);
04700
04701 if(res) break;
04702 if(myrpt->remmode == REM_MODE_FM){
04703 switch(myrpt->offset){
04704
04705 case REM_MINUS:
04706 res = sayfile(mychannel,"rpt/minus");
04707 break;
04708
04709 case REM_SIMPLEX:
04710 res = sayfile(mychannel,"rpt/simplex");
04711 break;
04712
04713 case REM_PLUS:
04714 res = sayfile(mychannel,"rpt/plus");
04715 break;
04716
04717 default:
04718 break;
04719 }
04720 }
04721 else{
04722 switch(myrpt->remmode){
04723
04724 case REM_MODE_USB:
04725 res = saycharstr(mychannel, "USB");
04726 break;
04727
04728 case REM_MODE_LSB:
04729 res = saycharstr(mychannel, "LSB");
04730 break;
04731
04732 case REM_MODE_AM:
04733 res = saycharstr(mychannel, "AM");
04734 break;
04735
04736
04737 default:
04738 break;
04739 }
04740 }
04741
04742 if (res == -1) break;
04743
04744 if(mytele->mode == REMSHORTSTATUS){
04745 wait_interval(myrpt, DLY_COMP, mychannel);
04746 if (!res) res = telem_lookup(myrpt,mychannel, myrpt->name, "functcomplete");
04747 break;
04748 }
04749
04750 if (strcmp(myrpt->remoterig,remote_rig_ic706))
04751 {
04752 switch(myrpt->powerlevel){
04753
04754 case REM_LOWPWR:
04755 res = sayfile(mychannel,"rpt/lopwr") ;
04756 break;
04757 case REM_MEDPWR:
04758 res = sayfile(mychannel,"rpt/medpwr");
04759 break;
04760 case REM_HIPWR:
04761 res = sayfile(mychannel,"rpt/hipwr");
04762 break;
04763 }
04764 }
04765
04766 rbimode = ((!strncmp(myrpt->remoterig,remote_rig_rbi,3))
04767 || (!strncmp(myrpt->remoterig,remote_rig_ic706,3)));
04768 if (res || (sayfile(mychannel,"rpt/rxpl") == -1)) break;
04769 if (rbimode && (sayfile(mychannel,"rpt/txpl") == -1)) break;
04770 if ((sayfile(mychannel,"rpt/frequency") == -1) ||
04771 (saycharstr(mychannel,myrpt->rxpl) == -1)) break;
04772 if ((!rbimode) && ((sayfile(mychannel,"rpt/txpl") == -1) ||
04773 (sayfile(mychannel,"rpt/frequency") == -1) ||
04774 (saycharstr(mychannel,myrpt->txpl) == -1))) break;
04775 if(myrpt->remmode == REM_MODE_FM){
04776 if ((sayfile(mychannel,"rpt/rxpl") == -1) ||
04777 (sayfile(mychannel,((myrpt->rxplon) ? "rpt/on" : "rpt/off")) == -1) ||
04778 (sayfile(mychannel,"rpt/txpl") == -1) ||
04779 (sayfile(mychannel,((myrpt->txplon) ? "rpt/on" : "rpt/off")) == -1))
04780 {
04781 break;
04782 }
04783 }
04784 wait_interval(myrpt, DLY_COMP, mychannel);
04785 if (!res) res = telem_lookup(myrpt,mychannel, myrpt->name, "functcomplete");
04786 break;
04787 case STATUS:
04788
04789 wait_interval(myrpt, DLY_TELEM, mychannel);
04790 hastx = 0;
04791 linkbase.next = &linkbase;
04792 linkbase.prev = &linkbase;
04793 rpt_mutex_lock(&myrpt->lock);
04794
04795 l = myrpt->links.next;
04796 while(l != &myrpt->links)
04797 {
04798 if (l->name[0] == '0')
04799 {
04800 l = l->next;
04801 continue;
04802 }
04803 l1 = ast_malloc(sizeof(struct rpt_link));
04804 if (!l1)
04805 {
04806 ast_log(LOG_WARNING, "Cannot alloc memory on %s\n", mychannel->name);
04807 remque((struct qelem *)mytele);
04808 myrpt->active_telem = NULL;
04809 rpt_mutex_unlock(&myrpt->lock);
04810 ast_log(LOG_NOTICE,"Telemetry thread aborted at line %d, mode: %d\n",__LINE__, mytele->mode);
04811 ast_free(nodename);
04812 ast_free(ident);
04813 ast_free(mytele);
04814 ast_hangup(mychannel);
04815 pthread_exit(NULL);
04816 }
04817 memcpy(l1,l,sizeof(struct rpt_link));
04818 l1->next = l1->prev = NULL;
04819 insque((struct qelem *)l1,(struct qelem *)linkbase.next);
04820 l = l->next;
04821 }
04822 rpt_mutex_unlock(&myrpt->lock);
04823 res = saynode(myrpt,mychannel,myrpt->name);
04824 if (myrpt->callmode)
04825 {
04826 hastx = 1;
04827 res = ast_streamfile(mychannel, "rpt/autopatch_on", mychannel->language);
04828 if (!res)
04829 res = ast_waitstream(mychannel, "");
04830 else
04831 ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", mychannel->name);
04832 ast_stopstream(mychannel);
04833 }
04834 l = linkbase.next;
04835 while(l != &linkbase)
04836 {
04837 char *s;
04838
04839 hastx = 1;
04840 res = saynode(myrpt,mychannel,l->name);
04841 s = "rpt/tranceive";
04842 if (!l->mode) s = "rpt/monitor";
04843 if (!l->thisconnected) s = "rpt/connecting";
04844 res = ast_streamfile(mychannel, s, mychannel->language);
04845 if (!res)
04846 res = ast_waitstream(mychannel, "");
04847 else
04848 ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", mychannel->name);
04849 ast_stopstream(mychannel);
04850 l = l->next;
04851 }
04852 if (!hastx)
04853 {
04854 res = ast_streamfile(mychannel, "rpt/repeat_only", mychannel->language);
04855 if (!res)
04856 res = ast_waitstream(mychannel, "");
04857 else
04858 ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", mychannel->name);
04859 ast_stopstream(mychannel);
04860 }
04861
04862 l = linkbase.next;
04863 while(l != &linkbase)
04864 {
04865 l1 = l;
04866 l = l->next;
04867 remque((struct qelem *)l1);
04868 ast_free(l1);
04869 }
04870 imdone = 1;
04871 break;
04872 case FULLSTATUS:
04873 rpt_mutex_lock(&myrpt->lock);
04874
04875 __mklinklist(myrpt,NULL,lbuf);
04876 rpt_mutex_unlock(&myrpt->lock);
04877
04878 ns = finddelim(lbuf,strs,MAXLINKLIST);
04879
04880 if (ns) qsort((void *)strs,ns,sizeof(char *),mycompar);
04881
04882 wait_interval(myrpt, DLY_TELEM, mychannel);
04883 hastx = 0;
04884 res = saynode(myrpt,mychannel,myrpt->name);
04885 if (myrpt->callmode)
04886 {
04887 hastx = 1;
04888 res = ast_streamfile(mychannel, "rpt/autopatch_on", mychannel->language);
04889 if (!res)
04890 res = ast_waitstream(mychannel, "");
04891 else
04892 ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", mychannel->name);
04893 ast_stopstream(mychannel);
04894 }
04895
04896 for(i = 0; i < ns; i++)
04897 {
04898 char *s,mode = 'T';
04899
04900
04901 if ((*strs[i] < '0') || (*strs[i] > '9'))
04902 {
04903 mode = *strs[i];
04904 strs[i]++;
04905 }
04906
04907 hastx = 1;
04908 res = saynode(myrpt,mychannel,strs[i]);
04909 s = "rpt/tranceive";
04910 if (mode == 'R') s = "rpt/monitor";
04911 if (mode == 'C') s = "rpt/connecting";
04912 res = ast_streamfile(mychannel, s, mychannel->language);
04913 if (!res)
04914 res = ast_waitstream(mychannel, "");
04915 else
04916 ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", mychannel->name);
04917 ast_stopstream(mychannel);
04918 }
04919 if (!hastx)
04920 {
04921 res = ast_streamfile(mychannel, "rpt/repeat_only", mychannel->language);
04922 if (!res)
04923 res = ast_waitstream(mychannel, "");
04924 else
04925 ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", mychannel->name);
04926 ast_stopstream(mychannel);
04927 }
04928 imdone = 1;
04929 break;
04930
04931 case LASTNODEKEY:
04932 rpt_mutex_lock(&myrpt->lock);
04933 if(myrpt->lastnodewhichkeyedusup){
04934 p = ast_strdup(myrpt->lastnodewhichkeyedusup);
04935 if(!p){
04936 ast_log(LOG_WARNING, "ast_strdup failed in telemetery LASTNODEKEY");
04937 imdone = 1;
04938 break;
04939 }
04940 }
04941 else
04942 p = NULL;
04943 rpt_mutex_unlock(&myrpt->lock);
04944 if(!p){
04945 imdone = 1;
04946 break;
04947 }
04948 wait_interval(myrpt, DLY_TELEM, mychannel);
04949 res = saynode(myrpt,mychannel,p);
04950 ast_free(p);
04951 imdone = 1;
04952 break;
04953
04954 case UNAUTHTX:
04955 wait_interval(myrpt, DLY_TELEM, mychannel);
04956 res = ast_streamfile(mychannel, "rpt/unauthtx", mychannel->language);
04957 if (!res)
04958 res = ast_waitstream(mychannel, "");
04959 else
04960 ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", mychannel->name);
04961 ast_stopstream(mychannel);
04962 imdone = 1;
04963 break;
04964
04965 case PARROT:
04966
04967 sprintf(mystr,PARROTFILE,myrpt->name,(unsigned int)mytele->parrot);
04968 if (ast_fileexists(mystr,NULL,mychannel->language) <= 0)
04969 {
04970 imdone = 1;
04971 myrpt->parrotstate = 0;
04972 break;
04973 }
04974 wait_interval(myrpt, DLY_PARROT, mychannel);
04975 sprintf(mystr,PARROTFILE,myrpt->name,(unsigned int)mytele->parrot);
04976 res = ast_streamfile(mychannel, mystr, mychannel->language);
04977 if (!res)
04978 res = ast_waitstream(mychannel, "");
04979 else
04980 ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", mychannel->name);
04981 ast_stopstream(mychannel);
04982 sprintf(mystr,PARROTFILE,myrpt->name,(unsigned int)mytele->parrot);
04983 strcat(mystr,".wav");
04984 unlink(mystr);
04985 imdone = 1;
04986 myrpt->parrotstate = 0;
04987 break;
04988
04989 case TIMEOUT:
04990 res = saynode(myrpt,mychannel,myrpt->name);
04991 if (!res)
04992 res = ast_streamfile(mychannel, "rpt/timeout", mychannel->language);
04993 break;
04994
04995 case TIMEOUT_WARNING:
04996 time(&t);
04997 res = saynode(myrpt,mychannel,myrpt->name);
04998 if (!res)
04999 res = ast_streamfile(mychannel, "rpt/timeout-warning", mychannel->language);
05000 if (!res)
05001 res = ast_waitstream(mychannel, "");
05002 else
05003 ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", mychannel->name);
05004 ast_stopstream(mychannel);
05005 if(!res)
05006 ast_say_number(mychannel, myrpt->p.remotetimeout -
05007 (t - myrpt->last_activity_time),
05008 "", mychannel->language, (char *) NULL);
05009 if (!res)
05010 res = ast_waitstream(mychannel, "");
05011 ast_stopstream(mychannel);
05012 res = ast_streamfile(mychannel, "queue-seconds", mychannel->language);
05013 break;
05014
05015 case ACT_TIMEOUT_WARNING:
05016 time(&t);
05017 res = saynode(myrpt,mychannel,myrpt->name);
05018 if (!res)
05019 res = ast_streamfile(mychannel, "rpt/act-timeout-warning", mychannel->language);
05020 if (!res)
05021 res = ast_waitstream(mychannel, "");
05022 else
05023 ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", mychannel->name);
05024 ast_stopstream(mychannel);
05025 if(!res)
05026 ast_say_number(mychannel, myrpt->p.remoteinacttimeout -
05027 (t - myrpt->last_activity_time),
05028 "", mychannel->language, (char *) NULL);
05029 if (!res)
05030 res = ast_waitstream(mychannel, "");
05031 ast_stopstream(mychannel);
05032 res = ast_streamfile(mychannel, "queue-seconds", mychannel->language);
05033 break;
05034
05035 case STATS_TIME:
05036 case STATS_TIME_LOCAL:
05037 wait_interval(myrpt, DLY_TELEM, mychannel);
05038 t = time(NULL);
05039 rpt_localtime(&t, &localtm);
05040
05041 if((localtm.tm_hour >= 0) && (localtm.tm_hour < 12))
05042 p = "rpt/goodmorning";
05043 else if((localtm.tm_hour >= 12) && (localtm.tm_hour < 18))
05044 p = "rpt/goodafternoon";
05045 else
05046 p = "rpt/goodevening";
05047 if (sayfile(mychannel,p) == -1)
05048 {
05049 imdone = 1;
05050 break;
05051 }
05052
05053 if (sayfile(mychannel,"rpt/thetimeis") == -1)
05054 {
05055 imdone = 1;
05056 break;
05057 }
05058
05059 res = ast_say_time(mychannel, t, "", mychannel->language);
05060 if (!res)
05061 res = ast_waitstream(mychannel, "");
05062 ast_stopstream(mychannel);
05063 imdone = 1;
05064 break;
05065 case STATS_VERSION:
05066 p = strstr(tdesc, "version");
05067 if(!p)
05068 break;
05069 if(sscanf(p, "version %30d.%30d", &vmajor, &vminor) != 2)
05070 break;
05071 wait_interval(myrpt, DLY_TELEM, mychannel);
05072
05073 if (sayfile(mychannel,"rpt/version") == -1)
05074 {
05075 imdone = 1;
05076 break;
05077 }
05078 if(!res)
05079 ast_say_number(mychannel, vmajor, "", mychannel->language, (char *) NULL);
05080 if (!res)
05081 res = ast_waitstream(mychannel, "");
05082 ast_stopstream(mychannel);
05083 if (saycharstr(mychannel,".") == -1)
05084 {
05085 imdone = 1;
05086 break;
05087 }
05088 if(!res)
05089 ast_say_number(mychannel, vminor, "", mychannel->language, (char *) NULL);
05090 if (!res){
05091 res = ast_waitstream(mychannel, "");
05092 ast_stopstream(mychannel);
05093 }
05094 else
05095 ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", mychannel->name);
05096 imdone = 1;
05097 break;
05098 case ARB_ALPHA:
05099 wait_interval(myrpt, DLY_TELEM, mychannel);
05100 if(mytele->param)
05101 saycharstr(mychannel, mytele->param);
05102 imdone = 1;
05103 break;
05104 case REV_PATCH:
05105 wait_interval(myrpt, DLY_TELEM, mychannel);
05106 if(mytele->param) {
05107
05108
05109 char *tpl_working, *tpl_current;
05110 char *tmp[100], *myparm;
05111 int looptemp=0,idx=0, dres = 0;
05112
05113
05114 tpl_working = ast_strdup(mytele->param);
05115 myparm = strsep(&tpl_working,",");
05116 tpl_current=strsep(&tpl_working, ":");
05117
05118 while(tpl_current && looptemp < sizeof(tmp)) {
05119 tmp[looptemp]=tpl_current;
05120 looptemp++;
05121 tpl_current=strsep(&tpl_working,":");
05122 }
05123
05124 for(idx=0; idx<looptemp; idx++) {
05125 if(!strcmp(tmp[idx], "PARKED")) {
05126 ast_say_digits(mychannel, atoi(myparm), "", mychannel->language);
05127 } else if(!strcmp(tmp[idx], "NODE")) {
05128 ast_say_digits(mychannel, atoi(myrpt->name), "", mychannel->language);
05129 } else {
05130 dres = ast_streamfile(mychannel, tmp[idx], mychannel->language);
05131 if(!dres) {
05132 dres = ast_waitstream(mychannel, "");
05133 } else {
05134 ast_log(LOG_WARNING, "ast_streamfile of %s failed on %s\n", tmp[idx], mychannel->name);
05135 dres = 0;
05136 }
05137 }
05138 }
05139 ast_free(tpl_working);
05140 }
05141 imdone = 1;
05142 break;
05143 case TEST_TONE:
05144 imdone = 1;
05145 if (myrpt->stopgen) break;
05146 myrpt->stopgen = -1;
05147 if ((res = ast_tonepair_start(mychannel, 1004.0, 0, 99999999, 7200.0)))
05148 {
05149 myrpt->stopgen = 0;
05150 break;
05151 }
05152 while(mychannel->generatordata && (myrpt->stopgen <= 0)) {
05153 if (ast_safe_sleep(mychannel,1)) break;
05154 imdone = 1;
05155 }
05156 myrpt->stopgen = 0;
05157 break;
05158 default:
05159 break;
05160 }
05161 if (!imdone)
05162 {
05163 if (!res)
05164 res = ast_waitstream(mychannel, "");
05165 else {
05166 ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", mychannel->name);
05167 res = 0;
05168 }
05169 }
05170 ast_stopstream(mychannel);
05171 rpt_mutex_lock(&myrpt->lock);
05172 if (mytele->mode == TAILMSG)
05173 {
05174 if (!res)
05175 {
05176 myrpt->tailmessagen++;
05177 if(myrpt->tailmessagen >= myrpt->p.tailmessagemax) myrpt->tailmessagen = 0;
05178 }
05179 else
05180 {
05181 myrpt->tmsgtimer = myrpt->p.tailsquashedtime;
05182 }
05183 }
05184 remque((struct qelem *)mytele);
05185 myrpt->active_telem = NULL;
05186 rpt_mutex_unlock(&myrpt->lock);
05187 ast_free(nodename);
05188 ast_free(ident);
05189 ast_free(mytele);
05190 ast_hangup(mychannel);
05191 #ifdef APP_RPT_LOCK_DEBUG
05192 {
05193 struct lockthread *t;
05194
05195 sleep(5);
05196 ast_mutex_lock(&locklock);
05197 t = get_lockthread(pthread_self());
05198 if (t) memset(t,0,sizeof(struct lockthread));
05199 ast_mutex_unlock(&locklock);
05200 }
05201 #endif
05202 pthread_exit(NULL);
05203 }
05204
05205 static void rpt_telemetry(struct rpt *myrpt,int mode, void *data)
05206 {
05207 struct rpt_tele *tele;
05208 struct rpt_link *mylink = NULL;
05209 int res;
05210 pthread_attr_t attr;
05211 char *v1, *v2;
05212
05213 if(debug > 6)
05214 ast_log(LOG_NOTICE,"mode=%i data=%s\n",mode, (char *)data);
05215
05216 switch(mode)
05217 {
05218 case UNKEY:
05219
05220
05221 v1 = (char *) ast_variable_retrieve(myrpt->cfg, myrpt->name,
05222 "unlinkedct");
05223 v2 = (char *) ast_variable_retrieve(myrpt->cfg, myrpt->name,
05224 "remotect");
05225 if (telem_lookup(myrpt,NULL, myrpt->name, "remotemon") &&
05226 telem_lookup(myrpt,NULL, myrpt->name, "remotetx") &&
05227 telem_lookup(myrpt,NULL, myrpt->name, "cmdmode") &&
05228 (!(v1 && telem_lookup(myrpt,NULL, myrpt->name, v1))) &&
05229 (!(v2 && telem_lookup(myrpt,NULL, myrpt->name, v2)))) return;
05230 break;
05231 case LINKUNKEY:
05232 if (!ast_variable_retrieve(myrpt->cfg, myrpt->name, "linkunkeyct"))
05233 return;
05234 break;
05235 default:
05236 break;
05237 }
05238 tele = ast_malloc(sizeof(struct rpt_tele));
05239 if (!tele)
05240 {
05241 ast_log(LOG_WARNING, "Unable to allocate memory\n");
05242 pthread_exit(NULL);
05243 return;
05244 }
05245
05246 memset((char *)tele,0,sizeof(struct rpt_tele));
05247 tele->rpt = myrpt;
05248 tele->mode = mode;
05249 if (mode == PARROT) tele->parrot = (uintptr_t) data;
05250 else mylink = (struct rpt_link *) data;
05251 rpt_mutex_lock(&myrpt->lock);
05252 if((mode == CONNFAIL) || (mode == REMDISC) || (mode == CONNECTED) ||
05253 (mode == LINKUNKEY)){
05254 memset(&tele->mylink,0,sizeof(struct rpt_link));
05255 if (mylink){
05256 memcpy(&tele->mylink,mylink,sizeof(struct rpt_link));
05257 }
05258 }
05259 else if ((mode == ARB_ALPHA) || (mode == REV_PATCH) || (mode == PLAYBACK)) {
05260 strncpy(tele->param, (char *) data, TELEPARAMSIZE - 1);
05261 tele->param[TELEPARAMSIZE - 1] = 0;
05262 }
05263 if (mode == REMXXX) tele->submode = (intptr_t) data;
05264 insque((struct qelem *)tele, (struct qelem *)myrpt->tele.next);
05265 rpt_mutex_unlock(&myrpt->lock);
05266 pthread_attr_init(&attr);
05267 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
05268 res = ast_pthread_create(&tele->threadid,&attr,rpt_tele_thread,(void *) tele);
05269 if(res < 0){
05270 rpt_mutex_lock(&myrpt->lock);
05271 remque((struct qlem *) tele);
05272 rpt_mutex_unlock(&myrpt->lock);
05273 ast_log(LOG_WARNING, "Could not create telemetry thread: %s",strerror(res));
05274 }
05275 return;
05276 }
05277
05278 static void *rpt_call(void *this)
05279 {
05280 struct dahdi_confinfo ci;
05281 struct rpt *myrpt = (struct rpt *)this;
05282 int res;
05283 int stopped,congstarted,dialtimer,lastcidx,aborted;
05284 struct ast_channel *mychannel,*genchannel;
05285
05286 myrpt->mydtmf = 0;
05287
05288 mychannel = ast_request("DAHDI",AST_FORMAT_SLINEAR,"pseudo",NULL);
05289 if (!mychannel)
05290 {
05291 fprintf(stderr,"rpt:Sorry unable to obtain pseudo channel\n");
05292 pthread_exit(NULL);
05293 }
05294 #ifdef AST_CDR_FLAG_POST_DISABLED
05295 if (mychannel->cdr)
05296 ast_set_flag(mychannel->cdr,AST_CDR_FLAG_POST_DISABLED);
05297 #endif
05298 ci.chan = 0;
05299 ci.confno = myrpt->conf;
05300 #if 0
05301 ci.confmode = DAHDI_CONF_REALANDPSEUDO | DAHDI_CONF_TALKER | DAHDI_CONF_LISTENER
05302 | DAHDI_CONF_PSEUDO_TALKER | DAHDI_CONF_PSEUDO_LISTENER;
05303 #endif
05304 ci.confmode = DAHDI_CONF_CONF | DAHDI_CONF_TALKER | DAHDI_CONF_LISTENER;
05305
05306 if (ioctl(mychannel->fds[0],DAHDI_SETCONF,&ci) == -1)
05307 {
05308 ast_log(LOG_WARNING, "Unable to set conference mode to Announce\n");
05309 ast_hangup(mychannel);
05310 myrpt->callmode = 0;
05311 pthread_exit(NULL);
05312 }
05313
05314 genchannel = ast_request("DAHDI",AST_FORMAT_SLINEAR,"pseudo",NULL);
05315 if (!genchannel)
05316 {
05317 fprintf(stderr,"rpt:Sorry unable to obtain pseudo channel\n");
05318 ast_hangup(mychannel);
05319 pthread_exit(NULL);
05320 }
05321 #ifdef AST_CDR_FLAG_POST_DISABLED
05322 if (genchannel->cdr)
05323 ast_set_flag(genchannel->cdr,AST_CDR_FLAG_POST_DISABLED);
05324 #endif
05325 ci.chan = 0;
05326 ci.confno = myrpt->conf;
05327 ci.confmode = DAHDI_CONF_REALANDPSEUDO | DAHDI_CONF_TALKER | DAHDI_CONF_LISTENER
05328 | DAHDI_CONF_PSEUDO_TALKER | DAHDI_CONF_PSEUDO_LISTENER;
05329
05330 if (ioctl(genchannel->fds[0],DAHDI_SETCONF,&ci) == -1)
05331 {
05332 ast_log(LOG_WARNING, "Unable to set conference mode to Announce\n");
05333 ast_hangup(mychannel);
05334 ast_hangup(genchannel);
05335 myrpt->callmode = 0;
05336 pthread_exit(NULL);
05337 }
05338 if (myrpt->p.tonezone && (tone_zone_set_zone(mychannel->fds[0],myrpt->p.tonezone) == -1))
05339 {
05340 ast_log(LOG_WARNING, "Unable to set tone zone %s\n",myrpt->p.tonezone);
05341 ast_hangup(mychannel);
05342 ast_hangup(genchannel);
05343 myrpt->callmode = 0;
05344 pthread_exit(NULL);
05345 }
05346 if (myrpt->p.tonezone && (tone_zone_set_zone(genchannel->fds[0],myrpt->p.tonezone) == -1))
05347 {
05348 ast_log(LOG_WARNING, "Unable to set tone zone %s\n",myrpt->p.tonezone);
05349 ast_hangup(mychannel);
05350 ast_hangup(genchannel);
05351 myrpt->callmode = 0;
05352 pthread_exit(NULL);
05353 }
05354
05355 if ((!myrpt->patchquiet) && (tone_zone_play_tone(genchannel->fds[0],DAHDI_TONE_DIALTONE) < 0))
05356 {
05357 ast_log(LOG_WARNING, "Cannot start dialtone\n");
05358 ast_hangup(mychannel);
05359 ast_hangup(genchannel);
05360 myrpt->callmode = 0;
05361 pthread_exit(NULL);
05362 }
05363 stopped = 0;
05364 congstarted = 0;
05365 dialtimer = 0;
05366 lastcidx = 0;
05367 myrpt->calldigittimer = 0;
05368 aborted = 0;
05369
05370 while ((myrpt->callmode == 1) || (myrpt->callmode == 4))
05371 {
05372 if((myrpt->patchdialtime)&&(myrpt->callmode == 1)&&(myrpt->cidx != lastcidx)){
05373 dialtimer = 0;
05374 lastcidx = myrpt->cidx;
05375 }
05376
05377 if((myrpt->patchdialtime)&&(dialtimer >= myrpt->patchdialtime)){
05378 if(debug)
05379 ast_log(LOG_NOTICE, "dialtimer %i > patchdialtime %i\n", dialtimer,myrpt->patchdialtime);
05380 rpt_mutex_lock(&myrpt->lock);
05381 aborted = 1;
05382 myrpt->callmode = 0;
05383 rpt_mutex_unlock(&myrpt->lock);
05384 break;
05385 }
05386
05387 if ((!myrpt->patchquiet) && (!stopped) && (myrpt->callmode == 1) && (myrpt->cidx > 0))
05388 {
05389 stopped = 1;
05390
05391 tone_zone_play_tone(genchannel->fds[0],-1);
05392 }
05393 if (myrpt->callmode == 1)
05394 {
05395 if(myrpt->calldigittimer > PATCH_DIALPLAN_TIMEOUT)
05396 {
05397 myrpt->callmode = 2;
05398 break;
05399 }
05400
05401 if (myrpt->calldigittimer)
05402 myrpt->calldigittimer += MSWAIT;
05403 }
05404 if (myrpt->callmode == 4)
05405 {
05406 if(!congstarted){
05407 congstarted = 1;
05408
05409 tone_zone_play_tone(genchannel->fds[0],DAHDI_TONE_CONGESTION);
05410 }
05411 }
05412 res = ast_safe_sleep(mychannel, MSWAIT);
05413 if (res < 0)
05414 {
05415 if(debug)
05416 ast_log(LOG_NOTICE, "ast_safe_sleep=%i\n", res);
05417 ast_hangup(mychannel);
05418 ast_hangup(genchannel);
05419 rpt_mutex_lock(&myrpt->lock);
05420 myrpt->callmode = 0;
05421 rpt_mutex_unlock(&myrpt->lock);
05422 pthread_exit(NULL);
05423 }
05424 dialtimer += MSWAIT;
05425 }
05426
05427 tone_zone_play_tone(genchannel->fds[0],-1);
05428
05429 if (!myrpt->callmode)
05430 {
05431 if(debug)
05432 ast_log(LOG_NOTICE, "callmode==0\n");
05433 ast_hangup(mychannel);
05434 ast_hangup(genchannel);
05435 rpt_mutex_lock(&myrpt->lock);
05436 myrpt->callmode = 0;
05437 myrpt->macropatch=0;
05438 channel_revert(myrpt);
05439 rpt_mutex_unlock(&myrpt->lock);
05440 if((!myrpt->patchquiet) && aborted)
05441 rpt_telemetry(myrpt, TERM, NULL);
05442 pthread_exit(NULL);
05443 }
05444
05445 if (myrpt->p.ourcallerid && *myrpt->p.ourcallerid){
05446 char *name, *loc, *instr;
05447 instr = ast_strdup(myrpt->p.ourcallerid);
05448 if(instr){
05449 ast_callerid_parse(instr, &name, &loc);
05450 if(loc){
05451 if(mychannel->cid.cid_num)
05452 ast_free(mychannel->cid.cid_num);
05453 mychannel->cid.cid_num = ast_strdup(loc);
05454 }
05455 if(name){
05456 if(mychannel->cid.cid_name)
05457 ast_free(mychannel->cid.cid_name);
05458 mychannel->cid.cid_name = ast_strdup(name);
05459 }
05460 ast_free(instr);
05461 }
05462 }
05463
05464 ast_copy_string(mychannel->exten, myrpt->exten, sizeof(mychannel->exten) - 1);
05465 ast_copy_string(mychannel->context, myrpt->patchcontext, sizeof(mychannel->context) - 1);
05466
05467 if (myrpt->p.acctcode)
05468 ast_cdr_setaccount(mychannel,myrpt->p.acctcode);
05469 mychannel->priority = 1;
05470 ast_channel_undefer_dtmf(mychannel);
05471 if (ast_pbx_start(mychannel) < 0)
05472 {
05473 ast_log(LOG_WARNING, "Unable to start PBX!!\n");
05474 ast_hangup(mychannel);
05475 ast_hangup(genchannel);
05476 rpt_mutex_lock(&myrpt->lock);
05477 myrpt->callmode = 0;
05478 rpt_mutex_unlock(&myrpt->lock);
05479 pthread_exit(NULL);
05480 }
05481 usleep(10000);
05482 rpt_mutex_lock(&myrpt->lock);
05483 myrpt->callmode = 3;
05484
05485 ci.chan = 0;
05486 ci.confno = myrpt->conf;
05487 ci.confmode = (myrpt->p.duplex == 2) ? DAHDI_CONF_CONFANNMON :
05488 (DAHDI_CONF_CONF | DAHDI_CONF_LISTENER | DAHDI_CONF_TALKER);
05489
05490 if (ioctl(myrpt->pchannel->fds[0],DAHDI_SETCONF,&ci) == -1)
05491 {
05492 ast_log(LOG_WARNING, "Unable to set conference mode to Announce\n");
05493 ast_hangup(mychannel);
05494 ast_hangup(genchannel);
05495 myrpt->callmode = 0;
05496 pthread_exit(NULL);
05497 }
05498
05499 if (ioctl(mychannel->fds[0],DAHDI_CHANNO,&res) == -1)
05500 {
05501 ast_log(LOG_WARNING, "Unable to get autopatch channel number\n");
05502 ast_hangup(mychannel);
05503 myrpt->callmode = 0;
05504 pthread_exit(NULL);
05505 }
05506 ci.chan = 0;
05507 ci.confno = res;
05508 ci.confmode = DAHDI_CONF_MONITOR;
05509
05510 if (ioctl(myrpt->voxchannel->fds[0],DAHDI_SETCONF,&ci) == -1)
05511 {
05512 ast_log(LOG_WARNING, "Unable to set conference mode to Announce\n");
05513 ast_hangup(mychannel);
05514 myrpt->callmode = 0;
05515 pthread_exit(NULL);
05516 }
05517 while(myrpt->callmode)
05518 {
05519 if ((!mychannel->pbx) && (myrpt->callmode != 4))
05520 {
05521
05522 if(myrpt->patchfarenddisconnect || (myrpt->p.duplex < 2)){
05523 if(debug)ast_log(LOG_NOTICE,"callmode=%i, patchfarenddisconnect=%i, duplex=%i\n",\
05524 myrpt->callmode,myrpt->patchfarenddisconnect,myrpt->p.duplex);
05525 myrpt->callmode = 0;
05526 myrpt->macropatch=0;
05527 if(!myrpt->patchquiet){
05528 rpt_mutex_unlock(&myrpt->lock);
05529 rpt_telemetry(myrpt, TERM, NULL);
05530 rpt_mutex_lock(&myrpt->lock);
05531 }
05532 }
05533 else{
05534 myrpt->callmode = 4;
05535 rpt_mutex_unlock(&myrpt->lock);
05536
05537 tone_zone_play_tone(genchannel->fds[0],DAHDI_TONE_CONGESTION);
05538 rpt_mutex_lock(&myrpt->lock);
05539 }
05540 }
05541 if (myrpt->mydtmf)
05542 {
05543 struct ast_frame wf = {AST_FRAME_DTMF, } ;
05544 wf.subclass = myrpt->mydtmf;
05545 rpt_mutex_unlock(&myrpt->lock);
05546 ast_queue_frame(mychannel,&wf);
05547 #ifdef NEW_ASTERISK
05548 ast_senddigit(genchannel,myrpt->mydtmf,0);
05549 #else
05550 ast_senddigit(genchannel,myrpt->mydtmf);
05551 #endif
05552 rpt_mutex_lock(&myrpt->lock);
05553 myrpt->mydtmf = 0;
05554 }
05555 rpt_mutex_unlock(&myrpt->lock);
05556 usleep(MSWAIT * 1000);
05557 rpt_mutex_lock(&myrpt->lock);
05558 }
05559 if(debug)
05560 ast_log(LOG_NOTICE, "exit channel loop\n");
05561 rpt_mutex_unlock(&myrpt->lock);
05562 tone_zone_play_tone(genchannel->fds[0],-1);
05563 if (mychannel->pbx) ast_softhangup(mychannel,AST_SOFTHANGUP_DEV);
05564 ast_hangup(genchannel);
05565 rpt_mutex_lock(&myrpt->lock);
05566 myrpt->callmode = 0;
05567 myrpt->macropatch=0;
05568 channel_revert(myrpt);
05569 rpt_mutex_unlock(&myrpt->lock);
05570
05571 ci.chan = 0;
05572 ci.confno = myrpt->conf;
05573 ci.confmode = ((myrpt->p.duplex == 2) || (myrpt->p.duplex == 4)) ? DAHDI_CONF_CONFANNMON :
05574 (DAHDI_CONF_CONF | DAHDI_CONF_LISTENER | DAHDI_CONF_TALKER);
05575
05576 if (ioctl(myrpt->pchannel->fds[0],DAHDI_SETCONF,&ci) == -1)
05577 {
05578 ast_log(LOG_WARNING, "Unable to set conference mode to Announce\n");
05579 }
05580 pthread_exit(NULL);
05581 }
05582
05583 static void send_link_dtmf(struct rpt *myrpt,char c)
05584 {
05585 char str[300];
05586 struct ast_frame wf;
05587 struct rpt_link *l;
05588
05589 snprintf(str, sizeof(str), "D %s %s %d %c", myrpt->cmdnode, myrpt->name, ++(myrpt->dtmfidx), c);
05590 wf.frametype = AST_FRAME_TEXT;
05591 wf.subclass = 0;
05592 wf.offset = 0;
05593 wf.mallocd = 0;
05594 wf.datalen = strlen(str) + 1;
05595 wf.samples = 0;
05596 l = myrpt->links.next;
05597
05598 while(l != &myrpt->links)
05599 {
05600 if (l->name[0] == '0')
05601 {
05602 l = l->next;
05603 continue;
05604 }
05605
05606 if (!strcmp(l->name,myrpt->cmdnode))
05607 {
05608 wf.data.ptr = str;
05609 if (l->chan) ast_write(l->chan,&wf);
05610 return;
05611 }
05612 l = l->next;
05613 }
05614 l = myrpt->links.next;
05615
05616 while(l != &myrpt->links)
05617 {
05618 wf.data.ptr = str;
05619 if (l->chan) ast_write(l->chan,&wf);
05620 l = l->next;
05621 }
05622 return;
05623 }
05624
05625 static void send_link_keyquery(struct rpt *myrpt)
05626 {
05627 char str[300];
05628 struct ast_frame wf;
05629 struct rpt_link *l;
05630
05631 rpt_mutex_lock(&myrpt->lock);
05632 memset(myrpt->topkey,0,sizeof(myrpt->topkey));
05633 myrpt->topkeystate = 1;
05634 time(&myrpt->topkeytime);
05635 rpt_mutex_unlock(&myrpt->lock);
05636 snprintf(str, sizeof(str), "K? * %s 0 0", myrpt->name);
05637 wf.frametype = AST_FRAME_TEXT;
05638 wf.subclass = 0;
05639 wf.offset = 0;
05640 wf.mallocd = 0;
05641 wf.datalen = strlen(str) + 1;
05642 wf.samples = 0;
05643 l = myrpt->links.next;
05644
05645 while(l != &myrpt->links)
05646 {
05647 wf.data.ptr = str;
05648 if (l->chan) ast_write(l->chan,&wf);
05649 l = l->next;
05650 }
05651 return;
05652 }
05653
05654
05655
05656 static void send_newkey(struct ast_channel *chan)
05657 {
05658
05659
05660 ast_sendtext(chan,newkeystr);
05661 return;
05662 }
05663
05664
05665
05666
05667
05668
05669
05670
05671
05672
05673
05674
05675
05676 static int connect_link(struct rpt *myrpt, char* node, int mode, int perma)
05677 {
05678 char *val, *s, *s1, *s2, *tele;
05679 char lstr[MAXLINKLIST],*strs[MAXLINKLIST];
05680 char tmp[300], deststr[300] = "",modechange = 0;
05681 char sx[320],*sy;
05682 struct rpt_link *l;
05683 int reconnects = 0;
05684 int i,n;
05685 struct dahdi_confinfo ci;
05686
05687 val = node_lookup(myrpt,node);
05688 if (!val){
05689 if(strlen(node) >= myrpt->longestnode)
05690 return -1;
05691 return 1;
05692 }
05693
05694 if(!strcmp(myrpt->name,node))
05695 return -2;
05696
05697 if(debug > 3){
05698 ast_log(LOG_NOTICE,"Connect attempt to node %s\n", node);
05699 ast_log(LOG_NOTICE,"Mode: %s\n",(mode)?"Transceive":"Monitor");
05700 ast_log(LOG_NOTICE,"Connection type: %s\n",(perma)?"Permalink":"Normal");
05701 }
05702
05703 strncpy(tmp,val,sizeof(tmp) - 1);
05704 s = tmp;
05705 s1 = strsep(&s,",");
05706 if (!strchr(s1,':') && strchr(s1,'/') && strncasecmp(s1, "local/", 6))
05707 {
05708 sy = strchr(s1,'/');
05709 *sy = 0;
05710 sprintf(sx,"%s:4569/%s",s1,sy + 1);
05711 s1 = sx;
05712 }
05713 s2 = strsep(&s,",");
05714 rpt_mutex_lock(&myrpt->lock);
05715 l = myrpt->links.next;
05716
05717 while(l != &myrpt->links){
05718 if (l->name[0] == '0')
05719 {
05720 l = l->next;
05721 continue;
05722 }
05723
05724 if (!strcmp(l->name, node))
05725 break;
05726 l = l->next;
05727 }
05728
05729 if (l != &myrpt->links){
05730
05731 if ((l->mode) || (!l->chan)) {
05732 rpt_mutex_unlock(&myrpt->lock);
05733 return 2;
05734 }
05735 reconnects = l->reconnects;
05736 rpt_mutex_unlock(&myrpt->lock);
05737 if (l->chan) ast_softhangup(l->chan, AST_SOFTHANGUP_DEV);
05738 l->retries = l->max_retries + 1;
05739 l->disced = 2;
05740 modechange = 1;
05741 } else
05742 {
05743 __mklinklist(myrpt,NULL,lstr);
05744 rpt_mutex_unlock(&myrpt->lock);
05745 n = finddelim(lstr,strs,MAXLINKLIST);
05746 for(i = 0; i < n; i++)
05747 {
05748 if ((*strs[i] < '0') ||
05749 (*strs[i] > '9')) strs[i]++;
05750 if (!strcmp(strs[i],node))
05751 {
05752 return 2;
05753 }
05754 }
05755 }
05756 strncpy(myrpt->lastlinknode,node,MAXNODESTR - 1);
05757
05758 l = ast_malloc(sizeof(struct rpt_link));
05759 if (!l)
05760 {
05761 ast_log(LOG_WARNING, "Unable to malloc\n");
05762 return -1;
05763 }
05764
05765 memset((char *)l,0,sizeof(struct rpt_link));
05766 l->mode = mode;
05767 l->outbound = 1;
05768 l->thisconnected = 0;
05769 voxinit_link(l,1);
05770 strncpy(l->name, node, MAXNODESTR - 1);
05771 l->isremote = (s && ast_true(s));
05772 if (modechange) l->connected = 1;
05773 l->hasconnected = l->perma = perma;
05774 #ifdef ALLOW_LOCAL_CHANNELS
05775 if ((strncasecmp(s1,"iax2/", 5) == 0) || (strncasecmp(s1, "local/", 6) == 0))
05776 strncpy(deststr, s1, sizeof(deststr));
05777 else
05778 snprintf(deststr, sizeof(deststr), "IAX2/%s", s1);
05779 #else
05780 snprintf(deststr, sizeof(deststr), "IAX2/%s", s1);
05781 #endif
05782 tele = strchr(deststr, '/');
05783 if (!tele){
05784 ast_log(LOG_WARNING,"link3:Dial number (%s) must be in format tech/number\n",deststr);
05785 ast_free(l);
05786 return -1;
05787 }
05788 *tele++ = 0;
05789 l->chan = ast_request(deststr, AST_FORMAT_SLINEAR, tele,NULL);
05790 if (l->chan){
05791 ast_set_read_format(l->chan, AST_FORMAT_SLINEAR);
05792 ast_set_write_format(l->chan, AST_FORMAT_SLINEAR);
05793 #ifdef AST_CDR_FLAG_POST_DISABLED
05794 if (l->chan->cdr)
05795 ast_set_flag(l->chan->cdr,AST_CDR_FLAG_POST_DISABLED);
05796 #endif
05797 #ifndef NEW_ASTERISK
05798 l->chan->whentohangup = 0;
05799 #endif
05800 l->chan->appl = "Apprpt";
05801 l->chan->data = "(Remote Rx)";
05802 if (debug > 3)
05803 ast_log(LOG_NOTICE, "rpt (remote) initiating call to %s/%s on %s\n",
05804 deststr, tele, l->chan->name);
05805 if(l->chan->cid.cid_num)
05806 ast_free(l->chan->cid.cid_num);
05807 l->chan->cid.cid_num = ast_strdup(myrpt->name);
05808 ast_call(l->chan,tele,999);
05809 }
05810 else {
05811 if(debug > 3)
05812 ast_log(LOG_NOTICE, "Unable to place call to %s/%s on %s\n",
05813 deststr,tele,l->chan->name);
05814 if (myrpt->p.archivedir)
05815 {
05816 char str[100];
05817 sprintf(str,"LINKFAIL,%s",l->name);
05818 donodelog(myrpt,str);
05819 }
05820 ast_free(l);
05821 return -1;
05822 }
05823
05824 l->pchan = ast_request("DAHDI",AST_FORMAT_SLINEAR,"pseudo",NULL);
05825 if (!l->pchan){
05826 ast_log(LOG_WARNING,"rpt connect: Sorry unable to obtain pseudo channel\n");
05827 ast_hangup(l->chan);
05828 ast_free(l);
05829 return -1;
05830 }
05831 ast_set_read_format(l->pchan, AST_FORMAT_SLINEAR);
05832 ast_set_write_format(l->pchan, AST_FORMAT_SLINEAR);
05833 #ifdef AST_CDR_FLAG_POST_DISABLED
05834 if (l->pchan->cdr)
05835 ast_set_flag(l->pchan->cdr,AST_CDR_FLAG_POST_DISABLED);
05836 #endif
05837
05838 ci.chan = 0;
05839 ci.confno = myrpt->conf;
05840 ci.confmode = DAHDI_CONF_CONF | DAHDI_CONF_LISTENER | DAHDI_CONF_TALKER;
05841
05842 if (ioctl(l->pchan->fds[0], DAHDI_SETCONF, &ci) == -1)
05843 {
05844 ast_log(LOG_WARNING, "Unable to set conference mode to Announce\n");
05845 ast_hangup(l->chan);
05846 ast_hangup(l->pchan);
05847 ast_free(l);
05848 return -1;
05849 }
05850 rpt_mutex_lock(&myrpt->lock);
05851 l->reconnects = reconnects;
05852
05853 l->max_retries = MAX_RETRIES;
05854 if (perma)
05855 l->max_retries = MAX_RETRIES_PERM;
05856 if (l->isremote) l->retries = l->max_retries + 1;
05857 insque((struct qelem *)l,(struct qelem *)myrpt->links.next);
05858 __kickshort(myrpt);
05859 rpt_mutex_unlock(&myrpt->lock);
05860 if (!l->phonemode) send_newkey(l->chan);
05861 return 0;
05862 }
05863
05864
05865
05866
05867
05868
05869
05870 static int function_ilink(struct rpt *myrpt, char *param, char *digits, int command_source, struct rpt_link *mylink)
05871 {
05872
05873 char *val, *s, *s1, *s2;
05874 char tmp[300];
05875 char digitbuf[MAXNODESTR],*strs[MAXLINKLIST];
05876 char mode,perma;
05877 char sx[320],*sy;
05878 struct rpt_link *l;
05879 int i,r;
05880
05881 if(!param)
05882 return DC_ERROR;
05883
05884
05885 if (myrpt->p.s[myrpt->p.sysstate_cur].txdisable || myrpt->p.s[myrpt->p.sysstate_cur].linkfundisable )
05886 return DC_ERROR;
05887
05888 strncpy(digitbuf,digits,MAXNODESTR - 1);
05889
05890 if(debug > 6)
05891 printf("@@@@ ilink param = %s, digitbuf = %s\n", (param)? param : "(null)", digitbuf);
05892
05893 switch(myatoi(param)){
05894 case 11:
05895 case 1:
05896 if ((digitbuf[0] == '0') && (myrpt->lastlinknode[0]))
05897 strcpy(digitbuf,myrpt->lastlinknode);
05898 val = node_lookup(myrpt,digitbuf);
05899 if (!val){
05900 if(strlen(digitbuf) >= myrpt->longestnode)
05901 return DC_ERROR;
05902 break;
05903 }
05904 strncpy(tmp,val,sizeof(tmp) - 1);
05905 s = tmp;
05906 s1 = strsep(&s,",");
05907 if (!strchr(s1,':') && strchr(s1,'/') && strncasecmp(s1, "local/", 6))
05908 {
05909 sy = strchr(s1,'/');
05910 *sy = 0;
05911 sprintf(sx,"%s:4569/%s",s1,sy + 1);
05912 s1 = sx;
05913 }
05914 s2 = strsep(&s,",");
05915 rpt_mutex_lock(&myrpt->lock);
05916 l = myrpt->links.next;
05917
05918 while(l != &myrpt->links){
05919 if (l->name[0] == '0')
05920 {
05921 l = l->next;
05922 continue;
05923 }
05924
05925 if (!strcmp(l->name, digitbuf))
05926 break;
05927 l = l->next;
05928 }
05929 if (l != &myrpt->links){
05930 struct ast_frame wf;
05931
05932
05933 if ((myatoi(param) < 10) &&
05934 (l->max_retries > MAX_RETRIES))
05935 {
05936 rpt_mutex_unlock(&myrpt->lock);
05937 return DC_COMPLETE;
05938 }
05939 strncpy(myrpt->lastlinknode,digitbuf,MAXNODESTR - 1);
05940 l->retries = l->max_retries + 1;
05941 l->disced = 1;
05942 rpt_mutex_unlock(&myrpt->lock);
05943 wf.frametype = AST_FRAME_TEXT;
05944 wf.subclass = 0;
05945 wf.offset = 0;
05946 wf.mallocd = 0;
05947 wf.datalen = strlen(discstr) + 1;
05948 wf.samples = 0;
05949 wf.data.ptr = discstr;
05950 if (l->chan)
05951 {
05952 ast_write(l->chan,&wf);
05953 if (ast_safe_sleep(l->chan,250) == -1) return DC_ERROR;
05954 ast_softhangup(l->chan,AST_SOFTHANGUP_DEV);
05955 }
05956 rpt_telemetry(myrpt, COMPLETE, NULL);
05957 return DC_COMPLETE;
05958 }
05959 rpt_mutex_unlock(&myrpt->lock);
05960 return DC_COMPLETE;
05961 case 2:
05962 case 3:
05963 case 12:
05964 case 13:
05965 if ((digitbuf[0] == '0') && (myrpt->lastlinknode[0]))
05966 strcpy(digitbuf,myrpt->lastlinknode);
05967
05968 perma = (atoi(param) > 10) ? 1 : 0;
05969 mode = (atoi(param) & 1) ? 1 : 0;
05970 r = connect_link(myrpt, digitbuf, mode, perma);
05971 switch(r){
05972 case -2:
05973 return DC_COMPLETE;
05974
05975 case 0:
05976 rpt_telemetry(myrpt, COMPLETE, NULL);
05977 return DC_COMPLETE;
05978
05979 case 1:
05980 break;
05981
05982 case 2:
05983 rpt_telemetry(myrpt, REMALREADY, NULL);
05984 return DC_COMPLETE;
05985
05986 default:
05987 rpt_telemetry(myrpt, CONNFAIL, NULL);
05988 return DC_COMPLETE;
05989 }
05990 break;
05991
05992 case 4:
05993
05994
05995 if (((command_source != SOURCE_RPT) &&
05996 (command_source != SOURCE_PHONE) &&
05997 (command_source != SOURCE_ALT) &&
05998 (command_source != SOURCE_DPHONE)) ||
05999 (myrpt->links.next == &myrpt->links))
06000 return DC_COMPLETE;
06001
06002
06003 if ((myrpt->cmdnode[0]) || (!strcmp(myrpt->name, digitbuf))){
06004
06005 rpt_telemetry(myrpt, REMALREADY, NULL);
06006 return DC_COMPLETE;
06007 }
06008 if ((digitbuf[0] == '0') && (myrpt->lastlinknode[0]))
06009 strcpy(digitbuf,myrpt->lastlinknode);
06010
06011 val = node_lookup(myrpt,digitbuf);
06012 if (!val){
06013 if(strlen(digitbuf) >= myrpt->longestnode)
06014 return DC_ERROR;
06015 break;
06016
06017 }
06018 rpt_mutex_lock(&myrpt->lock);
06019 strcpy(myrpt->lastlinknode,digitbuf);
06020 strncpy(myrpt->cmdnode, digitbuf, sizeof(myrpt->cmdnode) - 1);
06021 rpt_mutex_unlock(&myrpt->lock);
06022 rpt_telemetry(myrpt, REMGO, NULL);
06023 return DC_COMPLETE;
06024
06025 case 5:
06026 rpt_telemetry(myrpt, STATUS, NULL);
06027 return DC_COMPLETE;
06028
06029 case 15:
06030 rpt_telemetry(myrpt, FULLSTATUS, NULL);
06031 return DC_COMPLETE;
06032
06033
06034 case 6:
06035 rpt_mutex_lock(&myrpt->lock);
06036 myrpt->savednodes[0] = 0;
06037 l = myrpt->links.next;
06038
06039 while(l != &myrpt->links){
06040 struct ast_frame wf;
06041 if (l->name[0] == '0')
06042 {
06043 l = l->next;
06044 continue;
06045 }
06046
06047 sprintf(tmp,"%c%c%s",(l->mode) ? 'X' : 'M',(l->perma) ? 'P':'T',l->name);
06048 if(strlen(tmp) + strlen(myrpt->savednodes) + 1 < MAXNODESTR){
06049 if(myrpt->savednodes[0])
06050 strcat(myrpt->savednodes, ",");
06051 strcat(myrpt->savednodes, tmp);
06052 }
06053 l->retries = l->max_retries + 1;
06054 l->disced = 2;
06055 rpt_mutex_unlock(&myrpt->lock);
06056
06057
06058 wf.frametype = AST_FRAME_TEXT;
06059 wf.subclass = 0;
06060 wf.offset = 0;
06061 wf.mallocd = 0;
06062 wf.datalen = strlen(discstr) + 1;
06063 wf.samples = 0;
06064 wf.data.ptr = discstr;
06065 if (l->chan)
06066 {
06067 ast_write(l->chan,&wf);
06068 ast_safe_sleep(l->chan,250);
06069 ast_softhangup(l->chan,AST_SOFTHANGUP_DEV);
06070 }
06071 rpt_mutex_lock(&myrpt->lock);
06072 l = l->next;
06073 }
06074 rpt_mutex_unlock(&myrpt->lock);
06075 if(debug > 3)
06076 ast_log(LOG_NOTICE,"Nodes disconnected: %s\n",myrpt->savednodes);
06077 rpt_telemetry(myrpt, COMPLETE, NULL);
06078 return DC_COMPLETE;
06079
06080 case 7:
06081 rpt_telemetry(myrpt, LASTNODEKEY, NULL);
06082 break;
06083
06084
06085 #ifdef _MDC_DECODE_H_
06086 case 8:
06087 myrpt->lastunit = 0xd00d;
06088 mdc1200_notify(myrpt,NULL,myrpt->lastunit);
06089 mdc1200_send(myrpt,myrpt->lastunit);
06090 break;
06091 #endif
06092
06093 case 16:
06094 strcpy(tmp, myrpt->savednodes);
06095 finddelim(tmp, strs, MAXLINKLIST);
06096 for(i = 0; tmp[0] && strs[i] != NULL && i < MAXLINKLIST; i++){
06097 s1 = strs[i];
06098 mode = (s1[0] == 'X') ? 1 : 0;
06099 perma = (s1[1] == 'P') ? 1 : 0;
06100 connect_link(myrpt, s1 + 2, mode, perma);
06101 }
06102 rpt_telemetry(myrpt, COMPLETE, NULL);
06103 break;
06104
06105 case 200:
06106 case 201:
06107 case 202:
06108 case 203:
06109 case 204:
06110 case 205:
06111 case 206:
06112 case 207:
06113 case 208:
06114 case 209:
06115 case 210:
06116 case 211:
06117 case 212:
06118 case 213:
06119 case 214:
06120 case 215:
06121 if (((myrpt->p.propagate_dtmf) &&
06122 (command_source == SOURCE_LNK)) ||
06123 ((myrpt->p.propagate_phonedtmf) &&
06124 ((command_source == SOURCE_PHONE) ||
06125 (command_source == SOURCE_ALT) ||
06126 (command_source == SOURCE_DPHONE))))
06127 do_dtmf_local(myrpt,
06128 remdtmfstr[myatoi(param) - 200]);
06129 default:
06130 return DC_ERROR;
06131
06132 }
06133
06134 return DC_INDETERMINATE;
06135 }
06136
06137
06138
06139
06140
06141 static int function_autopatchup(struct rpt *myrpt, char *param, char *digitbuf, int command_source, struct rpt_link *mylink)
06142 {
06143 pthread_attr_t attr;
06144 int i, idx, paramlength;
06145 char *lparam;
06146 char *value = NULL;
06147 char *paramlist[20];
06148
06149 static char *keywords[] = {
06150 "context",
06151 "dialtime",
06152 "farenddisconnect",
06153 "noct",
06154 "quiet",
06155 NULL
06156 };
06157
06158 if (myrpt->p.s[myrpt->p.sysstate_cur].txdisable || myrpt->p.s[myrpt->p.sysstate_cur].autopatchdisable)
06159 return DC_ERROR;
06160
06161 if(debug)
06162 printf("@@@@ Autopatch up\n");
06163
06164 if(!myrpt->callmode){
06165
06166 myrpt->patchnoct = 0;
06167 myrpt->patchdialtime = 0;
06168 myrpt->patchfarenddisconnect = 0;
06169 myrpt->patchquiet = 0;
06170 strncpy(myrpt->patchcontext, myrpt->p.ourcontext, MAXPATCHCONTEXT);
06171
06172 if(param){
06173
06174 lparam = ast_strdup(param);
06175 if(!lparam){
06176 ast_log(LOG_ERROR,"App_rpt out of memory on line %d\n",__LINE__);
06177 return DC_ERROR;
06178 }
06179 paramlength = finddelim(lparam, paramlist, 20);
06180 for(i = 0; i < paramlength; i++){
06181 idx = matchkeyword(paramlist[i], &value, keywords);
06182 if(value)
06183 value = skipchars(value, "= ");
06184 switch(idx){
06185
06186 case 1:
06187 strncpy(myrpt->patchcontext, value, MAXPATCHCONTEXT - 1) ;
06188 break;
06189
06190 case 2:
06191 myrpt->patchdialtime = atoi(value);
06192 break;
06193
06194 case 3:
06195 myrpt->patchfarenddisconnect = atoi(value);
06196 break;
06197
06198 case 4:
06199 myrpt->patchnoct = atoi(value);
06200 break;
06201
06202 case 5:
06203 myrpt->patchquiet = atoi(value);
06204 break;
06205
06206 default:
06207 break;
06208 }
06209 }
06210 ast_free(lparam);
06211 }
06212 }
06213
06214 rpt_mutex_lock(&myrpt->lock);
06215
06216
06217
06218 if ((myrpt->callmode == 2) || (myrpt->callmode == 3)){
06219 myrpt->mydtmf = myrpt->p.endchar;
06220 }
06221 if (myrpt->callmode){
06222 rpt_mutex_unlock(&myrpt->lock);
06223 return DC_COMPLETE;
06224 }
06225 myrpt->callmode = 1;
06226 myrpt->cidx = 0;
06227 myrpt->exten[myrpt->cidx] = 0;
06228 rpt_mutex_unlock(&myrpt->lock);
06229 pthread_attr_init(&attr);
06230 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
06231 ast_pthread_create(&myrpt->rpt_call_thread,&attr,rpt_call,(void *) myrpt);
06232 return DC_COMPLETE;
06233 }
06234
06235
06236
06237
06238
06239 static int function_autopatchdn(struct rpt *myrpt, char *param, char *digitbuf, int command_source, struct rpt_link *mylink)
06240 {
06241 if (myrpt->p.s[myrpt->p.sysstate_cur].txdisable || myrpt->p.s[myrpt->p.sysstate_cur].autopatchdisable)
06242 return DC_ERROR;
06243
06244 if(debug)
06245 printf("@@@@ Autopatch down\n");
06246
06247 rpt_mutex_lock(&myrpt->lock);
06248
06249 myrpt->macropatch=0;
06250
06251 if (!myrpt->callmode){
06252 rpt_mutex_unlock(&myrpt->lock);
06253 return DC_COMPLETE;
06254 }
06255
06256 myrpt->callmode = 0;
06257 channel_revert(myrpt);
06258 rpt_mutex_unlock(&myrpt->lock);
06259 rpt_telemetry(myrpt, TERM, NULL);
06260 return DC_COMPLETE;
06261 }
06262
06263
06264
06265
06266
06267 static int function_status(struct rpt *myrpt, char *param, char *digitbuf, int command_source, struct rpt_link *mylink)
06268 {
06269
06270 if (!param)
06271 return DC_ERROR;
06272
06273 if ((myrpt->p.s[myrpt->p.sysstate_cur].txdisable) || (myrpt->p.s[myrpt->p.sysstate_cur].userfundisable))
06274 return DC_ERROR;
06275
06276 if(debug)
06277 printf("@@@@ status param = %s, digitbuf = %s\n", (param)? param : "(null)", digitbuf);
06278
06279 switch(myatoi(param)){
06280 case 1:
06281 rpt_telemetry(myrpt, ID1, NULL);
06282 return DC_COMPLETE;
06283 case 2:
06284 rpt_telemetry(myrpt, STATS_TIME, NULL);
06285 return DC_COMPLETE;
06286 case 3:
06287 rpt_telemetry(myrpt, STATS_VERSION, NULL);
06288 return DC_COMPLETE;
06289 case 11:
06290 rpt_telemetry(myrpt, ID , NULL);
06291 return DC_COMPLETE;
06292 case 12:
06293 rpt_telemetry(myrpt, STATS_TIME_LOCAL, NULL);
06294 return DC_COMPLETE;
06295 default:
06296 return DC_ERROR;
06297 }
06298 return DC_INDETERMINATE;
06299 }
06300
06301
06302
06303 static int function_macro(struct rpt *myrpt, char *param, char *digitbuf, int command_source, struct rpt_link *mylink)
06304 {
06305 char *val;
06306 int i;
06307 if (myrpt->remote)
06308 return DC_ERROR;
06309
06310 if(debug)
06311 printf("@@@@ macro-oni param = %s, digitbuf = %s\n", (param)? param : "(null)", digitbuf);
06312
06313 if(strlen(digitbuf) < 1)
06314 return DC_INDETERMINATE;
06315
06316 for(i = 0 ; i < digitbuf[i] ; i++) {
06317 if((digitbuf[i] < '0') || (digitbuf[i] > '9'))
06318 return DC_ERROR;
06319 }
06320
06321 if (*digitbuf == '0') val = myrpt->p.startupmacro;
06322 else val = (char *) ast_variable_retrieve(myrpt->cfg, myrpt->p.macro, digitbuf);
06323
06324 if (!val){
06325 if (strlen(digitbuf) < myrpt->macro_longest)
06326 return DC_INDETERMINATE;
06327 rpt_telemetry(myrpt, MACRO_NOTFOUND, NULL);
06328 return DC_COMPLETE;
06329 }
06330 rpt_mutex_lock(&myrpt->lock);
06331 if ((MAXMACRO - strlen(myrpt->macrobuf)) < strlen(val))
06332 {
06333 rpt_mutex_unlock(&myrpt->lock);
06334 rpt_telemetry(myrpt, MACRO_BUSY, NULL);
06335 return DC_ERROR;
06336 }
06337 myrpt->macrotimer = MACROTIME;
06338 strncat(myrpt->macrobuf,val,MAXMACRO - 1);
06339 rpt_mutex_unlock(&myrpt->lock);
06340 return DC_COMPLETE;
06341 }
06342
06343
06344
06345
06346
06347 static int function_playback(struct rpt *myrpt, char *param, char *digitbuf, int command_source, struct rpt_link *mylink)
06348 {
06349
06350 if (myrpt->remote)
06351 return DC_ERROR;
06352
06353 if(debug)
06354 printf("@@@@ playback param = %s, digitbuf = %s\n", (param)? param : "(null)", digitbuf);
06355
06356 if (ast_fileexists(param,NULL,myrpt->rxchannel->language) <= 0)
06357 return DC_ERROR;
06358
06359 rpt_telemetry(myrpt,PLAYBACK,param);
06360 return DC_COMPLETE;
06361 }
06362
06363
06364
06365
06366
06367 static int function_cop(struct rpt *myrpt, char *param, char *digitbuf, int command_source, struct rpt_link *mylink)
06368 {
06369 char string[16];
06370 int res;
06371
06372 int i, r;
06373
06374 if(!param)
06375 return DC_ERROR;
06376
06377 switch(myatoi(param)){
06378 case 1:
06379 res = system("killall -9 asterisk");
06380 return DC_COMPLETE;
06381
06382 case 2:
06383 myrpt->p.s[myrpt->p.sysstate_cur].txdisable = 0;
06384 rpt_telemetry(myrpt, ARB_ALPHA, (void *) "RPTENA");
06385 return DC_COMPLETE;
06386
06387 case 3:
06388 myrpt->p.s[myrpt->p.sysstate_cur].txdisable = 1;
06389 return DC_COMPLETE;
06390
06391 case 4:
06392 if (myrpt->stopgen < 0)
06393 {
06394 myrpt->stopgen = 1;
06395 }
06396 else
06397 {
06398 myrpt->stopgen = 0;
06399 rpt_telemetry(myrpt, TEST_TONE, NULL);
06400 }
06401 return DC_COMPLETE;
06402
06403 case 5:
06404 myrpt->disgorgetime = time(NULL) + 10;
06405 return DC_COMPLETE;
06406
06407 case 6:
06408 if (command_source != SOURCE_PHONE) return DC_INDETERMINATE;
06409 return DC_DOKEY;
06410
06411
06412 case 7:
06413 myrpt->p.s[myrpt->p.sysstate_cur].totdisable = 0;
06414 rpt_telemetry(myrpt, ARB_ALPHA, (void *) "TOTENA");
06415 return DC_COMPLETE;
06416
06417 case 8:
06418 myrpt->p.s[myrpt->p.sysstate_cur].totdisable = 1;
06419 rpt_telemetry(myrpt, ARB_ALPHA, (void *) "TOTDIS");
06420 return DC_COMPLETE;
06421
06422 case 9:
06423 myrpt->p.s[myrpt->p.sysstate_cur].autopatchdisable = 0;
06424 rpt_telemetry(myrpt, ARB_ALPHA, (void *) "APENA");
06425 return DC_COMPLETE;
06426
06427 case 10:
06428 myrpt->p.s[myrpt->p.sysstate_cur].autopatchdisable = 1;
06429 rpt_telemetry(myrpt, ARB_ALPHA, (void *) "APDIS");
06430 return DC_COMPLETE;
06431
06432 case 11:
06433 myrpt->p.s[myrpt->p.sysstate_cur].linkfundisable = 0;
06434 rpt_telemetry(myrpt, ARB_ALPHA, (void *) "LNKENA");
06435 return DC_COMPLETE;
06436
06437 case 12:
06438 myrpt->p.s[myrpt->p.sysstate_cur].linkfundisable = 1;
06439 rpt_telemetry(myrpt, ARB_ALPHA, (void *) "LNKDIS");
06440 return DC_COMPLETE;
06441
06442 case 13:
06443 string[0] = string[1] = 'S';
06444 string[2] = myrpt->p.sysstate_cur + '0';
06445 string[3] = '\0';
06446 rpt_telemetry(myrpt, ARB_ALPHA, (void *) string);
06447 return DC_COMPLETE;
06448
06449 case 14:
06450 if(strlen(digitbuf) == 0)
06451 break;
06452 if((digitbuf[0] < '0') || (digitbuf[0] > '9'))
06453 return DC_ERROR;
06454 myrpt->p.sysstate_cur = digitbuf[0] - '0';
06455 string[0] = string[1] = 'S';
06456 string[2] = myrpt->p.sysstate_cur + '0';
06457 string[3] = '\0';
06458 rpt_telemetry(myrpt, ARB_ALPHA, (void *) string);
06459 return DC_COMPLETE;
06460
06461 case 15:
06462 myrpt->p.s[myrpt->p.sysstate_cur].schedulerdisable = 0;
06463 rpt_telemetry(myrpt, ARB_ALPHA, (void *) "SKENA");
06464 return DC_COMPLETE;
06465
06466 case 16:
06467 myrpt->p.s[myrpt->p.sysstate_cur].schedulerdisable = 1;
06468 rpt_telemetry(myrpt, ARB_ALPHA, (void *) "SKDIS");
06469 return DC_COMPLETE;
06470
06471 case 17:
06472 myrpt->p.s[myrpt->p.sysstate_cur].userfundisable = 0;
06473 rpt_telemetry(myrpt, ARB_ALPHA, (void *) "UFENA");
06474 return DC_COMPLETE;
06475
06476 case 18:
06477 myrpt->p.s[myrpt->p.sysstate_cur].userfundisable = 1;
06478 rpt_telemetry(myrpt, ARB_ALPHA, (void *) "UFDIS");
06479 return DC_COMPLETE;
06480
06481 case 19:
06482 myrpt->p.s[myrpt->p.sysstate_cur].alternatetail = 1;
06483 rpt_telemetry(myrpt, ARB_ALPHA, (void *) "ATENA");
06484 return DC_COMPLETE;
06485
06486 case 20:
06487 myrpt->p.s[myrpt->p.sysstate_cur].alternatetail = 0;
06488 rpt_telemetry(myrpt, ARB_ALPHA, (void *) "ATDIS");
06489 return DC_COMPLETE;
06490
06491 case 21:
06492 birdbath(myrpt);
06493 if (myrpt->p.parrotmode < 2)
06494 {
06495 myrpt->p.parrotmode = 0;
06496 rpt_telemetry(myrpt,COMPLETE,NULL);
06497 return DC_COMPLETE;
06498 }
06499 break;
06500
06501 case 22:
06502 birdbath(myrpt);
06503 if (myrpt->p.parrotmode < 2)
06504 {
06505 myrpt->p.parrotmode = 1;
06506 rpt_telemetry(myrpt,COMPLETE,NULL);
06507 return DC_COMPLETE;
06508 }
06509 break;
06510 case 23:
06511 birdbath(myrpt);
06512 rpt_telemetry(myrpt,COMPLETE,NULL);
06513 return DC_COMPLETE;
06514 case 24:
06515 flush_telem(myrpt);
06516 rpt_telemetry(myrpt,COMPLETE,NULL);
06517 return DC_COMPLETE;
06518 case 25:
06519 send_link_keyquery(myrpt);
06520 myrpt->topkeylong = 0;
06521 rpt_telemetry(myrpt,COMPLETE,NULL);
06522 return DC_COMPLETE;
06523 case 26:
06524 send_link_keyquery(myrpt);
06525 myrpt->topkeylong = 1;
06526 rpt_telemetry(myrpt,COMPLETE,NULL);
06527 return DC_COMPLETE;
06528
06529 case 30:
06530
06531 if(strlen(digitbuf) < 2)
06532 break;
06533
06534 for(i = 0 ; i < 2 ; i++){
06535 if((digitbuf[i] < '0') || (digitbuf[i] > '9'))
06536 return DC_ERROR;
06537 }
06538
06539 r = retreive_memory(myrpt, digitbuf);
06540 if (r < 0){
06541 rpt_telemetry(myrpt,MEMNOTFOUND,NULL);
06542 return DC_COMPLETE;
06543 }
06544 if (r > 0){
06545 return DC_ERROR;
06546 }
06547 if (setrem(myrpt) == -1) return DC_ERROR;
06548 return DC_COMPLETE;
06549
06550 case 31:
06551
06552
06553 if(strlen(digitbuf) < 2)
06554 break;
06555
06556 for(i = 0 ; i < 2 ; i++){
06557 if((digitbuf[i] < '0') || (digitbuf[i] > '9'))
06558 return DC_ERROR;
06559 }
06560 channel_steer(myrpt,digitbuf);
06561 return DC_COMPLETE;
06562
06563 case 32:
06564 i = strlen(digitbuf);
06565 if(!i){
06566 if(debug > 3)
06567 ast_log(LOG_NOTICE,"Padtest entered");
06568 myrpt->inpadtest = 1;
06569 }
06570 else{
06571 if(debug > 3)
06572 ast_log(LOG_NOTICE,"Padtest len= %d digits=%s",i,digitbuf);
06573 if(digitbuf[i-1] != myrpt->p.endchar)
06574 break;
06575 rpt_telemetry(myrpt, ARB_ALPHA, digitbuf);
06576 myrpt->inpadtest = 0;
06577 if(debug > 3)
06578 ast_log(LOG_NOTICE,"Padtest exited");
06579 return DC_COMPLETE;
06580 }
06581 }
06582 return DC_INDETERMINATE;
06583 }
06584
06585
06586
06587 static int collect_function_digits(struct rpt *myrpt, char *digits,
06588 int command_source, struct rpt_link *mylink)
06589 {
06590 int i,rv;
06591 char *stringp,*action,*param,*functiondigits;
06592 char function_table_name[30] = "";
06593 char workstring[200];
06594
06595 struct ast_variable *vp;
06596
06597 if (debug > 6) ast_log(LOG_NOTICE,"digits=%s source=%d\n",digits, command_source);
06598
06599
06600
06601
06602 if (command_source == SOURCE_DPHONE) {
06603 if (!myrpt->p.dphone_functions) return DC_INDETERMINATE;
06604 strncpy(function_table_name, myrpt->p.dphone_functions, sizeof(function_table_name) - 1);
06605 }
06606 else if (command_source == SOURCE_ALT) {
06607 if (!myrpt->p.alt_functions) return DC_INDETERMINATE;
06608 strncpy(function_table_name, myrpt->p.alt_functions, sizeof(function_table_name) - 1);
06609 }
06610 else if (command_source == SOURCE_PHONE) {
06611 if (!myrpt->p.phone_functions) return DC_INDETERMINATE;
06612 strncpy(function_table_name, myrpt->p.phone_functions, sizeof(function_table_name) - 1);
06613 }
06614 else if (command_source == SOURCE_LNK)
06615 strncpy(function_table_name, myrpt->p.link_functions, sizeof(function_table_name) - 1);
06616 else
06617 strncpy(function_table_name, myrpt->p.functions, sizeof(function_table_name) - 1);
06618
06619 vp = ast_variable_browse(myrpt->cfg, function_table_name);
06620 while(vp) {
06621 if(!strncasecmp(vp->name, digits, strlen(vp->name)))
06622 break;
06623 vp = vp->next;
06624 }
06625
06626 if(!vp) {
06627 int n;
06628
06629 n = myrpt->longestfunc;
06630 if (command_source == SOURCE_LNK) n = myrpt->link_longestfunc;
06631 else
06632 if (command_source == SOURCE_PHONE) n = myrpt->phone_longestfunc;
06633 else
06634 if (command_source == SOURCE_ALT) n = myrpt->alt_longestfunc;
06635 else
06636 if (command_source == SOURCE_DPHONE) n = myrpt->dphone_longestfunc;
06637
06638 if(strlen(digits) >= n)
06639 return DC_ERROR;
06640 else
06641 return DC_INDETERMINATE;
06642 }
06643
06644 strncpy(workstring, vp->value, sizeof(workstring) - 1 );
06645 stringp = workstring;
06646 action = strsep(&stringp, ",");
06647 param = stringp;
06648 if(debug)
06649 printf("@@@@ action: %s, param = %s\n",action, (param) ? param : "(null)");
06650
06651 for(i = 0 ; i < (sizeof(function_table)/sizeof(struct function_table_tag)); i++){
06652 if(!strncasecmp(action, function_table[i].action, strlen(action)))
06653 break;
06654 }
06655 if(debug)
06656 printf("@@@@ table index i = %d\n",i);
06657 if(i == (sizeof(function_table)/sizeof(struct function_table_tag))){
06658
06659 return DC_ERROR;
06660 }
06661 if(function_table[i].function == NULL){
06662
06663 if(debug)
06664 printf("@@@@ NULL for action: %s\n",action);
06665 return DC_ERROR;
06666 }
06667 functiondigits = digits + strlen(vp->name);
06668 rv=(*function_table[i].function)(myrpt, param, functiondigits, command_source, mylink);
06669 if (debug > 6) ast_log(LOG_NOTICE,"rv=%i\n",rv);
06670 return(rv);
06671 }
06672
06673
06674 static void handle_link_data(struct rpt *myrpt, struct rpt_link *mylink,
06675 char *str)
06676 {
06677
06678
06679 char tmp[512], tmp1[512], cmd[300] = "", dest[300], src[300], c;
06680 int i,seq, res, ts;
06681 struct rpt_link *l;
06682 struct ast_frame wf;
06683
06684 wf.frametype = AST_FRAME_TEXT;
06685 wf.subclass = 0;
06686 wf.offset = 0;
06687 wf.mallocd = 0;
06688 wf.datalen = strlen(str) + 1;
06689 wf.samples = 0;
06690
06691 strncpy(tmp,str,sizeof(tmp) - 1);
06692
06693 if (!strcmp(tmp,discstr))
06694 {
06695 mylink->disced = 1;
06696 mylink->retries = mylink->max_retries + 1;
06697 ast_softhangup(mylink->chan,AST_SOFTHANGUP_DEV);
06698 return;
06699 }
06700 if (!strcmp(tmp,newkeystr))
06701 {
06702 mylink->newkey = 1;
06703 return;
06704 }
06705 if (tmp[0] == 'L')
06706 {
06707 rpt_mutex_lock(&myrpt->lock);
06708 strcpy(mylink->linklist,tmp + 2);
06709 time(&mylink->linklistreceived);
06710 rpt_mutex_unlock(&myrpt->lock);
06711 if (debug > 6) ast_log(LOG_NOTICE,"@@@@ node %s received node list %s from node %s\n",
06712 myrpt->name,tmp,mylink->name);
06713 return;
06714 }
06715 if (tmp[0] == 'K')
06716 {
06717 if (sscanf(tmp,"%299s %299s %299s %30d %30d",cmd,dest,src,&seq,&ts) != 5)
06718 {
06719 ast_log(LOG_WARNING, "Unable to parse keying string %s\n",str);
06720 return;
06721 }
06722 if (dest[0] == '0')
06723 {
06724 strcpy(dest,myrpt->name);
06725 }
06726
06727 if (strcmp(dest,myrpt->name))
06728 {
06729 l = myrpt->links.next;
06730
06731 while(l != &myrpt->links)
06732 {
06733 if (l->name[0] == '0')
06734 {
06735 l = l->next;
06736 continue;
06737 }
06738
06739 if ((l == mylink) || (!strcmp(l->name,mylink->name)))
06740 {
06741 l = l->next;
06742 continue;
06743 }
06744
06745 if (!strcmp(l->name,dest))
06746 {
06747
06748 if (strcmp(l->name,src)) {
06749 wf.data.ptr = str;
06750 if (l->chan) ast_write(l->chan,&wf);
06751 }
06752 return;
06753 }
06754 l = l->next;
06755 }
06756 }
06757
06758 if ((strcmp(dest,myrpt->name)) || (dest[0] == '*'))
06759 {
06760 l = myrpt->links.next;
06761
06762 while(l != &myrpt->links)
06763 {
06764 if (l->name[0] == '0')
06765 {
06766 l = l->next;
06767 continue;
06768 }
06769
06770 if ((l == mylink) || (!strcmp(l->name,mylink->name)))
06771 {
06772 l = l->next;
06773 continue;
06774 }
06775
06776 if (strcmp(l->name,src)) {
06777 wf.data.ptr = str;
06778 if (l->chan) ast_write(l->chan,&wf);
06779 }
06780 l = l->next;
06781 }
06782 }
06783
06784 if (strcmp(dest,myrpt->name) && (dest[0] != '*')) return;
06785 if (cmd[1] == '?')
06786 {
06787 time_t now;
06788 int n = 0;
06789
06790 time(&now);
06791 if (myrpt->lastkeyedtime)
06792 {
06793 n = (int)(now - myrpt->lastkeyedtime);
06794 }
06795 sprintf(tmp1,"K %s %s %d %d",src,myrpt->name,myrpt->keyed,n);
06796 wf.data.ptr = tmp1;
06797 wf.datalen = strlen(tmp1) + 1;
06798 if (mylink->chan) ast_write(mylink->chan,&wf);
06799 return;
06800 }
06801 if (myrpt->topkeystate != 1) return;
06802 rpt_mutex_lock(&myrpt->lock);
06803 for(i = 0; i < TOPKEYN; i++)
06804 {
06805 if (!strcmp(myrpt->topkey[i].node,src)) break;
06806 }
06807 if (i >= TOPKEYN)
06808 {
06809 for(i = 0; i < TOPKEYN; i++)
06810 {
06811 if (!myrpt->topkey[i].node[0]) break;
06812 }
06813 }
06814 if (i < TOPKEYN)
06815 {
06816 strncpy(myrpt->topkey[i].node,src,TOPKEYMAXSTR - 1);
06817 myrpt->topkey[i].timesince = ts;
06818 myrpt->topkey[i].keyed = seq;
06819 }
06820 rpt_mutex_unlock(&myrpt->lock);
06821 return;
06822 }
06823 if (tmp[0] == 'I')
06824 {
06825 if (sscanf(tmp, "%299s %299s %30x", cmd, src, &seq) != 3)
06826 {
06827 ast_log(LOG_WARNING, "Unable to parse ident string %s\n",str);
06828 return;
06829 }
06830 mdc1200_notify(myrpt,src,seq);
06831 strcpy(dest,"*");
06832 }
06833 else
06834 {
06835 if (sscanf(tmp, "%299s %299s %299s %30d %1c", cmd, dest, src, &seq, &c) != 5)
06836 {
06837 ast_log(LOG_WARNING, "Unable to parse link string %s\n",str);
06838 return;
06839 }
06840 if (strcmp(cmd,"D"))
06841 {
06842 ast_log(LOG_WARNING, "Unable to parse link string %s\n",str);
06843 return;
06844 }
06845 }
06846 if (dest[0] == '0')
06847 {
06848 strcpy(dest,myrpt->name);
06849 }
06850
06851
06852 if (strcmp(dest,myrpt->name))
06853 {
06854 l = myrpt->links.next;
06855
06856 while(l != &myrpt->links)
06857 {
06858 if (l->name[0] == '0')
06859 {
06860 l = l->next;
06861 continue;
06862 }
06863
06864 if ((l == mylink) || (!strcmp(l->name,mylink->name)))
06865 {
06866 l = l->next;
06867 continue;
06868 }
06869
06870 if (!strcmp(l->name,dest))
06871 {
06872
06873 if (strcmp(l->name,src)) {
06874 wf.data.ptr = str;
06875 if (l->chan) ast_write(l->chan,&wf);
06876 }
06877 return;
06878 }
06879 l = l->next;
06880 }
06881 l = myrpt->links.next;
06882
06883 while(l != &myrpt->links)
06884 {
06885 if (l->name[0] == '0')
06886 {
06887 l = l->next;
06888 continue;
06889 }
06890
06891 if ((l == mylink) || (!strcmp(l->name,mylink->name)))
06892 {
06893 l = l->next;
06894 continue;
06895 }
06896
06897 if (strcmp(l->name,src)) {
06898 wf.data.ptr = str;
06899 if (l->chan) ast_write(l->chan,&wf);
06900 }
06901 l = l->next;
06902 }
06903 return;
06904 }
06905 if (myrpt->p.archivedir)
06906 {
06907 char dtmfstr[100];
06908
06909 sprintf(dtmfstr,"DTMF,%s,%c",mylink->name,c);
06910 donodelog(myrpt,dtmfstr);
06911 }
06912 c = func_xlat(myrpt,c,&myrpt->p.outxlat);
06913 if (!c) return;
06914 rpt_mutex_lock(&myrpt->lock);
06915 if (c == myrpt->p.endchar) myrpt->stopgen = 1;
06916 if (myrpt->callmode == 1)
06917 {
06918 myrpt->exten[myrpt->cidx++] = c;
06919 myrpt->exten[myrpt->cidx] = 0;
06920
06921 if (ast_exists_extension(myrpt->pchannel,myrpt->patchcontext,myrpt->exten,1,NULL))
06922 {
06923
06924 if (!ast_matchmore_extension(myrpt->pchannel,myrpt->patchcontext,
06925 myrpt->exten,1,NULL))
06926 {
06927 myrpt->callmode = 2;
06928 if(!myrpt->patchquiet)
06929 {
06930 rpt_mutex_unlock(&myrpt->lock);
06931 rpt_telemetry(myrpt,PROC,NULL);
06932 rpt_mutex_lock(&myrpt->lock);
06933 }
06934 }
06935 else
06936 {
06937 myrpt->calldigittimer = 1;
06938 }
06939 }
06940
06941 if (!ast_canmatch_extension(myrpt->pchannel,myrpt->patchcontext,myrpt->exten,1,NULL))
06942 {
06943
06944 myrpt->callmode = 4;
06945 }
06946 }
06947 if ((!myrpt->inpadtest) &&(c == myrpt->p.funcchar))
06948 {
06949 myrpt->rem_dtmfidx = 0;
06950 myrpt->rem_dtmfbuf[myrpt->rem_dtmfidx] = 0;
06951 time(&myrpt->rem_dtmf_time);
06952 rpt_mutex_unlock(&myrpt->lock);
06953 return;
06954 }
06955 else if (myrpt->rem_dtmfidx < 0)
06956 {
06957 if ((myrpt->callmode == 2) || (myrpt->callmode == 3))
06958 {
06959 myrpt->mydtmf = c;
06960 }
06961 if (myrpt->p.propagate_dtmf) do_dtmf_local(myrpt,c);
06962 if (myrpt->p.propagate_phonedtmf) do_dtmf_phone(myrpt,mylink,c);
06963 rpt_mutex_unlock(&myrpt->lock);
06964 return;
06965 }
06966 else if (((myrpt->inpadtest) || (c != myrpt->p.endchar)) && (myrpt->rem_dtmfidx >= 0))
06967 {
06968 time(&myrpt->rem_dtmf_time);
06969 if (myrpt->rem_dtmfidx < MAXDTMF)
06970 {
06971 myrpt->rem_dtmfbuf[myrpt->rem_dtmfidx++] = c;
06972 myrpt->rem_dtmfbuf[myrpt->rem_dtmfidx] = 0;
06973
06974 rpt_mutex_unlock(&myrpt->lock);
06975 strncpy(cmd, myrpt->rem_dtmfbuf, sizeof(cmd) - 1);
06976 res = collect_function_digits(myrpt, cmd, SOURCE_LNK, mylink);
06977 rpt_mutex_lock(&myrpt->lock);
06978
06979 switch(res){
06980
06981 case DC_INDETERMINATE:
06982 break;
06983
06984 case DC_REQ_FLUSH:
06985 myrpt->rem_dtmfidx = 0;
06986 myrpt->rem_dtmfbuf[0] = 0;
06987 break;
06988
06989
06990 case DC_COMPLETE:
06991 case DC_COMPLETEQUIET:
06992 myrpt->totalexecdcommands++;
06993 myrpt->dailyexecdcommands++;
06994 strncpy(myrpt->lastdtmfcommand, cmd, MAXDTMF-1);
06995 myrpt->lastdtmfcommand[MAXDTMF-1] = '\0';
06996 myrpt->rem_dtmfbuf[0] = 0;
06997 myrpt->rem_dtmfidx = -1;
06998 myrpt->rem_dtmf_time = 0;
06999 break;
07000
07001 case DC_ERROR:
07002 default:
07003 myrpt->rem_dtmfbuf[0] = 0;
07004 myrpt->rem_dtmfidx = -1;
07005 myrpt->rem_dtmf_time = 0;
07006 break;
07007 }
07008 }
07009
07010 }
07011 rpt_mutex_unlock(&myrpt->lock);
07012 return;
07013 }
07014
07015 static void handle_link_phone_dtmf(struct rpt *myrpt, struct rpt_link *mylink,
07016 char c)
07017 {
07018
07019 char cmd[300];
07020 int res;
07021
07022 if (myrpt->p.archivedir)
07023 {
07024 char str[100];
07025
07026 sprintf(str,"DTMF(P),%s,%c",mylink->name,c);
07027 donodelog(myrpt,str);
07028 }
07029 rpt_mutex_lock(&myrpt->lock);
07030
07031 if (mylink->phonemode == 3)
07032 {
07033 if(c == myrpt->p.endchar)
07034 {
07035 mylink->lastrealrx = 0;
07036 rpt_mutex_unlock(&myrpt->lock);
07037 return;
07038 }
07039
07040 if(c == myrpt->p.funcchar)
07041 {
07042 mylink->lastrealrx = !mylink->lastrealrx;
07043 rpt_mutex_unlock(&myrpt->lock);
07044 return;
07045 }
07046 }
07047 else
07048 {
07049 if (c == myrpt->p.endchar)
07050 {
07051 if (mylink->lastrx)
07052 {
07053 mylink->lastrealrx = 0;
07054 rpt_mutex_unlock(&myrpt->lock);
07055 return;
07056 }
07057 myrpt->stopgen = 1;
07058 if (myrpt->cmdnode[0])
07059 {
07060 myrpt->cmdnode[0] = 0;
07061 myrpt->dtmfidx = -1;
07062 myrpt->dtmfbuf[0] = 0;
07063 rpt_mutex_unlock(&myrpt->lock);
07064 rpt_telemetry(myrpt,COMPLETE,NULL);
07065 return;
07066 }
07067 }
07068 }
07069 if (myrpt->cmdnode[0])
07070 {
07071 rpt_mutex_unlock(&myrpt->lock);
07072 send_link_dtmf(myrpt,c);
07073 return;
07074 }
07075 if (myrpt->callmode == 1)
07076 {
07077 myrpt->exten[myrpt->cidx++] = c;
07078 myrpt->exten[myrpt->cidx] = 0;
07079
07080 if (ast_exists_extension(myrpt->pchannel,myrpt->patchcontext,myrpt->exten,1,NULL))
07081 {
07082
07083 if (!ast_matchmore_extension(myrpt->pchannel,myrpt->patchcontext,
07084 myrpt->exten,1,NULL))
07085 {
07086 myrpt->callmode = 2;
07087 if(!myrpt->patchquiet)
07088 {
07089 rpt_mutex_unlock(&myrpt->lock);
07090 rpt_telemetry(myrpt,PROC,NULL);
07091 rpt_mutex_lock(&myrpt->lock);
07092 }
07093 }
07094 else
07095 {
07096 myrpt->calldigittimer = 1;
07097 }
07098 }
07099
07100 if (!ast_canmatch_extension(myrpt->pchannel,myrpt->patchcontext,myrpt->exten,1,NULL))
07101 {
07102
07103 myrpt->callmode = 4;
07104 }
07105 }
07106 if ((myrpt->callmode == 2) || (myrpt->callmode == 3))
07107 {
07108 myrpt->mydtmf = c;
07109 }
07110 if ((!myrpt->inpadtest) && (c == myrpt->p.funcchar))
07111 {
07112 myrpt->rem_dtmfidx = 0;
07113 myrpt->rem_dtmfbuf[myrpt->rem_dtmfidx] = 0;
07114 time(&myrpt->rem_dtmf_time);
07115 rpt_mutex_unlock(&myrpt->lock);
07116 return;
07117 }
07118 else if (((myrpt->inpadtest) || (c != myrpt->p.endchar)) && (myrpt->rem_dtmfidx >= 0))
07119 {
07120 time(&myrpt->rem_dtmf_time);
07121 if (myrpt->rem_dtmfidx < MAXDTMF)
07122 {
07123 myrpt->rem_dtmfbuf[myrpt->rem_dtmfidx++] = c;
07124 myrpt->rem_dtmfbuf[myrpt->rem_dtmfidx] = 0;
07125
07126 rpt_mutex_unlock(&myrpt->lock);
07127 strncpy(cmd, myrpt->rem_dtmfbuf, sizeof(cmd) - 1);
07128 switch(mylink->phonemode)
07129 {
07130 case 1:
07131 res = collect_function_digits(myrpt, cmd,
07132 SOURCE_PHONE, mylink);
07133 break;
07134 case 2:
07135 res = collect_function_digits(myrpt, cmd,
07136 SOURCE_DPHONE,mylink);
07137 break;
07138 case 4:
07139 res = collect_function_digits(myrpt, cmd,
07140 SOURCE_ALT,mylink);
07141 break;
07142 default:
07143 res = collect_function_digits(myrpt, cmd,
07144 SOURCE_LNK, mylink);
07145 break;
07146 }
07147
07148 rpt_mutex_lock(&myrpt->lock);
07149
07150 switch(res){
07151
07152 case DC_INDETERMINATE:
07153 break;
07154
07155 case DC_DOKEY:
07156 mylink->lastrealrx = 1;
07157 break;
07158
07159 case DC_REQ_FLUSH:
07160 myrpt->rem_dtmfidx = 0;
07161 myrpt->rem_dtmfbuf[0] = 0;
07162 break;
07163
07164
07165 case DC_COMPLETE:
07166 case DC_COMPLETEQUIET:
07167 myrpt->totalexecdcommands++;
07168 myrpt->dailyexecdcommands++;
07169 strncpy(myrpt->lastdtmfcommand, cmd, MAXDTMF-1);
07170 myrpt->lastdtmfcommand[MAXDTMF-1] = '\0';
07171 myrpt->rem_dtmfbuf[0] = 0;
07172 myrpt->rem_dtmfidx = -1;
07173 myrpt->rem_dtmf_time = 0;
07174 break;
07175
07176 case DC_ERROR:
07177 default:
07178 myrpt->rem_dtmfbuf[0] = 0;
07179 myrpt->rem_dtmfidx = -1;
07180 myrpt->rem_dtmf_time = 0;
07181 break;
07182 }
07183 }
07184
07185 }
07186 rpt_mutex_unlock(&myrpt->lock);
07187 return;
07188 }
07189
07190
07191
07192
07193
07194
07195
07196
07197
07198
07199
07200
07201
07202
07203
07204
07205
07206
07207
07208
07209
07210
07211
07212
07213
07214
07215
07216
07217
07218
07219
07220
07221 static int rbi_mhztoband(char *str)
07222 {
07223 int i;
07224
07225 i = atoi(str) / 10;
07226 switch(i)
07227 {
07228 case 2:
07229 return 10;
07230 case 5:
07231 return 11;
07232 case 14:
07233 return 2;
07234 case 22:
07235 return 3;
07236 case 44:
07237 return 4;
07238 case 124:
07239 return 0;
07240 case 125:
07241 return 1;
07242 case 126:
07243 return 8;
07244 case 127:
07245 return 5;
07246 case 128:
07247 return 6;
07248 case 129:
07249 return 7;
07250 default:
07251 break;
07252 }
07253 return -1;
07254 }
07255
07256
07257 static int rbi_pltocode(char *str)
07258 {
07259 int i;
07260 char *s;
07261
07262 s = strchr(str,'.');
07263 i = 0;
07264 if (s) i = atoi(s + 1);
07265 i += atoi(str) * 10;
07266 switch(i)
07267 {
07268 case 670:
07269 return 0;
07270 case 719:
07271 return 1;
07272 case 744:
07273 return 2;
07274 case 770:
07275 return 3;
07276 case 797:
07277 return 4;
07278 case 825:
07279 return 5;
07280 case 854:
07281 return 6;
07282 case 885:
07283 return 7;
07284 case 915:
07285 return 8;
07286 case 948:
07287 return 9;
07288 case 974:
07289 return 10;
07290 case 1000:
07291 return 11;
07292 case 1035:
07293 return 12;
07294 case 1072:
07295 return 13;
07296 case 1109:
07297 return 14;
07298 case 1148:
07299 return 15;
07300 case 1188:
07301 return 16;
07302 case 1230:
07303 return 17;
07304 case 1273:
07305 return 18;
07306 case 1318:
07307 return 19;
07308 case 1365:
07309 return 20;
07310 case 1413:
07311 return 21;
07312 case 1462:
07313 return 22;
07314 case 1514:
07315 return 23;
07316 case 1567:
07317 return 24;
07318 case 1622:
07319 return 25;
07320 case 1679:
07321 return 26;
07322 case 1738:
07323 return 27;
07324 case 1799:
07325 return 28;
07326 case 1862:
07327 return 29;
07328 case 1928:
07329 return 30;
07330 case 2035:
07331 return 31;
07332 case 2107:
07333 return 32;
07334 case 2181:
07335 return 33;
07336 case 2257:
07337 return 34;
07338 case 2336:
07339 return 35;
07340 case 2418:
07341 return 36;
07342 case 2503:
07343 return 37;
07344 }
07345 return -1;
07346 }
07347
07348
07349
07350
07351
07352 static void rbi_out_parallel(struct rpt *myrpt,unsigned char *data)
07353 {
07354 #ifdef __i386__
07355 int i,j;
07356 unsigned char od,d;
07357 static volatile long long delayvar;
07358
07359 for(i = 0 ; i < 5 ; i++){
07360 od = *data++;
07361 for(j = 0 ; j < 8 ; j++){
07362 d = od & 1;
07363 outb(d,myrpt->p.iobase);
07364
07365 for(delayvar = 1; delayvar < 15000; delayvar++);
07366 od >>= 1;
07367 outb(d | 2,myrpt->p.iobase);
07368
07369 for(delayvar = 1; delayvar < 30000; delayvar++);
07370 outb(d,myrpt->p.iobase);
07371
07372 for(delayvar = 1; delayvar < 10000; delayvar++);
07373 }
07374 }
07375
07376 for(delayvar = 1; delayvar < 50000; delayvar++);
07377 #endif
07378 }
07379
07380 static void rbi_out(struct rpt *myrpt,unsigned char *data)
07381 {
07382 struct dahdi_radio_param r;
07383
07384 memset(&r,0,sizeof(struct dahdi_radio_param));
07385 r.radpar = DAHDI_RADPAR_REMMODE;
07386 r.data = DAHDI_RADPAR_REM_RBI1;
07387
07388 if (ioctl(myrpt->dahdirxchannel->fds[0],DAHDI_RADIO_SETPARAM,&r) == -1)
07389 {
07390 rbi_out_parallel(myrpt,data);
07391 return;
07392 }
07393 r.radpar = DAHDI_RADPAR_REMCOMMAND;
07394 memcpy(&r.data,data,5);
07395 if (ioctl(myrpt->dahdirxchannel->fds[0],DAHDI_RADIO_SETPARAM,&r) == -1)
07396 {
07397 ast_log(LOG_WARNING,"Cannot send RBI command for channel %s\n",myrpt->dahdirxchannel->name);
07398 return;
07399 }
07400 }
07401
07402 static int serial_remote_io(struct rpt *myrpt, unsigned char *txbuf, int txbytes,
07403 unsigned char *rxbuf, int rxmaxbytes, int asciiflag)
07404 {
07405 int i,j,idx,oldmode,olddata;
07406 struct dahdi_radio_param prm;
07407 char c;
07408
07409 if(debug) {
07410 ast_log(LOG_NOTICE, "ioport=%s iofd=0x%x\n",myrpt->p.ioport,myrpt->iofd);
07411 printf("String output was:\n");
07412 for(i = 0; i < txbytes; i++)
07413 printf("%02X ", (unsigned char ) txbuf[i]);
07414 printf("\n");
07415 }
07416
07417 if (myrpt->iofd >= 0)
07418 {
07419 if (write(myrpt->iofd,txbuf,txbytes) != txbytes)
07420 {
07421 return -1;
07422 }
07423 if ((!rxmaxbytes) || (rxbuf == NULL))
07424 {
07425 return(0);
07426 }
07427 memset(rxbuf,0,rxmaxbytes);
07428 for(i = 0; i < rxmaxbytes; i++)
07429 {
07430 j = read(myrpt->iofd,&c,1);
07431 if (j < 1)
07432 {
07433 return(i);
07434 }
07435 rxbuf[i] = c;
07436 if (asciiflag & 1)
07437 {
07438 rxbuf[i + 1] = 0;
07439 if (c == '\r') break;
07440 }
07441 }
07442 if(debug) {
07443 printf("String returned was:\n");
07444 for(j = 0; j < i; j++)
07445 printf("%02X ", (unsigned char ) rxbuf[j]);
07446 printf("\n");
07447 }
07448 return(i);
07449 }
07450
07451
07452 if (myrpt->rxchannel != myrpt->dahdirxchannel) return -1;
07453
07454 prm.radpar = DAHDI_RADPAR_UIOMODE;
07455 if (ioctl(myrpt->dahdirxchannel->fds[0],DAHDI_RADIO_GETPARAM,&prm) == -1) return -1;
07456 oldmode = prm.data;
07457 prm.radpar = DAHDI_RADPAR_UIODATA;
07458 if (ioctl(myrpt->dahdirxchannel->fds[0],DAHDI_RADIO_GETPARAM,&prm) == -1) return -1;
07459 olddata = prm.data;
07460 prm.radpar = DAHDI_RADPAR_REMMODE;
07461 if (asciiflag & 1) prm.data = DAHDI_RADPAR_REM_SERIAL_ASCII;
07462 else prm.data = DAHDI_RADPAR_REM_SERIAL;
07463 if (ioctl(myrpt->dahdirxchannel->fds[0],DAHDI_RADIO_SETPARAM,&prm) == -1) return -1;
07464 if (asciiflag & 2)
07465 {
07466 i = DAHDI_ONHOOK;
07467 if (ioctl(myrpt->dahdirxchannel->fds[0],DAHDI_HOOK,&i) == -1) return -1;
07468 usleep(100000);
07469 }
07470 prm.radpar = DAHDI_RADPAR_REMCOMMAND;
07471 prm.data = rxmaxbytes;
07472 memcpy(prm.buf,txbuf,txbytes);
07473 prm.index = txbytes;
07474 if (ioctl(myrpt->dahdirxchannel->fds[0],DAHDI_RADIO_SETPARAM,&prm) == -1) return -1;
07475 if (rxbuf)
07476 {
07477 *rxbuf = 0;
07478 memcpy(rxbuf,prm.buf,prm.index);
07479 }
07480 idx = prm.index;
07481 prm.radpar = DAHDI_RADPAR_REMMODE;
07482 prm.data = DAHDI_RADPAR_REM_NONE;
07483 if (ioctl(myrpt->dahdirxchannel->fds[0],DAHDI_RADIO_SETPARAM,&prm) == -1) return -1;
07484 if (asciiflag & 2)
07485 {
07486 i = DAHDI_OFFHOOK;
07487 if (ioctl(myrpt->dahdirxchannel->fds[0],DAHDI_HOOK,&i) == -1) return -1;
07488 }
07489 prm.radpar = DAHDI_RADPAR_UIOMODE;
07490 prm.data = oldmode;
07491 if (ioctl(myrpt->dahdirxchannel->fds[0],DAHDI_RADIO_SETPARAM,&prm) == -1) return -1;
07492 prm.radpar = DAHDI_RADPAR_UIODATA;
07493 prm.data = olddata;
07494 if (ioctl(myrpt->dahdirxchannel->fds[0],DAHDI_RADIO_SETPARAM,&prm) == -1) return -1;
07495 return(idx);
07496 }
07497
07498 static int civ_cmd(struct rpt *myrpt,unsigned char *cmd, int cmdlen)
07499 {
07500 unsigned char rxbuf[100];
07501 int i,rv ;
07502
07503 rv = serial_remote_io(myrpt,cmd,cmdlen,rxbuf,cmdlen + 6,0);
07504 if (rv == -1) return(-1);
07505 if (rv != (cmdlen + 6)) return(1);
07506 for(i = 0; i < 6; i++)
07507 if (rxbuf[i] != cmd[i]) return(1);
07508 if (rxbuf[cmdlen] != 0xfe) return(1);
07509 if (rxbuf[cmdlen + 1] != 0xfe) return(1);
07510 if (rxbuf[cmdlen + 4] != 0xfb) return(1);
07511 if (rxbuf[cmdlen + 5] != 0xfd) return(1);
07512 return(0);
07513 }
07514
07515 static int sendkenwood(struct rpt *myrpt,char *txstr, char *rxstr)
07516 {
07517 int i;
07518
07519 ast_log(LOG_NOTICE,"Sent to kenwood: %s\n",txstr);
07520 if (debug) printf("Send to kenwood: %s\n",txstr);
07521 i = serial_remote_io(myrpt, (unsigned char *)txstr, strlen(txstr),
07522 (unsigned char *)rxstr,RAD_SERIAL_BUFLEN - 1,3);
07523 if (i < 0) return -1;
07524 if ((i > 0) && (rxstr[i - 1] == '\r'))
07525 rxstr[i-- - 1] = 0;
07526 if (debug) printf("Got from kenwood: %s\n",rxstr);
07527 ast_log(LOG_NOTICE,"Got from kenwood: %s\n",rxstr);
07528 return(i);
07529 }
07530
07531
07532 static int kenwood_pltocode(char *str)
07533 {
07534 int i;
07535 char *s;
07536
07537 s = strchr(str,'.');
07538 i = 0;
07539 if (s) i = atoi(s + 1);
07540 i += atoi(str) * 10;
07541 switch(i)
07542 {
07543 case 670:
07544 return 1;
07545 case 719:
07546 return 3;
07547 case 744:
07548 return 4;
07549 case 770:
07550 return 5;
07551 case 797:
07552 return 6;
07553 case 825:
07554 return 7;
07555 case 854:
07556 return 8;
07557 case 885:
07558 return 9;
07559 case 915:
07560 return 10;
07561 case 948:
07562 return 11;
07563 case 974:
07564 return 12;
07565 case 1000:
07566 return 13;
07567 case 1035:
07568 return 14;
07569 case 1072:
07570 return 15;
07571 case 1109:
07572 return 16;
07573 case 1148:
07574 return 17;
07575 case 1188:
07576 return 18;
07577 case 1230:
07578 return 19;
07579 case 1273:
07580 return 20;
07581 case 1318:
07582 return 21;
07583 case 1365:
07584 return 22;
07585 case 1413:
07586 return 23;
07587 case 1462:
07588 return 24;
07589 case 1514:
07590 return 25;
07591 case 1567:
07592 return 26;
07593 case 1622:
07594 return 27;
07595 case 1679:
07596 return 28;
07597 case 1738:
07598 return 29;
07599 case 1799:
07600 return 30;
07601 case 1862:
07602 return 31;
07603 case 1928:
07604 return 32;
07605 case 2035:
07606 return 33;
07607 case 2107:
07608 return 34;
07609 case 2181:
07610 return 35;
07611 case 2257:
07612 return 36;
07613 case 2336:
07614 return 37;
07615 case 2418:
07616 return 38;
07617 case 2503:
07618 return 39;
07619 }
07620 return -1;
07621 }
07622
07623 static int sendrxkenwood(struct rpt *myrpt, char *txstr, char *rxstr,
07624 char *cmpstr)
07625 {
07626 int i,j;
07627
07628 for(i = 0;i < KENWOOD_RETRIES;i++)
07629 {
07630 j = sendkenwood(myrpt,txstr,rxstr);
07631 if (j < 0) return(j);
07632 if (j == 0) continue;
07633 if (!strncmp(rxstr,cmpstr,strlen(cmpstr))) return(0);
07634 }
07635 return(-1);
07636 }
07637
07638 static int setkenwood(struct rpt *myrpt)
07639 {
07640 char rxstr[RAD_SERIAL_BUFLEN],txstr[RAD_SERIAL_BUFLEN],freq[20];
07641 char mhz[MAXREMSTR],offset[20],band,decimals[MAXREMSTR],band1,band2;
07642 int myrxpl;
07643
07644 int offsets[] = {0,2,1};
07645 int powers[] = {2,1,0};
07646
07647 if (sendrxkenwood(myrpt,"VMC 0,0\r",rxstr,"VMC") < 0) return -1;
07648 split_freq(mhz, decimals, myrpt->freq);
07649 if (atoi(mhz) > 400)
07650 {
07651 band = '6';
07652 band1 = '1';
07653 band2 = '5';
07654 strcpy(offset,"005000000");
07655 }
07656 else
07657 {
07658 band = '2';
07659 band1 = '0';
07660 band2 = '2';
07661 strcpy(offset,"000600000");
07662 }
07663 strcpy(freq,"000000");
07664 strncpy(freq,decimals,strlen(decimals));
07665 myrxpl = myrpt->rxplon;
07666 if (IS_XPMR(myrpt)) myrxpl = 0;
07667 sprintf(txstr,"VW %c,%05d%s,0,%d,0,%d,%d,,%02d,,%02d,%s\r",
07668 band,atoi(mhz),freq,offsets[(int)myrpt->offset],
07669 (myrpt->txplon != 0),myrxpl,
07670 kenwood_pltocode(myrpt->txpl),kenwood_pltocode(myrpt->rxpl),
07671 offset);
07672 if (sendrxkenwood(myrpt,txstr,rxstr,"VW") < 0) return -1;
07673 sprintf(txstr,"RBN %c\r",band2);
07674 if (sendrxkenwood(myrpt,txstr,rxstr,"RBN") < 0) return -1;
07675 sprintf(txstr,"PC %c,%d\r",band1,powers[(int)myrpt->powerlevel]);
07676 if (sendrxkenwood(myrpt,txstr,rxstr,"PC") < 0) return -1;
07677 return 0;
07678 }
07679
07680 static int set_tm271(struct rpt *myrpt)
07681 {
07682 char rxstr[RAD_SERIAL_BUFLEN],txstr[RAD_SERIAL_BUFLEN],freq[20];
07683 char mhz[MAXREMSTR],decimals[MAXREMSTR];
07684
07685 int offsets[] = {0,2,1};
07686 int powers[] = {2,1,0};
07687
07688 split_freq(mhz, decimals, myrpt->freq);
07689 strcpy(freq,"000000");
07690 strncpy(freq,decimals,strlen(decimals));
07691
07692 sprintf(txstr,"VF %04d%s,4,%d,0,%d,0,0,%d,%d,000,00600000,0,0\r",
07693 atoi(mhz),freq,offsets[(int)myrpt->offset],
07694 (myrpt->txplon != 0),kenwood_pltocode(myrpt->txpl),
07695 kenwood_pltocode(myrpt->rxpl));
07696
07697 if (sendrxkenwood(myrpt,txstr,rxstr,"VF") < 0) return -1;
07698 if (sendrxkenwood(myrpt,"VM 0\r",rxstr,"VM") < 0) return -1;
07699 sprintf(txstr,"PC %d\r",powers[(int)myrpt->powerlevel]);
07700 if (sendrxkenwood(myrpt,txstr,rxstr,"PC") < 0) return -1;
07701 return 0;
07702 }
07703
07704 static int setrbi(struct rpt *myrpt)
07705 {
07706 char tmp[MAXREMSTR] = "",*s;
07707 unsigned char rbicmd[5];
07708 int band,txoffset = 0,txpower = 0,rxpl;
07709
07710
07711 if (!myrpt->remoterig) return(0);
07712 if (!myrpt->remoterig[0]) return(0);
07713
07714 if (strncmp(myrpt->remoterig,remote_rig_rbi,3)) return(0);
07715 if (setrbi_check(myrpt) == -1) return(-1);
07716 strncpy(tmp, myrpt->freq, sizeof(tmp) - 1);
07717 s = strchr(tmp,'.');
07718
07719
07720 if (s == NULL){
07721 if(debug)
07722 printf("@@@@ Frequency needs a decimal\n");
07723 return -1;
07724 }
07725
07726 *s++ = 0;
07727 if (strlen(tmp) < 2){
07728 if(debug)
07729 printf("@@@@ Bad MHz digits: %s\n", tmp);
07730 return -1;
07731 }
07732
07733 if (strlen(s) < 3){
07734 if(debug)
07735 printf("@@@@ Bad KHz digits: %s\n", s);
07736 return -1;
07737 }
07738
07739 if ((s[2] != '0') && (s[2] != '5')){
07740 if(debug)
07741 printf("@@@@ KHz must end in 0 or 5: %c\n", s[2]);
07742 return -1;
07743 }
07744
07745 band = rbi_mhztoband(tmp);
07746 if (band == -1){
07747 if(debug)
07748 printf("@@@@ Bad Band: %s\n", tmp);
07749 return -1;
07750 }
07751
07752 rxpl = rbi_pltocode(myrpt->rxpl);
07753
07754 if (rxpl == -1){
07755 if(debug)
07756 printf("@@@@ Bad TX PL: %s\n", myrpt->rxpl);
07757 return -1;
07758 }
07759
07760
07761 switch(myrpt->offset)
07762 {
07763 case REM_MINUS:
07764 txoffset = 0;
07765 break;
07766 case REM_PLUS:
07767 txoffset = 0x10;
07768 break;
07769 case REM_SIMPLEX:
07770 txoffset = 0x20;
07771 break;
07772 }
07773 switch(myrpt->powerlevel)
07774 {
07775 case REM_LOWPWR:
07776 txpower = 0;
07777 break;
07778 case REM_MEDPWR:
07779 txpower = 0x20;
07780 break;
07781 case REM_HIPWR:
07782 txpower = 0x10;
07783 break;
07784 }
07785 rbicmd[0] = 0;
07786 rbicmd[1] = band | txpower | 0xc0;
07787 rbicmd[2] = (*(s - 2) - '0') | txoffset | 0x80;
07788 if (s[2] == '5') rbicmd[2] |= 0x40;
07789 rbicmd[3] = ((*s - '0') << 4) + (s[1] - '0');
07790 rbicmd[4] = rxpl;
07791 if (myrpt->txplon) rbicmd[4] |= 0x40;
07792 if (myrpt->rxplon) rbicmd[4] |= 0x80;
07793 rbi_out(myrpt,rbicmd);
07794 return 0;
07795 }
07796
07797 static int setrtx(struct rpt *myrpt)
07798 {
07799 char tmp[MAXREMSTR] = "",*s,rigstr[200],pwr,res = 0;
07800 int band,txoffset = 0,txpower = 0,rxpl,txpl;
07801 float ofac;
07802 double txfreq;
07803
07804
07805 if (!myrpt->remoterig) return(0);
07806 if (!myrpt->remoterig[0]) return(0);
07807
07808 if (!ISRIG_RTX(myrpt->remoterig)) return(0);
07809
07810 if (!IS_XPMR(myrpt)) return(0);
07811 strncpy(tmp, myrpt->freq, sizeof(tmp) - 1);
07812 s = strchr(tmp,'.');
07813
07814
07815 if(debug)printf("setrtx() %s %s\n",myrpt->name,myrpt->remoterig);
07816
07817 if (s == NULL){
07818 if(debug)
07819 printf("@@@@ Frequency needs a decimal\n");
07820 return -1;
07821 }
07822 *s++ = 0;
07823 if (strlen(tmp) < 2){
07824 if(debug)
07825 printf("@@@@ Bad MHz digits: %s\n", tmp);
07826 return -1;
07827 }
07828
07829 if (strlen(s) < 3){
07830 if(debug)
07831 printf("@@@@ Bad KHz digits: %s\n", s);
07832 return -1;
07833 }
07834
07835 if ((s[2] != '0') && (s[2] != '5')){
07836 if(debug)
07837 printf("@@@@ KHz must end in 0 or 5: %c\n", s[2]);
07838 return -1;
07839 }
07840
07841 band = rbi_mhztoband(tmp);
07842 if (band == -1){
07843 if(debug)
07844 printf("@@@@ Bad Band: %s\n", tmp);
07845 return -1;
07846 }
07847
07848 rxpl = rbi_pltocode(myrpt->rxpl);
07849
07850 if (rxpl == -1){
07851 if(debug)
07852 printf("@@@@ Bad RX PL: %s\n", myrpt->rxpl);
07853 return -1;
07854 }
07855
07856 txpl = rbi_pltocode(myrpt->txpl);
07857
07858 if (txpl == -1){
07859 if(debug)
07860 printf("@@@@ Bad TX PL: %s\n", myrpt->txpl);
07861 return -1;
07862 }
07863
07864 switch(myrpt->offset)
07865 {
07866 case REM_MINUS:
07867 txoffset = 0;
07868 break;
07869 case REM_PLUS:
07870 txoffset = 0x10;
07871 break;
07872 case REM_SIMPLEX:
07873 txoffset = 0x20;
07874 break;
07875 }
07876 switch(myrpt->powerlevel)
07877 {
07878 case REM_LOWPWR:
07879 txpower = 0;
07880 break;
07881 case REM_MEDPWR:
07882 txpower = 0x20;
07883 break;
07884 case REM_HIPWR:
07885 txpower = 0x10;
07886 break;
07887 }
07888
07889 res = setrtx_check(myrpt);
07890 if (res < 0) return res;
07891 ofac = 0.0;
07892 if (myrpt->offset == REM_MINUS) ofac = -1.0;
07893 if (myrpt->offset == REM_PLUS) ofac = 1.0;
07894
07895 if (!strcmp(myrpt->remoterig,remote_rig_rtx450))
07896 txfreq = atof(myrpt->freq) + (ofac * 5.0);
07897 else
07898 txfreq = atof(myrpt->freq) + (ofac * 0.6);
07899
07900 pwr = 'L';
07901 if (myrpt->powerlevel == REM_HIPWR) pwr = 'H';
07902 if (!res)
07903 {
07904 sprintf(rigstr,"SETFREQ %s %f %s %s %c",myrpt->freq,txfreq,
07905 (myrpt->rxplon) ? myrpt->rxpl : "0.0",
07906 (myrpt->txplon) ? myrpt->txpl : "0.0",pwr);
07907 send_usb_txt(myrpt,rigstr);
07908 rpt_telemetry(myrpt,COMPLETE,NULL);
07909 res = 0;
07910 }
07911 return 0;
07912 }
07913 #if 0
07914
07915
07916
07917
07918 static int setxpmr(struct rpt *myrpt)
07919 {
07920 char rigstr[200];
07921 int rxpl,txpl;
07922
07923
07924 if (!myrpt->remoterig) return(0);
07925 if (!myrpt->remoterig[0]) return(0);
07926
07927 if (ISRIG_RTX(myrpt->remoterig)) return(0);
07928
07929 if (!IS_XPMR(myrpt)) return(0);
07930
07931 if(debug)printf("setxpmr() %s %s\n",myrpt->name,myrpt->remoterig );
07932
07933 rxpl = rbi_pltocode(myrpt->rxpl);
07934
07935 if (rxpl == -1){
07936 if(debug)
07937 printf("@@@@ Bad RX PL: %s\n", myrpt->rxpl);
07938 return -1;
07939 }
07940
07941 txpl = rbi_pltocode(myrpt->txpl);
07942 if (txpl == -1){
07943 if(debug)
07944 printf("@@@@ Bad TX PL: %s\n", myrpt->txpl);
07945 return -1;
07946 }
07947 sprintf(rigstr,"SETFREQ 0.0 0.0 %s %s L",
07948 (myrpt->rxplon) ? myrpt->rxpl : "0.0",
07949 (myrpt->txplon) ? myrpt->txpl : "0.0");
07950 send_usb_txt(myrpt,rigstr);
07951 return 0;
07952 }
07953 #endif
07954
07955 static int setrbi_check(struct rpt *myrpt)
07956 {
07957 char tmp[MAXREMSTR] = "",*s;
07958 int band,txpl;
07959
07960
07961 if (!myrpt->remote) return(0);
07962
07963 if (strncmp(myrpt->remoterig,remote_rig_rbi,3)) return(0);
07964 strncpy(tmp, myrpt->freq, sizeof(tmp) - 1);
07965 s = strchr(tmp,'.');
07966
07967
07968 if (s == NULL){
07969 if(debug)
07970 printf("@@@@ Frequency needs a decimal\n");
07971 return -1;
07972 }
07973
07974 *s++ = 0;
07975 if (strlen(tmp) < 2){
07976 if(debug)
07977 printf("@@@@ Bad MHz digits: %s\n", tmp);
07978 return -1;
07979 }
07980
07981 if (strlen(s) < 3){
07982 if(debug)
07983 printf("@@@@ Bad KHz digits: %s\n", s);
07984 return -1;
07985 }
07986
07987 if ((s[2] != '0') && (s[2] != '5')){
07988 if(debug)
07989 printf("@@@@ KHz must end in 0 or 5: %c\n", s[2]);
07990 return -1;
07991 }
07992
07993 band = rbi_mhztoband(tmp);
07994 if (band == -1){
07995 if(debug)
07996 printf("@@@@ Bad Band: %s\n", tmp);
07997 return -1;
07998 }
07999
08000 txpl = rbi_pltocode(myrpt->txpl);
08001
08002 if (txpl == -1){
08003 if(debug)
08004 printf("@@@@ Bad TX PL: %s\n", myrpt->txpl);
08005 return -1;
08006 }
08007 return 0;
08008 }
08009
08010 static int setrtx_check(struct rpt *myrpt)
08011 {
08012 char tmp[MAXREMSTR] = "",*s;
08013 int band,txpl,rxpl;
08014
08015
08016 if (!myrpt->remote) return(0);
08017
08018 if (strncmp(myrpt->remoterig,remote_rig_rbi,3)) return(0);
08019 strncpy(tmp, myrpt->freq, sizeof(tmp) - 1);
08020 s = strchr(tmp,'.');
08021
08022
08023 if (s == NULL){
08024 if(debug)
08025 printf("@@@@ Frequency needs a decimal\n");
08026 return -1;
08027 }
08028
08029 *s++ = 0;
08030 if (strlen(tmp) < 2){
08031 if(debug)
08032 printf("@@@@ Bad MHz digits: %s\n", tmp);
08033 return -1;
08034 }
08035
08036 if (strlen(s) < 3){
08037 if(debug)
08038 printf("@@@@ Bad KHz digits: %s\n", s);
08039 return -1;
08040 }
08041
08042 if ((s[2] != '0') && (s[2] != '5')){
08043 if(debug)
08044 printf("@@@@ KHz must end in 0 or 5: %c\n", s[2]);
08045 return -1;
08046 }
08047
08048 band = rbi_mhztoband(tmp);
08049 if (band == -1){
08050 if(debug)
08051 printf("@@@@ Bad Band: %s\n", tmp);
08052 return -1;
08053 }
08054
08055 txpl = rbi_pltocode(myrpt->txpl);
08056
08057 if (txpl == -1){
08058 if(debug)
08059 printf("@@@@ Bad TX PL: %s\n", myrpt->txpl);
08060 return -1;
08061 }
08062
08063 rxpl = rbi_pltocode(myrpt->rxpl);
08064
08065 if (rxpl == -1){
08066 if(debug)
08067 printf("@@@@ Bad RX PL: %s\n", myrpt->rxpl);
08068 return -1;
08069 }
08070 return 0;
08071 }
08072
08073 static int check_freq_kenwood(int m, int d, int *defmode)
08074 {
08075 int dflmd = REM_MODE_FM;
08076
08077 if (m == 144){
08078 if(d < 10100)
08079 return -1;
08080 }
08081 else if((m >= 145) && (m < 148)){
08082 ;
08083 }
08084 else if((m >= 430) && (m < 450)){
08085 ;
08086 }
08087 else
08088 return -1;
08089
08090 if(defmode)
08091 *defmode = dflmd;
08092
08093
08094 return 0;
08095 }
08096
08097
08098 static int check_freq_tm271(int m, int d, int *defmode)
08099 {
08100 int dflmd = REM_MODE_FM;
08101
08102 if (m == 144){
08103 if(d < 10100)
08104 return -1;
08105 }
08106 else if((m >= 145) && (m < 148)){
08107 ;
08108 }
08109 return -1;
08110
08111 if(defmode)
08112 *defmode = dflmd;
08113
08114
08115 return 0;
08116 }
08117
08118
08119
08120
08121
08122 static int check_freq_rbi(int m, int d, int *defmode)
08123 {
08124 int dflmd = REM_MODE_FM;
08125
08126 if(m == 50){
08127 if(d < 10100)
08128 return -1;
08129 }
08130 else if((m >= 51) && ( m < 54)){
08131 ;
08132 }
08133 else if(m == 144){
08134 if(d < 10100)
08135 return -1;
08136 }
08137 else if((m >= 145) && (m < 148)){
08138 ;
08139 }
08140 else if((m >= 222) && (m < 225)){
08141 ;
08142 }
08143 else if((m >= 430) && (m < 450)){
08144 ;
08145 }
08146 else if((m >= 1240) && (m < 1300)){
08147 ;
08148 }
08149 else
08150 return -1;
08151
08152 if(defmode)
08153 *defmode = dflmd;
08154
08155
08156 return 0;
08157 }
08158
08159
08160
08161
08162 static int check_freq_rtx(int m, int d, int *defmode, struct rpt *myrpt)
08163 {
08164 int dflmd = REM_MODE_FM;
08165
08166 if (!strcmp(myrpt->remoterig,remote_rig_rtx150))
08167 {
08168
08169 if(m == 144){
08170 if(d < 10100)
08171 return -1;
08172 }
08173 else if((m >= 145) && (m < 148)){
08174 ;
08175 }
08176 else
08177 return -1;
08178 }
08179 else
08180 {
08181 if((m >= 430) && (m < 450)){
08182 ;
08183 }
08184 else
08185 return -1;
08186 }
08187 if(defmode)
08188 *defmode = dflmd;
08189
08190
08191 return 0;
08192 }
08193
08194
08195
08196
08197
08198 static int decimals2int(char *fraction)
08199 {
08200 int i;
08201 char len = strlen(fraction);
08202 int multiplier = 100000;
08203 int res = 0;
08204
08205 if(!len)
08206 return 0;
08207 for( i = 0 ; i < len ; i++, multiplier /= 10)
08208 res += (fraction[i] - '0') * multiplier;
08209 return res;
08210 }
08211
08212
08213
08214
08215
08216
08217 static int split_freq(char *mhz, char *decimals, char *freq)
08218 {
08219 char freq_copy[MAXREMSTR];
08220 char *decp;
08221
08222 decp = strchr(strncpy(freq_copy, freq, MAXREMSTR),'.');
08223 if(decp){
08224 *decp++ = 0;
08225 strncpy(mhz, freq_copy, MAXREMSTR);
08226 strcpy(decimals, "00000");
08227 strncpy(decimals, decp, strlen(decp));
08228 decimals[5] = 0;
08229 return 0;
08230 }
08231 else
08232 return -1;
08233
08234 }
08235
08236
08237
08238
08239
08240 static int split_ctcss_freq(char *hertz, char *decimal, char *freq)
08241 {
08242 char freq_copy[MAXREMSTR];
08243 char *decp;
08244
08245 decp = strchr(strncpy(freq_copy, freq, MAXREMSTR),'.');
08246 if(decp){
08247 *decp++ = 0;
08248 strncpy(hertz, freq_copy, MAXREMSTR);
08249 strncpy(decimal, decp, strlen(decp));
08250 decimal[strlen(decp)] = '\0';
08251 return 0;
08252 }
08253 else
08254 return -1;
08255 }
08256
08257
08258
08259
08260
08261
08262
08263
08264
08265
08266
08267 static int check_freq_ft897(int m, int d, int *defmode)
08268 {
08269 int dflmd = REM_MODE_FM;
08270
08271 if(m == 1){
08272 dflmd = REM_MODE_LSB;
08273 if(d < 80000)
08274 return -1;
08275 }
08276 else if(m == 3){
08277 dflmd = REM_MODE_LSB;
08278 if(d < 50000)
08279 return -1;
08280 }
08281 else if(m == 7){
08282 dflmd = REM_MODE_LSB;
08283 if(d > 30000)
08284 return -1;
08285 }
08286 else if(m == 14){
08287 dflmd = REM_MODE_USB;
08288 if(d > 35000)
08289 return -1;
08290 }
08291 else if(m == 18){
08292 dflmd = REM_MODE_USB;
08293 if((d < 6800) || (d > 16800))
08294 return -1;
08295 }
08296 else if(m == 21){
08297 dflmd = REM_MODE_USB;
08298 if((d < 20000) || (d > 45000))
08299 return -1;
08300 }
08301 else if(m == 24){
08302 dflmd = REM_MODE_USB;
08303 if((d < 89000) || (d > 99000))
08304 return -1;
08305 }
08306 else if(m == 28){
08307 dflmd = REM_MODE_USB;
08308 }
08309 else if(m == 29){
08310 if(d >= 51000)
08311 dflmd = REM_MODE_FM;
08312 else
08313 dflmd = REM_MODE_USB;
08314 if(d > 70000)
08315 return -1;
08316 }
08317 else if(m == 50){
08318 if(d >= 30000)
08319 dflmd = REM_MODE_FM;
08320 else
08321 dflmd = REM_MODE_USB;
08322
08323 }
08324 else if((m >= 51) && ( m < 54)){
08325 dflmd = REM_MODE_FM;
08326 }
08327 else if(m == 144){
08328 if(d >= 30000)
08329 dflmd = REM_MODE_FM;
08330 else
08331 dflmd = REM_MODE_USB;
08332 }
08333 else if((m >= 145) && (m < 148)){
08334 dflmd = REM_MODE_FM;
08335 }
08336 else if((m >= 430) && (m < 450)){
08337 if(m < 438)
08338 dflmd = REM_MODE_USB;
08339 else
08340 dflmd = REM_MODE_FM;
08341 ;
08342 }
08343 else
08344 return -1;
08345
08346 if(defmode)
08347 *defmode = dflmd;
08348
08349 return 0;
08350 }
08351
08352
08353
08354
08355
08356 static int set_freq_ft897(struct rpt *myrpt, char *newfreq)
08357 {
08358 unsigned char cmdstr[5];
08359 int fd,m,d;
08360 char mhz[MAXREMSTR];
08361 char decimals[MAXREMSTR];
08362
08363 fd = 0;
08364 if(debug)
08365 printf("New frequency: %s\n",newfreq);
08366
08367 if(split_freq(mhz, decimals, newfreq))
08368 return -1;
08369
08370 m = atoi(mhz);
08371 d = atoi(decimals);
08372
08373
08374
08375 cmdstr[0] = ((m / 100) << 4) + ((m % 100)/10);
08376 cmdstr[1] = ((m % 10) << 4) + (d / 10000);
08377 cmdstr[2] = (((d % 10000)/1000) << 4) + ((d % 1000)/ 100);
08378 cmdstr[3] = (((d % 100)/10) << 4) + (d % 10);
08379 cmdstr[4] = 0x01;
08380
08381 return serial_remote_io(myrpt, cmdstr, 5, NULL, 0, 0);
08382
08383 }
08384
08385
08386
08387 static int simple_command_ft897(struct rpt *myrpt, char command)
08388 {
08389 unsigned char cmdstr[5];
08390
08391 memset(cmdstr, 0, 5);
08392
08393 cmdstr[4] = command;
08394
08395 return serial_remote_io(myrpt, cmdstr, 5, NULL, 0, 0);
08396
08397 }
08398
08399
08400
08401 static int set_offset_ft897(struct rpt *myrpt, char offset)
08402 {
08403 unsigned char cmdstr[5];
08404
08405 memset(cmdstr, 0, 5);
08406
08407 switch(offset){
08408 case REM_SIMPLEX:
08409 cmdstr[0] = 0x89;
08410 break;
08411
08412 case REM_MINUS:
08413 cmdstr[0] = 0x09;
08414 break;
08415
08416 case REM_PLUS:
08417 cmdstr[0] = 0x49;
08418 break;
08419
08420 default:
08421 return -1;
08422 }
08423
08424 cmdstr[4] = 0x09;
08425
08426 return serial_remote_io(myrpt, cmdstr, 5, NULL, 0, 0);
08427 }
08428
08429
08430
08431 static int set_mode_ft897(struct rpt *myrpt, char newmode)
08432 {
08433 unsigned char cmdstr[5];
08434
08435 memset(cmdstr, 0, 5);
08436
08437 switch(newmode){
08438 case REM_MODE_FM:
08439 cmdstr[0] = 0x08;
08440 break;
08441
08442 case REM_MODE_USB:
08443 cmdstr[0] = 0x01;
08444 break;
08445
08446 case REM_MODE_LSB:
08447 cmdstr[0] = 0x00;
08448 break;
08449
08450 case REM_MODE_AM:
08451 cmdstr[0] = 0x04;
08452 break;
08453
08454 default:
08455 return -1;
08456 }
08457 cmdstr[4] = 0x07;
08458
08459 return serial_remote_io(myrpt, cmdstr, 5, NULL, 0, 0);
08460 }
08461
08462
08463
08464 static int set_ctcss_mode_ft897(struct rpt *myrpt, char txplon, char rxplon)
08465 {
08466 unsigned char cmdstr[5];
08467
08468 memset(cmdstr, 0, 5);
08469
08470 if(rxplon && txplon)
08471 cmdstr[0] = 0x2A;
08472 else if (!rxplon && txplon)
08473 cmdstr[0] = 0x4A;
08474 else if (rxplon && !txplon)
08475 cmdstr[0] = 0x3A;
08476 else
08477 cmdstr[0] = 0x8A;
08478
08479 cmdstr[4] = 0x0A;
08480
08481 return serial_remote_io(myrpt, cmdstr, 5, NULL, 0, 0);
08482 }
08483
08484
08485
08486
08487 static int set_ctcss_freq_ft897(struct rpt *myrpt, char *txtone, char *rxtone)
08488 {
08489 unsigned char cmdstr[5];
08490 char hertz[MAXREMSTR],decimal[MAXREMSTR];
08491 int h,d;
08492
08493 memset(cmdstr, 0, 5);
08494
08495 if(split_ctcss_freq(hertz, decimal, txtone))
08496 return -1;
08497
08498 h = atoi(hertz);
08499 d = atoi(decimal);
08500
08501 cmdstr[0] = ((h / 100) << 4) + (h % 100)/ 10;
08502 cmdstr[1] = ((h % 10) << 4) + (d % 10);
08503
08504 if(rxtone){
08505
08506 if(split_ctcss_freq(hertz, decimal, rxtone))
08507 return -1;
08508
08509 h = atoi(hertz);
08510 d = atoi(decimal);
08511
08512 cmdstr[2] = ((h / 100) << 4) + (h % 100)/ 10;
08513 cmdstr[3] = ((h % 10) << 4) + (d % 10);
08514 }
08515 cmdstr[4] = 0x0B;
08516
08517 return serial_remote_io(myrpt, cmdstr, 5, NULL, 0, 0);
08518 }
08519
08520
08521
08522 static int set_ft897(struct rpt *myrpt)
08523 {
08524 int res;
08525
08526 if(debug)
08527 printf("@@@@ lock on\n");
08528
08529 res = simple_command_ft897(myrpt, 0x00);
08530
08531 if(debug)
08532 printf("@@@@ ptt off\n");
08533
08534 if(!res)
08535 res = simple_command_ft897(myrpt, 0x88);
08536
08537 if(debug)
08538 printf("Modulation mode\n");
08539
08540 if(!res)
08541 res = set_mode_ft897(myrpt, myrpt->remmode);
08542
08543 if(debug)
08544 printf("Split off\n");
08545
08546 if(!res)
08547 simple_command_ft897(myrpt, 0x82);
08548
08549 if(debug)
08550 printf("Frequency\n");
08551
08552 if(!res)
08553 res = set_freq_ft897(myrpt, myrpt->freq);
08554 if((myrpt->remmode == REM_MODE_FM)){
08555 if(debug)
08556 printf("Offset\n");
08557 if(!res)
08558 res = set_offset_ft897(myrpt, myrpt->offset);
08559 if((!res)&&(myrpt->rxplon || myrpt->txplon)){
08560 if(debug)
08561 printf("CTCSS tone freqs.\n");
08562 res = set_ctcss_freq_ft897(myrpt, myrpt->txpl, myrpt->rxpl);
08563 }
08564 if(!res){
08565 if(debug)
08566 printf("CTCSS mode\n");
08567 res = set_ctcss_mode_ft897(myrpt, myrpt->txplon, myrpt->rxplon);
08568 }
08569 }
08570 if((myrpt->remmode == REM_MODE_USB)||(myrpt->remmode == REM_MODE_LSB)){
08571 if(debug)
08572 printf("Clarifier off\n");
08573 simple_command_ft897(myrpt, 0x85);
08574 }
08575 return res;
08576 }
08577
08578 static int closerem_ft897(struct rpt *myrpt)
08579 {
08580 simple_command_ft897(myrpt, 0x88);
08581 return 0;
08582 }
08583
08584
08585
08586
08587
08588
08589
08590 static int multimode_bump_freq_ft897(struct rpt *myrpt, int interval)
08591 {
08592 int m,d;
08593 char mhz[MAXREMSTR], decimals[MAXREMSTR];
08594
08595 if(debug)
08596 printf("Before bump: %s\n", myrpt->freq);
08597
08598 if(split_freq(mhz, decimals, myrpt->freq))
08599 return -1;
08600
08601 m = atoi(mhz);
08602 d = atoi(decimals);
08603
08604 d += (interval / 10);
08605 if(d < 0){
08606 m--;
08607 d += 100000;
08608 }
08609 else if(d >= 100000){
08610 m++;
08611 d -= 100000;
08612 }
08613
08614 if(check_freq_ft897(m, d, NULL)){
08615 if(debug)
08616 printf("Bump freq invalid\n");
08617 return -1;
08618 }
08619
08620 snprintf(myrpt->freq, MAXREMSTR, "%d.%05d", m, d);
08621
08622 if(debug)
08623 printf("After bump: %s\n", myrpt->freq);
08624
08625 return set_freq_ft897(myrpt, myrpt->freq);
08626 }
08627
08628
08629
08630
08631
08632
08633
08634
08635
08636
08637 static int check_freq_ic706(int m, int d, int *defmode, char mars)
08638 {
08639 int dflmd = REM_MODE_FM;
08640 int rv=0;
08641
08642 if(debug > 6)
08643 ast_log(LOG_NOTICE,"(%i,%i,%i,%i)\n",m,d,*defmode,mars);
08644
08645
08646
08647 if(m == 1){
08648 dflmd = REM_MODE_LSB;
08649 if(d < 80000)rv=-1;
08650 }
08651 else if(m == 3){
08652 dflmd = REM_MODE_LSB;
08653 if(d < 50000)rv=-1;
08654 }
08655 else if(m == 7){
08656 dflmd = REM_MODE_LSB;
08657 if(d > 30000)rv=-1;
08658 }
08659 else if(m == 14){
08660 dflmd = REM_MODE_USB;
08661 if(d > 35000)rv=-1;
08662 }
08663 else if(m == 18){
08664 dflmd = REM_MODE_USB;
08665 if((d < 6800) || (d > 16800))rv=-1;
08666 }
08667 else if(m == 21){
08668 dflmd = REM_MODE_USB;
08669 if((d < 20000) || (d > 45000))rv=-1;
08670 }
08671 else if(m == 24){
08672 dflmd = REM_MODE_USB;
08673 if((d < 89000) || (d > 99000))rv=-1;
08674 }
08675 else if(m == 28){
08676 dflmd = REM_MODE_USB;
08677 }
08678 else if(m == 29){
08679 if(d >= 51000)
08680 dflmd = REM_MODE_FM;
08681 else
08682 dflmd = REM_MODE_USB;
08683 if(d > 70000)rv=-1;
08684 }
08685 else if(m == 50){
08686 if(d >= 30000)
08687 dflmd = REM_MODE_FM;
08688 else
08689 dflmd = REM_MODE_USB;
08690 }
08691 else if((m >= 51) && ( m < 54)){
08692 dflmd = REM_MODE_FM;
08693 }
08694 else if(m == 144){
08695 if(d >= 30000)
08696 dflmd = REM_MODE_FM;
08697 else
08698 dflmd = REM_MODE_USB;
08699 }
08700 else if((m >= 145) && (m < 148)){
08701 dflmd = REM_MODE_FM;
08702 }
08703 else if((m >= 430) && (m < 450)){
08704 if(m < 438)
08705 dflmd = REM_MODE_USB;
08706 else
08707 dflmd = REM_MODE_FM;
08708 }
08709
08710
08711 if(mars && rv<0){
08712 if((m >= 450) && (m < 470)){
08713 dflmd = REM_MODE_FM;
08714 rv=0;
08715 }
08716 else if((m >= 148) && (m < 174)){
08717 dflmd = REM_MODE_FM;
08718 rv=0;
08719 }
08720 else if((m >= 138) && (m < 144)){
08721 dflmd = REM_MODE_AM;
08722 rv=0;
08723 }
08724 else if((m >= 108) && (m < 138)){
08725 dflmd = REM_MODE_AM;
08726 rv=0;
08727 }
08728 else if( (m==0 && d>=55000) || (m==1 && d<=75000) ){
08729 dflmd = REM_MODE_AM;
08730 rv=0;
08731 }
08732 else if( (m == 1 && d>75000) || (m>1 && m<30) ){
08733 dflmd = REM_MODE_AM;
08734 rv=0;
08735 }
08736 }
08737
08738 if(defmode)
08739 *defmode = dflmd;
08740
08741 if(debug > 1)
08742 ast_log(LOG_NOTICE,"(%i,%i,%i,%i) returning %i\n",m,d,*defmode,mars,rv);
08743
08744 return rv;
08745 }
08746
08747
08748 static int ic706_pltocode(char *str)
08749 {
08750 int i;
08751 char *s;
08752 int rv=-1;
08753
08754 s = strchr(str,'.');
08755 i = 0;
08756 if (s) i = atoi(s + 1);
08757 i += atoi(str) * 10;
08758 switch(i)
08759 {
08760 case 670:
08761 rv=0;
08762 case 693:
08763 rv=1;
08764 case 719:
08765 rv=2;
08766 case 744:
08767 rv=3;
08768 case 770:
08769 rv=4;
08770 case 797:
08771 rv=5;
08772 case 825:
08773 rv=6;
08774 case 854:
08775 rv=7;
08776 case 885:
08777 rv=8;
08778 case 915:
08779 rv=9;
08780 case 948:
08781 rv=10;
08782 case 974:
08783 rv=11;
08784 case 1000:
08785 rv=12;
08786 case 1035:
08787 rv=13;
08788 case 1072:
08789 rv=14;
08790 case 1109:
08791 rv=15;
08792 case 1148:
08793 rv=16;
08794 case 1188:
08795 rv=17;
08796 case 1230:
08797 rv=18;
08798 case 1273:
08799 rv=19;
08800 case 1318:
08801 rv=20;
08802 case 1365:
08803 rv=21;
08804 case 1413:
08805 rv=22;
08806 case 1462:
08807 rv=23;
08808 case 1514:
08809 rv=24;
08810 case 1567:
08811 rv=25;
08812 case 1598:
08813 rv=26;
08814 case 1622:
08815 rv=27;
08816 case 1655:
08817 rv=28;
08818 case 1679:
08819 rv=29;
08820 case 1713:
08821 rv=30;
08822 case 1738:
08823 rv=31;
08824 case 1773:
08825 rv=32;
08826 case 1799:
08827 rv=33;
08828 case 1835:
08829 rv=34;
08830 case 1862:
08831 rv=35;
08832 case 1899:
08833 rv=36;
08834 case 1928:
08835 rv=37;
08836 case 1966:
08837 rv=38;
08838 case 1995:
08839 rv=39;
08840 case 2035:
08841 rv=40;
08842 case 2065:
08843 rv=41;
08844 case 2107:
08845 rv=42;
08846 case 2181:
08847 rv=43;
08848 case 2257:
08849 rv=44;
08850 case 2291:
08851 rv=45;
08852 case 2336:
08853 rv=46;
08854 case 2418:
08855 rv=47;
08856 case 2503:
08857 rv=48;
08858 case 2541:
08859 rv=49;
08860 }
08861 if(debug > 1)
08862 ast_log(LOG_NOTICE,"%i rv=%i\n",i, rv);
08863
08864 return rv;
08865 }
08866
08867
08868
08869 static int simple_command_ic706(struct rpt *myrpt, char command, char subcommand)
08870 {
08871 unsigned char cmdstr[10];
08872
08873 cmdstr[0] = cmdstr[1] = 0xfe;
08874 cmdstr[2] = myrpt->p.civaddr;
08875 cmdstr[3] = 0xe0;
08876 cmdstr[4] = command;
08877 cmdstr[5] = subcommand;
08878 cmdstr[6] = 0xfd;
08879
08880 return(civ_cmd(myrpt,cmdstr,7));
08881 }
08882
08883
08884
08885
08886
08887 static int set_freq_ic706(struct rpt *myrpt, char *newfreq)
08888 {
08889 unsigned char cmdstr[20];
08890 char mhz[MAXREMSTR], decimals[MAXREMSTR];
08891 int fd,m,d;
08892
08893 fd = 0;
08894 if(debug)
08895 ast_log(LOG_NOTICE,"newfreq:%s\n",newfreq);
08896
08897 if(split_freq(mhz, decimals, newfreq))
08898 return -1;
08899
08900 m = atoi(mhz);
08901 d = atoi(decimals);
08902
08903
08904
08905 cmdstr[0] = cmdstr[1] = 0xfe;
08906 cmdstr[2] = myrpt->p.civaddr;
08907 cmdstr[3] = 0xe0;
08908 cmdstr[4] = 5;
08909 cmdstr[5] = ((d % 10) << 4);
08910 cmdstr[6] = (((d % 1000)/ 100) << 4) + ((d % 100)/10);
08911 cmdstr[7] = ((d / 10000) << 4) + ((d % 10000)/1000);
08912 cmdstr[8] = (((m % 100)/10) << 4) + (m % 10);
08913 cmdstr[9] = (m / 100);
08914 cmdstr[10] = 0xfd;
08915
08916 return(civ_cmd(myrpt,cmdstr,11));
08917 }
08918
08919
08920
08921 static int set_offset_ic706(struct rpt *myrpt, char offset)
08922 {
08923 unsigned char c;
08924
08925 if(debug > 6)
08926 ast_log(LOG_NOTICE,"offset=%i\n",offset);
08927
08928 switch(offset){
08929 case REM_SIMPLEX:
08930 c = 0x10;
08931 break;
08932
08933 case REM_MINUS:
08934 c = 0x11;
08935 break;
08936
08937 case REM_PLUS:
08938 c = 0x12;
08939 break;
08940
08941 default:
08942 return -1;
08943 }
08944
08945 return simple_command_ic706(myrpt,0x0f,c);
08946
08947 }
08948
08949
08950
08951 static int set_mode_ic706(struct rpt *myrpt, char newmode)
08952 {
08953 unsigned char c;
08954
08955 if(debug > 6)
08956 ast_log(LOG_NOTICE,"newmode=%i\n",newmode);
08957
08958 switch(newmode){
08959 case REM_MODE_FM:
08960 c = 5;
08961 break;
08962
08963 case REM_MODE_USB:
08964 c = 1;
08965 break;
08966
08967 case REM_MODE_LSB:
08968 c = 0;
08969 break;
08970
08971 case REM_MODE_AM:
08972 c = 2;
08973 break;
08974
08975 default:
08976 return -1;
08977 }
08978 return simple_command_ic706(myrpt,6,c);
08979 }
08980
08981
08982
08983 static int set_ctcss_mode_ic706(struct rpt *myrpt, char txplon, char rxplon)
08984 {
08985 unsigned char cmdstr[10];
08986 int rv;
08987
08988 if(debug > 6)
08989 ast_log(LOG_NOTICE,"txplon=%i rxplon=%i \n",txplon,rxplon);
08990
08991 cmdstr[0] = cmdstr[1] = 0xfe;
08992 cmdstr[2] = myrpt->p.civaddr;
08993 cmdstr[3] = 0xe0;
08994 cmdstr[4] = 0x16;
08995 cmdstr[5] = 0x42;
08996 cmdstr[6] = (txplon != 0);
08997 cmdstr[7] = 0xfd;
08998
08999 rv = civ_cmd(myrpt,cmdstr,8);
09000 if (rv) return(-1);
09001
09002 cmdstr[0] = cmdstr[1] = 0xfe;
09003 cmdstr[2] = myrpt->p.civaddr;
09004 cmdstr[3] = 0xe0;
09005 cmdstr[4] = 0x16;
09006 cmdstr[5] = 0x43;
09007 cmdstr[6] = (rxplon != 0);
09008 cmdstr[7] = 0xfd;
09009
09010 return(civ_cmd(myrpt,cmdstr,8));
09011 }
09012
09013 #if 0
09014
09015
09016 static int set_ctcss_freq_ic706(struct rpt *myrpt, char *txtone, char *rxtone)
09017 {
09018 unsigned char cmdstr[10];
09019 char hertz[MAXREMSTR],decimal[MAXREMSTR];
09020 int h,d,rv;
09021
09022 memset(cmdstr, 0, 5);
09023
09024 if(debug > 6)
09025 ast_log(LOG_NOTICE,"txtone=%s rxtone=%s \n",txtone,rxtone);
09026
09027 if(split_ctcss_freq(hertz, decimal, txtone))
09028 return -1;
09029
09030 h = atoi(hertz);
09031 d = atoi(decimal);
09032
09033 cmdstr[0] = cmdstr[1] = 0xfe;
09034 cmdstr[2] = myrpt->p.civaddr;
09035 cmdstr[3] = 0xe0;
09036 cmdstr[4] = 0x1b;
09037 cmdstr[5] = 0;
09038 cmdstr[6] = ((h / 100) << 4) + (h % 100)/ 10;
09039 cmdstr[7] = ((h % 10) << 4) + (d % 10);
09040 cmdstr[8] = 0xfd;
09041
09042 rv = civ_cmd(myrpt,cmdstr,9);
09043 if (rv) return(-1);
09044
09045 if (!rxtone) return(0);
09046
09047 if(split_ctcss_freq(hertz, decimal, rxtone))
09048 return -1;
09049
09050 h = atoi(hertz);
09051 d = atoi(decimal);
09052
09053 cmdstr[0] = cmdstr[1] = 0xfe;
09054 cmdstr[2] = myrpt->p.civaddr;
09055 cmdstr[3] = 0xe0;
09056 cmdstr[4] = 0x1b;
09057 cmdstr[5] = 1;
09058 cmdstr[6] = ((h / 100) << 4) + (h % 100)/ 10;
09059 cmdstr[7] = ((h % 10) << 4) + (d % 10);
09060 cmdstr[8] = 0xfd;
09061 return(civ_cmd(myrpt,cmdstr,9));
09062 }
09063 #endif
09064
09065 static int vfo_ic706(struct rpt *myrpt)
09066 {
09067 unsigned char cmdstr[10];
09068
09069 cmdstr[0] = cmdstr[1] = 0xfe;
09070 cmdstr[2] = myrpt->p.civaddr;
09071 cmdstr[3] = 0xe0;
09072 cmdstr[4] = 7;
09073 cmdstr[5] = 0xfd;
09074
09075 return(civ_cmd(myrpt,cmdstr,6));
09076 }
09077
09078 static int mem2vfo_ic706(struct rpt *myrpt)
09079 {
09080 unsigned char cmdstr[10];
09081
09082 cmdstr[0] = cmdstr[1] = 0xfe;
09083 cmdstr[2] = myrpt->p.civaddr;
09084 cmdstr[3] = 0xe0;
09085 cmdstr[4] = 0x0a;
09086 cmdstr[5] = 0xfd;
09087
09088 return(civ_cmd(myrpt,cmdstr,6));
09089 }
09090
09091 static int select_mem_ic706(struct rpt *myrpt, int slot)
09092 {
09093 unsigned char cmdstr[10];
09094
09095 cmdstr[0] = cmdstr[1] = 0xfe;
09096 cmdstr[2] = myrpt->p.civaddr;
09097 cmdstr[3] = 0xe0;
09098 cmdstr[4] = 8;
09099 cmdstr[5] = 0;
09100 cmdstr[6] = ((slot / 10) << 4) + (slot % 10);
09101 cmdstr[7] = 0xfd;
09102
09103 return(civ_cmd(myrpt,cmdstr,8));
09104 }
09105
09106 static int set_ic706(struct rpt *myrpt)
09107 {
09108 int res = 0,i;
09109
09110 if(debug)ast_log(LOG_NOTICE, "Set to VFO A iobase=%i\n",myrpt->p.iobase);
09111
09112 if (!res)
09113 res = simple_command_ic706(myrpt,7,0);
09114
09115 if((myrpt->remmode == REM_MODE_FM))
09116 {
09117 i = ic706_pltocode(myrpt->rxpl);
09118 if (i == -1) return -1;
09119 if(debug)
09120 printf("Select memory number\n");
09121 if (!res)
09122 res = select_mem_ic706(myrpt,i + IC706_PL_MEMORY_OFFSET);
09123 if(debug)
09124 printf("Transfer memory to VFO\n");
09125 if (!res)
09126 res = mem2vfo_ic706(myrpt);
09127 }
09128
09129 if(debug)
09130 printf("Set to VFO\n");
09131
09132 if (!res)
09133 res = vfo_ic706(myrpt);
09134
09135 if(debug)
09136 printf("Modulation mode\n");
09137
09138 if (!res)
09139 res = set_mode_ic706(myrpt, myrpt->remmode);
09140
09141 if(debug)
09142 printf("Split off\n");
09143
09144 if(!res)
09145 simple_command_ic706(myrpt, 0x82,0);
09146
09147 if(debug)
09148 printf("Frequency\n");
09149
09150 if(!res)
09151 res = set_freq_ic706(myrpt, myrpt->freq);
09152 if((myrpt->remmode == REM_MODE_FM)){
09153 if(debug)
09154 printf("Offset\n");
09155 if(!res)
09156 res = set_offset_ic706(myrpt, myrpt->offset);
09157 if(!res){
09158 if(debug)
09159 printf("CTCSS mode\n");
09160 res = set_ctcss_mode_ic706(myrpt, myrpt->txplon, myrpt->rxplon);
09161 }
09162 }
09163 return res;
09164 }
09165
09166
09167
09168
09169
09170
09171
09172 static int multimode_bump_freq_ic706(struct rpt *myrpt, int interval)
09173 {
09174 int m,d;
09175 char mhz[MAXREMSTR], decimals[MAXREMSTR];
09176 unsigned char cmdstr[20];
09177
09178 if(debug)
09179 printf("Before bump: %s\n", myrpt->freq);
09180
09181 if(split_freq(mhz, decimals, myrpt->freq))
09182 return -1;
09183
09184 m = atoi(mhz);
09185 d = atoi(decimals);
09186
09187 d += (interval / 10);
09188 if(d < 0){
09189 m--;
09190 d += 100000;
09191 }
09192 else if(d >= 100000){
09193 m++;
09194 d -= 100000;
09195 }
09196
09197 if(check_freq_ic706(m, d, NULL,myrpt->p.remote_mars)){
09198 if(debug)
09199 printf("Bump freq invalid\n");
09200 return -1;
09201 }
09202
09203 snprintf(myrpt->freq, MAXREMSTR, "%d.%05d", m, d);
09204
09205 if(debug)
09206 printf("After bump: %s\n", myrpt->freq);
09207
09208
09209
09210 cmdstr[0] = cmdstr[1] = 0xfe;
09211 cmdstr[2] = myrpt->p.civaddr;
09212 cmdstr[3] = 0xe0;
09213 cmdstr[4] = 0;
09214 cmdstr[5] = ((d % 10) << 4);
09215 cmdstr[6] = (((d % 1000)/ 100) << 4) + ((d % 100)/10);
09216 cmdstr[7] = ((d / 10000) << 4) + ((d % 10000)/1000);
09217 cmdstr[8] = (((m % 100)/10) << 4) + (m % 10);
09218 cmdstr[9] = (m / 100);
09219 cmdstr[10] = 0xfd;
09220
09221 return(serial_remote_io(myrpt,cmdstr,11,NULL,0,0));
09222 }
09223
09224
09225
09226
09227
09228
09229 static int setrem(struct rpt *myrpt)
09230 {
09231 char str[300];
09232 char *offsets[] = {"SIMPLEX","MINUS","PLUS"};
09233 char *powerlevels[] = {"LOW","MEDIUM","HIGH"};
09234 char *modes[] = {"FM","USB","LSB","AM"};
09235 int res = -1;
09236
09237 #if 0
09238 printf("FREQ,%s,%s,%s,%s,%s,%s,%d,%d\n",myrpt->freq,
09239 modes[(int)myrpt->remmode],
09240 myrpt->txpl,myrpt->rxpl,offsets[(int)myrpt->offset],
09241 powerlevels[(int)myrpt->powerlevel],myrpt->txplon,
09242 myrpt->rxplon);
09243 #endif
09244 if (myrpt->p.archivedir)
09245 {
09246 sprintf(str,"FREQ,%s,%s,%s,%s,%s,%s,%d,%d",myrpt->freq,
09247 modes[(int)myrpt->remmode],
09248 myrpt->txpl,myrpt->rxpl,offsets[(int)myrpt->offset],
09249 powerlevels[(int)myrpt->powerlevel],myrpt->txplon,
09250 myrpt->rxplon);
09251 donodelog(myrpt,str);
09252 }
09253 if(!strcmp(myrpt->remoterig, remote_rig_ft897))
09254 {
09255 rpt_telemetry(myrpt,SETREMOTE,NULL);
09256 res = 0;
09257 }
09258 if(!strcmp(myrpt->remoterig, remote_rig_ic706))
09259 {
09260 rpt_telemetry(myrpt,SETREMOTE,NULL);
09261 res = 0;
09262 }
09263 if(!strcmp(myrpt->remoterig, remote_rig_tm271))
09264 {
09265 rpt_telemetry(myrpt,SETREMOTE,NULL);
09266 res = 0;
09267 }
09268 else if(!strcmp(myrpt->remoterig, remote_rig_rbi))
09269 {
09270 res = setrbi_check(myrpt);
09271 if (!res)
09272 {
09273 rpt_telemetry(myrpt,SETREMOTE,NULL);
09274 res = 0;
09275 }
09276 }
09277 else if(ISRIG_RTX(myrpt->remoterig))
09278 {
09279 setrtx(myrpt);
09280 res = 0;
09281 }
09282 else if(!strcmp(myrpt->remoterig, remote_rig_kenwood)) {
09283 rpt_telemetry(myrpt,SETREMOTE,NULL);
09284 res = 0;
09285 }
09286 else
09287 res = 0;
09288
09289 if (res < 0) ast_log(LOG_ERROR,"Unable to send remote command on node %s\n",myrpt->name);
09290
09291 return res;
09292 }
09293
09294 static int closerem(struct rpt *myrpt)
09295 {
09296 if(!strcmp(myrpt->remoterig, remote_rig_ft897))
09297 return closerem_ft897(myrpt);
09298 else
09299 return 0;
09300 }
09301
09302
09303
09304
09305
09306 static int check_freq(struct rpt *myrpt, int m, int d, int *defmode)
09307 {
09308 if(!strcmp(myrpt->remoterig, remote_rig_ft897))
09309 return check_freq_ft897(m, d, defmode);
09310 else if(!strcmp(myrpt->remoterig, remote_rig_ic706))
09311 return check_freq_ic706(m, d, defmode,myrpt->p.remote_mars);
09312 else if(!strcmp(myrpt->remoterig, remote_rig_rbi))
09313 return check_freq_rbi(m, d, defmode);
09314 else if(!strcmp(myrpt->remoterig, remote_rig_kenwood))
09315 return check_freq_kenwood(m, d, defmode);
09316 else if(!strcmp(myrpt->remoterig, remote_rig_tm271))
09317 return check_freq_tm271(m, d, defmode);
09318 else if(ISRIG_RTX(myrpt->remoterig))
09319 return check_freq_rtx(m, d, defmode, myrpt);
09320 else
09321 return -1;
09322 }
09323
09324
09325
09326
09327
09328
09329 static char check_tx_freq(struct rpt *myrpt)
09330 {
09331 int i,rv=0;
09332 int radio_mhz, radio_decimals, ulimit_mhz, ulimit_decimals, llimit_mhz, llimit_decimals;
09333 char radio_mhz_char[MAXREMSTR];
09334 char radio_decimals_char[MAXREMSTR];
09335 char limit_mhz_char[MAXREMSTR];
09336 char limit_decimals_char[MAXREMSTR];
09337 char limits[256];
09338 char *limit_ranges[40];
09339 struct ast_variable *limitlist;
09340
09341 if(debug > 3){
09342 ast_log(LOG_NOTICE, "myrpt->freq = %s\n", myrpt->freq);
09343 }
09344
09345
09346
09347 if(!myrpt->p.txlimitsstanzaname || !myrpt->loginuser[0] || !myrpt->loginlevel[0]){
09348 if(debug > 3){
09349 ast_log(LOG_NOTICE, "No tx band table defined, or no user logged in. rv=1\n");
09350 }
09351 rv=1;
09352 return 1;
09353 }
09354
09355
09356 limitlist = ast_variable_browse(myrpt->cfg, myrpt->p.txlimitsstanzaname);
09357
09358 if(!limitlist){
09359 ast_log(LOG_WARNING, "No entries in %s band table stanza. rv=0\n", myrpt->p.txlimitsstanzaname);
09360 rv=0;
09361 return 0;
09362 }
09363
09364 split_freq(radio_mhz_char, radio_decimals_char, myrpt->freq);
09365 radio_mhz = atoi(radio_mhz_char);
09366 radio_decimals = decimals2int(radio_decimals_char);
09367
09368 if(debug > 3){
09369 ast_log(LOG_NOTICE, "Login User = %s, login level = %s\n", myrpt->loginuser, myrpt->loginlevel);
09370 }
09371
09372
09373
09374 for(;limitlist; limitlist=limitlist->next){
09375 if(!strcmp(limitlist->name, myrpt->loginlevel))
09376 break;
09377 }
09378
09379 if(!limitlist){
09380 ast_log(LOG_WARNING, "Can't find %s entry in band table stanza %s. rv=0\n", myrpt->loginlevel, myrpt->p.txlimitsstanzaname);
09381 rv=0;
09382 return 0;
09383 }
09384
09385 if(debug > 3){
09386 ast_log(LOG_NOTICE, "Auth: %s = %s\n", limitlist->name, limitlist->value);
09387 }
09388
09389
09390
09391 strncpy(limits, limitlist->value, 256);
09392 limits[255] = 0;
09393 finddelim(limits, limit_ranges, 40);
09394 for(i = 0; i < 40 && limit_ranges[i] ; i++){
09395 char range[40];
09396 char *r,*s;
09397 strncpy(range, limit_ranges[i], 40);
09398 range[39] = 0;
09399 if(debug > 3)
09400 ast_log(LOG_NOTICE, "Check %s within %s\n", myrpt->freq, range);
09401
09402 r = strchr(range, '-');
09403 if(!r){
09404 ast_log(LOG_WARNING, "Malformed range in %s tx band table entry. rv=0\n", limitlist->name);
09405 rv=0;
09406 break;
09407 }
09408 *r++ = 0;
09409 s = eatwhite(range);
09410 r = eatwhite(r);
09411 split_freq(limit_mhz_char, limit_decimals_char, s);
09412 llimit_mhz = atoi(limit_mhz_char);
09413 llimit_decimals = decimals2int(limit_decimals_char);
09414 split_freq(limit_mhz_char, limit_decimals_char, r);
09415 ulimit_mhz = atoi(limit_mhz_char);
09416 ulimit_decimals = decimals2int(limit_decimals_char);
09417
09418 if((radio_mhz >= llimit_mhz) && (radio_mhz <= ulimit_mhz)){
09419 if(radio_mhz == llimit_mhz){
09420 if(radio_decimals >= llimit_decimals){
09421 if(llimit_mhz == ulimit_mhz){
09422 if(radio_decimals <= ulimit_decimals){
09423 rv=1;
09424 break;
09425 }
09426 else{
09427 if(debug > 3)
09428 ast_log(LOG_NOTICE, "Invalid TX frequency, debug msg 1\n");
09429 rv=0;
09430 break;
09431 }
09432 }
09433 else{
09434 rv=1;
09435 break;
09436 }
09437 }
09438 else{
09439 if(debug > 3)
09440 ast_log(LOG_NOTICE, "Invalid TX frequency, debug msg 2\n");
09441 rv=0;
09442 break;
09443 }
09444 }
09445 else if(radio_mhz == ulimit_mhz){
09446 if(radio_decimals <= ulimit_decimals){
09447 if(debug > 3)
09448 ast_log(LOG_NOTICE, "radio_decimals <= ulimit_decimals\n");
09449 rv=1;
09450 break;
09451 }
09452 else{
09453 if(debug > 3)
09454 ast_log(LOG_NOTICE, "Invalid TX frequency, debug msg 3\n");
09455 rv=0;
09456 break;
09457 }
09458 }
09459 else
09460 if(debug > 3)
09461 ast_log(LOG_NOTICE, "Valid TX freq within a multi-Mhz band and ok.\n");
09462 rv=1;
09463 break;
09464 }
09465 }
09466 if(debug > 3)
09467 ast_log(LOG_NOTICE, "rv=%i\n",rv);
09468
09469 return rv;
09470 }
09471
09472
09473
09474
09475
09476
09477 static int multimode_bump_freq(struct rpt *myrpt, int interval)
09478 {
09479 if(!strcmp(myrpt->remoterig, remote_rig_ft897))
09480 return multimode_bump_freq_ft897(myrpt, interval);
09481 else if(!strcmp(myrpt->remoterig, remote_rig_ic706))
09482 return multimode_bump_freq_ic706(myrpt, interval);
09483 else
09484 return -1;
09485 }
09486
09487
09488
09489
09490
09491
09492 static void stop_scan(struct rpt *myrpt)
09493 {
09494 myrpt->hfscanstop = 1;
09495 rpt_telemetry(myrpt,SCAN,0);
09496 }
09497
09498
09499
09500
09501
09502
09503 static int service_scan(struct rpt *myrpt)
09504 {
09505 int res, interval;
09506 char mhz[MAXREMSTR], decimals[MAXREMSTR], k10=0i, k100=0;
09507
09508 switch(myrpt->hfscanmode){
09509
09510 case HF_SCAN_DOWN_SLOW:
09511 interval = -10;
09512 break;
09513
09514 case HF_SCAN_DOWN_QUICK:
09515 interval = -50;
09516 break;
09517
09518 case HF_SCAN_DOWN_FAST:
09519 interval = -200;
09520 break;
09521
09522 case HF_SCAN_UP_SLOW:
09523 interval = 10;
09524 break;
09525
09526 case HF_SCAN_UP_QUICK:
09527 interval = 50;
09528 break;
09529
09530 case HF_SCAN_UP_FAST:
09531 interval = 200;
09532 break;
09533
09534 default:
09535 myrpt->hfscanmode = 0;
09536 return -1;
09537 }
09538
09539 res = split_freq(mhz, decimals, myrpt->freq);
09540
09541 if(!res){
09542 k100 =decimals[0];
09543 k10 = decimals[1];
09544 res = multimode_bump_freq(myrpt, interval);
09545 }
09546
09547 if(!res)
09548 res = split_freq(mhz, decimals, myrpt->freq);
09549
09550
09551 if(res){
09552 myrpt->hfscanmode = 0;
09553 myrpt->hfscanstatus = -2;
09554 return -1;
09555 }
09556
09557
09558 if(k10 != decimals[1]){
09559 int myhund = (interval < 0) ? k100 : decimals[0];
09560 int myten = (interval < 0) ? k10 : decimals[1];
09561 myrpt->hfscanstatus = (myten == '0') ? (myhund - '0') * 100 : (myten - '0') * 10;
09562 } else myrpt->hfscanstatus = 0;
09563 return res;
09564
09565 }
09566
09567
09568
09569 static int get_mem_set(struct rpt *myrpt, char *digitbuf)
09570 {
09571 int res=0;
09572 if(debug)ast_log(LOG_NOTICE," digitbuf=%s\n", digitbuf);
09573 res = retreive_memory(myrpt, digitbuf);
09574 if(!res)res=setrem(myrpt);
09575 if(debug)ast_log(LOG_NOTICE," freq=%s res=%i\n", myrpt->freq, res);
09576 return res;
09577 }
09578
09579
09580
09581
09582 static int channel_steer(struct rpt *myrpt, char *data)
09583 {
09584 int res=0;
09585
09586 if(debug)ast_log(LOG_NOTICE,"remoterig=%s, data=%s\n",myrpt->remoterig,data);
09587 if (!myrpt->remoterig) return(0);
09588 if(data<=0)
09589 {
09590 res=-1;
09591 }
09592 else
09593 {
09594 myrpt->nowchan=strtod(data,NULL);
09595 if(!strcmp(myrpt->remoterig, remote_rig_ppp16))
09596 {
09597 char string[16];
09598 sprintf(string,"SETCHAN %d ",myrpt->nowchan);
09599 send_usb_txt(myrpt,string);
09600 }
09601 else
09602 {
09603 if(get_mem_set(myrpt, data))res=-1;
09604 }
09605 }
09606 if(debug)ast_log(LOG_NOTICE,"nowchan=%i res=%i\n",myrpt->nowchan, res);
09607 return res;
09608 }
09609
09610
09611 static int channel_revert(struct rpt *myrpt)
09612 {
09613 int res=0;
09614 if(debug)ast_log(LOG_NOTICE,"remoterig=%s, nowchan=%02d, waschan=%02d\n",myrpt->remoterig,myrpt->nowchan,myrpt->waschan);
09615 if (!myrpt->remoterig) return(0);
09616 if(myrpt->nowchan!=myrpt->waschan)
09617 {
09618 char data[8];
09619 if(debug)ast_log(LOG_NOTICE,"reverting.\n");
09620 sprintf(data,"%02d",myrpt->waschan);
09621 myrpt->nowchan=myrpt->waschan;
09622 channel_steer(myrpt,data);
09623 res=1;
09624 }
09625 return(res);
09626 }
09627
09628
09629
09630
09631 static int function_remote(struct rpt *myrpt, char *param, char *digitbuf, int command_source, struct rpt_link *mylink)
09632 {
09633 char *s,*s1,*s2;
09634 int i,j,r,ht,k,l,ls2,m,d,offset,offsave, modesave, defmode=0;
09635 intptr_t p;
09636 char multimode = 0;
09637 char oc,*cp,*cp1,*cp2;
09638 char tmp[20], freq[20] = "", savestr[20] = "";
09639 char mhz[MAXREMSTR], decimals[MAXREMSTR];
09640
09641 if(debug > 6) {
09642 ast_log(LOG_NOTICE,"%s param=%s digitbuf=%s source=%i\n",myrpt->name,param,digitbuf,command_source);
09643 }
09644
09645 if((!param) || (command_source == SOURCE_RPT) || (command_source == SOURCE_LNK))
09646 return DC_ERROR;
09647
09648 p = myatoi(param);
09649
09650 if ((p != 99) && (p != 5) && (p != 140) && myrpt->p.authlevel &&
09651 (!myrpt->loginlevel[0])) return DC_ERROR;
09652 multimode = multimode_capable(myrpt);
09653
09654 switch(p){
09655
09656 case 1:
09657 if(strlen(digitbuf) < 2)
09658 break;
09659
09660 for(i = 0 ; i < 2 ; i++){
09661 if((digitbuf[i] < '0') || (digitbuf[i] > '9'))
09662 return DC_ERROR;
09663 }
09664 r=get_mem_set(myrpt, digitbuf);
09665 if (r < 0){
09666 rpt_telemetry(myrpt,MEMNOTFOUND,NULL);
09667 return DC_COMPLETE;
09668 }
09669 else if (r > 0){
09670 return DC_ERROR;
09671 }
09672 return DC_COMPLETE;
09673
09674 case 2:
09675
09676
09677 for(i = 0, j = 0, k = 0, l = 0 ; digitbuf[i] ; i++){
09678 if(digitbuf[i] == '*'){
09679 j++;
09680 continue;
09681 }
09682 if((digitbuf[i] < '0') || (digitbuf[i] > '9'))
09683 goto invalid_freq;
09684 else{
09685 if(j == 0)
09686 l++;
09687 if(j == 1)
09688 k++;
09689 }
09690 }
09691
09692 i = strlen(digitbuf) - 1;
09693 if(multimode){
09694 if((j > 2) || (l > 3) || (k > 6))
09695 goto invalid_freq;
09696 }
09697 else{
09698 if((j > 2) || (l > 4) || (k > 3))
09699 goto invalid_freq;
09700 }
09701
09702
09703
09704 if(j < 2)
09705 break;
09706
09707
09708
09709 strncpy(tmp, digitbuf ,sizeof(tmp) - 1);
09710
09711 s = tmp;
09712 s1 = strsep(&s, "*");
09713 s2 = strsep(&s,"*");
09714 ls2 = strlen(s2);
09715
09716 switch(ls2){
09717 case 1:
09718 ht = 0;
09719 k = 100 * atoi(s2);
09720 break;
09721
09722 case 2:
09723 ht = 0;
09724 k = 10 * atoi(s2);
09725 break;
09726
09727 case 3:
09728 if(!multimode){
09729 if((s2[2] != '0')&&(s2[2] != '5'))
09730 goto invalid_freq;
09731 }
09732 ht = 0;
09733 k = atoi(s2);
09734 break;
09735 case 4:
09736 k = atoi(s2)/10;
09737 ht = 10 * (atoi(s2+(ls2-1)));
09738 break;
09739
09740 case 5:
09741 k = atoi(s2)/100;
09742 ht = (atoi(s2+(ls2-2)));
09743 break;
09744
09745 default:
09746 goto invalid_freq;
09747 }
09748
09749
09750
09751 snprintf(freq, sizeof(freq), "%s.%03d%02d",s1, k, ht);
09752
09753 if(debug)
09754 ast_log(LOG_NOTICE, "New frequency: %s\n", freq);
09755
09756 split_freq(mhz, decimals, freq);
09757 m = atoi(mhz);
09758 d = atoi(decimals);
09759
09760 if(check_freq(myrpt, m, d, &defmode))
09761 goto invalid_freq;
09762
09763
09764 if((defmode == REM_MODE_FM) && (digitbuf[i] == '*'))
09765 break;
09766
09767
09768 offset = REM_SIMPLEX;
09769
09770 if(defmode == REM_MODE_FM){
09771 oc = *s;
09772
09773 if (oc){
09774 switch(oc){
09775 case '1':
09776 offset = REM_MINUS;
09777 break;
09778
09779 case '2':
09780 offset = REM_SIMPLEX;
09781 break;
09782
09783 case '3':
09784 offset = REM_PLUS;
09785 break;
09786
09787 default:
09788 goto invalid_freq;
09789 }
09790 }
09791 }
09792 offsave = myrpt->offset;
09793 modesave = myrpt->remmode;
09794 strncpy(savestr, myrpt->freq, sizeof(savestr) - 1);
09795 strncpy(myrpt->freq, freq, sizeof(myrpt->freq) - 1);
09796 myrpt->offset = offset;
09797 myrpt->remmode = defmode;
09798
09799 if (setrem(myrpt) == -1){
09800 myrpt->offset = offsave;
09801 myrpt->remmode = modesave;
09802 strncpy(myrpt->freq, savestr, sizeof(myrpt->freq) - 1);
09803 goto invalid_freq;
09804 }
09805
09806 return DC_COMPLETE;
09807
09808 invalid_freq:
09809 rpt_telemetry(myrpt,INVFREQ,NULL);
09810 return DC_ERROR;
09811
09812 case 3:
09813 for(i = 0, j = 0, k = 0, l = 0 ; digitbuf[i] ; i++){
09814 if(digitbuf[i] == '*'){
09815 j++;
09816 continue;
09817 }
09818 if((digitbuf[i] < '0') || (digitbuf[i] > '9'))
09819 return DC_ERROR;
09820 else{
09821 if(j)
09822 l++;
09823 else
09824 k++;
09825 }
09826 }
09827 if((j > 1) || (k > 3) || (l > 1))
09828 return DC_ERROR;
09829 i = strlen(digitbuf) - 1;
09830 if((j != 1) || (k < 2)|| (l != 1))
09831 break;
09832 if(debug)
09833 printf("PL digits entered %s\n", digitbuf);
09834
09835 strncpy(tmp, digitbuf, sizeof(tmp) - 1);
09836
09837 s = strchr(tmp,'*');
09838 if(s)
09839 *s = '.';
09840 strncpy(savestr, myrpt->rxpl, sizeof(savestr) - 1);
09841 strncpy(myrpt->rxpl, tmp, sizeof(myrpt->rxpl) - 1);
09842 if(!strcmp(myrpt->remoterig, remote_rig_rbi))
09843 {
09844 strncpy(myrpt->txpl, tmp, sizeof(myrpt->txpl) - 1);
09845 }
09846 if (setrem(myrpt) == -1){
09847 strncpy(myrpt->rxpl, savestr, sizeof(myrpt->rxpl) - 1);
09848 return DC_ERROR;
09849 }
09850 return DC_COMPLETE;
09851
09852 case 4:
09853
09854 if(!strcmp(myrpt->remoterig, remote_rig_rbi))
09855 return DC_ERROR;
09856
09857
09858
09859
09860
09861 if(!strcmp(myrpt->remoterig, remote_rig_ic706))
09862 {
09863 if(debug)
09864 ast_log(LOG_WARNING,"Setting IC706 Tx CTCSS Code Not Supported. Set Rx Code for both.\n");
09865 return DC_ERROR;
09866 }
09867 for(i = 0, j = 0, k = 0, l = 0 ; digitbuf[i] ; i++){
09868 if(digitbuf[i] == '*'){
09869 j++;
09870 continue;
09871 }
09872 if((digitbuf[i] < '0') || (digitbuf[i] > '9'))
09873 return DC_ERROR;
09874 else{
09875 if(j)
09876 l++;
09877 else
09878 k++;
09879 }
09880 }
09881 if((j > 1) || (k > 3) || (l > 1))
09882 return DC_ERROR;
09883 i = strlen(digitbuf) - 1;
09884 if((j != 1) || (k < 2)|| (l != 1))
09885 break;
09886 if(debug)
09887 printf("PL digits entered %s\n", digitbuf);
09888
09889 strncpy(tmp, digitbuf, sizeof(tmp) - 1);
09890
09891 s = strchr(tmp,'*');
09892 if(s)
09893 *s = '.';
09894 strncpy(savestr, myrpt->txpl, sizeof(savestr) - 1);
09895 strncpy(myrpt->txpl, tmp, sizeof(myrpt->txpl) - 1);
09896
09897 if (setrem(myrpt) == -1){
09898 strncpy(myrpt->txpl, savestr, sizeof(myrpt->txpl) - 1);
09899 return DC_ERROR;
09900 }
09901 return DC_COMPLETE;
09902
09903
09904 case 6:
09905 if(strlen(digitbuf) < 1)
09906 break;
09907
09908 if(!multimode)
09909 return DC_ERROR;
09910
09911 switch(*digitbuf){
09912 case '1':
09913 split_freq(mhz, decimals, myrpt->freq);
09914 m=atoi(mhz);
09915 if(m < 29)
09916 return DC_ERROR;
09917 myrpt->remmode = REM_MODE_FM;
09918
09919 rpt_telemetry(myrpt,REMMODE,NULL);
09920 break;
09921
09922 case '2':
09923 myrpt->remmode = REM_MODE_USB;
09924 rpt_telemetry(myrpt,REMMODE,NULL);
09925 break;
09926
09927 case '3':
09928 myrpt->remmode = REM_MODE_LSB;
09929 rpt_telemetry(myrpt,REMMODE,NULL);
09930 break;
09931
09932 case '4':
09933 myrpt->remmode = REM_MODE_AM;
09934 rpt_telemetry(myrpt,REMMODE,NULL);
09935 break;
09936
09937 default:
09938 return DC_ERROR;
09939 }
09940
09941 if(setrem(myrpt))
09942 return DC_ERROR;
09943 return DC_COMPLETEQUIET;
09944 case 99:
09945
09946 if (myrpt->loginlevel[0])
09947 return DC_ERROR;
09948 *myrpt->loginuser = 0;
09949 myrpt->loginlevel[0] = 0;
09950 cp = ast_strdup(param);
09951 cp1 = strchr(cp,',');
09952 ast_mutex_lock(&myrpt->lock);
09953 if (cp1)
09954 {
09955 *cp1 = 0;
09956 cp2 = strchr(cp1 + 1,',');
09957 if (cp2)
09958 {
09959 *cp2 = 0;
09960 strncpy(myrpt->loginlevel,cp2 + 1,
09961 sizeof(myrpt->loginlevel) - 1);
09962 }
09963 strncpy(myrpt->loginuser,cp1 + 1,sizeof(myrpt->loginuser));
09964 ast_mutex_unlock(&myrpt->lock);
09965 if (myrpt->p.archivedir)
09966 {
09967 char str[100];
09968
09969 sprintf(str,"LOGIN,%s,%s",
09970 myrpt->loginuser,myrpt->loginlevel);
09971 donodelog(myrpt,str);
09972 }
09973 if (debug)
09974 printf("loginuser %s level %s\n",myrpt->loginuser,myrpt->loginlevel);
09975 rpt_telemetry(myrpt,REMLOGIN,NULL);
09976 }
09977 ast_free(cp);
09978 return DC_COMPLETEQUIET;
09979 case 100:
09980 myrpt->rxplon = 0;
09981 setrem(myrpt);
09982 rpt_telemetry(myrpt,REMXXX,(void *)p);
09983 return DC_COMPLETEQUIET;
09984 case 101:
09985 myrpt->rxplon = 1;
09986 setrem(myrpt);
09987 rpt_telemetry(myrpt,REMXXX,(void *)p);
09988 return DC_COMPLETEQUIET;
09989 case 102:
09990 myrpt->txplon = 0;
09991 setrem(myrpt);
09992 rpt_telemetry(myrpt,REMXXX,(void *)p);
09993 return DC_COMPLETEQUIET;
09994 case 103:
09995 myrpt->txplon = 1;
09996 setrem(myrpt);
09997 rpt_telemetry(myrpt,REMXXX,(void *)p);
09998 return DC_COMPLETEQUIET;
09999 case 104:
10000 if(!strcmp(myrpt->remoterig, remote_rig_ic706))
10001 return DC_ERROR;
10002 myrpt->powerlevel = REM_LOWPWR;
10003 setrem(myrpt);
10004 rpt_telemetry(myrpt,REMXXX,(void *)p);
10005 return DC_COMPLETEQUIET;
10006 case 105:
10007 if(!strcmp(myrpt->remoterig, remote_rig_ic706))
10008 return DC_ERROR;
10009 if (ISRIG_RTX(myrpt->remoterig)) return DC_ERROR;
10010 myrpt->powerlevel = REM_MEDPWR;
10011 setrem(myrpt);
10012 rpt_telemetry(myrpt,REMXXX,(void *)p);
10013 return DC_COMPLETEQUIET;
10014 case 106:
10015 if(!strcmp(myrpt->remoterig, remote_rig_ic706))
10016 return DC_ERROR;
10017 myrpt->powerlevel = REM_HIPWR;
10018 setrem(myrpt);
10019 rpt_telemetry(myrpt,REMXXX,(void *)p);
10020 return DC_COMPLETEQUIET;
10021 case 107:
10022 multimode_bump_freq(myrpt, -20);
10023 return DC_COMPLETE;
10024 case 108:
10025 multimode_bump_freq(myrpt, -100);
10026 return DC_COMPLETE;
10027 case 109:
10028 multimode_bump_freq(myrpt, -500);
10029 return DC_COMPLETE;
10030 case 110:
10031 multimode_bump_freq(myrpt, 20);
10032 return DC_COMPLETE;
10033 case 111:
10034 multimode_bump_freq(myrpt, 100);
10035 return DC_COMPLETE;
10036 case 112:
10037 multimode_bump_freq(myrpt, 500);
10038 return DC_COMPLETE;
10039 case 113:
10040 myrpt->scantimer = REM_SCANTIME;
10041 myrpt->hfscanmode = HF_SCAN_DOWN_SLOW;
10042 rpt_telemetry(myrpt,REMXXX,(void *)p);
10043 return DC_COMPLETEQUIET;
10044 case 114:
10045 myrpt->scantimer = REM_SCANTIME;
10046 myrpt->hfscanmode = HF_SCAN_DOWN_QUICK;
10047 rpt_telemetry(myrpt,REMXXX,(void *)p);
10048 return DC_COMPLETEQUIET;
10049 case 115:
10050 myrpt->scantimer = REM_SCANTIME;
10051 myrpt->hfscanmode = HF_SCAN_DOWN_FAST;
10052 rpt_telemetry(myrpt,REMXXX,(void *)p);
10053 return DC_COMPLETEQUIET;
10054 case 116:
10055 myrpt->scantimer = REM_SCANTIME;
10056 myrpt->hfscanmode = HF_SCAN_UP_SLOW;
10057 rpt_telemetry(myrpt,REMXXX,(void *)p);
10058 return DC_COMPLETEQUIET;
10059 case 117:
10060 myrpt->scantimer = REM_SCANTIME;
10061 myrpt->hfscanmode = HF_SCAN_UP_QUICK;
10062 rpt_telemetry(myrpt,REMXXX,(void *)p);
10063 return DC_COMPLETEQUIET;
10064 case 118:
10065 myrpt->scantimer = REM_SCANTIME;
10066 myrpt->hfscanmode = HF_SCAN_UP_FAST;
10067 rpt_telemetry(myrpt,REMXXX,(void *)p);
10068 return DC_COMPLETEQUIET;
10069 case 119:
10070 if(debug > 3)
10071 ast_log(LOG_NOTICE,"TUNE REQUEST\n");
10072
10073 if((!myrpt->tunerequest) &&
10074 ((!strcmp(myrpt->remoterig, remote_rig_ft897) ||
10075 !strcmp(myrpt->remoterig, remote_rig_ic706)) )) {
10076 myrpt->remotetx = 0;
10077 ast_indicate(myrpt->txchannel,AST_CONTROL_RADIO_UNKEY);
10078 myrpt->tunerequest = 1;
10079 rpt_telemetry(myrpt,TUNE,NULL);
10080 return DC_COMPLETEQUIET;
10081 }
10082 return DC_ERROR;
10083 case 5:
10084 rpt_telemetry(myrpt,REMLONGSTATUS,NULL);
10085 return DC_COMPLETEQUIET;
10086 case 140:
10087 rpt_telemetry(myrpt,REMSHORTSTATUS,NULL);
10088 return DC_COMPLETEQUIET;
10089 case 200:
10090 case 201:
10091 case 202:
10092 case 203:
10093 case 204:
10094 case 205:
10095 case 206:
10096 case 207:
10097 case 208:
10098 case 209:
10099 case 210:
10100 case 211:
10101 case 212:
10102 case 213:
10103 case 214:
10104 case 215:
10105 do_dtmf_local(myrpt,remdtmfstr[p - 200]);
10106 return DC_COMPLETEQUIET;
10107 default:
10108 break;
10109 }
10110 return DC_INDETERMINATE;
10111 }
10112
10113
10114 static int handle_remote_dtmf_digit(struct rpt *myrpt,char c, char *keyed, int phonemode)
10115 {
10116 time_t now;
10117 int ret,res = 0,src;
10118
10119 if(debug > 6)
10120 ast_log(LOG_NOTICE,"c=%c phonemode=%i dtmfidx=%i\n",c,phonemode,myrpt->dtmfidx);
10121
10122 time(&myrpt->last_activity_time);
10123
10124 if(myrpt->hfscanmode){
10125 stop_scan(myrpt);
10126 return 0;
10127 }
10128
10129 time(&now);
10130
10131 if ((myrpt->dtmf_time_rem + DTMF_TIMEOUT) < now)
10132 {
10133 myrpt->dtmfidx = -1;
10134 myrpt->dtmfbuf[0] = 0;
10135 myrpt->dtmf_time_rem = 0;
10136 }
10137
10138 if (myrpt->dtmfidx == -1)
10139 {
10140
10141 if (c != myrpt->p.funcchar)
10142 {
10143 if (!myrpt->p.propagate_dtmf)
10144 {
10145 rpt_mutex_lock(&myrpt->lock);
10146 do_dtmf_local(myrpt,c);
10147 rpt_mutex_unlock(&myrpt->lock);
10148 }
10149 return 0;
10150 }
10151 myrpt->dtmfidx = 0;
10152 myrpt->dtmfbuf[0] = 0;
10153 myrpt->dtmf_time_rem = now;
10154 return 0;
10155 }
10156
10157 if (myrpt->dtmfidx >= MAXDTMF)
10158 {
10159 myrpt->dtmfidx = 0;
10160 myrpt->dtmfbuf[0] = 0;
10161 myrpt->dtmf_time_rem = now;
10162 }
10163 if (c == myrpt->p.funcchar)
10164 {
10165
10166 if ((myrpt->dtmfidx < 1) ||
10167 (myrpt->dtmfbuf[myrpt->dtmfidx - 1] == myrpt->p.funcchar))
10168 {
10169 myrpt->dtmfidx = 0;
10170 myrpt->dtmfbuf[0] = 0;
10171 myrpt->dtmf_time_rem = now;
10172 return 0;
10173 }
10174 }
10175 myrpt->dtmfbuf[myrpt->dtmfidx++] = c;
10176 myrpt->dtmfbuf[myrpt->dtmfidx] = 0;
10177 myrpt->dtmf_time_rem = now;
10178
10179
10180 src = SOURCE_RMT;
10181 if (phonemode == 2) src = SOURCE_DPHONE;
10182 else if (phonemode) src = SOURCE_PHONE;
10183 else if (phonemode == 4) src = SOURCE_ALT;
10184 ret = collect_function_digits(myrpt, myrpt->dtmfbuf, src, NULL);
10185
10186 switch(ret){
10187
10188 case DC_INDETERMINATE:
10189 res = 0;
10190 break;
10191
10192 case DC_DOKEY:
10193 if (keyed) *keyed = 1;
10194 res = 0;
10195 break;
10196
10197 case DC_REQ_FLUSH:
10198 myrpt->dtmfidx = 0;
10199 myrpt->dtmfbuf[0] = 0;
10200 res = 0;
10201 break;
10202
10203
10204 case DC_COMPLETE:
10205 res = 1;
10206 case DC_COMPLETEQUIET:
10207 myrpt->totalexecdcommands++;
10208 myrpt->dailyexecdcommands++;
10209 strncpy(myrpt->lastdtmfcommand, myrpt->dtmfbuf, MAXDTMF-1);
10210 myrpt->lastdtmfcommand[MAXDTMF-1] = '\0';
10211 myrpt->dtmfbuf[0] = 0;
10212 myrpt->dtmfidx = -1;
10213 myrpt->dtmf_time_rem = 0;
10214 break;
10215
10216 case DC_ERROR:
10217 default:
10218 myrpt->dtmfbuf[0] = 0;
10219 myrpt->dtmfidx = -1;
10220 myrpt->dtmf_time_rem = 0;
10221 res = 0;
10222 break;
10223 }
10224
10225 return res;
10226 }
10227
10228 static int handle_remote_data(struct rpt *myrpt, char *str)
10229 {
10230
10231
10232 char tmp[300], cmd[300], dest[300], src[300], c;
10233 int seq,res;
10234
10235
10236 strncpy(tmp,str,sizeof(tmp) - 1);
10237 if (!strcmp(tmp,discstr)) return 0;
10238 if (!strcmp(tmp,newkeystr))
10239 {
10240 myrpt->newkey = 1;
10241 return 0;
10242 }
10243
10244 #ifndef DO_NOT_NOTIFY_MDC1200_ON_REMOTE_BASES
10245 if (tmp[0] == 'I')
10246 {
10247 if (sscanf(tmp,"%s %s %x",cmd,src,&seq) != 3)
10248 {
10249 ast_log(LOG_WARNING, "Unable to parse ident string %s\n",str);
10250 return 0;
10251 }
10252 mdc1200_notify(myrpt,src,seq);
10253 return 0;
10254 }
10255 #endif
10256
10257
10258 if (sscanf(tmp, "%299s %299s %299s %30d %1c", cmd, dest, src, &seq, &c) != 5)
10259 {
10260 ast_log(LOG_WARNING, "Unable to parse link string %s\n",str);
10261 return 0;
10262 }
10263 if (strcmp(cmd,"D"))
10264 {
10265 ast_log(LOG_WARNING, "Unable to parse link string %s\n",str);
10266 return 0;
10267 }
10268
10269 if (strcmp(dest,myrpt->name)) return 0;
10270 if (myrpt->p.archivedir)
10271 {
10272 char dtmfstr[100];
10273
10274 sprintf(dtmfstr,"DTMF,%c",c);
10275 donodelog(myrpt,dtmfstr);
10276 }
10277 c = func_xlat(myrpt,c,&myrpt->p.outxlat);
10278 if (!c) return(0);
10279 res = handle_remote_dtmf_digit(myrpt,c, NULL, 0);
10280 if (res != 1)
10281 return res;
10282 rpt_telemetry(myrpt,COMPLETE,NULL);
10283 return 0;
10284 }
10285
10286 static int handle_remote_phone_dtmf(struct rpt *myrpt, char c, char *keyed, int phonemode)
10287 {
10288 int res;
10289
10290
10291 if(phonemode == 3)
10292 {
10293 if (keyed && *keyed && ((c == myrpt->p.funcchar) || (c == myrpt->p.endchar)))
10294 {
10295 *keyed = 0;
10296 return 0;
10297 }
10298 else if (keyed && !*keyed && (c = myrpt->p.funcchar))
10299 {
10300 *keyed = 1;
10301 return 0;
10302 }
10303 }
10304 else
10305 {
10306
10307 if (keyed && *keyed && (c == myrpt->p.endchar))
10308 {
10309 *keyed = 0;
10310 return DC_INDETERMINATE;
10311 }
10312 }
10313 if (myrpt->p.archivedir)
10314 {
10315 char str[100];
10316
10317 sprintf(str,"DTMF(P),%c",c);
10318 donodelog(myrpt,str);
10319 }
10320 res = handle_remote_dtmf_digit(myrpt,c,keyed, phonemode);
10321 if (res != 1)
10322 return res;
10323 rpt_telemetry(myrpt,COMPLETE,NULL);
10324 return 0;
10325 }
10326
10327 static int attempt_reconnect(struct rpt *myrpt, struct rpt_link *l)
10328 {
10329 char *val, *s, *s1, *s2, *tele;
10330 char tmp[300], deststr[300] = "";
10331 char sx[320],*sy;
10332
10333
10334 val = node_lookup(myrpt,l->name);
10335 if (!val)
10336 {
10337 fprintf(stderr,"attempt_reconnect: cannot find node %s\n",l->name);
10338 return -1;
10339 }
10340
10341 rpt_mutex_lock(&myrpt->lock);
10342
10343 remque((struct qelem *) l);
10344 rpt_mutex_unlock(&myrpt->lock);
10345 strncpy(tmp,val,sizeof(tmp) - 1);
10346 s = tmp;
10347 s1 = strsep(&s,",");
10348 if (!strchr(s1,':') && strchr(s1,'/') && strncasecmp(s1, "local/", 6))
10349 {
10350 sy = strchr(s1,'/');
10351 *sy = 0;
10352 sprintf(sx,"%s:4569/%s",s1,sy + 1);
10353 s1 = sx;
10354 }
10355 s2 = strsep(&s,",");
10356 snprintf(deststr, sizeof(deststr), "IAX2/%s", s1);
10357 tele = strchr(deststr, '/');
10358 if (!tele) {
10359 fprintf(stderr,"attempt_reconnect:Dial number (%s) must be in format tech/number\n",deststr);
10360 return -1;
10361 }
10362 *tele++ = 0;
10363 l->elaptime = 0;
10364 l->connecttime = 0;
10365 l->thisconnected = 0;
10366 l->newkey = 0;
10367 l->chan = ast_request(deststr, AST_FORMAT_SLINEAR, tele,NULL);
10368 if (l->chan){
10369 ast_set_read_format(l->chan, AST_FORMAT_SLINEAR);
10370 ast_set_write_format(l->chan, AST_FORMAT_SLINEAR);
10371 #ifndef NEW_ASTERISK
10372 l->chan->whentohangup = 0;
10373 #endif
10374 l->chan->appl = "Apprpt";
10375 l->chan->data = "(Remote Rx)";
10376 if (option_verbose > 2)
10377 ast_verbose(VERBOSE_PREFIX_3 "rpt (attempt_reconnect) initiating call to %s/%s on %s\n",
10378 deststr, tele, l->chan->name);
10379 if(l->chan->cid.cid_num)
10380 ast_free(l->chan->cid.cid_num);
10381 l->chan->cid.cid_num = ast_strdup(myrpt->name);
10382 ast_call(l->chan,tele,999);
10383
10384 }
10385 else
10386 {
10387 if (option_verbose > 2)
10388 ast_verbose(VERBOSE_PREFIX_3 "Unable to place call to %s/%s on %s\n",
10389 deststr,tele,l->chan->name);
10390 return -1;
10391 }
10392 rpt_mutex_lock(&myrpt->lock);
10393
10394 insque((struct qelem *)l,(struct qelem *)myrpt->links.next);
10395 rpt_mutex_unlock(&myrpt->lock);
10396 ast_log(LOG_WARNING,"Reconnect Attempt to %s in process\n",l->name);
10397 if (!l->phonemode) send_newkey(l->chan);
10398 return 0;
10399 }
10400
10401
10402 static void local_dtmf_helper(struct rpt *myrpt,char c_in)
10403 {
10404 int res;
10405 pthread_attr_t attr;
10406 char cmd[MAXDTMF+1] = "",c;
10407
10408
10409 c = c_in & 0x7f;
10410 if (myrpt->p.archivedir)
10411 {
10412 char str[100];
10413
10414 sprintf(str,"DTMF,MAIN,%c",c);
10415 donodelog(myrpt,str);
10416 }
10417 if (c == myrpt->p.endchar)
10418 {
10419
10420 if (myrpt->p.simple && myrpt->callmode)
10421 {
10422 if(debug)
10423 ast_log(LOG_WARNING, "simple mode autopatch kill\n");
10424 rpt_mutex_lock(&myrpt->lock);
10425 myrpt->callmode = 0;
10426 myrpt->macropatch=0;
10427 channel_revert(myrpt);
10428 rpt_mutex_unlock(&myrpt->lock);
10429 rpt_telemetry(myrpt,TERM,NULL);
10430 return;
10431 }
10432 rpt_mutex_lock(&myrpt->lock);
10433 myrpt->stopgen = 1;
10434 if (myrpt->cmdnode[0])
10435 {
10436 myrpt->cmdnode[0] = 0;
10437 myrpt->dtmfidx = -1;
10438 myrpt->dtmfbuf[0] = 0;
10439 rpt_mutex_unlock(&myrpt->lock);
10440 rpt_telemetry(myrpt,COMPLETE,NULL);
10441 return;
10442 }
10443 else if(!myrpt->inpadtest)
10444 {
10445 rpt_mutex_unlock(&myrpt->lock);
10446 if (myrpt->p.propagate_phonedtmf)
10447 do_dtmf_phone(myrpt,NULL,c);
10448 return;
10449 }
10450 else
10451 rpt_mutex_unlock(&myrpt->lock);
10452 }
10453 rpt_mutex_lock(&myrpt->lock);
10454 if (myrpt->cmdnode[0])
10455 {
10456 rpt_mutex_unlock(&myrpt->lock);
10457 send_link_dtmf(myrpt,c);
10458 return;
10459 }
10460 if (!myrpt->p.simple)
10461 {
10462 if ((!myrpt->inpadtest)&&(c == myrpt->p.funcchar))
10463 {
10464 myrpt->dtmfidx = 0;
10465 myrpt->dtmfbuf[myrpt->dtmfidx] = 0;
10466 rpt_mutex_unlock(&myrpt->lock);
10467 time(&myrpt->dtmf_time);
10468 return;
10469 }
10470 else if (((myrpt->inpadtest)||(c != myrpt->p.endchar)) && (myrpt->dtmfidx >= 0))
10471 {
10472 time(&myrpt->dtmf_time);
10473
10474 if (myrpt->dtmfidx < MAXDTMF)
10475 {
10476 int src;
10477
10478 myrpt->dtmfbuf[myrpt->dtmfidx++] = c;
10479 myrpt->dtmfbuf[myrpt->dtmfidx] = 0;
10480
10481 strncpy(cmd, myrpt->dtmfbuf, sizeof(cmd) - 1);
10482
10483 rpt_mutex_unlock(&myrpt->lock);
10484 src = SOURCE_RPT;
10485 if (c_in & 0x80) src = SOURCE_ALT;
10486 res = collect_function_digits(myrpt, cmd, src, NULL);
10487 rpt_mutex_lock(&myrpt->lock);
10488 switch(res){
10489 case DC_INDETERMINATE:
10490 break;
10491 case DC_REQ_FLUSH:
10492 myrpt->dtmfidx = 0;
10493 myrpt->dtmfbuf[0] = 0;
10494 break;
10495 case DC_COMPLETE:
10496 case DC_COMPLETEQUIET:
10497 myrpt->totalexecdcommands++;
10498 myrpt->dailyexecdcommands++;
10499 strncpy(myrpt->lastdtmfcommand, cmd, MAXDTMF-1);
10500 myrpt->lastdtmfcommand[MAXDTMF-1] = '\0';
10501 myrpt->dtmfbuf[0] = 0;
10502 myrpt->dtmfidx = -1;
10503 myrpt->dtmf_time = 0;
10504 break;
10505
10506 case DC_ERROR:
10507 default:
10508 myrpt->dtmfbuf[0] = 0;
10509 myrpt->dtmfidx = -1;
10510 myrpt->dtmf_time = 0;
10511 break;
10512 }
10513 if(res != DC_INDETERMINATE) {
10514 rpt_mutex_unlock(&myrpt->lock);
10515 return;
10516 }
10517 }
10518 }
10519 }
10520 else
10521 {
10522 if ((!myrpt->callmode) && (c == myrpt->p.funcchar))
10523 {
10524 myrpt->callmode = 1;
10525 myrpt->patchnoct = 0;
10526 myrpt->patchquiet = 0;
10527 myrpt->patchfarenddisconnect = 0;
10528 myrpt->patchdialtime = 0;
10529 strncpy(myrpt->patchcontext, myrpt->p.ourcontext, MAXPATCHCONTEXT);
10530 myrpt->cidx = 0;
10531 myrpt->exten[myrpt->cidx] = 0;
10532 rpt_mutex_unlock(&myrpt->lock);
10533 pthread_attr_init(&attr);
10534 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
10535 ast_pthread_create(&myrpt->rpt_call_thread,&attr,rpt_call,(void *)myrpt);
10536 return;
10537 }
10538 }
10539 if (myrpt->callmode == 1)
10540 {
10541 myrpt->exten[myrpt->cidx++] = c;
10542 myrpt->exten[myrpt->cidx] = 0;
10543
10544 if (ast_exists_extension(myrpt->pchannel,myrpt->patchcontext,myrpt->exten,1,NULL))
10545 {
10546
10547 if (!ast_matchmore_extension(myrpt->pchannel,myrpt->patchcontext,
10548 myrpt->exten,1,NULL))
10549 {
10550 myrpt->callmode = 2;
10551 rpt_mutex_unlock(&myrpt->lock);
10552 if(!myrpt->patchquiet)
10553 rpt_telemetry(myrpt,PROC,NULL);
10554 return;
10555 }
10556 else
10557 {
10558 myrpt->calldigittimer = 1;
10559 }
10560 }
10561
10562 if (!ast_canmatch_extension(myrpt->pchannel,myrpt->patchcontext,myrpt->exten,1,NULL))
10563 {
10564
10565 myrpt->callmode = 4;
10566 }
10567 rpt_mutex_unlock(&myrpt->lock);
10568 return;
10569 }
10570 if ((myrpt->callmode == 2) || (myrpt->callmode == 3))
10571 {
10572 myrpt->mydtmf = c;
10573 }
10574 rpt_mutex_unlock(&myrpt->lock);
10575 if ((myrpt->dtmfidx < 0) && myrpt->p.propagate_phonedtmf)
10576 do_dtmf_phone(myrpt,NULL,c);
10577 return;
10578 }
10579
10580
10581
10582
10583 static void queue_id(struct rpt *myrpt)
10584 {
10585 if(myrpt->p.idtime){
10586 myrpt->mustid = myrpt->tailid = 0;
10587 myrpt->idtimer = myrpt->p.idtime;
10588 rpt_mutex_unlock(&myrpt->lock);
10589 rpt_telemetry(myrpt,ID,NULL);
10590 rpt_mutex_lock(&myrpt->lock);
10591 }
10592 }
10593
10594
10595
10596
10597 static void do_scheduler(struct rpt *myrpt)
10598 {
10599 int i,res;
10600
10601 #ifdef NEW_ASTERISK
10602 struct ast_tm tmnow;
10603 #else
10604 struct tm tmnow;
10605 #endif
10606 struct ast_variable *skedlist;
10607 char *strs[5],*vp,*val,value[100];
10608
10609 memcpy(&myrpt->lasttv, &myrpt->curtv, sizeof(struct timeval));
10610
10611 if( (res = gettimeofday(&myrpt->curtv, NULL)) < 0)
10612 ast_log(LOG_NOTICE, "Scheduler gettime of day returned: %s\n", strerror(res));
10613
10614
10615
10616 if(myrpt->lasttv.tv_sec == myrpt->curtv.tv_sec)
10617 return;
10618
10619 rpt_localtime(&myrpt->curtv.tv_sec, &tmnow);
10620
10621
10622
10623 if((tmnow.tm_hour == 0)&&(tmnow.tm_min == 0)&&(tmnow.tm_sec == 0)){
10624 myrpt->dailykeyups = 0;
10625 myrpt->dailytxtime = 0;
10626 myrpt->dailykerchunks = 0;
10627 myrpt->dailyexecdcommands = 0;
10628 }
10629
10630 if(tmnow.tm_sec != 0)
10631 return;
10632
10633
10634
10635
10636
10637
10638 if (myrpt->remote)
10639 return;
10640
10641
10642
10643 if(myrpt->p.s[myrpt->p.sysstate_cur].schedulerdisable){
10644 if(debug > 6)
10645 ast_log(LOG_NOTICE, "Scheduler disabled\n");
10646 return;
10647 }
10648
10649 if(!myrpt->p.skedstanzaname){
10650 if(debug > 6)
10651 ast_log(LOG_NOTICE,"No stanza for scheduler in rpt.conf\n");
10652 return;
10653 }
10654
10655
10656 skedlist = ast_variable_browse(myrpt->cfg, myrpt->p.skedstanzaname);
10657
10658 if(debug > 6){
10659 ast_log(LOG_NOTICE, "Time now: %02d:%02d %02d %02d %02d\n",
10660 tmnow.tm_hour,tmnow.tm_min,tmnow.tm_mday,tmnow.tm_mon + 1, tmnow.tm_wday);
10661 }
10662
10663 for(; skedlist; skedlist = skedlist->next){
10664 if(debug > 6)
10665 ast_log(LOG_NOTICE, "Scheduler entry %s = %s being considered\n",skedlist->name, skedlist->value);
10666 strncpy(value,skedlist->value,99);
10667 value[99] = 0;
10668
10669 for( i = 0, vp = value ; i < 5; i++){
10670 if(!*vp)
10671 break;
10672 while((*vp == ' ') || (*vp == 0x09))
10673 vp++;
10674 strs[i] = vp;
10675 while((*vp != ' ') && (*vp != 0x09) && (*vp != 0))
10676 vp++;
10677 if(*vp)
10678 *vp++ = 0;
10679 }
10680 if(debug > 6)
10681 ast_log(LOG_NOTICE, "i = %d, min = %s, hour = %s, mday=%s, mon=%s, wday=%s\n",i,
10682 strs[0], strs[1], strs[2], strs[3], strs[4]);
10683 if(i == 5){
10684 if((*strs[0] != '*')&&(atoi(strs[0]) != tmnow.tm_min))
10685 continue;
10686 if((*strs[1] != '*')&&(atoi(strs[1]) != tmnow.tm_hour))
10687 continue;
10688 if((*strs[2] != '*')&&(atoi(strs[2]) != tmnow.tm_mday))
10689 continue;
10690 if((*strs[3] != '*')&&(atoi(strs[3]) != tmnow.tm_mon + 1))
10691 continue;
10692 if(atoi(strs[4]) == 7)
10693 strs[4] = "0";
10694 if((*strs[4] != '*')&&(atoi(strs[4]) != tmnow.tm_wday))
10695 continue;
10696 if(debug)
10697 ast_log(LOG_NOTICE, "Executing scheduler entry %s = %s\n", skedlist->name, skedlist->value);
10698 if(atoi(skedlist->name) == 0)
10699 return;
10700 val = (char *) ast_variable_retrieve(myrpt->cfg, myrpt->p.macro, skedlist->name);
10701 if (!val){
10702 ast_log(LOG_WARNING,"Scheduler could not find macro %s\n",skedlist->name);
10703 return;
10704 }
10705 if ((MAXMACRO - strlen(myrpt->macrobuf)) < strlen(val)){
10706 ast_log(LOG_WARNING, "Scheduler could not execute macro %s: Macro buffer full\n",
10707 skedlist->name);
10708 return;
10709 }
10710 myrpt->macrotimer = MACROTIME;
10711 strncat(myrpt->macrobuf,val,MAXMACRO - 1);
10712 }
10713 else{
10714 ast_log(LOG_WARNING,"Malformed scheduler entry in rpt.conf: %s = %s\n",
10715 skedlist->name, skedlist->value);
10716 }
10717 }
10718
10719 }
10720
10721
10722 static void *rpt(void *this)
10723 {
10724 struct rpt *myrpt = (struct rpt *)this;
10725 char *tele,*idtalkover,c,myfirst,*p;
10726 int ms = MSWAIT,i,lasttx=0,val,remrx=0,identqueued,othertelemqueued;
10727 int tailmessagequeued,ctqueued,dtmfed,lastmyrx,localmsgqueued;
10728 struct ast_channel *who;
10729 struct dahdi_confinfo ci;
10730 time_t t;
10731 struct rpt_link *l,*m;
10732 struct rpt_tele *telem;
10733 char tmpstr[300],lstr[MAXLINKLIST];
10734
10735
10736 if (myrpt->p.archivedir) mkdir(myrpt->p.archivedir,0600);
10737 sprintf(tmpstr,"%s/%s",myrpt->p.archivedir,myrpt->name);
10738 mkdir(tmpstr,0600);
10739 rpt_mutex_lock(&myrpt->lock);
10740
10741 telem = myrpt->tele.next;
10742 while(telem != &myrpt->tele)
10743 {
10744 ast_softhangup(telem->chan,AST_SOFTHANGUP_DEV);
10745 telem = telem->next;
10746 }
10747 rpt_mutex_unlock(&myrpt->lock);
10748
10749 for(i = 0; i < nrpts; i++)
10750 {
10751 if (&rpt_vars[i] == myrpt)
10752 {
10753 load_rpt_vars(i,0);
10754 break;
10755 }
10756 }
10757
10758 rpt_mutex_lock(&myrpt->lock);
10759 while(myrpt->xlink)
10760 {
10761 myrpt->xlink = 3;
10762 rpt_mutex_unlock(&myrpt->lock);
10763 usleep(100000);
10764 rpt_mutex_lock(&myrpt->lock);
10765 }
10766 #ifdef HAVE_IOPERM
10767 if ((!strcmp(myrpt->remoterig, remote_rig_rbi)) &&
10768 (ioperm(myrpt->p.iobase,1,1) == -1))
10769 {
10770 rpt_mutex_unlock(&myrpt->lock);
10771 ast_log(LOG_WARNING, "Cant get io permission on IO port %x hex\n",myrpt->p.iobase);
10772 myrpt->rpt_thread = AST_PTHREADT_STOP;
10773 pthread_exit(NULL);
10774 }
10775 #endif
10776 strncpy(tmpstr,myrpt->rxchanname,sizeof(tmpstr) - 1);
10777 tele = strchr(tmpstr,'/');
10778 if (!tele)
10779 {
10780 fprintf(stderr,"rpt:Rxchannel Dial number (%s) must be in format tech/number\n",myrpt->rxchanname);
10781 rpt_mutex_unlock(&myrpt->lock);
10782 myrpt->rpt_thread = AST_PTHREADT_STOP;
10783 pthread_exit(NULL);
10784 }
10785 *tele++ = 0;
10786 myrpt->rxchannel = ast_request(tmpstr,AST_FORMAT_SLINEAR,tele,NULL);
10787 myrpt->dahdirxchannel = NULL;
10788 if (!strcasecmp(tmpstr,"DAHDI"))
10789 myrpt->dahdirxchannel = myrpt->rxchannel;
10790 if (myrpt->rxchannel)
10791 {
10792 if (myrpt->rxchannel->_state == AST_STATE_BUSY)
10793 {
10794 fprintf(stderr,"rpt:Sorry unable to obtain Rx channel\n");
10795 rpt_mutex_unlock(&myrpt->lock);
10796 ast_hangup(myrpt->rxchannel);
10797 myrpt->rpt_thread = AST_PTHREADT_STOP;
10798 pthread_exit(NULL);
10799 }
10800 ast_set_read_format(myrpt->rxchannel,AST_FORMAT_SLINEAR);
10801 ast_set_write_format(myrpt->rxchannel,AST_FORMAT_SLINEAR);
10802 #ifdef AST_CDR_FLAG_POST_DISABLED
10803 if (myrpt->rxchannel->cdr)
10804 ast_set_flag(myrpt->rxchannel->cdr,AST_CDR_FLAG_POST_DISABLED);
10805 #endif
10806 #ifndef NEW_ASTERISK
10807 myrpt->rxchannel->whentohangup = 0;
10808 #endif
10809 myrpt->rxchannel->appl = "Apprpt";
10810 myrpt->rxchannel->data = "(Repeater Rx)";
10811 if (option_verbose > 2)
10812 ast_verbose(VERBOSE_PREFIX_3 "rpt (Rx) initiating call to %s/%s on %s\n",
10813 tmpstr,tele,myrpt->rxchannel->name);
10814 ast_call(myrpt->rxchannel,tele,999);
10815 if (myrpt->rxchannel->_state != AST_STATE_UP)
10816 {
10817 rpt_mutex_unlock(&myrpt->lock);
10818 ast_hangup(myrpt->rxchannel);
10819 myrpt->rpt_thread = AST_PTHREADT_STOP;
10820 pthread_exit(NULL);
10821 }
10822 }
10823 else
10824 {
10825 fprintf(stderr,"rpt:Sorry unable to obtain Rx channel\n");
10826 rpt_mutex_unlock(&myrpt->lock);
10827 myrpt->rpt_thread = AST_PTHREADT_STOP;
10828 pthread_exit(NULL);
10829 }
10830 myrpt->dahditxchannel = NULL;
10831 if (myrpt->txchanname)
10832 {
10833 strncpy(tmpstr,myrpt->txchanname,sizeof(tmpstr) - 1);
10834 tele = strchr(tmpstr,'/');
10835 if (!tele)
10836 {
10837 fprintf(stderr,"rpt:Txchannel Dial number (%s) must be in format tech/number\n",myrpt->txchanname);
10838 rpt_mutex_unlock(&myrpt->lock);
10839 ast_hangup(myrpt->rxchannel);
10840 myrpt->rpt_thread = AST_PTHREADT_STOP;
10841 pthread_exit(NULL);
10842 }
10843 *tele++ = 0;
10844 myrpt->txchannel = ast_request(tmpstr,AST_FORMAT_SLINEAR,tele,NULL);
10845 if (!strcasecmp(tmpstr,"DAHDI"))
10846 myrpt->dahditxchannel = myrpt->txchannel;
10847 if (myrpt->txchannel)
10848 {
10849 if (myrpt->txchannel->_state == AST_STATE_BUSY)
10850 {
10851 fprintf(stderr,"rpt:Sorry unable to obtain Tx channel\n");
10852 rpt_mutex_unlock(&myrpt->lock);
10853 ast_hangup(myrpt->txchannel);
10854 ast_hangup(myrpt->rxchannel);
10855 myrpt->rpt_thread = AST_PTHREADT_STOP;
10856 pthread_exit(NULL);
10857 }
10858 ast_set_read_format(myrpt->txchannel,AST_FORMAT_SLINEAR);
10859 ast_set_write_format(myrpt->txchannel,AST_FORMAT_SLINEAR);
10860 #ifdef AST_CDR_FLAG_POST_DISABLED
10861 if (myrpt->txchannel->cdr)
10862 ast_set_flag(myrpt->txchannel->cdr,AST_CDR_FLAG_POST_DISABLED);
10863 #endif
10864 #ifndef NEW_ASTERISK
10865 myrpt->txchannel->whentohangup = 0;
10866 #endif
10867 myrpt->txchannel->appl = "Apprpt";
10868 myrpt->txchannel->data = "(Repeater Tx)";
10869 if (option_verbose > 2)
10870 ast_verbose(VERBOSE_PREFIX_3 "rpt (Tx) initiating call to %s/%s on %s\n",
10871 tmpstr,tele,myrpt->txchannel->name);
10872 ast_call(myrpt->txchannel,tele,999);
10873 if (myrpt->rxchannel->_state != AST_STATE_UP)
10874 {
10875 rpt_mutex_unlock(&myrpt->lock);
10876 ast_hangup(myrpt->rxchannel);
10877 ast_hangup(myrpt->txchannel);
10878 myrpt->rpt_thread = AST_PTHREADT_STOP;
10879 pthread_exit(NULL);
10880 }
10881 }
10882 else
10883 {
10884 fprintf(stderr,"rpt:Sorry unable to obtain Tx channel\n");
10885 rpt_mutex_unlock(&myrpt->lock);
10886 ast_hangup(myrpt->rxchannel);
10887 myrpt->rpt_thread = AST_PTHREADT_STOP;
10888 pthread_exit(NULL);
10889 }
10890 }
10891 else
10892 {
10893 myrpt->txchannel = myrpt->rxchannel;
10894 if (!strncasecmp(myrpt->rxchanname,"DAHDI",3))
10895 myrpt->dahditxchannel = myrpt->txchannel;
10896 }
10897 ast_indicate(myrpt->txchannel,AST_CONTROL_RADIO_KEY);
10898 ast_indicate(myrpt->txchannel,AST_CONTROL_RADIO_UNKEY);
10899
10900 myrpt->pchannel = ast_request("DAHDI",AST_FORMAT_SLINEAR,"pseudo",NULL);
10901 if (!myrpt->pchannel)
10902 {
10903 fprintf(stderr,"rpt:Sorry unable to obtain pseudo channel\n");
10904 rpt_mutex_unlock(&myrpt->lock);
10905 if (myrpt->txchannel != myrpt->rxchannel)
10906 ast_hangup(myrpt->txchannel);
10907 ast_hangup(myrpt->rxchannel);
10908 myrpt->rpt_thread = AST_PTHREADT_STOP;
10909 pthread_exit(NULL);
10910 }
10911 #ifdef AST_CDR_FLAG_POST_DISABLED
10912 if (myrpt->pchannel->cdr)
10913 ast_set_flag(myrpt->pchannel->cdr,AST_CDR_FLAG_POST_DISABLED);
10914 #endif
10915 if (!myrpt->dahdirxchannel) myrpt->dahdirxchannel = myrpt->pchannel;
10916 if (!myrpt->dahditxchannel)
10917 {
10918
10919 myrpt->dahditxchannel = ast_request("DAHDI",AST_FORMAT_SLINEAR,"pseudo",NULL);
10920 if (!myrpt->dahditxchannel)
10921 {
10922 fprintf(stderr,"rpt:Sorry unable to obtain pseudo channel\n");
10923 rpt_mutex_unlock(&myrpt->lock);
10924 if (myrpt->txchannel != myrpt->rxchannel)
10925 ast_hangup(myrpt->txchannel);
10926 ast_hangup(myrpt->rxchannel);
10927 myrpt->rpt_thread = AST_PTHREADT_STOP;
10928 pthread_exit(NULL);
10929 }
10930 ast_set_read_format(myrpt->dahditxchannel,AST_FORMAT_SLINEAR);
10931 ast_set_write_format(myrpt->dahditxchannel,AST_FORMAT_SLINEAR);
10932 #ifdef AST_CDR_FLAG_POST_DISABLED
10933 if (myrpt->dahditxchannel->cdr)
10934 ast_set_flag(myrpt->dahditxchannel->cdr,AST_CDR_FLAG_POST_DISABLED);
10935 #endif
10936 }
10937
10938 myrpt->monchannel = ast_request("DAHDI",AST_FORMAT_SLINEAR,"pseudo",NULL);
10939 if (!myrpt->monchannel)
10940 {
10941 fprintf(stderr,"rpt:Sorry unable to obtain pseudo channel\n");
10942 rpt_mutex_unlock(&myrpt->lock);
10943 if (myrpt->txchannel != myrpt->rxchannel)
10944 ast_hangup(myrpt->txchannel);
10945 ast_hangup(myrpt->rxchannel);
10946 myrpt->rpt_thread = AST_PTHREADT_STOP;
10947 pthread_exit(NULL);
10948 }
10949 ast_set_read_format(myrpt->monchannel,AST_FORMAT_SLINEAR);
10950 ast_set_write_format(myrpt->monchannel,AST_FORMAT_SLINEAR);
10951 #ifdef AST_CDR_FLAG_POST_DISABLED
10952 if (myrpt->monchannel->cdr)
10953 ast_set_flag(myrpt->monchannel->cdr,AST_CDR_FLAG_POST_DISABLED);
10954 #endif
10955
10956 ci.chan = 0;
10957 ci.confno = -1;
10958 ci.confmode = DAHDI_CONF_CONF | DAHDI_CONF_LISTENER;
10959
10960 if (ioctl(myrpt->dahditxchannel->fds[0],DAHDI_SETCONF,&ci) == -1)
10961 {
10962 ast_log(LOG_WARNING, "Unable to set conference mode to Announce\n");
10963 rpt_mutex_unlock(&myrpt->lock);
10964 ast_hangup(myrpt->pchannel);
10965 ast_hangup(myrpt->monchannel);
10966 if (myrpt->txchannel != myrpt->rxchannel)
10967 ast_hangup(myrpt->txchannel);
10968 ast_hangup(myrpt->rxchannel);
10969 myrpt->rpt_thread = AST_PTHREADT_STOP;
10970 pthread_exit(NULL);
10971 }
10972
10973 myrpt->txconf = ci.confno;
10974
10975 ci.chan = 0;
10976 ci.confno = -1;
10977 ci.confmode = ((myrpt->p.duplex == 2) || (myrpt->p.duplex == 4)) ? DAHDI_CONF_CONFANNMON :
10978 (DAHDI_CONF_CONF | DAHDI_CONF_LISTENER | DAHDI_CONF_TALKER);
10979
10980 if (ioctl(myrpt->pchannel->fds[0],DAHDI_SETCONF,&ci) == -1)
10981 {
10982 ast_log(LOG_WARNING, "Unable to set conference mode to Announce\n");
10983 rpt_mutex_unlock(&myrpt->lock);
10984 ast_hangup(myrpt->pchannel);
10985 ast_hangup(myrpt->monchannel);
10986 if (myrpt->txchannel != myrpt->rxchannel)
10987 ast_hangup(myrpt->txchannel);
10988 ast_hangup(myrpt->rxchannel);
10989 myrpt->rpt_thread = AST_PTHREADT_STOP;
10990 pthread_exit(NULL);
10991 }
10992
10993 myrpt->conf = ci.confno;
10994
10995 ci.chan = 0;
10996 if ((strstr(myrpt->txchannel->name,"pseudo") == NULL) &&
10997 (myrpt->dahditxchannel == myrpt->txchannel))
10998 {
10999
11000 if (ioctl(myrpt->txchannel->fds[0],DAHDI_CHANNO,&ci.confno) == -1)
11001 {
11002 ast_log(LOG_WARNING, "Unable to set tx channel's chan number\n");
11003 rpt_mutex_unlock(&myrpt->lock);
11004 ast_hangup(myrpt->pchannel);
11005 ast_hangup(myrpt->monchannel);
11006 if (myrpt->txchannel != myrpt->rxchannel)
11007 ast_hangup(myrpt->txchannel);
11008 ast_hangup(myrpt->rxchannel);
11009 myrpt->rpt_thread = AST_PTHREADT_STOP;
11010 pthread_exit(NULL);
11011 }
11012 ci.confmode = DAHDI_CONF_MONITORTX;
11013 }
11014 else
11015 {
11016 ci.confno = myrpt->txconf;
11017 ci.confmode = DAHDI_CONF_CONFANNMON;
11018 }
11019
11020 if (ioctl(myrpt->monchannel->fds[0],DAHDI_SETCONF,&ci) == -1)
11021 {
11022 ast_log(LOG_WARNING, "Unable to set conference mode for monitor\n");
11023 rpt_mutex_unlock(&myrpt->lock);
11024 ast_hangup(myrpt->pchannel);
11025 ast_hangup(myrpt->monchannel);
11026 if (myrpt->txchannel != myrpt->rxchannel)
11027 ast_hangup(myrpt->txchannel);
11028 ast_hangup(myrpt->rxchannel);
11029 myrpt->rpt_thread = AST_PTHREADT_STOP;
11030 pthread_exit(NULL);
11031 }
11032
11033 myrpt->parrotchannel = ast_request("DAHDI",AST_FORMAT_SLINEAR,"pseudo",NULL);
11034 if (!myrpt->parrotchannel)
11035 {
11036 fprintf(stderr,"rpt:Sorry unable to obtain pseudo channel\n");
11037 rpt_mutex_unlock(&myrpt->lock);
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 ast_set_read_format(myrpt->parrotchannel,AST_FORMAT_SLINEAR);
11045 ast_set_write_format(myrpt->parrotchannel,AST_FORMAT_SLINEAR);
11046 #ifdef AST_CDR_FLAG_POST_DISABLED
11047 if (myrpt->parrotchannel->cdr)
11048 ast_set_flag(myrpt->parrotchannel->cdr,AST_CDR_FLAG_POST_DISABLED);
11049 #endif
11050
11051 myrpt->voxchannel = ast_request("DAHDI",AST_FORMAT_SLINEAR,"pseudo",NULL);
11052 if (!myrpt->voxchannel)
11053 {
11054 fprintf(stderr,"rpt:Sorry unable to obtain pseudo channel\n");
11055 rpt_mutex_unlock(&myrpt->lock);
11056 if (myrpt->txchannel != myrpt->rxchannel)
11057 ast_hangup(myrpt->txchannel);
11058 ast_hangup(myrpt->rxchannel);
11059 myrpt->rpt_thread = AST_PTHREADT_STOP;
11060 pthread_exit(NULL);
11061 }
11062 ast_set_read_format(myrpt->voxchannel,AST_FORMAT_SLINEAR);
11063 ast_set_write_format(myrpt->voxchannel,AST_FORMAT_SLINEAR);
11064 #ifdef AST_CDR_FLAG_POST_DISABLED
11065 if (myrpt->voxchannel->cdr)
11066 ast_set_flag(myrpt->voxchannel->cdr,AST_CDR_FLAG_POST_DISABLED);
11067 #endif
11068
11069 myrpt->txpchannel = ast_request("DAHDI",AST_FORMAT_SLINEAR,"pseudo",NULL);
11070 if (!myrpt->txpchannel)
11071 {
11072 fprintf(stderr,"rpt:Sorry unable to obtain pseudo channel\n");
11073 rpt_mutex_unlock(&myrpt->lock);
11074 ast_hangup(myrpt->pchannel);
11075 ast_hangup(myrpt->monchannel);
11076 if (myrpt->txchannel != myrpt->rxchannel)
11077 ast_hangup(myrpt->txchannel);
11078 ast_hangup(myrpt->rxchannel);
11079 myrpt->rpt_thread = AST_PTHREADT_STOP;
11080 pthread_exit(NULL);
11081 }
11082 #ifdef AST_CDR_FLAG_POST_DISABLED
11083 if (myrpt->txpchannel->cdr)
11084 ast_set_flag(myrpt->txpchannel->cdr,AST_CDR_FLAG_POST_DISABLED);
11085 #endif
11086
11087 ci.chan = 0;
11088 ci.confno = myrpt->txconf;
11089 ci.confmode = DAHDI_CONF_CONF | DAHDI_CONF_TALKER ;
11090
11091 if (ioctl(myrpt->txpchannel->fds[0],DAHDI_SETCONF,&ci) == -1)
11092 {
11093 ast_log(LOG_WARNING, "Unable to set conference mode to Announce\n");
11094 rpt_mutex_unlock(&myrpt->lock);
11095 ast_hangup(myrpt->txpchannel);
11096 ast_hangup(myrpt->monchannel);
11097 if (myrpt->txchannel != myrpt->rxchannel)
11098 ast_hangup(myrpt->txchannel);
11099 ast_hangup(myrpt->rxchannel);
11100 myrpt->rpt_thread = AST_PTHREADT_STOP;
11101 pthread_exit(NULL);
11102 }
11103
11104 myrpt->iofd = -1;
11105 if (myrpt->p.ioport && ((myrpt->iofd = openserial(myrpt,myrpt->p.ioport)) == -1))
11106 {
11107 ast_log(LOG_ERROR, "Unable to open %s\n",myrpt->p.ioport);
11108 rpt_mutex_unlock(&myrpt->lock);
11109 ast_hangup(myrpt->pchannel);
11110 if (myrpt->txchannel != myrpt->rxchannel)
11111 ast_hangup(myrpt->txchannel);
11112 ast_hangup(myrpt->rxchannel);
11113 pthread_exit(NULL);
11114 }
11115
11116
11117
11118 myrpt->links.next = &myrpt->links;
11119 myrpt->links.prev = &myrpt->links;
11120 myrpt->tailtimer = 0;
11121 myrpt->totimer = 0;
11122 myrpt->tmsgtimer = myrpt->p.tailmessagetime;
11123 myrpt->idtimer = myrpt->p.politeid;
11124 myrpt->mustid = myrpt->tailid = 0;
11125 myrpt->callmode = 0;
11126 myrpt->tounkeyed = 0;
11127 myrpt->tonotify = 0;
11128 myrpt->retxtimer = 0;
11129 myrpt->rerxtimer = 0;
11130 myrpt->skedtimer = 0;
11131 myrpt->tailevent = 0;
11132 lasttx = 0;
11133 myrpt->keyed = 0;
11134 myrpt->txkeyed = 0;
11135 time(&myrpt->lastkeyedtime);
11136 myrpt->lastkeyedtime -= RPT_LOCKOUT_SECS;
11137 time(&myrpt->lasttxkeyedtime);
11138 myrpt->lasttxkeyedtime -= RPT_LOCKOUT_SECS;
11139 idtalkover = (char *) ast_variable_retrieve(myrpt->cfg, myrpt->name, "idtalkover");
11140 myrpt->dtmfidx = -1;
11141 myrpt->dtmfbuf[0] = 0;
11142 myrpt->rem_dtmfidx = -1;
11143 myrpt->rem_dtmfbuf[0] = 0;
11144 myrpt->dtmf_time = 0;
11145 myrpt->rem_dtmf_time = 0;
11146 myrpt->inpadtest = 0;
11147 myrpt->disgorgetime = 0;
11148 myrpt->lastnodewhichkeyedusup[0] = '\0';
11149 myrpt->dailytxtime = 0;
11150 myrpt->totaltxtime = 0;
11151 myrpt->dailykeyups = 0;
11152 myrpt->totalkeyups = 0;
11153 myrpt->dailykerchunks = 0;
11154 myrpt->totalkerchunks = 0;
11155 myrpt->dailyexecdcommands = 0;
11156 myrpt->totalexecdcommands = 0;
11157 myrpt->timeouts = 0;
11158 myrpt->exten[0] = '\0';
11159 myrpt->lastdtmfcommand[0] = '\0';
11160 voxinit_rpt(myrpt,1);
11161 myrpt->wasvox = 0;
11162 if (myrpt->p.startupmacro)
11163 {
11164 snprintf(myrpt->macrobuf,MAXMACRO - 1,"PPPP%s",myrpt->p.startupmacro);
11165 }
11166 rpt_mutex_unlock(&myrpt->lock);
11167 val = 1;
11168 ast_channel_setoption(myrpt->rxchannel,AST_OPTION_RELAXDTMF,&val,sizeof(char),0);
11169 val = 1;
11170 ast_channel_setoption(myrpt->rxchannel,AST_OPTION_TONE_VERIFY,&val,sizeof(char),0);
11171 if (myrpt->p.archivedir) donodelog(myrpt,"STARTUP");
11172 dtmfed = 0;
11173 if (myrpt->remoterig && !ISRIG_RTX(myrpt->remoterig)) setrem(myrpt);
11174 lastmyrx = 0;
11175 myfirst = 0;
11176 while (ms >= 0)
11177 {
11178 struct ast_frame *f,*f1,*f2;
11179 struct ast_channel *cs[300],*cs1[300];
11180 int totx=0,elap=0,n,x,toexit=0;
11181
11182
11183 if((myrpt->disgorgetime) && (time(NULL) >= myrpt->disgorgetime)){
11184 struct rpt_link *dl;
11185 struct rpt_tele *dt;
11186
11187 myrpt->disgorgetime = 0;
11188 ast_log(LOG_NOTICE,"********** Variable Dump Start (app_rpt) **********\n");
11189 ast_log(LOG_NOTICE,"totx = %d\n",totx);
11190 ast_log(LOG_NOTICE,"remrx = %d\n",remrx);
11191 ast_log(LOG_NOTICE,"lasttx = %d\n",lasttx);
11192 ast_log(LOG_NOTICE,"elap = %d\n",elap);
11193 ast_log(LOG_NOTICE,"toexit = %d\n",toexit);
11194
11195 ast_log(LOG_NOTICE,"myrpt->keyed = %d\n",myrpt->keyed);
11196 ast_log(LOG_NOTICE,"myrpt->localtx = %d\n",myrpt->localtx);
11197 ast_log(LOG_NOTICE,"myrpt->callmode = %d\n",myrpt->callmode);
11198 ast_log(LOG_NOTICE,"myrpt->mustid = %d\n",myrpt->mustid);
11199 ast_log(LOG_NOTICE,"myrpt->tounkeyed = %d\n",myrpt->tounkeyed);
11200 ast_log(LOG_NOTICE,"myrpt->tonotify = %d\n",myrpt->tonotify);
11201 ast_log(LOG_NOTICE,"myrpt->retxtimer = %ld\n",myrpt->retxtimer);
11202 ast_log(LOG_NOTICE,"myrpt->totimer = %d\n",myrpt->totimer);
11203 ast_log(LOG_NOTICE,"myrpt->tailtimer = %d\n",myrpt->tailtimer);
11204 ast_log(LOG_NOTICE,"myrpt->tailevent = %d\n",myrpt->tailevent);
11205
11206 dl = myrpt->links.next;
11207 while(dl != &myrpt->links){
11208 ast_log(LOG_NOTICE,"*** Link Name: %s ***\n",dl->name);
11209 ast_log(LOG_NOTICE," link->lasttx %d\n",dl->lasttx);
11210 ast_log(LOG_NOTICE," link->lastrx %d\n",dl->lastrx);
11211 ast_log(LOG_NOTICE," link->connected %d\n",dl->connected);
11212 ast_log(LOG_NOTICE," link->hasconnected %d\n",dl->hasconnected);
11213 ast_log(LOG_NOTICE," link->outbound %d\n",dl->outbound);
11214 ast_log(LOG_NOTICE," link->disced %d\n",dl->disced);
11215 ast_log(LOG_NOTICE," link->killme %d\n",dl->killme);
11216 ast_log(LOG_NOTICE," link->disctime %ld\n",dl->disctime);
11217 ast_log(LOG_NOTICE," link->retrytimer %ld\n",dl->retrytimer);
11218 ast_log(LOG_NOTICE," link->retries = %d\n",dl->retries);
11219 ast_log(LOG_NOTICE," link->reconnects = %d\n",dl->reconnects);
11220 ast_log(LOG_NOTICE," link->newkey = %d\n",dl->newkey);
11221 dl = dl->next;
11222 }
11223
11224 dt = myrpt->tele.next;
11225 if(dt != &myrpt->tele)
11226 ast_log(LOG_NOTICE,"*** Telemetry Queue ***\n");
11227 while(dt != &myrpt->tele){
11228 ast_log(LOG_NOTICE," Telemetry mode: %d\n",dt->mode);
11229 dt = dt->next;
11230 }
11231 ast_log(LOG_NOTICE,"******* Variable Dump End (app_rpt) *******\n");
11232
11233 }
11234
11235
11236 if (myrpt->reload)
11237 {
11238 struct rpt_tele *inner_telem;
11239
11240 rpt_mutex_lock(&myrpt->lock);
11241 inner_telem = myrpt->tele.next;
11242 while(inner_telem != &myrpt->tele)
11243 {
11244 ast_softhangup(inner_telem->chan,AST_SOFTHANGUP_DEV);
11245 inner_telem = inner_telem->next;
11246 }
11247 myrpt->reload = 0;
11248 rpt_mutex_unlock(&myrpt->lock);
11249 usleep(10000);
11250
11251 for(i = 0; i < nrpts; i++)
11252 {
11253 if (&rpt_vars[i] == myrpt)
11254 {
11255 load_rpt_vars(i,0);
11256 break;
11257 }
11258 }
11259 }
11260
11261 rpt_mutex_lock(&myrpt->lock);
11262 if (ast_check_hangup(myrpt->rxchannel)) break;
11263 if (ast_check_hangup(myrpt->txchannel)) break;
11264 if (ast_check_hangup(myrpt->pchannel)) break;
11265 if (ast_check_hangup(myrpt->monchannel)) break;
11266 if (myrpt->parrotchannel &&
11267 ast_check_hangup(myrpt->parrotchannel)) break;
11268 if (myrpt->voxchannel &&
11269 ast_check_hangup(myrpt->voxchannel)) break;
11270 if (ast_check_hangup(myrpt->txpchannel)) break;
11271 if (myrpt->dahditxchannel && ast_check_hangup(myrpt->dahditxchannel)) break;
11272
11273
11274 myrpt->localtx = myrpt->keyed;
11275
11276 l = myrpt->links.next;
11277 remrx = 0;
11278 while(l != &myrpt->links)
11279 {
11280 if (l->lastrx){
11281 remrx = 1;
11282 if(l->name[0] != '0')
11283 strcpy(myrpt->lastnodewhichkeyedusup, l->name);
11284 }
11285 l = l->next;
11286 }
11287
11288 if(myrpt->p.idtime)
11289 myrpt->mustid |= (myrpt->idtimer) && (myrpt->keyed || remrx) ;
11290
11291
11292 if (myrpt->p.duplex > 1)
11293 {
11294 totx = myrpt->callmode;
11295 totx = totx || myrpt->localtx;
11296 }
11297 else
11298 {
11299 int myrx = myrpt->localtx || remrx || (!myrpt->callmode);
11300
11301 if (lastmyrx != myrx)
11302 {
11303 voxinit_rpt(myrpt,!myrx);
11304 lastmyrx = myrx;
11305 }
11306 totx = 0;
11307 if (myrpt->callmode && (myrpt->voxtotimer <= 0))
11308 {
11309 if (myrpt->voxtostate)
11310 {
11311 myrpt->voxtotimer = myrpt->p.voxtimeout_ms;
11312 myrpt->voxtostate = 0;
11313 }
11314 else
11315 {
11316 myrpt->voxtotimer = myrpt->p.voxrecover_ms;
11317 myrpt->voxtostate = 1;
11318 }
11319 }
11320 if (!myrpt->voxtostate)
11321 totx = myrpt->callmode && myrpt->wasvox;
11322 }
11323
11324 identqueued = 0;
11325 localmsgqueued = 0;
11326 othertelemqueued = 0;
11327 tailmessagequeued = 0;
11328 ctqueued = 0;
11329 telem = myrpt->tele.next;
11330 while(telem != &myrpt->tele)
11331 {
11332 if((telem->mode == ID) || (telem->mode == IDTALKOVER)){
11333 identqueued = 1;
11334 }
11335 else if(telem->mode == TAILMSG)
11336 {
11337 tailmessagequeued = 1;
11338 }
11339 else if(telem->mode == STATS_TIME_LOCAL)
11340 {
11341 localmsgqueued = 1;
11342 }
11343 else
11344 {
11345 if ((telem->mode != UNKEY) && (telem->mode != LINKUNKEY))
11346 othertelemqueued = 1;
11347 else
11348 ctqueued = 1;
11349 }
11350 telem = telem->next;
11351 }
11352
11353
11354 if (!myrpt->p.notelemtx) totx = totx || othertelemqueued;
11355
11356
11357 myrpt->exttx = totx;
11358 totx = totx || myrpt->dtmf_local_timer;
11359
11360 if (myrpt->p.duplex < 2) myrpt->exttx = myrpt->exttx || myrpt->localtx;
11361
11362 totx = totx || remrx;
11363
11364 if (myrpt->p.duplex > 0)
11365 totx = totx || identqueued || ctqueued || localmsgqueued;
11366
11367 if (myrpt->p.duplex > 1)
11368 {
11369 totx = totx || (myrpt->dtmfidx > -1) ||
11370 myrpt->cmdnode[0];
11371 }
11372
11373 totx = totx || (myrpt->parrotstate > 1);
11374
11375 if (!totx)
11376 {
11377 myrpt->totimer = myrpt->p.totime;
11378 myrpt->tounkeyed = 0;
11379 myrpt->tonotify = 0;
11380 }
11381 else{
11382 myrpt->tailtimer = myrpt->p.s[myrpt->p.sysstate_cur].alternatetail ?
11383 myrpt->p.althangtime :
11384 myrpt->p.hangtime;
11385 }
11386
11387 totx = totx && myrpt->totimer;
11388
11389 if ((!myrpt->totimer) && (!myrpt->tonotify))
11390 {
11391 myrpt->tonotify = 1;
11392 myrpt->timeouts++;
11393 rpt_mutex_unlock(&myrpt->lock);
11394 rpt_telemetry(myrpt,TIMEOUT,NULL);
11395 rpt_mutex_lock(&myrpt->lock);
11396 }
11397
11398
11399 if ((!totx) && (!myrpt->totimer) && (!myrpt->tounkeyed) && (!myrpt->keyed))
11400 {
11401 myrpt->tounkeyed = 1;
11402 }
11403 if ((!totx) && (!myrpt->totimer) && myrpt->tounkeyed && myrpt->keyed)
11404 {
11405 myrpt->totimer = myrpt->p.totime;
11406 myrpt->tounkeyed = 0;
11407 myrpt->tonotify = 0;
11408 rpt_mutex_unlock(&myrpt->lock);
11409 continue;
11410 }
11411
11412 if ((!totx) && (!myrpt->totimer) && (myrpt->callmode == 4))
11413 {
11414 if(debug)
11415 ast_log(LOG_NOTICE, "timed-out and in circuit busy after call\n");
11416 myrpt->callmode = 0;
11417 myrpt->macropatch=0;
11418 channel_revert(myrpt);
11419 }
11420
11421 if (!myrpt->totimer) myrpt->tailtimer = 0;
11422
11423 if (myrpt->totimer) totx = totx || myrpt->tailtimer;
11424
11425
11426 if ((myrpt->keyed || remrx) && ((identqueued && idtalkover) || (tailmessagequeued))) {
11427 int hasid = 0,hastalkover = 0;
11428
11429 telem = myrpt->tele.next;
11430 while(telem != &myrpt->tele){
11431 if(telem->mode == ID){
11432 if (telem->chan) ast_softhangup(telem->chan, AST_SOFTHANGUP_DEV);
11433 hasid = 1;
11434 }
11435 if(telem->mode == TAILMSG){
11436 if (telem->chan) ast_softhangup(telem->chan, AST_SOFTHANGUP_DEV);
11437 }
11438 if (telem->mode == IDTALKOVER) hastalkover = 1;
11439 telem = telem->next;
11440 }
11441 rpt_mutex_unlock(&myrpt->lock);
11442 if (hasid && (!hastalkover)) rpt_telemetry(myrpt, IDTALKOVER, NULL);
11443 rpt_mutex_lock(&myrpt->lock);
11444 }
11445
11446
11447
11448
11449
11450 if(myrpt->mustid && (!myrpt->idtimer))
11451 queue_id(myrpt);
11452
11453 if ((myrpt->p.idtime && totx && (!myrpt->exttx) &&
11454 (myrpt->idtimer <= myrpt->p.politeid) && myrpt->tailtimer))
11455 {
11456 myrpt->tailid = 1;
11457 }
11458
11459
11460
11461 if(myrpt->tailevent){
11462 myrpt->tailevent = 0;
11463 if(myrpt->tailid){
11464 totx = 1;
11465 queue_id(myrpt);
11466 }
11467 else if ((myrpt->p.tailmessages[0]) &&
11468 (myrpt->p.tailmessagetime) && (myrpt->tmsgtimer == 0)){
11469 totx = 1;
11470 myrpt->tmsgtimer = myrpt->p.tailmessagetime;
11471 rpt_mutex_unlock(&myrpt->lock);
11472 rpt_telemetry(myrpt, TAILMSG, NULL);
11473 rpt_mutex_lock(&myrpt->lock);
11474 }
11475 }
11476
11477
11478
11479
11480 if (myrpt->p.duplex > 0) totx = totx || (myrpt->tele.next != &myrpt->tele);
11481 totx = totx && !myrpt->p.s[myrpt->p.sysstate_cur].txdisable;
11482 myrpt->txrealkeyed = totx;
11483 totx = totx || (!AST_LIST_EMPTY(&myrpt->txq));
11484 if (totx && (!lasttx))
11485 {
11486 char mydate[100],myfname[100];
11487 time_t myt;
11488
11489 if (myrpt->monstream) ast_closestream(myrpt->monstream);
11490 if (myrpt->p.archivedir)
11491 {
11492 long blocksleft;
11493
11494 time(&myt);
11495 strftime(mydate,sizeof(mydate) - 1,"%Y%m%d%H%M%S",
11496 localtime(&myt));
11497 sprintf(myfname,"%s/%s/%s",myrpt->p.archivedir,
11498 myrpt->name,mydate);
11499 myrpt->monstream = ast_writefile(myfname,"wav49",
11500 "app_rpt Air Archive",O_CREAT | O_APPEND,0,0600);
11501 if (myrpt->p.monminblocks)
11502 {
11503 blocksleft = diskavail(myrpt);
11504 if (blocksleft >= myrpt->p.monminblocks)
11505 donodelog(myrpt,"TXKEY,MAIN");
11506 } else donodelog(myrpt,"TXKEY,MAIN");
11507 }
11508 lasttx = 1;
11509 myrpt->txkeyed = 1;
11510 time(&myrpt->lasttxkeyedtime);
11511 myrpt->dailykeyups++;
11512 myrpt->totalkeyups++;
11513 rpt_mutex_unlock(&myrpt->lock);
11514 ast_indicate(myrpt->txchannel,AST_CONTROL_RADIO_KEY);
11515 rpt_mutex_lock(&myrpt->lock);
11516 }
11517 if ((!totx) && lasttx)
11518 {
11519 if (myrpt->monstream) ast_closestream(myrpt->monstream);
11520 myrpt->monstream = NULL;
11521
11522 lasttx = 0;
11523 myrpt->txkeyed = 0;
11524 time(&myrpt->lasttxkeyedtime);
11525 rpt_mutex_unlock(&myrpt->lock);
11526 ast_indicate(myrpt->txchannel,AST_CONTROL_RADIO_UNKEY);
11527 rpt_mutex_lock(&myrpt->lock);
11528 donodelog(myrpt,"TXUNKEY,MAIN");
11529 }
11530 time(&t);
11531
11532 if ((!myrpt->cmdnode[0]) && (myrpt->dtmfidx >= 0) && ((myrpt->dtmf_time + DTMF_TIMEOUT) < t))
11533 {
11534 myrpt->inpadtest = 0;
11535 myrpt->dtmfidx = -1;
11536 myrpt->dtmfbuf[0] = 0;
11537 }
11538
11539 if ((myrpt->rem_dtmfidx >= 0) && ((myrpt->rem_dtmf_time + DTMF_TIMEOUT) < t))
11540 {
11541 myrpt->inpadtest = 0;
11542 myrpt->rem_dtmfidx = -1;
11543 myrpt->rem_dtmfbuf[0] = 0;
11544 }
11545
11546 if (myrpt->exttx && myrpt->parrotchannel &&
11547 myrpt->p.parrotmode && (!myrpt->parrotstate))
11548 {
11549 char myfname[300];
11550
11551 ci.confno = myrpt->conf;
11552 ci.confmode = DAHDI_CONF_CONFANNMON;
11553 ci.chan = 0;
11554
11555
11556 if (ioctl(myrpt->parrotchannel->fds[0],DAHDI_SETCONF,&ci) == -1)
11557 {
11558 ast_log(LOG_WARNING, "Unable to set conference mode for parrot\n");
11559 break;
11560 }
11561
11562 sprintf(myfname,PARROTFILE,myrpt->name,myrpt->parrotcnt);
11563 strcat(myfname,".wav");
11564 unlink(myfname);
11565 sprintf(myfname,PARROTFILE,myrpt->name,myrpt->parrotcnt);
11566 myrpt->parrotstate = 1;
11567 myrpt->parrottimer = myrpt->p.parrottime;
11568 if (myrpt->parrotstream)
11569 ast_closestream(myrpt->parrotstream);
11570 myrpt->parrotstream = NULL;
11571 myrpt->parrotstream = ast_writefile(myfname,"wav",
11572 "app_rpt Parrot",O_CREAT | O_TRUNC,0,0600);
11573 }
11574
11575
11576
11577 l = myrpt->links.next;
11578 while(l != &myrpt->links)
11579 {
11580 if (l->killme)
11581 {
11582
11583 remque((struct qelem *) l);
11584 if (!strcmp(myrpt->cmdnode,l->name))
11585 myrpt->cmdnode[0] = 0;
11586 rpt_mutex_unlock(&myrpt->lock);
11587
11588 if (l->chan) ast_hangup(l->chan);
11589 ast_hangup(l->pchan);
11590 ast_free(l);
11591 rpt_mutex_lock(&myrpt->lock);
11592
11593 l = myrpt->links.next;
11594 continue;
11595 }
11596 l = l->next;
11597 }
11598 n = 0;
11599 cs[n++] = myrpt->rxchannel;
11600 cs[n++] = myrpt->pchannel;
11601 cs[n++] = myrpt->monchannel;
11602 if (myrpt->parrotchannel) cs[n++] = myrpt->parrotchannel;
11603 if (myrpt->voxchannel) cs[n++] = myrpt->voxchannel;
11604 cs[n++] = myrpt->txpchannel;
11605 if (myrpt->txchannel != myrpt->rxchannel) cs[n++] = myrpt->txchannel;
11606 if (myrpt->dahditxchannel != myrpt->txchannel)
11607 cs[n++] = myrpt->dahditxchannel;
11608 l = myrpt->links.next;
11609 while(l != &myrpt->links)
11610 {
11611 if ((!l->killme) && (!l->disctime) && l->chan)
11612 {
11613 cs[n++] = l->chan;
11614 cs[n++] = l->pchan;
11615 }
11616 l = l->next;
11617 }
11618 if ((myrpt->topkeystate == 1) &&
11619 ((t - myrpt->topkeytime) > TOPKEYWAIT))
11620 {
11621 myrpt->topkeystate = 2;
11622 qsort(myrpt->topkey,TOPKEYN,sizeof(struct rpt_topkey),
11623 topcompar);
11624 }
11625 rpt_mutex_unlock(&myrpt->lock);
11626
11627 if (myrpt->topkeystate == 2)
11628 {
11629 rpt_telemetry(myrpt,TOPKEY,NULL);
11630 myrpt->topkeystate = 3;
11631 }
11632 ms = MSWAIT;
11633 for(x = 0; x < n; x++)
11634 {
11635 int s = -(-x - myrpt->scram - 1) % n;
11636 cs1[x] = cs[s];
11637 }
11638 myrpt->scram++;
11639 who = ast_waitfor_n(cs1,n,&ms);
11640 if (who == NULL) ms = 0;
11641 elap = MSWAIT - ms;
11642 rpt_mutex_lock(&myrpt->lock);
11643 l = myrpt->links.next;
11644 while(l != &myrpt->links)
11645 {
11646 int myrx;
11647
11648 if (l->voxtotimer) l->voxtotimer -= elap;
11649 if (l->voxtotimer < 0) l->voxtotimer = 0;
11650
11651 if (l->lasttx != l->lasttx1)
11652 {
11653 voxinit_link(l,!l->lasttx);
11654 l->lasttx1 = l->lasttx;
11655 }
11656 myrx = l->lastrealrx;
11657 if ((l->phonemode) && (l->phonevox))
11658 {
11659 myrx = myrx || (!AST_LIST_EMPTY(&l->rxq));
11660 if (l->voxtotimer <= 0)
11661 {
11662 if (l->voxtostate)
11663 {
11664 l->voxtotimer = myrpt->p.voxtimeout_ms;
11665 l->voxtostate = 0;
11666 }
11667 else
11668 {
11669 l->voxtotimer = myrpt->p.voxrecover_ms;
11670 l->voxtostate = 1;
11671 }
11672 }
11673 if (!l->voxtostate)
11674 myrx = myrx || l->wasvox ;
11675 }
11676 l->lastrx = myrx;
11677 if (l->linklisttimer)
11678 {
11679 l->linklisttimer -= elap;
11680 if (l->linklisttimer < 0) l->linklisttimer = 0;
11681 }
11682 if ((!l->linklisttimer) && (l->name[0] != '0') && (!l->isremote))
11683 {
11684 struct ast_frame lf;
11685
11686 memset(&lf,0,sizeof(lf));
11687 lf.frametype = AST_FRAME_TEXT;
11688 lf.subclass = 0;
11689 lf.offset = 0;
11690 lf.mallocd = 0;
11691 lf.samples = 0;
11692 l->linklisttimer = LINKLISTTIME;
11693 strcpy(lstr,"L ");
11694 __mklinklist(myrpt,l,lstr + 2);
11695 if (l->chan)
11696 {
11697 lf.datalen = strlen(lstr) + 1;
11698 lf.data.ptr = lstr;
11699 ast_write(l->chan,&lf);
11700 if (debug > 6) ast_log(LOG_NOTICE,
11701 "@@@@ node %s sent node string %s to node %s\n",
11702 myrpt->name,lstr,l->name);
11703 }
11704 }
11705 if (l->newkey)
11706 {
11707 if ((l->retxtimer += elap) >= REDUNDANT_TX_TIME)
11708 {
11709 l->retxtimer = 0;
11710 if (l->chan && l->phonemode == 0)
11711 {
11712 if (l->lasttx)
11713 ast_indicate(l->chan,AST_CONTROL_RADIO_KEY);
11714 else
11715 ast_indicate(l->chan,AST_CONTROL_RADIO_UNKEY);
11716 }
11717 }
11718 if ((l->rerxtimer += elap) >= (REDUNDANT_TX_TIME * 5))
11719 {
11720 if (debug == 7) printf("@@@@ rx un-key\n");
11721 l->lastrealrx = 0;
11722 l->rerxtimer = 0;
11723 if (l->lastrx1)
11724 {
11725 if (myrpt->p.archivedir)
11726 {
11727 char str[100];
11728
11729 sprintf(str,"RXUNKEY(T),%s",l->name);
11730 donodelog(myrpt,str);
11731 }
11732 if(myrpt->p.duplex)
11733 rpt_telemetry(myrpt,LINKUNKEY,l);
11734 l->lastrx1 = 0;
11735 }
11736 }
11737 }
11738 if (l->disctime)
11739 {
11740 l->disctime -= elap;
11741 if (l->disctime <= 0)
11742 l->disctime = 0;
11743 }
11744
11745 if (l->retrytimer)
11746 {
11747 l->retrytimer -= elap;
11748 if (l->retrytimer < 0) l->retrytimer = 0;
11749 }
11750
11751
11752 l->connecttime += elap;
11753
11754
11755 if (l->elaptime < 0)
11756 {
11757 l = l->next;
11758 continue;
11759 }
11760 l->elaptime += elap;
11761
11762 if ((l->elaptime > MAXCONNECTTIME) &&
11763 ((!l->chan) || (l->chan->_state != AST_STATE_UP)))
11764 {
11765 l->elaptime = 0;
11766 rpt_mutex_unlock(&myrpt->lock);
11767 if (l->chan) ast_softhangup(l->chan,AST_SOFTHANGUP_DEV);
11768 rpt_mutex_lock(&myrpt->lock);
11769 break;
11770 }
11771 if ((!l->chan) && (!l->retrytimer) && l->outbound &&
11772 (l->retries++ < l->max_retries) && (l->hasconnected))
11773 {
11774 if (l->chan) ast_hangup(l->chan);
11775 l->chan = 0;
11776 rpt_mutex_unlock(&myrpt->lock);
11777 if ((l->name[0] != '0') && (!l->isremote))
11778 {
11779 if (attempt_reconnect(myrpt,l) == -1)
11780 {
11781 l->retrytimer = RETRY_TIMER_MS;
11782 }
11783 }
11784 else
11785 {
11786 l->retrytimer = l->max_retries + 1;
11787 }
11788
11789 rpt_mutex_lock(&myrpt->lock);
11790 break;
11791 }
11792 if ((!l->chan) && (!l->retrytimer) && l->outbound &&
11793 (l->retries >= l->max_retries))
11794 {
11795
11796 remque((struct qelem *) l);
11797 if (!strcmp(myrpt->cmdnode,l->name))
11798 myrpt->cmdnode[0] = 0;
11799 rpt_mutex_unlock(&myrpt->lock);
11800 if (l->name[0] != '0')
11801 {
11802 if (!l->hasconnected)
11803 rpt_telemetry(myrpt,CONNFAIL,l);
11804 else rpt_telemetry(myrpt,REMDISC,l);
11805 }
11806 if (myrpt->p.archivedir)
11807 {
11808 char str[100];
11809
11810 if (!l->hasconnected)
11811 sprintf(str,"LINKFAIL,%s",l->name);
11812 else
11813 sprintf(str,"LINKDISC,%s",l->name);
11814 donodelog(myrpt,str);
11815 }
11816
11817 ast_hangup(l->pchan);
11818 ast_free(l);
11819 rpt_mutex_lock(&myrpt->lock);
11820 break;
11821 }
11822 if ((!l->chan) && (!l->disctime) && (!l->outbound))
11823 {
11824 if(debug)ast_log(LOG_NOTICE, "LINKDISC AA\n");
11825
11826 remque((struct qelem *) l);
11827 if(myrpt->links.next==&myrpt->links)channel_revert(myrpt);
11828 if (!strcmp(myrpt->cmdnode,l->name))myrpt->cmdnode[0] = 0;
11829 rpt_mutex_unlock(&myrpt->lock);
11830 if (l->name[0] != '0')
11831 {
11832 rpt_telemetry(myrpt,REMDISC,l);
11833 }
11834 if (myrpt->p.archivedir)
11835 {
11836 char str[100];
11837 sprintf(str,"LINKDISC,%s",l->name);
11838 donodelog(myrpt,str);
11839 }
11840
11841 ast_hangup(l->pchan);
11842 ast_free(l);
11843 rpt_mutex_lock(&myrpt->lock);
11844 break;
11845 }
11846 l = l->next;
11847 }
11848 if (myrpt->linkposttimer)
11849 {
11850 myrpt->linkposttimer -= elap;
11851 if (myrpt->linkposttimer < 0) myrpt->linkposttimer = 0;
11852 }
11853 if (myrpt->linkposttimer <= 0)
11854 {
11855 int nstr;
11856 char lst,*str;
11857 time_t now;
11858
11859 myrpt->linkposttimer = LINKPOSTTIME;
11860 nstr = 0;
11861 for(l = myrpt->links.next; l != &myrpt->links; l = l->next)
11862 {
11863
11864 if (l->name[0] == '0') continue;
11865 nstr += strlen(l->name) + 1;
11866 }
11867 str = ast_malloc(nstr + 256);
11868 if (!str)
11869 {
11870 ast_log(LOG_NOTICE,"Cannot ast_malloc()\n");
11871 break;
11872 }
11873 nstr = 0;
11874 strcpy(str,"nodes=");
11875 for(l = myrpt->links.next; l != &myrpt->links; l = l->next)
11876 {
11877
11878 if (l->name[0] == '0') continue;
11879 lst = 'T';
11880 if (!l->mode) lst = 'R';
11881 if (!l->thisconnected) lst = 'C';
11882 if (nstr) strcat(str,",");
11883 sprintf(str + strlen(str),"%c%s",lst,l->name);
11884 nstr = 1;
11885 }
11886 p = strstr(tdesc, "version");
11887 if(p){
11888 int vmajor,vminor;
11889 if(sscanf(p, "version %30d.%30d", &vmajor, &vminor) == 2)
11890 sprintf(str + strlen(str),"&apprptvers=%d.%d",vmajor,vminor);
11891 }
11892 time(&now);
11893 sprintf(str + strlen(str),"&apprptuptime=%d",(int)(now-starttime));
11894 sprintf(str + strlen(str),
11895 "&totalkerchunks=%d&totalkeyups=%d&totaltxtime=%d&timeouts=%d&totalexecdcommands=%d",
11896 myrpt->totalkerchunks,myrpt->totalkeyups,(int) myrpt->totaltxtime/1000,
11897 myrpt->timeouts,myrpt->totalexecdcommands);
11898 rpt_mutex_unlock(&myrpt->lock);
11899 statpost(myrpt,str);
11900 rpt_mutex_lock(&myrpt->lock);
11901 ast_free(str);
11902 }
11903 if (myrpt->keyposttimer)
11904 {
11905 myrpt->keyposttimer -= elap;
11906 if (myrpt->keyposttimer < 0) myrpt->keyposttimer = 0;
11907 }
11908 if (myrpt->keyposttimer <= 0)
11909 {
11910 char str[100];
11911 int diff = 0;
11912 time_t now;
11913
11914 myrpt->keyposttimer = KEYPOSTTIME;
11915 time(&now);
11916 if (myrpt->lastkeyedtime)
11917 {
11918 diff = (int)(now - myrpt->lastkeyedtime);
11919 }
11920 sprintf(str,"keyed=%d&keytime=%d",myrpt->keyed,diff);
11921 rpt_mutex_unlock(&myrpt->lock);
11922 statpost(myrpt,str);
11923 rpt_mutex_lock(&myrpt->lock);
11924 }
11925 if(totx){
11926 myrpt->dailytxtime += elap;
11927 myrpt->totaltxtime += elap;
11928 }
11929 i = myrpt->tailtimer;
11930 if (myrpt->tailtimer) myrpt->tailtimer -= elap;
11931 if (myrpt->tailtimer < 0) myrpt->tailtimer = 0;
11932 if((i) && (myrpt->tailtimer == 0))
11933 myrpt->tailevent = 1;
11934 if ((!myrpt->p.s[myrpt->p.sysstate_cur].totdisable) && myrpt->totimer) myrpt->totimer -= elap;
11935 if (myrpt->totimer < 0) myrpt->totimer = 0;
11936 if (myrpt->idtimer) myrpt->idtimer -= elap;
11937 if (myrpt->idtimer < 0) myrpt->idtimer = 0;
11938 if (myrpt->tmsgtimer) myrpt->tmsgtimer -= elap;
11939 if (myrpt->tmsgtimer < 0) myrpt->tmsgtimer = 0;
11940 if (myrpt->voxtotimer) myrpt->voxtotimer -= elap;
11941 if (myrpt->voxtotimer < 0) myrpt->voxtotimer = 0;
11942 if (myrpt->exttx)
11943 {
11944 myrpt->parrottimer = myrpt->p.parrottime;
11945 }
11946 else
11947 {
11948 if (myrpt->parrottimer) myrpt->parrottimer -= elap;
11949 if (myrpt->parrottimer < 0) myrpt->parrottimer = 0;
11950 }
11951
11952 if (myrpt->macrotimer) myrpt->macrotimer -= elap;
11953 if (myrpt->macrotimer < 0) myrpt->macrotimer = 0;
11954
11955 if (myrpt->dtmf_local_timer)
11956 {
11957 if (myrpt->dtmf_local_timer > 1) myrpt->dtmf_local_timer -= elap;
11958 if (myrpt->dtmf_local_timer < 1) myrpt->dtmf_local_timer = 1;
11959 }
11960 do_dtmf_local(myrpt,0);
11961
11962 if (myrpt->skedtimer <= 0){
11963 myrpt->skedtimer = 200;
11964 do_scheduler(myrpt);
11965 }
11966 else
11967 myrpt->skedtimer -=elap;
11968 if (!ms)
11969 {
11970 rpt_mutex_unlock(&myrpt->lock);
11971 continue;
11972 }
11973 if (myrpt->p.parrotmode && (myrpt->parrotstate == 1) &&
11974 (myrpt->parrottimer <= 0))
11975 {
11976
11977 ci.confno = 0;
11978 ci.confmode = 0;
11979 ci.chan = 0;
11980
11981
11982 if (ioctl(myrpt->parrotchannel->fds[0],DAHDI_SETCONF,&ci) == -1)
11983 {
11984 ast_log(LOG_WARNING, "Unable to set conference mode for parrot\n");
11985 break;
11986 }
11987 if (myrpt->parrotstream)
11988 ast_closestream(myrpt->parrotstream);
11989 myrpt->parrotstream = NULL;
11990 myrpt->parrotstate = 2;
11991 rpt_telemetry(myrpt,PARROT,(void *) ((intptr_t)myrpt->parrotcnt++));
11992 }
11993 if (myrpt->cmdAction.state == CMD_STATE_READY)
11994 {
11995 int status;
11996 myrpt->cmdAction.state = CMD_STATE_EXECUTING;
11997
11998 rpt_mutex_unlock(&myrpt->lock);
11999
12000 status = (*function_table[myrpt->cmdAction.functionNumber].function)(myrpt,myrpt->cmdAction.param, myrpt->cmdAction.digits, myrpt->cmdAction.command_source, NULL);
12001
12002 rpt_mutex_lock(&myrpt->lock);
12003 myrpt->cmdAction.state = CMD_STATE_IDLE;
12004 }
12005
12006 c = myrpt->macrobuf[0];
12007 time(&t);
12008 if (c && (!myrpt->macrotimer) &&
12009 starttime && (t > (starttime + START_DELAY)))
12010 {
12011 char cin = c & 0x7f;
12012 myrpt->macrotimer = MACROTIME;
12013 memmove(myrpt->macrobuf,myrpt->macrobuf + 1,MAXMACRO - 1);
12014 if ((cin == 'p') || (cin == 'P'))
12015 myrpt->macrotimer = MACROPTIME;
12016 rpt_mutex_unlock(&myrpt->lock);
12017 if (myrpt->p.archivedir)
12018 {
12019 char str[100];
12020
12021 sprintf(str,"DTMF(M),MAIN,%c",cin);
12022 donodelog(myrpt,str);
12023 }
12024 local_dtmf_helper(myrpt,c);
12025 } else rpt_mutex_unlock(&myrpt->lock);
12026 if (who == myrpt->rxchannel)
12027 {
12028 int ismuted;
12029
12030 f = ast_read(myrpt->rxchannel);
12031 if (!f)
12032 {
12033 if (debug) printf("@@@@ rpt:Hung Up\n");
12034 break;
12035 }
12036 if (f->frametype == AST_FRAME_VOICE)
12037 {
12038 #ifdef _MDC_DECODE_H_
12039 unsigned char ubuf[2560];
12040 short *sp;
12041 int n;
12042 #endif
12043
12044 if ((!myrpt->localtx) && (!myrpt->p.linktolink)) {
12045 memset(f->data.ptr,0,f->datalen);
12046 }
12047
12048 #ifdef _MDC_DECODE_H_
12049 sp = (short *) f->data;
12050
12051 for(n = 0; n < f->datalen / 2; n++)
12052 {
12053 ubuf[n] = (*sp++ >> 8) + 128;
12054 }
12055 n = mdc_decoder_process_samples(myrpt->mdc,ubuf,f->datalen / 2);
12056 if (n == 1)
12057 {
12058 unsigned char op,arg;
12059 unsigned short unitID;
12060
12061 mdc_decoder_get_packet(myrpt->mdc,&op,&arg,&unitID);
12062 if (debug > 2)
12063 {
12064 ast_log(LOG_NOTICE,"Got (single-length) packet:\n");
12065 ast_log(LOG_NOTICE,"op: %02x, arg: %02x, UnitID: %04x\n",
12066 op & 255,arg & 255,unitID);
12067 }
12068 if ((op == 1) && (arg == 0))
12069 {
12070 myrpt->lastunit = unitID;
12071 mdc1200_notify(myrpt,NULL,myrpt->lastunit);
12072 mdc1200_send(myrpt,myrpt->lastunit);
12073 }
12074 }
12075 if ((debug > 2) && (i == 2))
12076 {
12077 unsigned char op,arg,ex1,ex2,ex3,ex4;
12078 unsigned short unitID;
12079
12080 mdc_decoder_get_double_packet(myrpt->mdc,&op,&arg,&unitID,
12081 &ex1,&ex2,&ex3,&ex4);
12082 ast_log(LOG_NOTICE,"Got (double-length) packet:\n");
12083 ast_log(LOG_NOTICE,"op: %02x, arg: %02x, UnitID: %04x\n",
12084 op & 255,arg & 255,unitID);
12085 ast_log(LOG_NOTICE,"ex1: %02x, ex2: %02x, ex3: %02x, ex4: %02x\n",
12086 ex1 & 255, ex2 & 255, ex3 & 255, ex4 & 255);
12087 }
12088 #endif
12089 #ifdef __RPT_NOTCH
12090
12091 rpt_filter(myrpt,f->data,f->datalen / 2);
12092 #endif
12093 if (ioctl(myrpt->dahdirxchannel->fds[0], DAHDI_GETCONFMUTE, &ismuted) == -1)
12094 {
12095 ismuted = 0;
12096 }
12097 if (dtmfed) ismuted = 1;
12098 dtmfed = 0;
12099 if (ismuted)
12100 {
12101 memset(f->data.ptr,0,f->datalen);
12102 if (myrpt->lastf1)
12103 memset(myrpt->lastf1->data.ptr,0,myrpt->lastf1->datalen);
12104 if (myrpt->lastf2)
12105 memset(myrpt->lastf2->data.ptr,0,myrpt->lastf2->datalen);
12106 }
12107 if (f) f2 = ast_frdup(f);
12108 else f2 = NULL;
12109 f1 = myrpt->lastf2;
12110 myrpt->lastf2 = myrpt->lastf1;
12111 myrpt->lastf1 = f2;
12112 if (ismuted)
12113 {
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 (f1)
12120 {
12121 ast_write(myrpt->pchannel,f1);
12122 ast_frfree(f1);
12123 }
12124 }
12125 #ifndef OLD_ASTERISK
12126 else if (f->frametype == AST_FRAME_DTMF_BEGIN)
12127 {
12128 if (myrpt->lastf1)
12129 memset(myrpt->lastf1->data.ptr,0,myrpt->lastf1->datalen);
12130 if (myrpt->lastf2)
12131 memset(myrpt->lastf2->data.ptr,0,myrpt->lastf2->datalen);
12132 dtmfed = 1;
12133 }
12134 #endif
12135 else if (f->frametype == AST_FRAME_DTMF)
12136 {
12137 c = (char) f->subclass;
12138 ast_frfree(f);
12139 if (myrpt->lastf1)
12140 memset(myrpt->lastf1->data.ptr,0,myrpt->lastf1->datalen);
12141 if (myrpt->lastf2)
12142 memset(myrpt->lastf2->data.ptr,0,myrpt->lastf2->datalen);
12143 dtmfed = 1;
12144 if (!myrpt->keyed) continue;
12145 c = func_xlat(myrpt,c,&myrpt->p.inxlat);
12146 if (c) local_dtmf_helper(myrpt,c);
12147 continue;
12148 }
12149 else if (f->frametype == AST_FRAME_CONTROL)
12150 {
12151 if (f->subclass == AST_CONTROL_HANGUP)
12152 {
12153 if (debug) printf("@@@@ rpt:Hung Up\n");
12154 ast_frfree(f);
12155 break;
12156 }
12157
12158 if (f->subclass == AST_CONTROL_RADIO_KEY)
12159 {
12160 if ((!lasttx) || (myrpt->p.duplex > 1) || (myrpt->p.linktolink))
12161 {
12162 if (debug == 7) printf("@@@@ rx key\n");
12163 myrpt->keyed = 1;
12164 time(&myrpt->lastkeyedtime);
12165 myrpt->keyposttimer = KEYPOSTSHORTTIME;
12166 }
12167 if (myrpt->p.archivedir)
12168 {
12169 donodelog(myrpt,"RXKEY,MAIN");
12170 }
12171 if (f->datalen && f->data.ptr)
12172 {
12173 char busy = 0;
12174
12175 if (debug) ast_log(LOG_NOTICE,"Got PL %s on node %s\n",(char *)f->data.ptr,myrpt->name);
12176
12177 if (strstr((char *)f->data.ptr,"/M/")&& !myrpt->macropatch)
12178 {
12179 char value[16];
12180 strcat(value,"*6");
12181 myrpt->macropatch=1;
12182 rpt_mutex_lock(&myrpt->lock);
12183 if ((MAXMACRO - strlen(myrpt->macrobuf)) < strlen(value)){
12184 rpt_mutex_unlock(&myrpt->lock);
12185 busy=1;
12186 }
12187 if(!busy){
12188 myrpt->macrotimer = MACROTIME;
12189 strncat(myrpt->macrobuf,value,MAXMACRO - 1);
12190 if (!busy) strcpy(myrpt->lasttone,(char*)f->data.ptr);
12191 }
12192 rpt_mutex_unlock(&myrpt->lock);
12193 }
12194 else if (strcmp((char *)f->data.ptr,myrpt->lasttone))
12195 {
12196 char *value = (char *) ast_variable_retrieve(myrpt->cfg, myrpt->p.tonemacro, (char *)f->data.ptr);
12197 if (value)
12198 {
12199 if (debug) ast_log(LOG_NOTICE,"Tone %s doing %s on node %s\n",(char *) f->data.ptr,value,myrpt->name);
12200 rpt_mutex_lock(&myrpt->lock);
12201 if ((MAXMACRO - strlen(myrpt->macrobuf)) < strlen(value)){
12202 rpt_mutex_unlock(&myrpt->lock);
12203 busy=1;
12204 }
12205 if(!busy){
12206 myrpt->macrotimer = MACROTIME;
12207 strncat(myrpt->macrobuf,value,MAXMACRO - 1);
12208 }
12209 rpt_mutex_unlock(&myrpt->lock);
12210 }
12211 if (!busy) strcpy(myrpt->lasttone,(char*)f->data.ptr);
12212 }
12213 } else myrpt->lasttone[0] = 0;
12214 }
12215
12216 if (f->subclass == AST_CONTROL_RADIO_UNKEY)
12217 {
12218 if ((!lasttx) || (myrpt->p.duplex > 1) || (myrpt->p.linktolink))
12219 {
12220 if (debug == 7) printf("@@@@ rx un-key\n");
12221 if(myrpt->p.duplex && myrpt->keyed) {
12222 rpt_telemetry(myrpt,UNKEY,NULL);
12223 }
12224 }
12225 myrpt->keyed = 0;
12226 time(&myrpt->lastkeyedtime);
12227 myrpt->keyposttimer = KEYPOSTSHORTTIME;
12228 if (myrpt->p.archivedir)
12229 {
12230 donodelog(myrpt,"RXUNKEY,MAIN");
12231 }
12232 }
12233 }
12234 ast_frfree(f);
12235 continue;
12236 }
12237 if (who == myrpt->pchannel)
12238 {
12239 f = ast_read(myrpt->pchannel);
12240 if (!f)
12241 {
12242 if (debug) printf("@@@@ rpt:Hung Up\n");
12243 break;
12244 }
12245 if (f->frametype == AST_FRAME_VOICE)
12246 {
12247 ast_write(myrpt->txpchannel,f);
12248 }
12249 if (f->frametype == AST_FRAME_CONTROL)
12250 {
12251 if (f->subclass == AST_CONTROL_HANGUP)
12252 {
12253 if (debug) printf("@@@@ rpt:Hung Up\n");
12254 ast_frfree(f);
12255 break;
12256 }
12257 }
12258 ast_frfree(f);
12259 continue;
12260 }
12261 if (who == myrpt->txchannel)
12262 {
12263 f = ast_read(myrpt->txchannel);
12264 if (!f)
12265 {
12266 if (debug) printf("@@@@ rpt:Hung Up\n");
12267 break;
12268 }
12269 if (f->frametype == AST_FRAME_CONTROL)
12270 {
12271 if (f->subclass == AST_CONTROL_HANGUP)
12272 {
12273 if (debug) printf("@@@@ rpt:Hung Up\n");
12274 ast_frfree(f);
12275 break;
12276 }
12277 }
12278 ast_frfree(f);
12279 continue;
12280 }
12281 if (who == myrpt->dahditxchannel)
12282 {
12283 f = ast_read(myrpt->dahditxchannel);
12284 if (!f)
12285 {
12286 if (debug) printf("@@@@ rpt:Hung Up\n");
12287 break;
12288 }
12289 if (f->frametype == AST_FRAME_VOICE)
12290 {
12291 struct ast_frame *vframe;
12292
12293 if (myrpt->p.duplex < 2)
12294 {
12295 if (myrpt->txrealkeyed)
12296 {
12297 if ((!myfirst) && myrpt->callmode)
12298 {
12299 x = 0;
12300 AST_LIST_TRAVERSE(&myrpt->txq, vframe,
12301 frame_list) x++;
12302 for(;x < myrpt->p.simplexpatchdelay; x++)
12303 {
12304 vframe = ast_frdup(f);
12305 memset(vframe->data.ptr,0,vframe->datalen);
12306 AST_LIST_INSERT_TAIL(&myrpt->txq,vframe,frame_list);
12307 }
12308 myfirst = 1;
12309 }
12310 vframe = ast_frdup(f);
12311 AST_LIST_INSERT_TAIL(&myrpt->txq,
12312 vframe,frame_list);
12313 } else myfirst = 0;
12314 x = 0;
12315 AST_LIST_TRAVERSE(&myrpt->txq, vframe,
12316 frame_list) x++;
12317 if (!x)
12318 {
12319 memset(f->data.ptr,0,f->datalen);
12320 }
12321 else
12322 {
12323 ast_frfree(f);
12324 f = AST_LIST_REMOVE_HEAD(&myrpt->txq,
12325 frame_list);
12326 }
12327 }
12328 else
12329 {
12330 while((vframe = AST_LIST_REMOVE_HEAD(&myrpt->txq,
12331 frame_list))) ast_frfree(vframe);
12332 }
12333 ast_write(myrpt->txchannel,f);
12334 }
12335 if (f->frametype == AST_FRAME_CONTROL)
12336 {
12337 if (f->subclass == AST_CONTROL_HANGUP)
12338 {
12339 if (debug) printf("@@@@ rpt:Hung Up\n");
12340 ast_frfree(f);
12341 break;
12342 }
12343 }
12344 ast_frfree(f);
12345 continue;
12346 }
12347 toexit = 0;
12348 rpt_mutex_lock(&myrpt->lock);
12349 l = myrpt->links.next;
12350 while(l != &myrpt->links)
12351 {
12352 int remnomute;
12353 struct timeval now;
12354
12355 if (l->disctime)
12356 {
12357 l = l->next;
12358 continue;
12359 }
12360
12361 remrx = 0;
12362
12363 m = myrpt->links.next;
12364 while(m != &myrpt->links)
12365 {
12366
12367 if ((m != l) && (m->lastrx)) remrx = 1;
12368 m = m->next;
12369 }
12370 rpt_mutex_unlock(&myrpt->lock);
12371 now = ast_tvnow();
12372 if ((who == l->chan) || (!l->lastlinktv.tv_sec) ||
12373 (ast_tvdiff_ms(now,l->lastlinktv) >= 19))
12374 {
12375 l->lastlinktv = now;
12376 remnomute = myrpt->localtx &&
12377 (!(myrpt->cmdnode[0] ||
12378 (myrpt->dtmfidx > -1)));
12379 totx = (((l->isremote) ? (remnomute) :
12380 myrpt->exttx) || remrx) && l->mode;
12381 if (l->phonemode == 0 && l->chan && (l->lasttx != totx))
12382 {
12383 if (totx)
12384 {
12385 ast_indicate(l->chan,AST_CONTROL_RADIO_KEY);
12386 }
12387 else
12388 {
12389 ast_indicate(l->chan,AST_CONTROL_RADIO_UNKEY);
12390 }
12391 if (myrpt->p.archivedir)
12392 {
12393 char str[100];
12394
12395 if (totx)
12396 sprintf(str,"TXKEY,%s",l->name);
12397 else
12398 sprintf(str,"TXUNKEY,%s",l->name);
12399 donodelog(myrpt,str);
12400 }
12401 }
12402 l->lasttx = totx;
12403 }
12404 rpt_mutex_lock(&myrpt->lock);
12405 if (who == l->chan)
12406 {
12407 rpt_mutex_unlock(&myrpt->lock);
12408 f = ast_read(l->chan);
12409 if (!f)
12410 {
12411 rpt_mutex_lock(&myrpt->lock);
12412 __kickshort(myrpt);
12413 rpt_mutex_unlock(&myrpt->lock);
12414 if ((!l->disced) && (!l->outbound))
12415 {
12416 if ((l->name[0] == '0') || l->isremote)
12417 l->disctime = 1;
12418 else
12419 l->disctime = DISC_TIME;
12420 rpt_mutex_lock(&myrpt->lock);
12421 ast_hangup(l->chan);
12422 l->chan = 0;
12423 break;
12424 }
12425
12426 if (l->retrytimer)
12427 {
12428 ast_hangup(l->chan);
12429 l->chan = 0;
12430 rpt_mutex_lock(&myrpt->lock);
12431 break;
12432 }
12433 if (l->outbound && (l->retries++ < l->max_retries) && (l->hasconnected))
12434 {
12435 rpt_mutex_lock(&myrpt->lock);
12436 if (l->chan) ast_hangup(l->chan);
12437 l->chan = 0;
12438 l->hasconnected = 1;
12439 l->retrytimer = RETRY_TIMER_MS;
12440 l->elaptime = 0;
12441 l->connecttime = 0;
12442 l->thisconnected = 0;
12443 break;
12444 }
12445 rpt_mutex_lock(&myrpt->lock);
12446
12447 remque((struct qelem *) l);
12448 if (!strcmp(myrpt->cmdnode,l->name))
12449 myrpt->cmdnode[0] = 0;
12450 __kickshort(myrpt);
12451 rpt_mutex_unlock(&myrpt->lock);
12452 if (!l->hasconnected)
12453 rpt_telemetry(myrpt,CONNFAIL,l);
12454 else if (l->disced != 2) rpt_telemetry(myrpt,REMDISC,l);
12455 if (myrpt->p.archivedir)
12456 {
12457 char str[100];
12458
12459 if (!l->hasconnected)
12460 sprintf(str,"LINKFAIL,%s",l->name);
12461 else
12462 sprintf(str,"LINKDISC,%s",l->name);
12463 donodelog(myrpt,str);
12464 }
12465 if (l->lastf1) ast_frfree(l->lastf1);
12466 l->lastf1 = NULL;
12467 if (l->lastf2) ast_frfree(l->lastf2);
12468 l->lastf2 = NULL;
12469
12470 ast_hangup(l->chan);
12471 ast_hangup(l->pchan);
12472 ast_free(l);
12473 rpt_mutex_lock(&myrpt->lock);
12474 break;
12475 }
12476 if (f->frametype == AST_FRAME_VOICE)
12477 {
12478 int ismuted,n1;
12479
12480 if ((l->phonemode) && (l->phonevox))
12481 {
12482 n1 = dovox(&l->vox,
12483 f->data.ptr,f->datalen / 2);
12484 if (n1 != l->wasvox)
12485 {
12486 if (debug)ast_log(LOG_DEBUG,"Link Node %s, vox %d\n",l->name,n1);
12487 l->wasvox = n1;
12488 l->voxtostate = 0;
12489 if (n1) l->voxtotimer = myrpt->p.voxtimeout_ms;
12490 else l->voxtotimer = 0;
12491 }
12492 if (l->lastrealrx || n1)
12493 {
12494 if (!myfirst)
12495 {
12496 x = 0;
12497 AST_LIST_TRAVERSE(&l->rxq, f1,
12498 frame_list) x++;
12499 for(;x < myrpt->p.simplexphonedelay; x++)
12500 {
12501 f1 = ast_frdup(f);
12502 memset(f1->data.ptr,0,f1->datalen);
12503 AST_LIST_INSERT_TAIL(&l->rxq,
12504 f1,frame_list);
12505 }
12506 myfirst = 1;
12507 }
12508 f1 = ast_frdup(f);
12509 AST_LIST_INSERT_TAIL(&l->rxq,f1,frame_list);
12510 } else myfirst = 0;
12511 x = 0;
12512 AST_LIST_TRAVERSE(&l->rxq, f1,frame_list) x++;
12513 if (!x)
12514 {
12515 memset(f->data.ptr,0,f->datalen);
12516 }
12517 else
12518 {
12519 ast_frfree(f);
12520 f = AST_LIST_REMOVE_HEAD(&l->rxq,frame_list);
12521 }
12522 if (ioctl(l->chan->fds[0], DAHDI_GETCONFMUTE, &ismuted) == -1)
12523 {
12524 ismuted = 0;
12525 }
12526
12527 ismuted |= (!l->lastrx);
12528 if (l->dtmfed && l->phonemode) ismuted = 1;
12529 l->dtmfed = 0;
12530 if (ismuted)
12531 {
12532 memset(f->data.ptr,0,f->datalen);
12533 if (l->lastf1)
12534 memset(l->lastf1->data.ptr,0,l->lastf1->datalen);
12535 if (l->lastf2)
12536 memset(l->lastf2->data.ptr,0,l->lastf2->datalen);
12537 }
12538 if (f) f2 = ast_frdup(f);
12539 else f2 = NULL;
12540 f1 = l->lastf2;
12541 l->lastf2 = l->lastf1;
12542 l->lastf1 = f2;
12543 if (ismuted)
12544 {
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 (f1)
12551 {
12552 ast_write(l->pchan,f1);
12553 ast_frfree(f1);
12554 }
12555 }
12556 else
12557 {
12558 if (!l->lastrx)
12559 memset(f->data.ptr,0,f->datalen);
12560 ast_write(l->pchan,f);
12561 }
12562 }
12563 #ifndef OLD_ASTERISK
12564 else if (f->frametype == AST_FRAME_DTMF_BEGIN)
12565 {
12566 if (l->lastf1)
12567 memset(l->lastf1->data.ptr,0,l->lastf1->datalen);
12568 if (l->lastf2)
12569 memset(l->lastf2->data.ptr,0,l->lastf2->datalen);
12570 l->dtmfed = 1;
12571 }
12572 #endif
12573 if (f->frametype == AST_FRAME_TEXT)
12574 {
12575 handle_link_data(myrpt,l,f->data.ptr);
12576 }
12577 if (f->frametype == AST_FRAME_DTMF)
12578 {
12579 if (l->lastf1)
12580 memset(l->lastf1->data.ptr,0,l->lastf1->datalen);
12581 if (l->lastf2)
12582 memset(l->lastf2->data.ptr,0,l->lastf2->datalen);
12583 l->dtmfed = 1;
12584 handle_link_phone_dtmf(myrpt,l,f->subclass);
12585 }
12586 if (f->frametype == AST_FRAME_CONTROL)
12587 {
12588 if (f->subclass == AST_CONTROL_ANSWER)
12589 {
12590 char lconnected = l->connected;
12591
12592 __kickshort(myrpt);
12593 l->connected = 1;
12594 l->hasconnected = 1;
12595 l->thisconnected = 1;
12596 l->elaptime = -1;
12597 if (!l->phonemode) send_newkey(l->chan);
12598 if (!l->isremote) l->retries = 0;
12599 if (!lconnected)
12600 {
12601 rpt_telemetry(myrpt,CONNECTED,l);
12602 if (myrpt->p.archivedir)
12603 {
12604 char str[100];
12605
12606 if (l->mode)
12607 sprintf(str,"LINKTRX,%s",l->name);
12608 else
12609 sprintf(str,"LINKMONITOR,%s",l->name);
12610 donodelog(myrpt,str);
12611 }
12612 }
12613 else
12614 l->reconnects++;
12615 }
12616
12617 if (f->subclass == AST_CONTROL_RADIO_KEY)
12618 {
12619 if (debug == 7 ) printf("@@@@ rx key\n");
12620 l->lastrealrx = 1;
12621 l->rerxtimer = 0;
12622 if (!l->lastrx1)
12623 {
12624 if (myrpt->p.archivedir)
12625 {
12626 char str[100];
12627
12628 sprintf(str,"RXKEY,%s",l->name);
12629 donodelog(myrpt,str);
12630 }
12631 l->lastrx1 = 1;
12632 }
12633 }
12634
12635 if (f->subclass == AST_CONTROL_RADIO_UNKEY)
12636 {
12637 if (debug == 7) printf("@@@@ rx un-key\n");
12638 l->lastrealrx = 0;
12639 l->rerxtimer = 0;
12640 if (l->lastrx1)
12641 {
12642 if (myrpt->p.archivedir)
12643 {
12644 char str[100];
12645
12646 sprintf(str,"RXUNKEY,%s",l->name);
12647 donodelog(myrpt,str);
12648 }
12649 l->lastrx1 = 0;
12650 if(myrpt->p.duplex)
12651 rpt_telemetry(myrpt,LINKUNKEY,l);
12652 }
12653 }
12654 if (f->subclass == AST_CONTROL_HANGUP)
12655 {
12656 ast_frfree(f);
12657 rpt_mutex_lock(&myrpt->lock);
12658 __kickshort(myrpt);
12659 rpt_mutex_unlock(&myrpt->lock);
12660 if ((!l->outbound) && (!l->disced))
12661 {
12662 if ((l->name[0] == '0') || l->isremote)
12663 l->disctime = 1;
12664 else
12665 l->disctime = DISC_TIME;
12666 rpt_mutex_lock(&myrpt->lock);
12667 ast_hangup(l->chan);
12668 l->chan = 0;
12669 break;
12670 }
12671 if (l->retrytimer)
12672 {
12673 if (l->chan) ast_hangup(l->chan);
12674 l->chan = 0;
12675 rpt_mutex_lock(&myrpt->lock);
12676 break;
12677 }
12678 if (l->outbound && (l->retries++ < l->max_retries) && (l->hasconnected))
12679 {
12680 rpt_mutex_lock(&myrpt->lock);
12681 if (l->chan) ast_hangup(l->chan);
12682 l->chan = 0;
12683 l->hasconnected = 1;
12684 l->elaptime = 0;
12685 l->retrytimer = RETRY_TIMER_MS;
12686 l->connecttime = 0;
12687 l->thisconnected = 0;
12688 break;
12689 }
12690 rpt_mutex_lock(&myrpt->lock);
12691
12692 remque((struct qelem *) l);
12693 if (!strcmp(myrpt->cmdnode,l->name))
12694 myrpt->cmdnode[0] = 0;
12695 __kickshort(myrpt);
12696 rpt_mutex_unlock(&myrpt->lock);
12697 if (!l->hasconnected)
12698 rpt_telemetry(myrpt,CONNFAIL,l);
12699 else if (l->disced != 2) rpt_telemetry(myrpt,REMDISC,l);
12700 if (myrpt->p.archivedir)
12701 {
12702 char str[100];
12703
12704 if (!l->hasconnected)
12705 sprintf(str,"LINKFAIL,%s",l->name);
12706 else
12707 sprintf(str,"LINKDISC,%s",l->name);
12708 donodelog(myrpt,str);
12709 }
12710 if (l->lastf1) ast_frfree(l->lastf1);
12711 l->lastf1 = NULL;
12712 if (l->lastf2) ast_frfree(l->lastf2);
12713 l->lastf2 = NULL;
12714
12715 ast_hangup(l->chan);
12716 ast_hangup(l->pchan);
12717 ast_free(l);
12718 rpt_mutex_lock(&myrpt->lock);
12719 break;
12720 }
12721 }
12722 ast_frfree(f);
12723 rpt_mutex_lock(&myrpt->lock);
12724 break;
12725 }
12726 if (who == l->pchan)
12727 {
12728 rpt_mutex_unlock(&myrpt->lock);
12729 f = ast_read(l->pchan);
12730 if (!f)
12731 {
12732 if (debug) printf("@@@@ rpt:Hung Up\n");
12733 toexit = 1;
12734 rpt_mutex_lock(&myrpt->lock);
12735 break;
12736 }
12737 if (f->frametype == AST_FRAME_VOICE)
12738 {
12739 if (l->chan) ast_write(l->chan,f);
12740 }
12741 if (f->frametype == AST_FRAME_CONTROL)
12742 {
12743 if (f->subclass == AST_CONTROL_HANGUP)
12744 {
12745 if (debug) printf("@@@@ rpt:Hung Up\n");
12746 ast_frfree(f);
12747 toexit = 1;
12748 rpt_mutex_lock(&myrpt->lock);
12749 break;
12750 }
12751 }
12752 ast_frfree(f);
12753 rpt_mutex_lock(&myrpt->lock);
12754 break;
12755 }
12756 l = l->next;
12757 }
12758 rpt_mutex_unlock(&myrpt->lock);
12759 if (toexit) break;
12760 if (who == myrpt->monchannel)
12761 {
12762 f = ast_read(myrpt->monchannel);
12763 if (!f)
12764 {
12765 if (debug) printf("@@@@ rpt:Hung Up\n");
12766 break;
12767 }
12768 if (f->frametype == AST_FRAME_VOICE)
12769 {
12770 if (myrpt->monstream)
12771 ast_writestream(myrpt->monstream,f);
12772 }
12773 if (f->frametype == AST_FRAME_CONTROL)
12774 {
12775 if (f->subclass == AST_CONTROL_HANGUP)
12776 {
12777 if (debug) printf("@@@@ rpt:Hung Up\n");
12778 ast_frfree(f);
12779 break;
12780 }
12781 }
12782 ast_frfree(f);
12783 continue;
12784 }
12785 if (myrpt->parrotchannel && (who == myrpt->parrotchannel))
12786 {
12787 f = ast_read(myrpt->parrotchannel);
12788 if (!f)
12789 {
12790 if (debug) printf("@@@@ rpt:Hung Up\n");
12791 break;
12792 }
12793 if (!myrpt->p.parrotmode)
12794 {
12795 char myfname[300];
12796
12797 if (myrpt->parrotstream)
12798 {
12799 ast_closestream(myrpt->parrotstream);
12800 myrpt->parrotstream = 0;
12801 }
12802 sprintf(myfname,PARROTFILE,myrpt->name,myrpt->parrotcnt);
12803 strcat(myfname,".wav");
12804 unlink(myfname);
12805 } else if (f->frametype == AST_FRAME_VOICE)
12806 {
12807 if (myrpt->parrotstream)
12808 ast_writestream(myrpt->parrotstream,f);
12809 }
12810 if (f->frametype == AST_FRAME_CONTROL)
12811 {
12812 if (f->subclass == AST_CONTROL_HANGUP)
12813 {
12814 if (debug) printf("@@@@ rpt:Hung Up\n");
12815 ast_frfree(f);
12816 break;
12817 }
12818 }
12819 ast_frfree(f);
12820 continue;
12821 }
12822 if (myrpt->voxchannel && (who == myrpt->voxchannel))
12823 {
12824 f = ast_read(myrpt->voxchannel);
12825 if (!f)
12826 {
12827 if (debug) printf("@@@@ rpt:Hung Up\n");
12828 break;
12829 }
12830 if (f->frametype == AST_FRAME_VOICE)
12831 {
12832 n = dovox(&myrpt->vox,f->data.ptr,f->datalen / 2);
12833 if (n != myrpt->wasvox)
12834 {
12835 if (debug) ast_log(LOG_DEBUG,"Node %s, vox %d\n",myrpt->name,n);
12836 myrpt->wasvox = n;
12837 myrpt->voxtostate = 0;
12838 if (n) myrpt->voxtotimer = myrpt->p.voxtimeout_ms;
12839 else myrpt->voxtotimer = 0;
12840 }
12841 }
12842 if (f->frametype == AST_FRAME_CONTROL)
12843 {
12844 if (f->subclass == AST_CONTROL_HANGUP)
12845 {
12846 if (debug) printf("@@@@ rpt:Hung Up\n");
12847 ast_frfree(f);
12848 break;
12849 }
12850 }
12851 ast_frfree(f);
12852 continue;
12853 }
12854 if (who == myrpt->txpchannel)
12855 {
12856 f = ast_read(myrpt->txpchannel);
12857 if (!f)
12858 {
12859 if (debug) printf("@@@@ rpt:Hung Up\n");
12860 break;
12861 }
12862 if (f->frametype == AST_FRAME_CONTROL)
12863 {
12864 if (f->subclass == AST_CONTROL_HANGUP)
12865 {
12866 if (debug) printf("@@@@ rpt:Hung Up\n");
12867 ast_frfree(f);
12868 break;
12869 }
12870 }
12871 ast_frfree(f);
12872 continue;
12873 }
12874 }
12875 usleep(100000);
12876 ast_hangup(myrpt->pchannel);
12877 ast_hangup(myrpt->monchannel);
12878 if (myrpt->parrotchannel) ast_hangup(myrpt->parrotchannel);
12879 myrpt->parrotstate = 0;
12880 if (myrpt->voxchannel) ast_hangup(myrpt->voxchannel);
12881 ast_hangup(myrpt->txpchannel);
12882 if (myrpt->txchannel != myrpt->rxchannel) ast_hangup(myrpt->txchannel);
12883 if (myrpt->dahditxchannel != myrpt->txchannel) ast_hangup(myrpt->dahditxchannel);
12884 if (myrpt->lastf1) ast_frfree(myrpt->lastf1);
12885 myrpt->lastf1 = NULL;
12886 if (myrpt->lastf2) ast_frfree(myrpt->lastf2);
12887 myrpt->lastf2 = NULL;
12888 ast_hangup(myrpt->rxchannel);
12889 rpt_mutex_lock(&myrpt->lock);
12890 l = myrpt->links.next;
12891 while(l != &myrpt->links)
12892 {
12893 struct rpt_link *ll = l;
12894
12895 remque((struct qelem *) l);
12896
12897 if (l->chan) ast_hangup(l->chan);
12898 ast_hangup(l->pchan);
12899 l = l->next;
12900 ast_free(ll);
12901 }
12902 if (myrpt->xlink == 1) myrpt->xlink = 2;
12903 rpt_mutex_unlock(&myrpt->lock);
12904 if (debug) printf("@@@@ rpt:Hung up channel\n");
12905 myrpt->rpt_thread = AST_PTHREADT_STOP;
12906 pthread_exit(NULL);
12907 return NULL;
12908 }
12909
12910
12911 static void *rpt_master(void *ignore)
12912 {
12913 int i,n;
12914 pthread_attr_t attr;
12915 struct ast_config *cfg;
12916 char *this,*val;
12917
12918
12919 nodelog.next = nodelog.prev = &nodelog;
12920
12921 this = NULL;
12922 n = 0;
12923 #ifndef OLD_ASTERISK
12924
12925 while(!ast_test_flag(&ast_options,AST_OPT_FLAG_FULLY_BOOTED))
12926 usleep(250000);
12927 #endif
12928 #ifdef NEW_ASTERISK
12929 rpt_vars[n].cfg = ast_config_load("rpt.conf",config_flags);
12930 #else
12931 rpt_vars[n].cfg = ast_config_load("rpt.conf");
12932 #endif
12933 cfg = rpt_vars[n].cfg;
12934 if (!cfg) {
12935 ast_log(LOG_NOTICE, "Unable to open radio repeater configuration rpt.conf. Radio Repeater disabled.\n");
12936 pthread_exit(NULL);
12937 }
12938 while((this = ast_category_browse(cfg,this)) != NULL)
12939 {
12940 for(i = 0 ; i < strlen(this) ; i++){
12941 if((this[i] < '0') || (this[i] > '9'))
12942 break;
12943 }
12944 if(i != strlen(this)) continue;
12945 memset(&rpt_vars[n],0,sizeof(rpt_vars[n]));
12946 rpt_vars[n].name = ast_strdup(this);
12947 val = (char *) ast_variable_retrieve(cfg,this,"rxchannel");
12948 if (val) rpt_vars[n].rxchanname = ast_strdup(val);
12949 val = (char *) ast_variable_retrieve(cfg,this,"txchannel");
12950 if (val) rpt_vars[n].txchanname = ast_strdup(val);
12951 rpt_vars[n].remote = 0;
12952 rpt_vars[n].remoterig = "";
12953 val = (char *) ast_variable_retrieve(cfg,this,"remote");
12954 if (val)
12955 {
12956 rpt_vars[n].remoterig = ast_strdup(val);
12957 rpt_vars[n].remote = 1;
12958 }
12959 val = (char *) ast_variable_retrieve(cfg,this,"radiotype");
12960 if (val) rpt_vars[n].remoterig = ast_strdup(val);
12961 ast_mutex_init(&rpt_vars[n].lock);
12962 ast_mutex_init(&rpt_vars[n].remlock);
12963 ast_mutex_init(&rpt_vars[n].statpost_lock);
12964 rpt_vars[n].tele.next = &rpt_vars[n].tele;
12965 rpt_vars[n].tele.prev = &rpt_vars[n].tele;
12966 rpt_vars[n].rpt_thread = AST_PTHREADT_NULL;
12967 rpt_vars[n].tailmessagen = 0;
12968 #ifdef _MDC_DECODE_H_
12969 rpt_vars[n].mdc = mdc_decoder_new(8000);
12970 #endif
12971 n++;
12972 }
12973 nrpts = n;
12974 ast_config_destroy(cfg);
12975
12976
12977 for(i = 0; i < n; i++)
12978 {
12979 load_rpt_vars(i,1);
12980
12981
12982 if (rpt_vars[i].remote)
12983 {
12984 if(retreive_memory(&rpt_vars[i],"init")){
12985 if (!strcmp(rpt_vars[i].remoterig,remote_rig_rtx450))
12986 strncpy(rpt_vars[i].freq, "446.500", sizeof(rpt_vars[i].freq) - 1);
12987 else
12988 strncpy(rpt_vars[i].freq, "146.580", sizeof(rpt_vars[i].freq) - 1);
12989 strncpy(rpt_vars[i].rxpl, "100.0", sizeof(rpt_vars[i].rxpl) - 1);
12990
12991 strncpy(rpt_vars[i].txpl, "100.0", sizeof(rpt_vars[i].txpl) - 1);
12992 rpt_vars[i].remmode = REM_MODE_FM;
12993 rpt_vars[i].offset = REM_SIMPLEX;
12994 rpt_vars[i].powerlevel = REM_LOWPWR;
12995 }
12996 continue;
12997 }
12998 else
12999 {
13000 rpt_vars[i].p.memory = rpt_vars[i].name;
13001 if(retreive_memory(&rpt_vars[i],"radiofreq")){
13002 if (!strcmp(rpt_vars[i].remoterig,remote_rig_rtx450))
13003 strncpy(rpt_vars[i].freq, "446.500", sizeof(rpt_vars[i].freq) - 1);
13004 else if (!strcmp(rpt_vars[i].remoterig,remote_rig_rtx150))
13005 strncpy(rpt_vars[i].freq, "146.580", sizeof(rpt_vars[i].freq) - 1);
13006 strncpy(rpt_vars[i].rxpl, "100.0", sizeof(rpt_vars[i].rxpl) - 1);
13007
13008 strncpy(rpt_vars[i].txpl, "100.0", sizeof(rpt_vars[i].txpl) - 1);
13009 rpt_vars[i].remmode = REM_MODE_FM;
13010 rpt_vars[i].offset = REM_SIMPLEX;
13011 rpt_vars[i].powerlevel = REM_LOWPWR;
13012 }
13013 ast_log(LOG_NOTICE,"Normal Repeater Init %s %s %s\n",rpt_vars[i].name, rpt_vars[i].remoterig, rpt_vars[i].freq);
13014 }
13015 if (!rpt_vars[i].p.ident)
13016 {
13017 ast_log(LOG_WARNING,"Did not specify ident for node %s\n",rpt_vars[i].name);
13018 ast_config_destroy(cfg);
13019 pthread_exit(NULL);
13020 }
13021 pthread_attr_init(&attr);
13022 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
13023 ast_pthread_create(&rpt_vars[i].rpt_thread,&attr,rpt,(void *) &rpt_vars[i]);
13024 }
13025 usleep(500000);
13026 time(&starttime);
13027 for(;;)
13028 {
13029
13030 for(i = 0; i < n; i++)
13031 {
13032 int rv;
13033 if (rpt_vars[i].remote) continue;
13034 if (rpt_vars[i].rpt_thread == AST_PTHREADT_STOP)
13035 rv = -1;
13036 else
13037 rv = pthread_kill(rpt_vars[i].rpt_thread,0);
13038 if (rv)
13039 {
13040 if(time(NULL) - rpt_vars[i].lastthreadrestarttime <= 15)
13041 {
13042 if(rpt_vars[i].threadrestarts >= 5)
13043 {
13044 ast_log(LOG_ERROR,"Continual RPT thread restarts, killing Asterisk\n");
13045 exit(1);
13046 }
13047 else
13048 {
13049 ast_log(LOG_NOTICE,"RPT thread restarted on %s\n",rpt_vars[i].name);
13050 rpt_vars[i].threadrestarts++;
13051 }
13052 }
13053 else
13054 rpt_vars[i].threadrestarts = 0;
13055
13056 rpt_vars[i].lastthreadrestarttime = time(NULL);
13057 pthread_attr_init(&attr);
13058 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
13059 ast_pthread_create(&rpt_vars[i].rpt_thread,&attr,rpt,(void *) &rpt_vars[i]);
13060
13061 ast_log(LOG_WARNING, "rpt_thread restarted on node %s\n", rpt_vars[i].name);
13062 }
13063
13064 }
13065 for(;;)
13066 {
13067 struct nodelog *nodep;
13068 char *space,datestr[100],fname[300];
13069 int fd;
13070
13071 ast_mutex_lock(&nodeloglock);
13072 nodep = nodelog.next;
13073 if(nodep == &nodelog)
13074 {
13075 ast_mutex_unlock(&nodeloglock);
13076 break;
13077 }
13078 remque((struct qelem *)nodep);
13079 ast_mutex_unlock(&nodeloglock);
13080 space = strchr(nodep->str,' ');
13081 if (!space)
13082 {
13083 ast_free(nodep);
13084 continue;
13085 }
13086 *space = 0;
13087 strftime(datestr,sizeof(datestr) - 1,"%Y%m%d",
13088 localtime(&nodep->timestamp));
13089 sprintf(fname,"%s/%s/%s.txt",nodep->archivedir,
13090 nodep->str,datestr);
13091 fd = open(fname,O_WRONLY | O_CREAT | O_APPEND,0600);
13092 if (fd == -1)
13093 {
13094 ast_log(LOG_ERROR,"Cannot open node log file %s for write",space + 1);
13095 ast_free(nodep);
13096 continue;
13097 }
13098 if (write(fd,space + 1,strlen(space + 1)) !=
13099 strlen(space + 1))
13100 {
13101 ast_log(LOG_ERROR,"Cannot write node log file %s for write",space + 1);
13102 ast_free(nodep);
13103 continue;
13104 }
13105 close(fd);
13106 ast_free(nodep);
13107 }
13108 sleep(2);
13109 }
13110 ast_config_destroy(cfg);
13111 pthread_exit(NULL);
13112 }
13113
13114 static int rpt_exec(struct ast_channel *chan, void *data)
13115 {
13116 int res=-1,i,rem_totx,rem_rx,remkeyed,n,phone_mode = 0;
13117 int iskenwood_pci4,authtold,authreq,setting,notremming,reming;
13118 int ismuted,dtmfed,phone_vox = 0;
13119 #ifdef OLD_ASTERISK
13120 struct localuser *u;
13121 #endif
13122 char tmp[256], keyed = 0,keyed1 = 0;
13123 char *options,*stringp,*tele,c,*altp,*memp;
13124 char sx[320],*sy;
13125 struct rpt *myrpt;
13126 struct ast_frame *f,*f1,*f2;
13127 struct ast_channel *who;
13128 struct ast_channel *cs[20];
13129 struct rpt_link *l;
13130 struct dahdi_confinfo ci;
13131 struct dahdi_params par;
13132 int ms,elap,nullfd;
13133 time_t t,last_timeout_warning;
13134 struct dahdi_radio_param z;
13135 struct rpt_tele *telem;
13136 int numlinks;
13137
13138 nullfd = open("/dev/null",O_RDWR);
13139 if (ast_strlen_zero(data)) {
13140 ast_log(LOG_WARNING, "Rpt requires an argument (system node)\n");
13141 return -1;
13142 }
13143
13144 strncpy(tmp, (char *)data, sizeof(tmp)-1);
13145 time(&t);
13146
13147 if (t < starttime) t = starttime + START_DELAY;
13148 if ((!starttime) || (t < (starttime + START_DELAY)))
13149 {
13150 ast_log(LOG_NOTICE,"Node %s rejecting call: too soon!\n",tmp);
13151 ast_safe_sleep(chan,3000);
13152 return -1;
13153 }
13154
13155 ast_log(LOG_NOTICE,"parsing argument=%s \n",tmp);
13156
13157 altp=strstr(tmp, "|*");
13158 if(altp){
13159 altp[0]=0;
13160 altp++;
13161 }
13162
13163 memp=strstr(tmp, "|M");
13164 if(memp){
13165 memp[0]=0;
13166 memp+=2;
13167 }
13168
13169 stringp=tmp;
13170 strsep(&stringp, "|");
13171 options = stringp;
13172
13173 ast_log(LOG_NOTICE,"options=%s \n",options);
13174 if(memp>0)ast_log(LOG_NOTICE,"memp=%s \n",memp);
13175 if(altp>0)ast_log(LOG_NOTICE,"altp=%s \n",altp);
13176
13177 myrpt = NULL;
13178
13179 for(i = 0; i < nrpts; i++)
13180 {
13181
13182 if (!strcmp(tmp,rpt_vars[i].name))
13183 {
13184 myrpt = &rpt_vars[i];
13185 break;
13186 }
13187 }
13188
13189 pbx_builtin_setvar_helper(chan, "RPT_STAT_ERR", "");
13190
13191 if (myrpt == NULL)
13192 {
13193 pbx_builtin_setvar_helper(chan, "RPT_STAT_ERR", "NODE_NOT_FOUND");
13194 ast_log(LOG_WARNING, "Cannot find specified system node %s\n",tmp);
13195 return (priority_jump(NULL,chan));
13196 }
13197
13198 numlinks=linkcount(myrpt);
13199
13200 if(options && *options == 'q')
13201 {
13202 char buf2[128];
13203
13204 if(myrpt->keyed)
13205 pbx_builtin_setvar_helper(chan, "RPT_STAT_RXKEYED", "1");
13206 else
13207 pbx_builtin_setvar_helper(chan, "RPT_STAT_RXKEYED", "0");
13208
13209 if(myrpt->txkeyed)
13210 pbx_builtin_setvar_helper(chan, "RPT_STAT_TXKEYED", "1");
13211 else
13212 pbx_builtin_setvar_helper(chan, "RPT_STAT_TXKEYED", "0");
13213
13214 snprintf(buf2,sizeof(buf2),"%s=%i", "RPT_STAT_XLINK", myrpt->xlink);
13215 pbx_builtin_setvar(chan, buf2);
13216 snprintf(buf2,sizeof(buf2),"%s=%i", "RPT_STAT_LINKS", numlinks);
13217 pbx_builtin_setvar(chan, buf2);
13218 snprintf(buf2,sizeof(buf2),"%s=%d", "RPT_STAT_WASCHAN", myrpt->waschan);
13219 pbx_builtin_setvar(chan, buf2);
13220 snprintf(buf2,sizeof(buf2),"%s=%d", "RPT_STAT_NOWCHAN", myrpt->nowchan);
13221 pbx_builtin_setvar(chan, buf2);
13222 snprintf(buf2,sizeof(buf2),"%s=%d", "RPT_STAT_DUPLEX", myrpt->p.duplex);
13223 pbx_builtin_setvar(chan, buf2);
13224 snprintf(buf2,sizeof(buf2),"%s=%d", "RPT_STAT_PARROT", myrpt->p.parrotmode);
13225 pbx_builtin_setvar(chan, buf2);
13226
13227
13228
13229
13230 snprintf(buf2,sizeof(buf2),"%s=%d", "RPT_STAT_CALLMODE", myrpt->callmode);
13231 pbx_builtin_setvar(chan, buf2);
13232 snprintf(buf2,sizeof(buf2),"%s=%s", "RPT_STAT_LASTTONE", myrpt->lasttone);
13233 pbx_builtin_setvar(chan, buf2);
13234
13235 return priority_jump(myrpt,chan);
13236 }
13237
13238 if(options && *options == 'o')
13239 {
13240 return(channel_revert(myrpt));
13241 }
13242
13243 #if 0
13244 if((altp)&&(*options == 'Z'))
13245 {
13246 rpt_push_alt_macro(myrpt,altp);
13247 return 0;
13248 }
13249 #endif
13250
13251
13252
13253 if (options && ((*options == 'P') || (*options == 'D') || (*options == 'R') || (*options == 'S')))
13254 {
13255 int val;
13256
13257 pbx_builtin_setvar_helper(chan, "RPT_STAT_BUSY", "0");
13258
13259 myrpt->bargechan=0;
13260 if(options && strstr(options, "f")>0)
13261 {
13262 myrpt->bargechan=1;
13263 }
13264
13265 if(memp>0)
13266 {
13267 char radiochan;
13268 radiochan=strtod(data,NULL);
13269
13270
13271 if(numlinks>0 && radiochan!=myrpt->nowchan && !myrpt->bargechan)
13272 {
13273 pbx_builtin_setvar_helper(chan, "RPT_STAT_BUSY", "1");
13274 ast_log(LOG_NOTICE, "Radio Channel Busy.\n");
13275 return (priority_jump(myrpt,chan));
13276 }
13277 else if(radiochan!=myrpt->nowchan || myrpt->bargechan)
13278 {
13279 channel_steer(myrpt,memp);
13280 }
13281 }
13282 if(altp)rpt_push_alt_macro(myrpt,altp);
13283 phone_mode = 1;
13284 if (*options == 'D') phone_mode = 2;
13285 if (*options == 'S') phone_mode = 3;
13286 ast_set_callerid(chan,"0","app_rpt user","0");
13287 val = 1;
13288 ast_channel_setoption(chan,AST_OPTION_TONE_VERIFY,&val,sizeof(char),0);
13289 if ((*(options + 1) == 'V') || (*(options + 1) == 'v')) phone_vox = 1;
13290 }
13291 else
13292 {
13293 #ifdef ALLOW_LOCAL_CHANNELS
13294
13295 if ( (strncmp(chan->name,"IAX2",4)) && (strncmp(chan->name,"Local",5)) ) {
13296 ast_log(LOG_WARNING, "We only accept links via IAX2 or Local!!\n");
13297 return -1;
13298 }
13299 #else
13300 if (strncmp(chan->name,"IAX2",4))
13301 {
13302 ast_log(LOG_WARNING, "We only accept links via IAX2!!\n");
13303 return -1;
13304 }
13305 #endif
13306 if(myrpt->p.s[myrpt->p.sysstate_cur].txdisable){
13307 ast_log(LOG_NOTICE, "Connect attempt to node %s with tx disabled", myrpt->name);
13308 return -1;
13309 }
13310 }
13311 if (options && (*options == 'R'))
13312 {
13313
13314 char *return_context;
13315 int length, m, lot, timeout = 0;
13316 char buffer[256],*template;
13317 char *working, *context, *exten, *priority;
13318 char *s,*orig_s;
13319
13320 rpt_mutex_lock(&myrpt->lock);
13321 m = myrpt->callmode;
13322 rpt_mutex_unlock(&myrpt->lock);
13323
13324 if ((!myrpt->p.nobusyout) && m)
13325 {
13326 if (chan->_state != AST_STATE_UP)
13327 {
13328 ast_indicate(chan,AST_CONTROL_BUSY);
13329 }
13330 while(ast_safe_sleep(chan,10000) != -1);
13331 return -1;
13332 }
13333
13334 if (chan->_state != AST_STATE_UP)
13335 {
13336 ast_answer(chan);
13337 if (!phone_mode) send_newkey(chan);
13338 }
13339
13340 length=strlen(options)+2;
13341 orig_s=ast_malloc(length);
13342 if(!orig_s) {
13343 ast_log(LOG_WARNING, "Out of memory\n");
13344 return -1;
13345 }
13346 s=orig_s;
13347 strncpy(s,options,length);
13348
13349 template=strsep(&s,"|");
13350 if(!template) {
13351 ast_log(LOG_WARNING, "An announce template must be defined\n");
13352 ast_free(orig_s);
13353 return -1;
13354 }
13355
13356 if(s) {
13357 timeout = atoi(strsep(&s, "|"));
13358 timeout *= 1000;
13359 }
13360
13361 return_context = s;
13362
13363 if(return_context != NULL) {
13364
13365
13366 working = return_context;
13367 context = strsep(&working, "|");
13368 exten = strsep(&working, "|");
13369 if(!exten) {
13370
13371 priority = context;
13372 exten = NULL;
13373 context = NULL;
13374 } else {
13375 priority = strsep(&working, "|");
13376 if(!priority) {
13377
13378 priority = exten;
13379 exten = context;
13380 context = NULL;
13381 }
13382 }
13383 if(atoi(priority) < 0) {
13384 ast_log(LOG_WARNING, "Priority '%s' must be a number > 0\n", priority);
13385 ast_free(orig_s);
13386 return -1;
13387 }
13388
13389 chan->priority = atoi(priority);
13390 #ifdef OLD_ASTERISK
13391 if(exten && strcasecmp(exten, "BYEXTENSION"))
13392 #else
13393 if(exten)
13394 #endif
13395 strncpy(chan->exten, exten, sizeof(chan->exten)-1);
13396 if(context)
13397 strncpy(chan->context, context, sizeof(chan->context)-1);
13398 } else {
13399 chan->priority++;
13400 }
13401
13402 if(option_verbose > 2) {
13403 ast_verbose( VERBOSE_PREFIX_3 "Return Context: (%s,%s,%d) ID: %s\n", chan->context,chan->exten, chan->priority, chan->cid.cid_num);
13404 if(!ast_exists_extension(chan, chan->context, chan->exten, chan->priority, chan->cid.cid_num)) {
13405 ast_verbose( VERBOSE_PREFIX_3 "Warning: Return Context Invalid, call will return to default|s\n");
13406 }
13407 }
13408
13409
13410
13411
13412 ast_masq_park_call(chan, NULL, timeout, &lot);
13413
13414 if (option_verbose > 2) ast_verbose( VERBOSE_PREFIX_3 "Call Parking Called, lot: %d, timeout: %d, context: %s\n", lot, timeout, return_context);
13415
13416 snprintf(buffer, sizeof(buffer) - 1, "%d,%s", lot, template + 1);
13417
13418 rpt_telemetry(myrpt,REV_PATCH,buffer);
13419
13420 ast_free(orig_s);
13421
13422 return 0;
13423
13424 }
13425
13426 if (!options)
13427 {
13428 struct ast_hostent ahp;
13429 struct hostent *hp;
13430 struct in_addr ia;
13431 char hisip[100],nodeip[100],*val, *s, *s1, *s2, *s3, *b,*b1;
13432
13433
13434 if (!chan->cid.cid_num)
13435 {
13436 ast_log(LOG_WARNING, "Does not have callerid on %s\n",tmp);
13437 return -1;
13438 }
13439
13440 memset(hisip,0,sizeof(hisip));
13441 #ifdef ALLOW_LOCAL_CHANNELS
13442
13443 if (strncmp(chan->name,"Local",5)==0) {
13444 strcpy(hisip,"127.0.0.1");
13445 } else {
13446 pbx_substitute_variables_helper(chan,"${IAXPEER(CURRENTCHANNEL)}",hisip,sizeof(hisip) - 1);
13447 }
13448 #else
13449 pbx_substitute_variables_helper(chan,"${IAXPEER(CURRENTCHANNEL)}",hisip,sizeof(hisip) - 1);
13450 #endif
13451
13452 if (!hisip[0])
13453 {
13454 ast_log(LOG_WARNING, "Link IP address cannot be determined!!\n");
13455 return -1;
13456 }
13457
13458 ast_callerid_parse(chan->cid.cid_num,&b,&b1);
13459 ast_shrink_phone_number(b1);
13460 if (!strcmp(myrpt->name,b1))
13461 {
13462 ast_log(LOG_WARNING, "Trying to link to self!!\n");
13463 return -1;
13464 }
13465
13466 if (*b1 < '1')
13467 {
13468 ast_log(LOG_WARNING, "Node %s Invalid for connection here!!\n",b1);
13469 return -1;
13470 }
13471
13472
13473
13474 val = node_lookup(myrpt,b1);
13475 if (!val)
13476 {
13477 ast_log(LOG_WARNING, "Reported node %s cannot be found!!\n",b1);
13478 return -1;
13479 }
13480 strncpy(tmp,val,sizeof(tmp) - 1);
13481 s = tmp;
13482 s1 = strsep(&s,",");
13483 if (!strchr(s1,':') && strchr(s1,'/') && strncasecmp(s1, "local/", 6))
13484 {
13485 sy = strchr(s1,'/');
13486 *sy = 0;
13487 sprintf(sx,"%s:4569/%s",s1,sy + 1);
13488 s1 = sx;
13489 }
13490 s2 = strsep(&s,",");
13491 if (!s2)
13492 {
13493 ast_log(LOG_WARNING, "Reported node %s not in correct format!!\n",b1);
13494 return -1;
13495 }
13496 if (strcmp(s2,"NONE")) {
13497 hp = ast_gethostbyname(s2, &ahp);
13498 if (!hp)
13499 {
13500 ast_log(LOG_WARNING, "Reported node %s, name %s cannot be found!!\n",b1,s2);
13501 return -1;
13502 }
13503 memcpy(&ia,hp->h_addr,sizeof(in_addr_t));
13504 #ifdef OLD_ASTERISK
13505 ast_inet_ntoa(nodeip,sizeof(nodeip) - 1,ia);
13506 #else
13507 strncpy(nodeip,ast_inet_ntoa(ia),sizeof(nodeip) - 1);
13508 #endif
13509 s3 = strchr(hisip,':');
13510 if (s3) *s3 = 0;
13511 if (strcmp(hisip,nodeip))
13512 {
13513 s3 = strchr(s1,'@');
13514 if (s3) s1 = s3 + 1;
13515 s3 = strchr(s1,'/');
13516 if (s3) *s3 = 0;
13517 s3 = strchr(s1,':');
13518 if (s3) *s3 = 0;
13519 hp = ast_gethostbyname(s1, &ahp);
13520 if (!hp)
13521 {
13522 ast_log(LOG_WARNING, "Reported node %s, name %s cannot be found!!\n",b1,s1);
13523 return -1;
13524 }
13525 memcpy(&ia,hp->h_addr,sizeof(in_addr_t));
13526 #ifdef OLD_ASTERISK
13527 ast_inet_ntoa(nodeip,sizeof(nodeip) - 1,ia);
13528 #else
13529 strncpy(nodeip,ast_inet_ntoa(ia),sizeof(nodeip) - 1);
13530 #endif
13531 if (strcmp(hisip,nodeip))
13532 {
13533 ast_log(LOG_WARNING, "Node %s IP %s does not match link IP %s!!\n",b1,nodeip,hisip);
13534 return -1;
13535 }
13536 }
13537 }
13538 }
13539
13540
13541 if (!myrpt->remote)
13542 {
13543 char *b,*b1;
13544 int reconnects = 0;
13545
13546 rpt_mutex_lock(&myrpt->lock);
13547 i = myrpt->xlink;
13548 rpt_mutex_unlock(&myrpt->lock);
13549 if (i)
13550 {
13551 ast_log(LOG_WARNING, "Cannot connect to node %s, system busy\n",myrpt->name);
13552 return -1;
13553 }
13554
13555 if (!chan->cid.cid_num)
13556 {
13557 ast_log(LOG_WARNING, "Doesnt have callerid on %s\n",tmp);
13558 return -1;
13559 }
13560
13561 ast_callerid_parse(chan->cid.cid_num,&b,&b1);
13562 ast_shrink_phone_number(b1);
13563 if (!strcmp(myrpt->name,b1))
13564 {
13565 ast_log(LOG_WARNING, "Trying to link to self!!\n");
13566 return -1;
13567 }
13568 rpt_mutex_lock(&myrpt->lock);
13569 l = myrpt->links.next;
13570
13571 while(l != &myrpt->links)
13572 {
13573 if (l->name[0] == '0')
13574 {
13575 l = l->next;
13576 continue;
13577 }
13578
13579 if (!strcmp(l->name,b1)) break;
13580 l = l->next;
13581 }
13582
13583 if (l != &myrpt->links)
13584 {
13585 l->killme = 1;
13586 l->retries = l->max_retries + 1;
13587 l->disced = 2;
13588 reconnects = l->reconnects;
13589 reconnects++;
13590 rpt_mutex_unlock(&myrpt->lock);
13591 usleep(500000);
13592 } else
13593 rpt_mutex_unlock(&myrpt->lock);
13594
13595 l = ast_malloc(sizeof(struct rpt_link));
13596 if (!l)
13597 {
13598 ast_log(LOG_WARNING, "Unable to malloc\n");
13599 pthread_exit(NULL);
13600 }
13601
13602 memset((char *)l,0,sizeof(struct rpt_link));
13603 l->mode = 1;
13604 strncpy(l->name,b1,MAXNODESTR - 1);
13605 l->isremote = 0;
13606 l->chan = chan;
13607 l->connected = 1;
13608 l->thisconnected = 1;
13609 l->hasconnected = 1;
13610 l->reconnects = reconnects;
13611 l->phonemode = phone_mode;
13612 l->phonevox = phone_vox;
13613 l->lastf1 = NULL;
13614 l->lastf2 = NULL;
13615 l->dtmfed = 0;
13616 voxinit_link(l,1);
13617 ast_set_read_format(l->chan,AST_FORMAT_SLINEAR);
13618 ast_set_write_format(l->chan,AST_FORMAT_SLINEAR);
13619
13620 l->pchan = ast_request("DAHDI",AST_FORMAT_SLINEAR,"pseudo",NULL);
13621 if (!l->pchan)
13622 {
13623 fprintf(stderr,"rpt:Sorry unable to obtain pseudo channel\n");
13624 pthread_exit(NULL);
13625 }
13626 ast_set_read_format(l->pchan,AST_FORMAT_SLINEAR);
13627 ast_set_write_format(l->pchan,AST_FORMAT_SLINEAR);
13628 #ifdef AST_CDR_FLAG_POST_DISABLED
13629 if (l->pchan->cdr)
13630 ast_set_flag(l->pchan->cdr,AST_CDR_FLAG_POST_DISABLED);
13631 #endif
13632
13633 ci.chan = 0;
13634 ci.confno = myrpt->conf;
13635 ci.confmode = DAHDI_CONF_CONF | DAHDI_CONF_LISTENER | DAHDI_CONF_TALKER;
13636
13637 if (ioctl(l->pchan->fds[0],DAHDI_SETCONF,&ci) == -1)
13638 {
13639 ast_log(LOG_WARNING, "Unable to set conference mode to Announce\n");
13640 pthread_exit(NULL);
13641 }
13642 rpt_mutex_lock(&myrpt->lock);
13643 if ((phone_mode == 2) && (!phone_vox)) l->lastrealrx = 1;
13644 l->max_retries = MAX_RETRIES;
13645
13646 insque((struct qelem *)l,(struct qelem *)myrpt->links.next);
13647 __kickshort(myrpt);
13648 rpt_mutex_unlock(&myrpt->lock);
13649 if (chan->_state != AST_STATE_UP) {
13650 ast_answer(chan);
13651 if (!phone_mode) send_newkey(chan);
13652 }
13653 if (myrpt->p.archivedir)
13654 {
13655 char str[100];
13656
13657 if (l->phonemode)
13658 sprintf(str,"LINK(P),%s",l->name);
13659 else
13660 sprintf(str,"LINK,%s",l->name);
13661 donodelog(myrpt,str);
13662 }
13663 if (!phone_mode) send_newkey(chan);
13664 return 0;
13665 }
13666
13667 rpt_mutex_lock(&myrpt->lock);
13668
13669 if (myrpt->remoteon)
13670 {
13671 rpt_mutex_unlock(&myrpt->lock);
13672 usleep(500000);
13673 if (myrpt->remoteon)
13674 {
13675 ast_log(LOG_WARNING, "Trying to use busy link on %s\n",tmp);
13676 #ifdef AST_CDR_FLAG_POST_DISABLED
13677 if (chan->cdr)
13678 ast_set_flag(chan->cdr,AST_CDR_FLAG_POST_DISABLED);
13679 #endif
13680 return -1;
13681 }
13682 rpt_mutex_lock(&myrpt->lock);
13683 }
13684 if (myrpt->p.rptnode)
13685 {
13686 char killedit = 0;
13687 time_t now;
13688
13689 time(&now);
13690 for(i = 0; i < nrpts; i++)
13691 {
13692 if (!strcasecmp(rpt_vars[i].name,myrpt->p.rptnode))
13693 {
13694 if ((rpt_vars[i].links.next != &rpt_vars[i].links) ||
13695 rpt_vars[i].keyed ||
13696 ((rpt_vars[i].lastkeyedtime + RPT_LOCKOUT_SECS) > now) ||
13697 rpt_vars[i].txkeyed ||
13698 ((rpt_vars[i].lasttxkeyedtime + RPT_LOCKOUT_SECS) > now))
13699 {
13700 rpt_mutex_unlock(&myrpt->lock);
13701 ast_log(LOG_WARNING, "Trying to use busy link (repeater node %s) on %s\n",rpt_vars[i].name,tmp);
13702 #ifdef AST_CDR_FLAG_POST_DISABLED
13703 if (chan->cdr)
13704 ast_set_flag(chan->cdr,AST_CDR_FLAG_POST_DISABLED);
13705 #endif
13706 return -1;
13707 }
13708 while(rpt_vars[i].xlink != 3)
13709 {
13710 if (!killedit)
13711 {
13712 ast_softhangup(rpt_vars[i].rxchannel,AST_SOFTHANGUP_DEV);
13713 rpt_vars[i].xlink = 1;
13714 killedit = 1;
13715 }
13716 rpt_mutex_unlock(&myrpt->lock);
13717 if (ast_safe_sleep(chan,500) == -1)
13718 {
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 rpt_mutex_lock(&myrpt->lock);
13726 }
13727 break;
13728 }
13729 }
13730 }
13731
13732 #ifdef HAVE_IOPERM
13733 if ( (!strcmp(myrpt->remoterig, remote_rig_rbi)||!strcmp(myrpt->remoterig, remote_rig_ppp16)) &&
13734 (ioperm(myrpt->p.iobase,1,1) == -1))
13735 {
13736 rpt_mutex_unlock(&myrpt->lock);
13737 ast_log(LOG_WARNING, "Can't get io permission on IO port %x hex\n",myrpt->p.iobase);
13738 return -1;
13739 }
13740 #endif
13741 myrpt->remoteon = 1;
13742 #ifdef OLD_ASTERISK
13743 LOCAL_USER_ADD(u);
13744 #endif
13745 rpt_mutex_unlock(&myrpt->lock);
13746
13747 for(i = 0; i < nrpts; i++)
13748 {
13749 if (&rpt_vars[i] == myrpt)
13750 {
13751 load_rpt_vars(i,0);
13752 break;
13753 }
13754 }
13755 rpt_mutex_lock(&myrpt->lock);
13756 tele = strchr(myrpt->rxchanname,'/');
13757 if (!tele)
13758 {
13759 fprintf(stderr,"rpt:Dial number must be in format tech/number\n");
13760 rpt_mutex_unlock(&myrpt->lock);
13761 pthread_exit(NULL);
13762 }
13763 *tele++ = 0;
13764 myrpt->rxchannel = ast_request(myrpt->rxchanname,AST_FORMAT_SLINEAR,tele,NULL);
13765 myrpt->dahdirxchannel = NULL;
13766 if (!strcasecmp(myrpt->rxchanname,"DAHDI"))
13767 myrpt->dahdirxchannel = myrpt->rxchannel;
13768 if (myrpt->rxchannel)
13769 {
13770 ast_set_read_format(myrpt->rxchannel,AST_FORMAT_SLINEAR);
13771 ast_set_write_format(myrpt->rxchannel,AST_FORMAT_SLINEAR);
13772 #ifdef AST_CDR_FLAG_POST_DISABLED
13773 if (myrpt->rxchannel->cdr)
13774 ast_set_flag(myrpt->rxchannel->cdr,AST_CDR_FLAG_POST_DISABLED);
13775 #endif
13776 #ifndef NEW_ASTERISK
13777 myrpt->rxchannel->whentohangup = 0;
13778 #endif
13779 myrpt->rxchannel->appl = "Apprpt";
13780 myrpt->rxchannel->data = "(Link Rx)";
13781 if (option_verbose > 2)
13782 ast_verbose(VERBOSE_PREFIX_3 "rpt (Rx) initiating call to %s/%s on %s\n",
13783 myrpt->rxchanname,tele,myrpt->rxchannel->name);
13784 rpt_mutex_unlock(&myrpt->lock);
13785 ast_call(myrpt->rxchannel,tele,999);
13786 rpt_mutex_lock(&myrpt->lock);
13787 }
13788 else
13789 {
13790 fprintf(stderr,"rpt:Sorry unable to obtain Rx channel\n");
13791 rpt_mutex_unlock(&myrpt->lock);
13792 pthread_exit(NULL);
13793 }
13794 *--tele = '/';
13795 myrpt->dahditxchannel = NULL;
13796 if (myrpt->txchanname)
13797 {
13798 tele = strchr(myrpt->txchanname,'/');
13799 if (!tele)
13800 {
13801 fprintf(stderr,"rpt:Dial number must be in format tech/number\n");
13802 rpt_mutex_unlock(&myrpt->lock);
13803 ast_hangup(myrpt->rxchannel);
13804 pthread_exit(NULL);
13805 }
13806 *tele++ = 0;
13807 myrpt->txchannel = ast_request(myrpt->txchanname,AST_FORMAT_SLINEAR,tele,NULL);
13808 if (!strncasecmp(myrpt->txchanname,"DAHDI",3))
13809 myrpt->dahditxchannel = myrpt->txchannel;
13810 if (myrpt->txchannel)
13811 {
13812 ast_set_read_format(myrpt->txchannel,AST_FORMAT_SLINEAR);
13813 ast_set_write_format(myrpt->txchannel,AST_FORMAT_SLINEAR);
13814 #ifdef AST_CDR_FLAG_POST_DISABLED
13815 if (myrpt->txchannel->cdr)
13816 ast_set_flag(myrpt->txchannel->cdr,AST_CDR_FLAG_POST_DISABLED);
13817 #endif
13818 #ifndef NEW_ASTERISK
13819 myrpt->txchannel->whentohangup = 0;
13820 #endif
13821 myrpt->txchannel->appl = "Apprpt";
13822 myrpt->txchannel->data = "(Link Tx)";
13823 if (option_verbose > 2)
13824 ast_verbose(VERBOSE_PREFIX_3 "rpt (Tx) initiating call to %s/%s on %s\n",
13825 myrpt->txchanname,tele,myrpt->txchannel->name);
13826 rpt_mutex_unlock(&myrpt->lock);
13827 ast_call(myrpt->txchannel,tele,999);
13828 rpt_mutex_lock(&myrpt->lock);
13829 }
13830 else
13831 {
13832 fprintf(stderr,"rpt:Sorry unable to obtain Tx channel\n");
13833 rpt_mutex_unlock(&myrpt->lock);
13834 ast_hangup(myrpt->rxchannel);
13835 pthread_exit(NULL);
13836 }
13837 *--tele = '/';
13838 }
13839 else
13840 {
13841 myrpt->txchannel = myrpt->rxchannel;
13842 if (!strncasecmp(myrpt->rxchanname,"DAHDI",3))
13843 myrpt->dahditxchannel = myrpt->rxchannel;
13844 }
13845
13846 myrpt->pchannel = ast_request("DAHDI",AST_FORMAT_SLINEAR,"pseudo",NULL);
13847 if (!myrpt->pchannel)
13848 {
13849 fprintf(stderr,"rpt:Sorry unable to obtain pseudo channel\n");
13850 rpt_mutex_unlock(&myrpt->lock);
13851 if (myrpt->txchannel != myrpt->rxchannel)
13852 ast_hangup(myrpt->txchannel);
13853 ast_hangup(myrpt->rxchannel);
13854 pthread_exit(NULL);
13855 }
13856 ast_set_read_format(myrpt->pchannel,AST_FORMAT_SLINEAR);
13857 ast_set_write_format(myrpt->pchannel,AST_FORMAT_SLINEAR);
13858 #ifdef AST_CDR_FLAG_POST_DISABLED
13859 if (myrpt->pchannel->cdr)
13860 ast_set_flag(myrpt->pchannel->cdr,AST_CDR_FLAG_POST_DISABLED);
13861 #endif
13862 if (!myrpt->dahdirxchannel) myrpt->dahdirxchannel = myrpt->pchannel;
13863 if (!myrpt->dahditxchannel) myrpt->dahditxchannel = myrpt->pchannel;
13864
13865 ci.chan = 0;
13866 ci.confno = -1;
13867 ci.confmode = DAHDI_CONF_CONFANNMON ;
13868
13869 if (ioctl(myrpt->pchannel->fds[0],DAHDI_SETCONF,&ci) == -1)
13870 {
13871 ast_log(LOG_WARNING, "Unable to set conference mode to Announce\n");
13872 rpt_mutex_unlock(&myrpt->lock);
13873 ast_hangup(myrpt->pchannel);
13874 if (myrpt->txchannel != myrpt->rxchannel)
13875 ast_hangup(myrpt->txchannel);
13876 ast_hangup(myrpt->rxchannel);
13877 pthread_exit(NULL);
13878 }
13879
13880 myrpt->conf = myrpt->txconf = ci.confno;
13881
13882 myrpt->iofd = -1;
13883 if (myrpt->p.ioport && ((myrpt->iofd = openserial(myrpt,myrpt->p.ioport)) == -1))
13884 {
13885 rpt_mutex_unlock(&myrpt->lock);
13886 ast_hangup(myrpt->pchannel);
13887 if (myrpt->txchannel != myrpt->rxchannel)
13888 ast_hangup(myrpt->txchannel);
13889 ast_hangup(myrpt->rxchannel);
13890 pthread_exit(NULL);
13891 }
13892 iskenwood_pci4 = 0;
13893 memset(&z,0,sizeof(z));
13894 if ((myrpt->iofd < 1) && (myrpt->txchannel == myrpt->dahditxchannel))
13895 {
13896 z.radpar = DAHDI_RADPAR_REMMODE;
13897 z.data = DAHDI_RADPAR_REM_NONE;
13898 res = ioctl(myrpt->dahditxchannel->fds[0],DAHDI_RADIO_SETPARAM,&z);
13899
13900 if ((!res) && (!strcmp(myrpt->remoterig,remote_rig_kenwood)))
13901 {
13902 z.radpar = DAHDI_RADPAR_UIOMODE;
13903 z.data = 1;
13904 if (ioctl(myrpt->dahditxchannel->fds[0],DAHDI_RADIO_SETPARAM,&z) == -1)
13905 {
13906 ast_log(LOG_ERROR,"Cannot set UIOMODE\n");
13907 return -1;
13908 }
13909 z.radpar = DAHDI_RADPAR_UIODATA;
13910 z.data = 3;
13911 if (ioctl(myrpt->dahditxchannel->fds[0],DAHDI_RADIO_SETPARAM,&z) == -1)
13912 {
13913 ast_log(LOG_ERROR,"Cannot set UIODATA\n");
13914 return -1;
13915 }
13916 i = DAHDI_OFFHOOK;
13917 if (ioctl(myrpt->dahditxchannel->fds[0],DAHDI_HOOK,&i) == -1)
13918 {
13919 ast_log(LOG_ERROR,"Cannot set hook\n");
13920 return -1;
13921 }
13922 iskenwood_pci4 = 1;
13923 }
13924 }
13925 if (myrpt->txchannel == myrpt->dahditxchannel)
13926 {
13927 i = DAHDI_ONHOOK;
13928 ioctl(myrpt->dahditxchannel->fds[0],DAHDI_HOOK,&i);
13929
13930 if ((myrpt->iofd < 1) && (!res) &&
13931 ((!strcmp(myrpt->remoterig,remote_rig_ft897)) ||
13932 (!strcmp(myrpt->remoterig,remote_rig_ic706)) ||
13933 (!strcmp(myrpt->remoterig,remote_rig_tm271))))
13934 {
13935 z.radpar = DAHDI_RADPAR_UIOMODE;
13936 z.data = 1;
13937 if (ioctl(myrpt->dahditxchannel->fds[0],DAHDI_RADIO_SETPARAM,&z) == -1)
13938 {
13939 ast_log(LOG_ERROR,"Cannot set UIOMODE\n");
13940 return -1;
13941 }
13942 z.radpar = DAHDI_RADPAR_UIODATA;
13943 z.data = 3;
13944 if (ioctl(myrpt->dahditxchannel->fds[0],DAHDI_RADIO_SETPARAM,&z) == -1)
13945 {
13946 ast_log(LOG_ERROR,"Cannot set UIODATA\n");
13947 return -1;
13948 }
13949 }
13950 }
13951 myrpt->remoterx = 0;
13952 myrpt->remotetx = 0;
13953 myrpt->retxtimer = 0;
13954 myrpt->rerxtimer = 0;
13955 myrpt->remoteon = 1;
13956 myrpt->dtmfidx = -1;
13957 myrpt->dtmfbuf[0] = 0;
13958 myrpt->dtmf_time_rem = 0;
13959 myrpt->hfscanmode = 0;
13960 myrpt->hfscanstatus = 0;
13961 if (myrpt->p.startupmacro)
13962 {
13963 snprintf(myrpt->macrobuf,MAXMACRO - 1,"PPPP%s",myrpt->p.startupmacro);
13964 }
13965 time(&myrpt->start_time);
13966 myrpt->last_activity_time = myrpt->start_time;
13967 last_timeout_warning = 0;
13968 myrpt->reload = 0;
13969 myrpt->tele.next = &myrpt->tele;
13970 myrpt->tele.prev = &myrpt->tele;
13971 myrpt->newkey = 0;
13972 rpt_mutex_unlock(&myrpt->lock);
13973 ast_set_write_format(chan, AST_FORMAT_SLINEAR);
13974 ast_set_read_format(chan, AST_FORMAT_SLINEAR);
13975 rem_rx = 0;
13976 remkeyed = 0;
13977
13978 if (myrpt->remote && (myrpt->rxchannel == myrpt->txchannel))
13979 {
13980 i = 128;
13981 ioctl(myrpt->dahdirxchannel->fds[0],DAHDI_ECHOCANCEL,&i);
13982 }
13983 if (chan->_state != AST_STATE_UP) {
13984 ast_answer(chan);
13985 if (!phone_mode) send_newkey(chan);
13986 }
13987
13988 if (myrpt->rxchannel == myrpt->dahdirxchannel)
13989 {
13990 if (ioctl(myrpt->dahdirxchannel->fds[0],DAHDI_GET_PARAMS,&par) != -1)
13991 {
13992 if (par.rxisoffhook)
13993 {
13994 ast_indicate(chan,AST_CONTROL_RADIO_KEY);
13995 myrpt->remoterx = 1;
13996 remkeyed = 1;
13997 }
13998 }
13999 }
14000 if (myrpt->p.archivedir)
14001 {
14002 char mycmd[100],mydate[100],*b,*b1;
14003 time_t myt;
14004 long blocksleft;
14005
14006
14007 mkdir(myrpt->p.archivedir,0600);
14008 sprintf(mycmd,"%s/%s",myrpt->p.archivedir,myrpt->name);
14009 mkdir(mycmd,0600);
14010 time(&myt);
14011 strftime(mydate,sizeof(mydate) - 1,"%Y%m%d%H%M%S",
14012 localtime(&myt));
14013 sprintf(mycmd,"mixmonitor start %s %s/%s/%s.wav49 a",chan->name,
14014 myrpt->p.archivedir,myrpt->name,mydate);
14015 if (myrpt->p.monminblocks)
14016 {
14017 blocksleft = diskavail(myrpt);
14018 if (myrpt->p.remotetimeout)
14019 {
14020 blocksleft -= (myrpt->p.remotetimeout *
14021 MONITOR_DISK_BLOCKS_PER_MINUTE) / 60;
14022 }
14023 if (blocksleft >= myrpt->p.monminblocks)
14024 ast_cli_command(nullfd,mycmd);
14025 } else ast_cli_command(nullfd,mycmd);
14026
14027 if (!chan->cid.cid_num)
14028 {
14029 b1 = "0";
14030 } else {
14031 ast_callerid_parse(chan->cid.cid_num,&b,&b1);
14032 ast_shrink_phone_number(b1);
14033 }
14034 sprintf(mycmd,"CONNECT,%s",b1);
14035 donodelog(myrpt,mycmd);
14036 }
14037 myrpt->loginuser[0] = 0;
14038 myrpt->loginlevel[0] = 0;
14039 myrpt->authtelltimer = 0;
14040 myrpt->authtimer = 0;
14041 authtold = 0;
14042 authreq = 0;
14043 if (myrpt->p.authlevel > 1) authreq = 1;
14044 setrem(myrpt);
14045 n = 0;
14046 dtmfed = 0;
14047 cs[n++] = chan;
14048 cs[n++] = myrpt->rxchannel;
14049 cs[n++] = myrpt->pchannel;
14050 if (myrpt->rxchannel != myrpt->txchannel)
14051 cs[n++] = myrpt->txchannel;
14052 if (!phone_mode) send_newkey(chan);
14053
14054 for(;;)
14055 {
14056 if (ast_check_hangup(chan)) break;
14057 if (ast_check_hangup(myrpt->rxchannel)) break;
14058 notremming = 0;
14059 setting = 0;
14060 reming = 0;
14061 telem = myrpt->tele.next;
14062 while(telem != &myrpt->tele)
14063 {
14064 if (telem->mode == SETREMOTE) setting = 1;
14065 if ((telem->mode == SETREMOTE) ||
14066 (telem->mode == SCAN) ||
14067 (telem->mode == TUNE)) reming = 1;
14068 else notremming = 1;
14069 telem = telem->next;
14070 }
14071 if (myrpt->reload)
14072 {
14073 myrpt->reload = 0;
14074
14075 for(i = 0; i < nrpts; i++)
14076 {
14077 if (&rpt_vars[i] == myrpt)
14078 {
14079 load_rpt_vars(i,0);
14080 break;
14081 }
14082 }
14083 }
14084 time(&t);
14085 if (myrpt->p.remotetimeout)
14086 {
14087 time_t r;
14088
14089 r = (t - myrpt->start_time);
14090 if (r >= myrpt->p.remotetimeout)
14091 {
14092 saynode(myrpt,chan,myrpt->name);
14093 sayfile(chan,"rpt/timeout");
14094 ast_safe_sleep(chan,1000);
14095 break;
14096 }
14097 if ((myrpt->p.remotetimeoutwarning) &&
14098 (r >= (myrpt->p.remotetimeout -
14099 myrpt->p.remotetimeoutwarning)) &&
14100 (r <= (myrpt->p.remotetimeout -
14101 myrpt->p.remotetimeoutwarningfreq)))
14102 {
14103 if (myrpt->p.remotetimeoutwarningfreq)
14104 {
14105 if ((t - last_timeout_warning) >=
14106 myrpt->p.remotetimeoutwarningfreq)
14107 {
14108 time(&last_timeout_warning);
14109 rpt_telemetry(myrpt,TIMEOUT_WARNING,0);
14110 }
14111 }
14112 else
14113 {
14114 if (!last_timeout_warning)
14115 {
14116 time(&last_timeout_warning);
14117 rpt_telemetry(myrpt,TIMEOUT_WARNING,0);
14118 }
14119 }
14120 }
14121 }
14122 if (myrpt->p.remoteinacttimeout && myrpt->last_activity_time)
14123 {
14124 time_t r;
14125
14126 r = (t - myrpt->last_activity_time);
14127 if (r >= myrpt->p.remoteinacttimeout)
14128 {
14129 saynode(myrpt,chan,myrpt->name);
14130 ast_safe_sleep(chan,1000);
14131 break;
14132 }
14133 if ((myrpt->p.remotetimeoutwarning) &&
14134 (r >= (myrpt->p.remoteinacttimeout -
14135 myrpt->p.remotetimeoutwarning)) &&
14136 (r <= (myrpt->p.remoteinacttimeout -
14137 myrpt->p.remotetimeoutwarningfreq)))
14138 {
14139 if (myrpt->p.remotetimeoutwarningfreq)
14140 {
14141 if ((t - last_timeout_warning) >=
14142 myrpt->p.remotetimeoutwarningfreq)
14143 {
14144 time(&last_timeout_warning);
14145 rpt_telemetry(myrpt,ACT_TIMEOUT_WARNING,0);
14146 }
14147 }
14148 else
14149 {
14150 if (!last_timeout_warning)
14151 {
14152 time(&last_timeout_warning);
14153 rpt_telemetry(myrpt,ACT_TIMEOUT_WARNING,0);
14154 }
14155 }
14156 }
14157 }
14158 ms = MSWAIT;
14159 who = ast_waitfor_n(cs,n,&ms);
14160 if (who == NULL) ms = 0;
14161 elap = MSWAIT - ms;
14162 if (myrpt->macrotimer) myrpt->macrotimer -= elap;
14163 if (myrpt->macrotimer < 0) myrpt->macrotimer = 0;
14164 if (!ms) continue;
14165
14166 if (myrpt->dtmf_local_timer)
14167 {
14168 if (myrpt->dtmf_local_timer > 1) myrpt->dtmf_local_timer -= elap;
14169 if (myrpt->dtmf_local_timer < 1) myrpt->dtmf_local_timer = 1;
14170 }
14171 rpt_mutex_lock(&myrpt->lock);
14172 do_dtmf_local(myrpt,0);
14173 rpt_mutex_unlock(&myrpt->lock);
14174
14175 rem_totx = myrpt->dtmf_local_timer && (!phone_mode);
14176 rem_totx |= keyed && (!myrpt->tunerequest);
14177 rem_rx = (remkeyed && (!setting)) || (myrpt->tele.next != &myrpt->tele);
14178 if(!strcmp(myrpt->remoterig, remote_rig_ic706))
14179 rem_totx |= myrpt->tunerequest;
14180
14181 if((debug > 6) && rem_totx) {
14182 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);
14183 }
14184 if (keyed && (!keyed1))
14185 {
14186 keyed1 = 1;
14187 }
14188
14189 if (!keyed && (keyed1))
14190 {
14191 time_t myt;
14192
14193 keyed1 = 0;
14194 time(&myt);
14195
14196 if ((myrpt->p.authlevel) &&
14197 (!myrpt->loginlevel[0]) &&
14198 (myt > (t + 3)))
14199 {
14200 authreq = 1;
14201 authtold = 0;
14202 myrpt->authtelltimer = AUTHTELLTIME - AUTHTXTIME;
14203 }
14204 }
14205
14206 if (rem_rx && (!myrpt->remoterx))
14207 {
14208 myrpt->remoterx = 1;
14209 ast_indicate(chan,AST_CONTROL_RADIO_KEY);
14210 }
14211 if ((!rem_rx) && (myrpt->remoterx))
14212 {
14213 myrpt->remoterx = 0;
14214 ast_indicate(chan,AST_CONTROL_RADIO_UNKEY);
14215 }
14216
14217 if (authreq && (!myrpt->loginlevel[0]))
14218 {
14219 if ((!authtold) && ((myrpt->authtelltimer += elap)
14220 >= AUTHTELLTIME))
14221 {
14222 authtold = 1;
14223 rpt_telemetry(myrpt,LOGINREQ,NULL);
14224 }
14225 if ((myrpt->authtimer += elap) >= AUTHLOGOUTTIME)
14226 {
14227 break;
14228 }
14229 }
14230 if (myrpt->newkey)
14231 {
14232 if ((myrpt->retxtimer += elap) >= REDUNDANT_TX_TIME)
14233 {
14234 myrpt->retxtimer = 0;
14235 if ((myrpt->remoterx) && (!myrpt->remotetx))
14236 ast_indicate(chan,AST_CONTROL_RADIO_KEY);
14237 else
14238 ast_indicate(chan,AST_CONTROL_RADIO_UNKEY);
14239 }
14240
14241 if ((myrpt->rerxtimer += elap) >= (REDUNDANT_TX_TIME * 2))
14242 {
14243 keyed = 0;
14244 myrpt->rerxtimer = 0;
14245 }
14246 }
14247 if (rem_totx && (!myrpt->remotetx))
14248 {
14249
14250 if ((!myrpt->p.authlevel) || myrpt->loginlevel[0])
14251 {
14252 if(debug > 6)
14253 ast_log(LOG_NOTICE,"Handle rem_totx=%i. dtmf_local_timer=%i tunerequest=%i\n",rem_totx,myrpt->dtmf_local_timer,myrpt->tunerequest);
14254
14255 myrpt->remotetx = 1;
14256
14257 if((myrpt->remtxfreqok = check_tx_freq(myrpt)))
14258 {
14259 time(&myrpt->last_activity_time);
14260 if ((iskenwood_pci4) && (myrpt->txchannel == myrpt->dahditxchannel))
14261 {
14262 z.radpar = DAHDI_RADPAR_UIODATA;
14263 z.data = 1;
14264 if (ioctl(myrpt->dahditxchannel->fds[0],DAHDI_RADIO_SETPARAM,&z) == -1)
14265 {
14266 ast_log(LOG_ERROR,"Cannot set UIODATA\n");
14267 return -1;
14268 }
14269 }
14270 else
14271 {
14272 ast_indicate(myrpt->txchannel,AST_CONTROL_RADIO_KEY);
14273 }
14274 if (myrpt->p.archivedir) donodelog(myrpt,"TXKEY");
14275 }
14276 }
14277 }
14278 if ((!rem_totx) && myrpt->remotetx)
14279 {
14280 myrpt->remotetx = 0;
14281 if(!myrpt->remtxfreqok){
14282 rpt_telemetry(myrpt,UNAUTHTX,NULL);
14283 }
14284 if ((iskenwood_pci4) && (myrpt->txchannel == myrpt->dahditxchannel))
14285 {
14286 z.radpar = DAHDI_RADPAR_UIODATA;
14287 z.data = 3;
14288 if (ioctl(myrpt->dahditxchannel->fds[0],DAHDI_RADIO_SETPARAM,&z) == -1)
14289 {
14290 ast_log(LOG_ERROR,"Cannot set UIODATA\n");
14291 return -1;
14292 }
14293 }
14294 else
14295 {
14296 ast_indicate(myrpt->txchannel,AST_CONTROL_RADIO_UNKEY);
14297 }
14298 if (myrpt->p.archivedir) donodelog(myrpt,"TXUNKEY");
14299 }
14300 if (myrpt->hfscanmode){
14301 myrpt->scantimer -= elap;
14302 if(myrpt->scantimer <= 0){
14303 if (!reming)
14304 {
14305 myrpt->scantimer = REM_SCANTIME;
14306 rpt_telemetry(myrpt,SCAN,0);
14307 } else myrpt->scantimer = 1;
14308 }
14309 }
14310 rpt_mutex_lock(&myrpt->lock);
14311 c = myrpt->macrobuf[0];
14312 if (c && (!myrpt->macrotimer))
14313 {
14314 myrpt->macrotimer = MACROTIME;
14315 memmove(myrpt->macrobuf,myrpt->macrobuf + 1,MAXMACRO - 1);
14316 if ((c == 'p') || (c == 'P'))
14317 myrpt->macrotimer = MACROPTIME;
14318 rpt_mutex_unlock(&myrpt->lock);
14319 if (myrpt->p.archivedir)
14320 {
14321 char str[100];
14322 sprintf(str,"DTMF(M),%c",c);
14323 donodelog(myrpt,str);
14324 }
14325 if (handle_remote_dtmf_digit(myrpt,c,&keyed,0) == -1) break;
14326 continue;
14327 } else rpt_mutex_unlock(&myrpt->lock);
14328 if (who == chan)
14329 {
14330 f = ast_read(chan);
14331 if (!f)
14332 {
14333 if (debug) printf("@@@@ link:Hung Up\n");
14334 break;
14335 }
14336 if (f->frametype == AST_FRAME_VOICE)
14337 {
14338 if (ioctl(chan->fds[0], DAHDI_GETCONFMUTE, &ismuted) == -1)
14339 {
14340 ismuted = 0;
14341 }
14342
14343 ismuted |= (!myrpt->remotetx);
14344 if (dtmfed && phone_mode) ismuted = 1;
14345 dtmfed = 0;
14346 if (ismuted)
14347 {
14348 memset(f->data.ptr,0,f->datalen);
14349 if (myrpt->lastf1)
14350 memset(myrpt->lastf1->data.ptr,0,myrpt->lastf1->datalen);
14351 if (myrpt->lastf2)
14352 memset(myrpt->lastf2->data.ptr,0,myrpt->lastf2->datalen);
14353 }
14354 if (f) f2 = ast_frdup(f);
14355 else f2 = NULL;
14356 f1 = myrpt->lastf2;
14357 myrpt->lastf2 = myrpt->lastf1;
14358 myrpt->lastf1 = f2;
14359 if (ismuted)
14360 {
14361 if (myrpt->lastf1)
14362 memset(myrpt->lastf1->data.ptr,0,myrpt->lastf1->datalen);
14363 if (myrpt->lastf2)
14364 memset(myrpt->lastf2->data.ptr,0,myrpt->lastf2->datalen);
14365 }
14366 if (f1)
14367 {
14368 if (phone_mode)
14369 ast_write(myrpt->txchannel,f1);
14370 else
14371 ast_write(myrpt->txchannel,f);
14372 ast_frfree(f1);
14373 }
14374 }
14375 #ifndef OLD_ASTERISK
14376 else if (f->frametype == AST_FRAME_DTMF_BEGIN)
14377 {
14378 if (myrpt->lastf1)
14379 memset(myrpt->lastf1->data.ptr,0,myrpt->lastf1->datalen);
14380 if (myrpt->lastf2)
14381 memset(myrpt->lastf2->data.ptr,0,myrpt->lastf2->datalen);
14382 dtmfed = 1;
14383 }
14384 #endif
14385 if (f->frametype == AST_FRAME_DTMF)
14386 {
14387 if (myrpt->lastf1)
14388 memset(myrpt->lastf1->data.ptr,0,myrpt->lastf1->datalen);
14389 if (myrpt->lastf2)
14390 memset(myrpt->lastf2->data.ptr,0,myrpt->lastf2->datalen);
14391 dtmfed = 1;
14392 if (handle_remote_phone_dtmf(myrpt,f->subclass,&keyed,phone_mode) == -1)
14393 {
14394 if (debug) printf("@@@@ rpt:Hung Up\n");
14395 ast_frfree(f);
14396 break;
14397 }
14398 }
14399 if (f->frametype == AST_FRAME_TEXT)
14400 {
14401 if (handle_remote_data(myrpt,f->data.ptr) == -1)
14402 {
14403 if (debug) printf("@@@@ rpt:Hung Up\n");
14404 ast_frfree(f);
14405 break;
14406 }
14407 }
14408 if (f->frametype == AST_FRAME_CONTROL)
14409 {
14410 if (f->subclass == AST_CONTROL_HANGUP)
14411 {
14412 if (debug) printf("@@@@ rpt:Hung Up\n");
14413 ast_frfree(f);
14414 break;
14415 }
14416
14417 if (f->subclass == AST_CONTROL_RADIO_KEY)
14418 {
14419 if (debug == 7) printf("@@@@ rx key\n");
14420 keyed = 1;
14421 myrpt->rerxtimer = 0;
14422 }
14423
14424 if (f->subclass == AST_CONTROL_RADIO_UNKEY)
14425 {
14426 myrpt->rerxtimer = 0;
14427 if (debug == 7) printf("@@@@ rx un-key\n");
14428 keyed = 0;
14429 }
14430 }
14431 ast_frfree(f);
14432 continue;
14433 }
14434 if (who == myrpt->rxchannel)
14435 {
14436 f = ast_read(myrpt->rxchannel);
14437 if (!f)
14438 {
14439 if (debug) printf("@@@@ link:Hung Up\n");
14440 break;
14441 }
14442 if (f->frametype == AST_FRAME_VOICE)
14443 {
14444 int myreming = 0;
14445
14446 if(!strcmp(myrpt->remoterig, remote_rig_kenwood))
14447 myreming = reming;
14448
14449 if (myreming || (!remkeyed) ||
14450 ((myrpt->remote) && (myrpt->remotetx)) ||
14451 ((myrpt->remmode != REM_MODE_FM) &&
14452 notremming))
14453 memset(f->data.ptr,0,f->datalen);
14454 ast_write(myrpt->pchannel,f);
14455 }
14456 else if (f->frametype == AST_FRAME_CONTROL)
14457 {
14458 if (f->subclass == AST_CONTROL_HANGUP)
14459 {
14460 if (debug) printf("@@@@ rpt:Hung Up\n");
14461 ast_frfree(f);
14462 break;
14463 }
14464
14465 if (f->subclass == AST_CONTROL_RADIO_KEY)
14466 {
14467 if (debug == 7) printf("@@@@ remote rx key\n");
14468 if (!myrpt->remotetx)
14469 {
14470 remkeyed = 1;
14471 }
14472 }
14473
14474 if (f->subclass == AST_CONTROL_RADIO_UNKEY)
14475 {
14476 if (debug == 7) printf("@@@@ remote rx un-key\n");
14477 if (!myrpt->remotetx)
14478 {
14479 remkeyed = 0;
14480 }
14481 }
14482 }
14483 ast_frfree(f);
14484 continue;
14485 }
14486 if (who == myrpt->pchannel)
14487 {
14488 f = ast_read(myrpt->pchannel);
14489 if (!f)
14490 {
14491 if (debug) printf("@@@@ link:Hung Up\n");
14492 break;
14493 }
14494 if (f->frametype == AST_FRAME_VOICE)
14495 {
14496 ast_write(chan,f);
14497 }
14498 if (f->frametype == AST_FRAME_CONTROL)
14499 {
14500 if (f->subclass == AST_CONTROL_HANGUP)
14501 {
14502 if (debug) printf("@@@@ rpt:Hung Up\n");
14503 ast_frfree(f);
14504 break;
14505 }
14506 }
14507 ast_frfree(f);
14508 continue;
14509 }
14510 if ((myrpt->rxchannel != myrpt->txchannel) &&
14511 (who == myrpt->txchannel))
14512 {
14513 f = ast_read(myrpt->txchannel);
14514 if (!f)
14515 {
14516 if (debug) printf("@@@@ link:Hung Up\n");
14517 break;
14518 }
14519 if (f->frametype == AST_FRAME_CONTROL)
14520 {
14521 if (f->subclass == AST_CONTROL_HANGUP)
14522 {
14523 if (debug) printf("@@@@ rpt:Hung Up\n");
14524 ast_frfree(f);
14525 break;
14526 }
14527 }
14528 ast_frfree(f);
14529 continue;
14530 }
14531 }
14532 if (myrpt->p.archivedir)
14533 {
14534 char mycmd[100],*b,*b1;
14535
14536
14537 if (!chan->cid.cid_num)
14538 {
14539 b1 = "0";
14540 } else {
14541 ast_callerid_parse(chan->cid.cid_num,&b,&b1);
14542 ast_shrink_phone_number(b1);
14543 }
14544 sprintf(mycmd,"DISCONNECT,%s",b1);
14545 donodelog(myrpt,mycmd);
14546 }
14547
14548 while(myrpt->tele.next != &myrpt->tele) usleep(100000);
14549 sprintf(tmp,"mixmonitor stop %s",chan->name);
14550 ast_cli_command(nullfd,tmp);
14551 close(nullfd);
14552 rpt_mutex_lock(&myrpt->lock);
14553 myrpt->hfscanmode = 0;
14554 myrpt->hfscanstatus = 0;
14555 myrpt->remoteon = 0;
14556 rpt_mutex_unlock(&myrpt->lock);
14557 if (myrpt->lastf1) ast_frfree(myrpt->lastf1);
14558 myrpt->lastf1 = NULL;
14559 if (myrpt->lastf2) ast_frfree(myrpt->lastf2);
14560 myrpt->lastf2 = NULL;
14561 if ((iskenwood_pci4) && (myrpt->txchannel == myrpt->dahditxchannel))
14562 {
14563 z.radpar = DAHDI_RADPAR_UIOMODE;
14564 z.data = 3;
14565 if (ioctl(myrpt->dahditxchannel->fds[0],DAHDI_RADIO_SETPARAM,&z) == -1)
14566 {
14567 ast_log(LOG_ERROR,"Cannot set UIOMODE\n");
14568 return -1;
14569 }
14570 z.radpar = DAHDI_RADPAR_UIODATA;
14571 z.data = 3;
14572 if (ioctl(myrpt->dahditxchannel->fds[0],DAHDI_RADIO_SETPARAM,&z) == -1)
14573 {
14574 ast_log(LOG_ERROR,"Cannot set UIODATA\n");
14575 return -1;
14576 }
14577 i = DAHDI_OFFHOOK;
14578 if (ioctl(myrpt->dahditxchannel->fds[0],DAHDI_HOOK,&i) == -1)
14579 {
14580 ast_log(LOG_ERROR,"Cannot set hook\n");
14581 return -1;
14582 }
14583 }
14584 if (myrpt->iofd) close(myrpt->iofd);
14585 myrpt->iofd = -1;
14586 ast_hangup(myrpt->pchannel);
14587 if (myrpt->rxchannel != myrpt->txchannel) ast_hangup(myrpt->txchannel);
14588 ast_hangup(myrpt->rxchannel);
14589 closerem(myrpt);
14590 if (myrpt->p.rptnode)
14591 {
14592 rpt_mutex_lock(&myrpt->lock);
14593 for(i = 0; i < nrpts; i++)
14594 {
14595 if (!strcasecmp(rpt_vars[i].name,myrpt->p.rptnode))
14596 {
14597 rpt_vars[i].xlink = 0;
14598 break;
14599 }
14600 }
14601 rpt_mutex_unlock(&myrpt->lock);
14602 }
14603 #ifdef OLD_ASTERISK
14604 LOCAL_USER_REMOVE(u);
14605 #endif
14606 return res;
14607 }
14608
14609 #ifndef OLD_ASTERISK
14610
14611
14612
14613 static int manager_rpt_local_nodes(struct mansession *s, const struct message *m)
14614 {
14615 int i;
14616 astman_append(s, "<?xml version=\"1.0\"?>\r\n");
14617 astman_append(s, "<nodes>\r\n");
14618 for (i=0; i< nrpts; i++)
14619 {
14620 astman_append(s, " <node>%s</node>\r\n", rpt_vars[i].name);
14621 }
14622 astman_append(s, "</nodes>\r\n");
14623 astman_append(s, "\r\n");
14624 return RESULT_SUCCESS;
14625 }
14626
14627
14628
14629
14630
14631
14632
14633 static void rpt_manager_success(struct mansession *s, const struct message *m)
14634 {
14635 const char *id = astman_get_header(m, "ActionID");
14636 if (!ast_strlen_zero(id))
14637 astman_append(s, "ActionID: %s\r\n", id);
14638 astman_append(s, "Response: Success\r\n");
14639 }
14640
14641
14642
14643
14644
14645 static int rpt_manager_do_stats(struct mansession *s, const struct message *m, char *str)
14646 {
14647 int i,j,numoflinks;
14648 int dailytxtime, dailykerchunks;
14649 time_t now;
14650 int totalkerchunks, dailykeyups, totalkeyups, timeouts;
14651 int totalexecdcommands, dailyexecdcommands, hours, minutes, seconds;
14652 long long totaltxtime;
14653 struct rpt_link *l;
14654 char *listoflinks[MAX_STAT_LINKS];
14655 char *lastdtmfcommand,*parrot_ena;
14656 char *tot_state, *ider_state, *patch_state;
14657 char *reverse_patch_state, *sys_ena, *tot_ena, *link_ena, *patch_ena;
14658 char *sch_ena, *input_signal, *called_number, *user_funs, *tail_type;
14659 char *transmitterkeyed;
14660 const char *node = astman_get_header(m, "Node");
14661 struct rpt *myrpt;
14662
14663 static char *not_applicable = "N/A";
14664
14665 tot_state = ider_state =
14666 patch_state = reverse_patch_state =
14667 input_signal = not_applicable;
14668 called_number = lastdtmfcommand = transmitterkeyed = NULL;
14669
14670 time(&now);
14671 for(i = 0; i < nrpts; i++)
14672 {
14673 if ((node)&&(!strcmp(node,rpt_vars[i].name))){
14674 rpt_manager_success(s,m);
14675
14676 myrpt = &rpt_vars[i];
14677
14678 if(myrpt->remote){
14679 char *loginuser, *loginlevel, *freq, *rxpl, *txpl, *modestr;
14680 char offset = 0, powerlevel = 0, rxplon = 0, txplon = 0, remoteon, remmode = 0, reportfmstuff;
14681 char offsetc,powerlevelc;
14682
14683 loginuser = loginlevel = freq = rxpl = txpl = NULL;
14684
14685 rpt_mutex_lock(&myrpt->lock);
14686 if((remoteon = myrpt->remoteon)){
14687 if(!ast_strlen_zero(myrpt->loginuser))
14688 loginuser = ast_strdup(myrpt->loginuser);
14689 if(!ast_strlen_zero(myrpt->loginlevel))
14690 loginlevel = ast_strdup(myrpt->loginlevel);
14691 if(!ast_strlen_zero(myrpt->freq))
14692 freq = ast_strdup(myrpt->freq);
14693 if(!ast_strlen_zero(myrpt->rxpl))
14694 rxpl = ast_strdup(myrpt->rxpl);
14695 if(!ast_strlen_zero(myrpt->txpl))
14696 txpl = ast_strdup(myrpt->txpl);
14697 remmode = myrpt->remmode;
14698 offset = myrpt->offset;
14699 powerlevel = myrpt->powerlevel;
14700 rxplon = myrpt->rxplon;
14701 txplon = myrpt->txplon;
14702 }
14703 rpt_mutex_unlock(&myrpt->lock);
14704 astman_append(s, "IsRemoteBase: YES\r\n");
14705 astman_append(s, "RemoteOn: %s\r\n",(remoteon) ? "YES": "NO");
14706 if(remoteon){
14707 if(loginuser){
14708 astman_append(s, "LogInUser: %s\r\n", loginuser);
14709 ast_free(loginuser);
14710 }
14711 if(loginlevel){
14712 astman_append(s, "LogInLevel: %s\r\n", loginlevel);
14713 ast_free(loginlevel);
14714 }
14715 if(freq){
14716 astman_append(s, "Freq: %s\r\n", freq);
14717 ast_free(freq);
14718 }
14719 reportfmstuff = 0;
14720 switch(remmode){
14721 case REM_MODE_FM:
14722 modestr = "FM";
14723 reportfmstuff = 1;
14724 break;
14725 case REM_MODE_AM:
14726 modestr = "AM";
14727 break;
14728 case REM_MODE_USB:
14729 modestr = "USB";
14730 break;
14731 default:
14732 modestr = "LSB";
14733 break;
14734 }
14735 astman_append(s, "RemMode: %s\r\n", modestr);
14736 if(reportfmstuff){
14737 switch(offset){
14738 case REM_SIMPLEX:
14739 offsetc = 'S';
14740 break;
14741 case REM_MINUS:
14742 offsetc = '-';
14743 break;
14744 default:
14745 offsetc = '+';
14746 break;
14747 }
14748 astman_append(s, "RemOffset: %c\r\n", offsetc);
14749 if(rxplon && rxpl){
14750 astman_append(s, "RxPl: %s\r\n",rxpl);
14751 ast_free(rxpl);
14752 }
14753 if(txplon && txpl){
14754 astman_append(s, "TxPl: %s\r\n",txpl);
14755 ast_free(txpl);
14756 }
14757 }
14758 switch(powerlevel){
14759 case REM_LOWPWR:
14760 powerlevelc = 'L';
14761 break;
14762 case REM_MEDPWR:
14763 powerlevelc = 'M';
14764 break;
14765 default:
14766 powerlevelc = 'H';
14767 break;
14768 }
14769 astman_append(s,"PowerLevel: %c\r\n", powerlevelc);
14770 }
14771 astman_append(s, "\r\n");
14772 return 0;
14773 }
14774
14775
14776
14777 rpt_mutex_lock(&myrpt->lock);
14778 dailytxtime = myrpt->dailytxtime;
14779 totaltxtime = myrpt->totaltxtime;
14780 dailykeyups = myrpt->dailykeyups;
14781 totalkeyups = myrpt->totalkeyups;
14782 dailykerchunks = myrpt->dailykerchunks;
14783 totalkerchunks = myrpt->totalkerchunks;
14784 dailyexecdcommands = myrpt->dailyexecdcommands;
14785 totalexecdcommands = myrpt->totalexecdcommands;
14786 timeouts = myrpt->timeouts;
14787
14788
14789
14790 reverse_patch_state = "DOWN";
14791 numoflinks = 0;
14792 l = myrpt->links.next;
14793 while(l && (l != &myrpt->links)){
14794 if(numoflinks >= MAX_STAT_LINKS){
14795 ast_log(LOG_NOTICE,
14796 "maximum number of links exceeds %d in rpt_do_stats()!",MAX_STAT_LINKS);
14797 break;
14798 }
14799 if (l->name[0] == '0'){
14800 reverse_patch_state = "UP";
14801 l = l->next;
14802 continue;
14803 }
14804 listoflinks[numoflinks] = ast_strdup(l->name);
14805 if(listoflinks[numoflinks] == NULL){
14806 break;
14807 }
14808 else{
14809 numoflinks++;
14810 }
14811 l = l->next;
14812 }
14813
14814 if(myrpt->keyed)
14815 input_signal = "YES";
14816 else
14817 input_signal = "NO";
14818
14819 if(myrpt->txkeyed)
14820 transmitterkeyed = "YES";
14821 else
14822 transmitterkeyed = "NO";
14823
14824 if(myrpt->p.parrotmode)
14825 parrot_ena = "ENABLED";
14826 else
14827 parrot_ena = "DISABLED";
14828
14829 if(myrpt->p.s[myrpt->p.sysstate_cur].txdisable)
14830 sys_ena = "DISABLED";
14831 else
14832 sys_ena = "ENABLED";
14833
14834 if(myrpt->p.s[myrpt->p.sysstate_cur].totdisable)
14835 tot_ena = "DISABLED";
14836 else
14837 tot_ena = "ENABLED";
14838
14839 if(myrpt->p.s[myrpt->p.sysstate_cur].linkfundisable)
14840 link_ena = "DISABLED";
14841 else
14842 link_ena = "ENABLED";
14843
14844 if(myrpt->p.s[myrpt->p.sysstate_cur].autopatchdisable)
14845 patch_ena = "DISABLED";
14846 else
14847 patch_ena = "ENABLED";
14848
14849 if(myrpt->p.s[myrpt->p.sysstate_cur].schedulerdisable)
14850 sch_ena = "DISABLED";
14851 else
14852 sch_ena = "ENABLED";
14853
14854 if(myrpt->p.s[myrpt->p.sysstate_cur].userfundisable)
14855 user_funs = "DISABLED";
14856 else
14857 user_funs = "ENABLED";
14858
14859 if(myrpt->p.s[myrpt->p.sysstate_cur].alternatetail)
14860 tail_type = "ALTERNATE";
14861 else
14862 tail_type = "STANDARD";
14863
14864 if(!myrpt->totimer)
14865 tot_state = "TIMED OUT!";
14866 else if(myrpt->totimer != myrpt->p.totime)
14867 tot_state = "ARMED";
14868 else
14869 tot_state = "RESET";
14870
14871 if(myrpt->tailid)
14872 ider_state = "QUEUED IN TAIL";
14873 else if(myrpt->mustid)
14874 ider_state = "QUEUED FOR CLEANUP";
14875 else
14876 ider_state = "CLEAN";
14877
14878 switch(myrpt->callmode){
14879 case 1:
14880 patch_state = "DIALING";
14881 break;
14882 case 2:
14883 patch_state = "CONNECTING";
14884 break;
14885 case 3:
14886 patch_state = "UP";
14887 break;
14888
14889 case 4:
14890 patch_state = "CALL FAILED";
14891 break;
14892
14893 default:
14894 patch_state = "DOWN";
14895 }
14896
14897 if(strlen(myrpt->exten)){
14898 called_number = ast_strdup(myrpt->exten);
14899 }
14900
14901 if(strlen(myrpt->lastdtmfcommand)){
14902 lastdtmfcommand = ast_strdup(myrpt->lastdtmfcommand);
14903 }
14904 rpt_mutex_unlock(&myrpt->lock);
14905
14906 astman_append(s, "IsRemoteBase: NO\r\n");
14907 astman_append(s, "NodeState: %d\r\n", myrpt->p.sysstate_cur);
14908 astman_append(s, "SignalOnInput: %s\r\n", input_signal);
14909 astman_append(s, "TransmitterKeyed: %s\r\n", transmitterkeyed);
14910 astman_append(s, "Transmitter: %s\r\n", sys_ena);
14911 astman_append(s, "Parrot: %s\r\n", parrot_ena);
14912 astman_append(s, "Scheduler: %s\r\n", sch_ena);
14913 astman_append(s, "TailLength: %s\r\n", tail_type);
14914 astman_append(s, "TimeOutTimer: %s\r\n", tot_ena);
14915 astman_append(s, "TimeOutTimerState: %s\r\n", tot_state);
14916 astman_append(s, "TimeOutsSinceSystemInitialization: %d\r\n", timeouts);
14917 astman_append(s, "IdentifierState: %s\r\n", ider_state);
14918 astman_append(s, "KerchunksToday: %d\r\n", dailykerchunks);
14919 astman_append(s, "KerchunksSinceSystemInitialization: %d\r\n", totalkerchunks);
14920 astman_append(s, "KeyupsToday: %d\r\n", dailykeyups);
14921 astman_append(s, "KeyupsSinceSystemInitialization: %d\r\n", totalkeyups);
14922 astman_append(s, "DtmfCommandsToday: %d\r\n", dailyexecdcommands);
14923 astman_append(s, "DtmfCommandsSinceSystemInitialization: %d\r\n", totalexecdcommands);
14924 astman_append(s, "LastDtmfCommandExecuted: %s\r\n",
14925 (lastdtmfcommand && strlen(lastdtmfcommand)) ? lastdtmfcommand : not_applicable);
14926 hours = dailytxtime/3600000;
14927 dailytxtime %= 3600000;
14928 minutes = dailytxtime/60000;
14929 dailytxtime %= 60000;
14930 seconds = dailytxtime/1000;
14931 dailytxtime %= 1000;
14932
14933 astman_append(s, "TxTimeToday: %02d:%02d:%02d.%d\r\n",
14934 hours, minutes, seconds, dailytxtime);
14935
14936 hours = (int) totaltxtime/3600000;
14937 totaltxtime %= 3600000;
14938 minutes = (int) totaltxtime/60000;
14939 totaltxtime %= 60000;
14940 seconds = (int) totaltxtime/1000;
14941 totaltxtime %= 1000;
14942
14943 astman_append(s, "TxTimeSinceSystemInitialization: %02d:%02d:%02d.%d\r\n",
14944 hours, minutes, seconds, (int) totaltxtime);
14945
14946 sprintf(str, "NodesCurrentlyConnectedToUs: ");
14947 if(!numoflinks){
14948 strcat(str,"<NONE>");
14949 }
14950 else{
14951 for(j = 0 ;j < numoflinks; j++){
14952 sprintf(str+strlen(str), "%s", listoflinks[j]);
14953 if(j < numoflinks - 1)
14954 strcat(str,",");
14955 }
14956 }
14957 astman_append(s,"%s\r\n", str);
14958
14959 astman_append(s, "Autopatch: %s\r\n", patch_ena);
14960 astman_append(s, "AutopatchState: %s\r\n", patch_state);
14961 astman_append(s, "AutopatchCalledNumber: %s\r\n",
14962 (called_number && strlen(called_number)) ? called_number : not_applicable);
14963 astman_append(s, "ReversePatchIaxrptConnected: %s\r\n", reverse_patch_state);
14964 astman_append(s, "UserLinkingCommands: %s\r\n", link_ena);
14965 astman_append(s, "UserFunctions: %s\r\n", user_funs);
14966
14967 for(j = 0; j < numoflinks; j++){
14968 ast_free(listoflinks[j]);
14969 }
14970 if(called_number){
14971 ast_free(called_number);
14972 }
14973 if(lastdtmfcommand){
14974 ast_free(lastdtmfcommand);
14975 }
14976 astman_append(s, "\r\n");
14977 return 0;
14978 }
14979 }
14980 astman_send_error(s, m, "RptStatus unknown or missing node");
14981 return -1;
14982 }
14983
14984
14985
14986
14987
14988
14989
14990 static int manager_rpt_status(struct mansession *s, const struct message *m)
14991 {
14992 int i,res,len,idx;
14993 int uptime,hours,minutes;
14994 time_t now;
14995 const char *cmd = astman_get_header(m, "Command");
14996 char *str;
14997 enum {MGRCMD_RPTSTAT,MGRCMD_NODESTAT};
14998 struct mgrcmdtbl{
14999 const char *cmd;
15000 int index;
15001 };
15002 static struct mgrcmdtbl mct[] = {
15003 {"RptStat",MGRCMD_RPTSTAT},
15004 {"NodeStat",MGRCMD_NODESTAT},
15005 {NULL,0}
15006 };
15007
15008 time(&now);
15009
15010 len = 1024;
15011 if(!(str = ast_malloc(len)))
15012 return -1;
15013
15014
15015 if(ast_strlen_zero(cmd)){
15016 astman_send_error(s, m, "RptStatus missing command");
15017 ast_free(str);
15018 return 0;
15019 }
15020
15021 for(i = 0 ; mct[i].cmd ; i++){
15022 if(!strcmp(mct[i].cmd, cmd))
15023 break;
15024 }
15025
15026 if(!mct[i].cmd){
15027 astman_send_error(s, m, "RptStatus unknown command");
15028 ast_free(str);
15029 return 0;
15030 }
15031 else
15032 idx = mct[i].index;
15033
15034 switch(idx){
15035
15036 case MGRCMD_RPTSTAT:
15037
15038 if((res = snprintf(str, len, "Nodes: ")) > -1)
15039 len -= res;
15040 else{
15041 ast_free(str);
15042 return 0;
15043 }
15044 for(i = 0; i < nrpts; i++){
15045 if(i < nrpts - 1){
15046 if((res = snprintf(str+strlen(str), len, "%s,",rpt_vars[i].name)) < 0){
15047 ast_free(str);
15048 return 0;
15049 }
15050 }
15051 else{
15052 if((res = snprintf(str+strlen(str), len, "%s",rpt_vars[i].name)) < 0){
15053 ast_free(str);
15054 return 0;
15055 }
15056 }
15057 len -= res;
15058 }
15059
15060 rpt_manager_success(s,m);
15061
15062 if(!nrpts)
15063 astman_append(s, "<NONE>\r\n");
15064 else
15065 astman_append(s, "%s\r\n", str);
15066
15067 uptime = (int)(now - starttime);
15068 hours = uptime/3600;
15069 uptime %= 3600;
15070 minutes = uptime/60;
15071 uptime %= 60;
15072
15073 astman_append(s, "RptUptime: %02d:%02d:%02d\r\n",
15074 hours, minutes, uptime);
15075
15076 astman_append(s, "\r\n");
15077 break;
15078
15079 case MGRCMD_NODESTAT:
15080 res = rpt_manager_do_stats(s,m,str);
15081 ast_free(str);
15082 return res;
15083
15084 default:
15085 astman_send_error(s, m, "RptStatus invalid command");
15086 break;
15087 }
15088 ast_free(str);
15089 return 0;
15090 }
15091
15092 #endif
15093
15094 #ifdef OLD_ASTERISK
15095 int unload_module()
15096 #else
15097 static int unload_module(void)
15098 #endif
15099 {
15100 int i, res;
15101
15102 #ifdef OLD_ASTERISK
15103 STANDARD_HANGUP_LOCALUSERS;
15104 #endif
15105 for(i = 0; i < nrpts; i++) {
15106 if (!strcmp(rpt_vars[i].name,rpt_vars[i].p.nodes)) continue;
15107 ast_mutex_destroy(&rpt_vars[i].lock);
15108 ast_mutex_destroy(&rpt_vars[i].remlock);
15109 }
15110 res = ast_unregister_application(app);
15111
15112 #ifdef NEW_ASTERISK
15113 ast_cli_unregister_multiple(rpt_cli,sizeof(rpt_cli) /
15114 sizeof(struct ast_cli_entry));
15115 #else
15116
15117 ast_cli_unregister(&cli_debug);
15118 ast_cli_unregister(&cli_dump);
15119 ast_cli_unregister(&cli_stats);
15120 ast_cli_unregister(&cli_lstats);
15121 ast_cli_unregister(&cli_nodes);
15122 ast_cli_unregister(&cli_local_nodes);
15123 ast_cli_unregister(&cli_reload);
15124 ast_cli_unregister(&cli_restart);
15125 ast_cli_unregister(&cli_fun);
15126 ast_cli_unregister(&cli_fun1);
15127 res |= ast_cli_unregister(&cli_cmd);
15128 #endif
15129 #ifndef OLD_ASTERISK
15130 res |= ast_manager_unregister("RptLocalNodes");
15131 res |= ast_manager_unregister("RptStatus");
15132 #endif
15133 return res;
15134 }
15135
15136 #ifdef OLD_ASTERISK
15137 int load_module()
15138 #else
15139 static int load_module(void)
15140 #endif
15141 {
15142 int res;
15143 ast_pthread_create(&rpt_master_thread,NULL,rpt_master,NULL);
15144
15145 #ifdef NEW_ASTERISK
15146 ast_cli_register_multiple(rpt_cli,sizeof(rpt_cli) /
15147 sizeof(struct ast_cli_entry));
15148 res = 0;
15149 #else
15150
15151 ast_cli_register(&cli_debug);
15152 ast_cli_register(&cli_dump);
15153 ast_cli_register(&cli_stats);
15154 ast_cli_register(&cli_lstats);
15155 ast_cli_register(&cli_nodes);
15156 ast_cli_register(&cli_local_nodes);
15157 ast_cli_register(&cli_reload);
15158 ast_cli_register(&cli_restart);
15159 ast_cli_register(&cli_fun);
15160 ast_cli_register(&cli_fun1);
15161 res = ast_cli_register(&cli_cmd);
15162 #endif
15163 #ifndef OLD_ASTERISK
15164 res |= ast_manager_register("RptLocalNodes", 0, manager_rpt_local_nodes, "List local node numbers");
15165 res |= ast_manager_register("RptStatus", 0, manager_rpt_status, "Return Rpt Status for CGI");
15166
15167 #endif
15168 res |= ast_register_application(app, rpt_exec, synopsis, descrip);
15169 return res;
15170 }
15171
15172 #ifdef OLD_ASTERISK
15173 char *description()
15174 {
15175 return tdesc;
15176 }
15177 int usecount(void)
15178 {
15179 int res;
15180 STANDARD_USECOUNT(res);
15181 return res;
15182 }
15183
15184 char *key()
15185 {
15186 return ASTERISK_GPL_KEY;
15187 }
15188 #endif
15189
15190 #ifdef OLD_ASTERISK
15191 int reload()
15192 #else
15193 static int reload(void)
15194 #endif
15195 {
15196 int n;
15197
15198 for(n = 0; n < nrpts; n++) rpt_vars[n].reload = 1;
15199 return(0);
15200 }
15201
15202
15203 #ifndef OLD_ASTERISK
15204
15205 AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_DEFAULT, "Radio Repeater/Remote Base Application",
15206 .load = load_module,
15207 .unload = unload_module,
15208 .reload = reload,
15209 );
15210 #endif
15211